// rdevent_line.cpp // // Abstract a Rivendell Log Manager Event // // (C) Copyright 2002-2022 Fred Gleason // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public // License along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // #include #include #include "rdapplication.h" #include "rdconf.h" #include "rdcart.h" #include "rddb.h" #include "rdescape_string.h" #include "rdevent.h" #include "rdevent_line.h" #include "rdeventimportlist.h" #include "rdschedcartlist.h" RDEventLine::RDEventLine(RDStation *station) { event_station=station; event_preimport_list=new RDEventImportList(); event_postimport_list=new RDEventImportList(); clear(); } QString RDEventLine::name() const { return event_name; } void RDEventLine::setName(const QString &name) { event_name=name; event_preimport_list->setEventName(event_name); event_preimport_list->setType(RDEventImportList::PreImport); event_postimport_list->setEventName(event_name); event_postimport_list->setType(RDEventImportList::PostImport); } int RDEventLine::preposition() const { return event_preposition; } void RDEventLine::setPreposition(int offset) { event_preposition=offset; } RDLogLine::TimeType RDEventLine::timeType() const { return event_time_type; } void RDEventLine::setTimeType(RDLogLine::TimeType type) { event_time_type=type; } int RDEventLine::graceTime() const { return event_grace_time; } void RDEventLine::setGraceTime(int offset) { event_grace_time=offset; } bool RDEventLine::useAutofill() const { return event_use_autofill; } void RDEventLine::setUseAutofill(bool state) { event_use_autofill=state; } int RDEventLine::autofillSlop() const { return event_autofill_slop; } void RDEventLine::setAutofillSlop(int slop) { event_autofill_slop=slop; } bool RDEventLine::useTimescale() const { return event_use_timescale; } void RDEventLine::setUseTimescale(bool state) { event_use_timescale=state; } RDEventLine::ImportSource RDEventLine::importSource() const { return event_import_source; } void RDEventLine::setImportSource(RDEventLine::ImportSource src) { event_import_source=src; } int RDEventLine::startSlop() const { return event_start_slop; } void RDEventLine::setStartSlop(int slop) { event_start_slop=slop; } int RDEventLine::endSlop() const { return event_end_slop; } void RDEventLine::setEndSlop(int slop) { event_end_slop=slop; } RDLogLine::TransType RDEventLine::firstTransType() const { return event_first_transtype; } void RDEventLine::setFirstTransType(RDLogLine::TransType trans) { event_first_transtype=trans; } RDLogLine::TransType RDEventLine::defaultTransType() const { return event_default_transtype; } void RDEventLine::setDefaultTransType(RDLogLine::TransType trans) { event_default_transtype=trans; } QColor RDEventLine::color() const { return event_color; } void RDEventLine::setColor(const QColor &color) { event_color=color; } QString RDEventLine::schedGroup() const { return event_sched_group; } void RDEventLine::setSchedGroup(QString str) { event_sched_group=str; } QString RDEventLine::HaveCode() const { return event_have_code; } void RDEventLine::setHaveCode(QString str) { event_have_code=str; } QString RDEventLine::HaveCode2() const { return event_have_code2; } void RDEventLine::setHaveCode2(QString str) { event_have_code2=str; } unsigned RDEventLine::titleSep() const { return event_title_sep; } void RDEventLine::setTitleSep(unsigned titlesep) { event_title_sep=titlesep; } QTime RDEventLine::startTime() const { return event_start_time; } void RDEventLine::setStartTime(const QTime &time) { event_start_time=time; } int RDEventLine::length() const { return event_length; } void RDEventLine::setLength(int msecs) { event_length=msecs; } void RDEventLine::clear() { event_name=""; event_preposition=0; event_time_type=RDLogLine::Relative; event_grace_time=0; event_use_autofill=false; event_use_timescale=false; event_import_source=RDEventLine::None; event_start_slop=0; event_end_slop=0; event_first_transtype=RDLogLine::Segue; event_default_transtype=RDLogLine::Segue; event_color=QColor(); event_preimport_list->clear(); event_postimport_list->clear(); event_start_time=QTime(0,0,0,0); event_length=0; event_autofill_slop=-1; event_sched_group=""; event_have_code=""; event_have_code2=""; event_artist_sep=15; event_title_sep=100; event_nested_event=""; } bool RDEventLine::load() { QString sql=QString("select ")+ "PREPOSITION,"+ // 00 "TIME_TYPE,"+ // 01 "GRACE_TIME,"+ // 02 "USE_AUTOFILL,"+ // 03 "USE_TIMESCALE,"+ // 04 "IMPORT_SOURCE,"+ // 05 "START_SLOP,"+ // 06 "END_SLOP,"+ // 07 "FIRST_TRANS_TYPE,"+ // 08 "DEFAULT_TRANS_TYPE,"+ // 09 "COLOR,"+ // 10 "AUTOFILL_SLOP,"+ // 11 "NESTED_EVENT,"+ // 12 "SCHED_GROUP,"+ // 13 "ARTIST_SEP,"+ // 14 "TITLE_SEP,"+ // 15 "HAVE_CODE,"+ // 16 "HAVE_CODE2 "+ // 17 "from EVENTS where "+ "NAME=\""+RDEscapeString(event_name)+"\""; RDSqlQuery *q=new RDSqlQuery(sql); if(!q->first()) { fprintf(stderr,"RDEventLine::load() EVENT NOT FOUND: %s\n", (const char *)event_name); delete q; return false; } event_preposition=q->value(0).toInt(); event_time_type=(RDLogLine::TimeType)q->value(1).toInt(); event_grace_time=q->value(2).toInt(); event_use_autofill=RDBool(q->value(3).toString()); event_use_timescale=RDBool(q->value(4).toString()); event_import_source=(RDEventLine::ImportSource)q->value(5).toInt(); event_start_slop=q->value(6).toInt(); event_end_slop=q->value(7).toInt(); event_first_transtype=(RDLogLine::TransType)q->value(8).toInt(); event_default_transtype=(RDLogLine::TransType)q->value(9).toInt(); if(q->value(10).isNull()) { event_color=QColor(); } else { event_color=QColor(q->value(10).toString()); } event_autofill_slop=q->value(11).toInt(); event_nested_event=q->value(12).toString(); event_sched_group=q->value(13).toString(); event_artist_sep=q->value(14).toInt(); event_title_sep=q->value(15).toInt(); event_have_code=q->value(16).toString(); event_have_code2=q->value(17).toString(); delete q; event_preimport_list->load(); event_postimport_list->load(); return true; } bool RDEventLine::save(RDConfig *config) { QString sql=QString("select NAME from EVENTS where ")+ "NAME=\""+RDEscapeString(event_name)+"\""; RDSqlQuery *q=new RDSqlQuery(sql); if(q->first()) { sql=QString("update EVENTS set ")+ QString().sprintf("PREPOSITION=%d,",event_preposition)+ QString().sprintf("TIME_TYPE=%d,",event_time_type)+ QString().sprintf("GRACE_TIME=%d,",event_grace_time)+ "USE_AUTOFILL=\""+RDYesNo(event_use_autofill)+"\","+ "USE_TIMESCALE=\""+RDYesNo(event_use_timescale)+"\","+ QString().sprintf("IMPORT_SOURCE=%d,",event_import_source)+ QString().sprintf("START_SLOP=%d,",event_start_slop)+ QString().sprintf("END_SLOP=%d,",event_end_slop)+ QString().sprintf("FIRST_TRANS_TYPE=%d,",event_first_transtype)+ QString().sprintf("DEFAULT_TRANS_TYPE=%d,",event_default_transtype)+ "COLOR=\""+RDEscapeString(event_color.name())+"\""+ QString().sprintf("AUTOFILL_SLOP=%d,",event_autofill_slop)+ "NESTED_EVENT=\""+RDEscapeString(event_nested_event)+"\","+ "SCHED_GROUP=\""+RDEscapeString(event_sched_group)+"\","+ QString().sprintf("ARTIST_SEP=%d,",event_artist_sep)+ QString().sprintf("TITLE_SEP=%d,",event_title_sep)+ "HAVE_CODE=\""+RDEscapeString(event_have_code)+"\","+ "HAVE_CODE2=\""+RDEscapeString(event_have_code2)+"\" "+ "where NAME=\""+RDEscapeString(event_name)+"\""; } else { sql=QString("insert into EVENTS set ")+ "NAME=\""+RDEscapeString(event_name)+"\","+ QString().sprintf("PREPOSITION=%d,",event_preposition)+ QString().sprintf("TIME_TYPE=%d,",event_time_type)+ QString().sprintf("GRACE_TIME=%d,",event_grace_time)+ "USE_AUTOFILL=\""+RDYesNo(event_use_autofill)+"\","+ "USE_TIMESCALE=\""+RDYesNo(event_use_timescale)+"\","+ QString().sprintf("IMPORT_SOURCE=%d,",event_import_source)+ QString().sprintf("START_SLOP=%d,",event_start_slop)+ QString().sprintf("END_SLOP=%d,",event_end_slop)+ QString().sprintf("FIRST_TRANS_TYPE=%d,",event_first_transtype)+ QString().sprintf("DEFAULT_TRANS_TYPE=%d,",event_default_transtype)+ "COLOR=\""+RDEscapeString(event_color.name())+"\","+ QString().sprintf("AUTOFILL_SLOP=%d,",event_autofill_slop)+ "SCHED_GROUP=\""+RDEscapeString(event_sched_group)+"\" where "+ "NAME=\""+RDEscapeString(event_name)+"\""; } delete q; q=new RDSqlQuery(sql); if(!q->isActive()) { delete q; return false; } delete q; event_preimport_list->save(); event_postimport_list->save(); return true; } bool RDEventLine::generateLog(QString logname,const QString &svcname, QString *report, QString clockname) { QString sql; RDSqlQuery *q; RDSqlQuery *q1; QTime time=event_start_time; QTime fill_start_time; int count=0; QString import_table; int postimport_length=0; RDLogLine::TransType trans_type=event_first_transtype; RDLogLine::TimeType time_type=event_time_type; RDLogLine::Type link_type=RDLogLine::MusicLink; int grace_time=event_grace_time; int link_id=0; // // Get Current Count and Link ID // sql=QString("select COUNT from LOG_LINES where ")+ "LOG_NAME=\""+RDEscapeString(logname)+"\" "+ "order by COUNT desc"; q=new RDSqlQuery(sql); if(q->first()) { count=q->value(0).toInt()+1; } delete q; sql=QString("select LINK_ID from LOG_LINES where ")+ "LOG_NAME=\""+RDEscapeString(logname)+"\" && "+ "LINK_ID>=0 "+ "order by LINK_ID desc"; q=new RDSqlQuery(sql); if(q->first()) { link_id=q->value(0).toInt()+1; } delete q; // // Override Default Parameters if Preposition Set // if(event_preposition>=0) { time_type=RDLogLine::Hard; grace_time=-1; if(QTime().msecsTo(time)>event_preposition) { time=time.addMSecs(-event_preposition); } else { time=QTime(); } } // // Pre-Import Carts // postimport_length=0; for(int i=0;isize()-1;i++) { RDEventImportItem *i_item=event_preimport_list->item(i); sql=QString("insert into LOG_LINES set ")+ "LOG_NAME=\""+RDEscapeString(logname)+"\","+ QString().sprintf("LINE_ID=%d,",count)+ QString().sprintf("COUNT=%d,",count)+ QString().sprintf("TYPE=%d,",i_item->eventType())+ QString().sprintf("SOURCE=%d,",RDLogLine::Template)+ QString().sprintf("START_TIME=%d,",QTime().msecsTo(time))+ QString().sprintf("GRACE_TIME=%d,",grace_time)+ QString().sprintf("CART_NUMBER=%u,",i_item->cartNumber())+ QString().sprintf("TIME_TYPE=%d,",time_type)+ QString().sprintf("TRANS_TYPE=%d,",i_item->transType())+ "COMMENT=\""+RDEscapeString(i_item->markerComment())+"\","+ QString().sprintf("EVENT_LENGTH=%d",event_length); RDSqlQuery::apply(sql); count++; trans_type=event_default_transtype; time_type=RDLogLine::Relative; grace_time=-1; postimport_length+=GetLength(i_item->cartNumber()); } // // Import Links // if(event_import_source==RDEventLine::Traffic || event_import_source==RDEventLine::Music) { switch(event_import_source) { case RDEventLine::Traffic: link_type=RDLogLine::TrafficLink; break; case RDEventLine::Music: link_type=RDLogLine::MusicLink; break; default: break; } QTime end_start_time=event_start_time.addMSecs(event_length); sql=QString("insert into LOG_LINES set ")+ "LOG_NAME=\""+RDEscapeString(logname)+"\","+ QString().sprintf("LINE_ID=%d,",count)+ QString().sprintf("COUNT=%d,",count)+ QString().sprintf("TYPE=%d,",link_type)+ QString().sprintf("SOURCE=%d,",RDLogLine::Template)+ QString().sprintf("START_TIME=%d,",QTime().msecsTo(time))+ QString().sprintf("GRACE_TIME=%d,",grace_time)+ QString().sprintf("TIME_TYPE=%d,",time_type)+ QString().sprintf("TRANS_TYPE=%d,",trans_type)+ "LINK_EVENT_NAME=\""+RDEscapeString(event_name)+"\","+ QString().sprintf("LINK_START_TIME=%d,", QTime().msecsTo(event_start_time))+ QString().sprintf("LINK_LENGTH=%d,", event_start_time.msecsTo(end_start_time))+ QString().sprintf("LINK_ID=%d,",link_id)+ QString().sprintf("LINK_START_SLOP=%d,",event_start_slop)+ QString().sprintf("LINK_END_SLOP=%d,",event_end_slop)+ QString().sprintf("EVENT_LENGTH=%d",event_length); q=new RDSqlQuery(sql); delete q; count++; time=time.addMSecs(event_length); trans_type=event_default_transtype; time_type=RDLogLine::Relative; grace_time=-1; } // Scheduler if(event_import_source == RDEventLine::Scheduler) { int artistsep; int titlesep; int stackid; int counter; RDLogLine::Source source=RDLogLine::Music; QString svcname_rp = svcname; svcname_rp.replace(" ","_"); time.addMSecs(postimport_length); if(event_artist_sep>=-1 && event_artist_sep<=50000) { artistsep = event_artist_sep; } else { artistsep = 15; } if(event_title_sep>=-1 && event_title_sep<=50000) { titlesep = event_title_sep; } else { titlesep = 100; } // // Get next stack id from the stack // sql=QString("select ")+ "MAX(SCHED_STACK_ID) "+ "from STACK_LINES where "+ "SERVICE_NAME=\""+RDEscapeString(svcname)+"\""; q=new RDSqlQuery(sql); if (q->next()) { stackid=q->value(0).toUInt(); } else { stackid=0; } stackid++; delete q; // // Load all carts in requested group into schedCL // sql=QString("select NUMBER,ARTIST,TITLE,")+ "CONCAT(GROUP_CONCAT(RPAD(SC.SCHED_CODE,11,' ') separator ''),'.') as SCHED_CODES"+ " from CART LEFT JOIN CART_SCHED_CODES AS SC on (NUMBER=SC.CART_NUMBER)"+ " where GROUP_NAME='"+RDEscapeString(schedGroup())+"'"+ " group by NUMBER"; RDSchedCartList *schedCL=new RDSchedCartList(); q=new RDSqlQuery(sql); while(q->next()) { QStringList codes=q->value(3).toString().split(" ",QString::SkipEmptyParts); if((codes.size()>0)&&(codes.last()==".")) { codes.removeLast(); } schedCL-> insertItem(q->value(0).toUInt(),0,0,q->value(1).toString(),q->value(2).toString(),codes); } delete q; ////////////////////////////////// // // // Add deconflicting rules here // // // ////////////////////////////////// // Reduce schedCL to match requested scheduler code if(event_have_code!=""||event_have_code2!="") { QStringList codes; if(event_have_code!="") { codes << event_have_code; } if(event_have_code2!="") { codes << event_have_code2; } for(counter=0;countergetNumberOfItems();counter++) { if(!schedCL->itemHasCodes(counter,codes)) { schedCL->removeItem(counter); counter--; } } } if(schedCL->getNumberOfItems()) { // // Title separation // // Iterate through schedCL and remove carts from schedCL that // match title on the stack. // if(titlesep>=0) { schedCL->save(); sql=QString("select TITLE from STACK_LINES where ")+ "SERVICE_NAME=\""+RDEscapeString(svcname)+"\" && "+ QString().sprintf("SCHED_STACK_ID >= %d",stackid-titlesep); q=new RDSqlQuery(sql); while (q->next()) { for(counter=0;countergetNumberOfItems();counter++) { if(q->value(0).toString()==schedCL->getItemTitle(counter)) { schedCL->removeItem(counter); counter--; } } } delete q; if(schedCL->getNumberOfItems()==0) { *report+=time.toString("hh:mm:ss")+" "+ QObject::tr("Rule broken: Title separation"); if(!HaveCode().isEmpty()) { *report+=QObject::tr(" with sched code(s): ")+HaveCode()+" "+HaveCode2(); } *report+="\n"; schedCL->restore(); } } // // Artist separation // // Iterate through schedCL and remove carts from schedCL that // match artist on the stack. // if(artistsep>=0) { schedCL->save(); sql=QString("select ARTIST from STACK_LINES where ")+ "SERVICE_NAME=\""+RDEscapeString(svcname)+"\" && "+ QString().sprintf("SCHED_STACK_ID >= %d",stackid-artistsep); q=new RDSqlQuery(sql); while (q->next()) { for(counter=0;countergetNumberOfItems();counter++) { if(q->value(0).toString()==schedCL->getItemArtist(counter)) { schedCL->removeItem(counter); counter--; } } } delete q; if(schedCL->getNumberOfItems()==0) { *report+=time.toString("hh:mm:ss")+" "+ QObject::tr("Rule broken: Artist separation"); if(!HaveCode().isEmpty()) { *report+=QObject::tr(" with sched code(s): ")+HaveCode()+" "+HaveCode2(); } *report+="\n"; schedCL->restore(); } } // Clock Scheduler Rules sql=QString("select ")+ "CODE,"+ // 00 "MAX_ROW,"+ // 01 "MIN_WAIT,"+ // 02 "NOT_AFTER,"+ // 03 "OR_AFTER,"+ // 04 "OR_AFTER_II "+ // 05 "from RULE_LINES where "+ "CLOCK_NAME=\""+RDEscapeString(clockname)+"\""; q=new RDSqlQuery(sql); while (q->next()) { // max in a row, min wait schedCL->save(); int range=q->value(1).toInt()+q->value(2).toInt(); int allowed=q->value(1).toInt(); QString wstr=q->value(0).toString(); wstr+=" "; wstr=wstr.left(11); sql=QString("select STACK_LINES.CART ")+ "from STACK_LINES left join STACK_SCHED_CODES "+ "on STACK_LINES.ID=STACK_SCHED_CODES.STACK_LINES_ID where "+ "STACK_LINES.SERVICE_NAME=\""+RDEscapeString(svcname)+"\" && "+ QString().sprintf("STACK_LINES.SCHED_STACK_ID > %d && ", stackid-range)+ "STACK_SCHED_CODES.SCHED_CODE=\""+RDEscapeString(wstr)+"\""; q1=new RDSqlQuery(sql); if(q1->size()>=allowed || allowed==0) { for(counter=0;countergetNumberOfItems();counter++) { if(schedCL->removeIfCode(counter,q->value(0).toString())) { counter--; } } } delete q1; if(schedCL->getNumberOfItems()==0) { *report+=time.toString("hh:mm:ss")+" "+ QObject::tr("Rule broken: Max. in a Row/Min. Wait for ")+ q->value(0).toString()+"\n"; schedCL->restore(); } // do not play after if(q->value(3).toString()!="") { schedCL->save(); QString wstr=q->value(3).toString(); wstr+=" "; wstr=wstr.left(11); sql=QString("select STACK_LINES.CART ")+ "from STACK_LINES left join STACK_SCHED_CODES "+ "on STACK_LINES.ID=STACK_SCHED_CODES.STACK_LINES_ID where "+ "STACK_LINES.SERVICE_NAME=\""+RDEscapeString(svcname)+"\" && "+ QString().sprintf("STACK_LINES.SCHED_STACK_ID=%d && ",stackid-1)+ "STACK_SCHED_CODES.SCHED_CODE=\""+RDEscapeString(wstr)+"\""; q1=new RDSqlQuery(sql); if(q1->size()>0) { for(counter=0;countergetNumberOfItems();counter++) { if(schedCL->removeIfCode(counter,q->value(0).toString())) { counter--; } } } delete q1; if(schedCL->getNumberOfItems()==0) { *report+=time.toString("hh:mm:ss")+" "+ QObject::tr("Rule broken: Do not schedule ")+ q->value(0).toString()+" "+QObject::tr("after")+" "+ q->value(3).toString()+"\n"; schedCL->restore(); } } // or after if (q->value(4).toString()!="") { schedCL->save(); QString wstr=q->value(4).toString(); wstr+=" "; wstr=wstr.left(11); sql=QString("select STACK_LINES.CART ")+ "from STACK_LINES left join STACK_SCHED_CODES "+ "on STACK_LINES.ID=STACK_SCHED_CODES.STACK_LINES_ID where "+ QString().sprintf("STACK_LINES.SCHED_STACK_ID=%d && ",stackid-1)+ "STACK_SCHED_CODES.SCHED_CODE=\""+RDEscapeString(wstr)+"\""; q1=new RDSqlQuery(sql); if(q1->size()>0) { for(counter=0;countergetNumberOfItems();counter++) { if(schedCL->removeIfCode(counter,q->value(0).toString())) { counter--; } } } delete q1; if(schedCL->getNumberOfItems()==0) { *report+=time.toString("hh:mm:ss")+" "+ QObject::tr("Rule broken: Do not schedule")+" "+ q->value(0).toString()+" "+QObject::tr("after")+" "+ q->value(4).toString()+"\n"; schedCL->restore(); } } // or after II if (q->value(5).toString()!="") { schedCL->save(); QString wstr=q->value(5).toString(); wstr+=" "; wstr=wstr.left(11); sql=QString("select STACK_LINES.CART ")+ "from STACK_LINES left join STACK_SCHED_CODES "+ "on STACK_LINES.ID=STACK_SCHED_CODES.STACK_LINES_ID where "+ QString().sprintf("STACK_LINES.SCHED_STACK_ID=%d && ",stackid-1)+ "STACK_SCHED_CODES.SCHED_CODE=\""+RDEscapeString(wstr)+"\""; q1=new RDSqlQuery(sql); if(q1->size()>0) { for(counter=0;countergetNumberOfItems();counter++) { if(schedCL->removeIfCode(counter,q->value(0).toString())) { counter--; } } } delete q1; if(schedCL->getNumberOfItems()==0) { *report+=time.toString("hh:mm:ss")+" "+ QObject::tr("Rule broken: Do not schedule")+" "+ q->value(0).toString()+" "+QObject::tr("after")+" "+ q->value(5).toString()+"\n"; schedCL->restore(); } } } delete q; //////////////////////////////// // // // End of deconflicting rules // // // //////////////////////////////// // // Pick a random cart from those that are remaining. // int schedpos=rand()%schedCL->getNumberOfItems(); sql=QString("insert into LOG_LINES set ")+ "LOG_NAME=\""+RDEscapeString(logname)+"\","+ QString().sprintf("LINE_ID=%d,",count)+ QString().sprintf("COUNT=%d,",count)+ QString().sprintf("TYPE=%d,",RDLogLine::Cart)+ QString().sprintf("SOURCE=%d,",source)+ QString().sprintf("START_TIME=%d,",QTime().msecsTo(time))+ QString().sprintf("GRACE_TIME=%d,",grace_time)+ QString().sprintf("CART_NUMBER=%u,",schedCL->getItemCartNumber(schedpos))+ QString().sprintf("TIME_TYPE=%d,",time_type)+ QString().sprintf("TRANS_TYPE=%d,",trans_type)+ "EXT_START_TIME="+RDCheckDateTime(time,"hh:mm:ss")+","+ QString().sprintf("EVENT_LENGTH=%d",event_length); q=new RDSqlQuery(sql); delete q; count++; sql=QString("insert into STACK_LINES set ")+ "SERVICE_NAME=\""+RDEscapeString(svcname)+"\","+ "SCHEDULED_AT=now(),"+ QString().sprintf("SCHED_STACK_ID=%u,",stackid)+ QString().sprintf("CART=%u,",schedCL->getItemCartNumber(schedpos))+ "ARTIST=\""+RDEscapeString(schedCL->getItemArtist(schedpos))+"\","+ "TITLE=\""+RDEscapeString(schedCL->getItemTitle(schedpos))+"\""; unsigned line_id=RDSqlQuery::run(sql).toUInt(); QStringList codes=schedCL->getItemSchedCodes(schedpos); for(int i=0;isize()-1;i++) { RDEventImportItem *i_item=event_postimport_list->item(i); sql=QString("insert into LOG_LINES set ")+ "LOG_NAME=\""+RDEscapeString(logname)+"\","+ QString().sprintf("LINE_ID=%d,",count)+ QString().sprintf("COUNT=%d,",count)+ QString().sprintf("TYPE=%d,",i_item->eventType())+ QString().sprintf("SOURCE=%d,",RDLogLine::Template)+ QString().sprintf("START_TIME=%d,",QTime().msecsTo(time))+ QString().sprintf("GRACE_TIME=%d,",grace_time)+ QString().sprintf("CART_NUMBER=%u,",i_item->cartNumber())+ QString().sprintf("TIME_TYPE=%d,",time_type)+ QString().sprintf("TRANS_TYPE=%d,",i_item->transType())+ "COMMENT=\""+RDEscapeString(i_item->markerComment())+"\","+ QString().sprintf("EVENT_LENGTH=%d",event_length); RDSqlQuery::apply(sql); count++; time=time.addMSecs(GetLength(i_item->cartNumber())); time_type=RDLogLine::Relative; trans_type=event_default_transtype; grace_time=-1; } return true; } bool RDEventLine::linkLog(RDLogEvent *e,RDLog *log,const QString &svcname, RDLogLine *link_logline,const QString &track_str, const QString &label_cart,const QString &track_cart, QString *errors) { // // FIXME: This entire method needs to be burned down and replaced // with a rewrite. // QString sql; RDSqlQuery *q; RDSqlQuery *q1; RDLogLine *logline=NULL; // // Initial Import Parameters // RDLogLine::Source event_src=RDLogLine::Manual; switch(event_import_source) { case RDEventLine::Music: event_src=RDLogLine::Music; break; case RDEventLine::Traffic: event_src=RDLogLine::Traffic; break; case RDEventLine::Scheduler: case RDEventLine::None: break; } bool suppress_link_parameter_inheritance= rda->config()->suppressLinkParameterInheritance(svcname); RDLogLine::TimeType time_type=link_logline->timeType(); RDLogLine::TransType trans_type=link_logline->transType(); int grace_time=link_logline->graceTime(); QTime time=link_logline->startTime(RDLogLine::Logged); // // Get slop factors for inline traffic breaks // int inline_start_slop=0; int inline_end_slop=0; if(event_import_source==RDEventLine::Music) { sql=QString("select ")+ "`NESTED_EVENT` "+ // 00 "from `EVENTS` where "+ "`NAME`='"+RDEscapeString(event_name)+"'"; q=new RDSqlQuery(sql); if(q->first()) { if(!q->value(0).toString().trimmed().isEmpty()) { sql=QString("select ")+ "`START_SLOP`,"+ // 00 "`END_SLOP` "+ // 01 "from `EVENTS` where "+ "`NAME`='"+RDEscapeString(q->value(0).toString().trimmed())+"'"; q1=new RDSqlQuery(sql); if(q1->first()) { inline_start_slop=q1->value(0).toInt(); inline_end_slop=q1->value(1).toInt(); } delete q1; } } delete q; } // // Insert Parent Link // if((event_import_source==RDEventLine::Music)|| (event_import_source==RDEventLine::Traffic)) { // // Clear Leading Event Values // time_type=RDLogLine::Relative; trans_type=event_default_transtype; grace_time=-1; if(log->includeImportMarkers()&& !(rda->config()->suppressMusicImportLinks()&& (event_import_source==RDEventLine::Music))) { e->insert(e->size(),1); logline=new RDLogLine(); *logline=*link_logline; logline->setId(e->nextId()); *(e->logLine(e->size()-1))=*logline; delete logline; logline=NULL; } else { if(!suppress_link_parameter_inheritance) { // // Propagate Leading Event Values to Next Event // time_type=link_logline->timeType(); trans_type=link_logline->transType(); grace_time=link_logline->graceTime(); } } } // // Calculate Event Time Boundaries // int start_start_hour=link_logline->linkStartTime().hour(); int start_start_secs=60000*link_logline->linkStartTime().minute()+ 1000*link_logline->linkStartTime().second(); int end_start_secs=start_start_secs+link_logline->linkLength(); // // Apply Slop Factors // if(start_start_hour==link_logline->linkStartTime(). addMSecs(-link_logline->linkStartSlop()).hour()) { start_start_secs-=link_logline->linkStartSlop(); } else { start_start_secs=0; // So we don't slop over into the previous hour } end_start_secs+=link_logline->linkEndSlop(); // // Load Matching Events and Insert into Log // sql=QString("select ")+ "CART_NUMBER,"+ // 00 "START_SECS,"+ // 01 "LENGTH,"+ // 02 "EXT_DATA,"+ // 03 "EXT_EVENT_ID,"+ // 04 "EXT_ANNC_TYPE,"+ // 05 "EXT_CART_NAME,"+ // 06 "TITLE,"+ // 07 "TYPE,"+ // 08 "LINK_START_TIME,"+ // 09 "LINK_LENGTH "+ // 10 "from IMPORTER_LINES where "+ "STATION_NAME=\""+RDEscapeString(event_station->name())+"\" && "+ QString().sprintf("PROCESS_ID=%u && ",getpid())+ QString().sprintf("(START_HOUR=%d)&&",start_start_hour)+ QString().sprintf("(START_SECS>=%d)&&",start_start_secs/1000)+ QString().sprintf("(START_SECS<=%d)&&",end_start_secs/1000)+ "(EVENT_USED=\"N\") order by LINE_ID"; q=new RDSqlQuery(sql); while(q->next()) { int length=GetLength(q->value(0).toUInt(),q->value(2).toInt()); // // Inline Traffic Break // if(q->value(8).toUInt()==RDLogLine::TrafficLink) { if((!event_nested_event.isEmpty()&&(event_nested_event!=event_name))) { e->insert(e->size(),1); logline=e->logLine(e->size()-1); logline->setId(e->nextId()); logline->setStartTime(RDLogLine::Logged,time); logline->setType(RDLogLine::TrafficLink); logline->setSource(event_src); logline->setEventLength(event_length); logline->setLinkEventName(event_nested_event); logline->setLinkStartTime(q->value(9).toTime()); logline->setLinkLength(q->value(10).toInt()); logline->setLinkStartSlop(inline_start_slop); logline->setLinkEndSlop(inline_end_slop); logline->setLinkId(link_logline->linkId()); logline->setLinkEmbedded(true); } } // // Voicetrack Marker // if(q->value(8).toUInt()==RDLogLine::Track) { e->insert(e->size(),1); logline=e->logLine(e->size()-1); logline->setId(e->nextId()); logline->setStartTime(RDLogLine::Logged,time); logline->setType(RDLogLine::Track); logline->setSource(event_src); logline->setMarkerComment(q->value(7).toString()); logline->setEventLength(event_length); logline->setLinkEventName(event_name); logline->setLinkStartTime(link_logline->linkStartTime()); logline->setLinkLength(link_logline->linkLength()); logline->setLinkStartSlop(link_logline->linkStartSlop()); logline->setLinkEndSlop(link_logline->linkEndSlop()); logline->setLinkId(link_logline->linkId()); logline->setLinkEmbedded(true); } // // Label/Note Cart // if(q->value(8).toUInt()==RDLogLine::Marker) { e->insert(e->size(),1); logline=e->logLine(e->size()-1); logline->setId(e->nextId()); logline->setStartTime(RDLogLine::Logged,time); logline->setType(RDLogLine::Marker); logline->setSource(event_src); logline->setMarkerComment(q->value(7).toString()); logline->setEventLength(event_length); logline->setLinkEventName(event_name); logline->setLinkStartTime(link_logline->linkStartTime()); logline->setLinkLength(link_logline->linkLength()); logline->setLinkStartSlop(link_logline->linkStartSlop()); logline->setLinkEndSlop(link_logline->linkEndSlop()); logline->setLinkId(link_logline->linkId()); logline->setLinkEmbedded(true); } // // Cart // if(q->value(8).toUInt()==RDLogLine::Cart) { e->insert(e->size(),1); logline=e->logLine(e->size()-1); logline->setId(e->nextId()); logline->setSource(event_src); logline-> setStartTime(RDLogLine::Logged, QTime(start_start_hour,0,0).addSecs(q->value(1).toInt())); logline->setType(RDLogLine::Cart); logline->setCartNumber(q->value(0).toUInt()); logline->setExtStartTime(QTime().addSecs(3600*start_start_hour+ q->value(1).toInt())); logline->setExtLength(q->value(2).toInt()); logline->setExtData(q->value(3).toString().trimmed()); logline->setExtEventId(q->value(4).toString().trimmed()); logline->setExtAnncType(q->value(5).toString().trimmed()); logline->setExtCartName(q->value(6).toString().trimmed()); logline->setEventLength(event_length); logline->setLinkEventName(event_name); logline->setLinkStartTime(link_logline->linkStartTime()); logline->setLinkLength(link_logline->linkLength()); logline->setLinkStartSlop(link_logline->linkStartSlop()); logline->setLinkEndSlop(link_logline->linkEndSlop()); logline->setLinkId(link_logline->linkId()); logline->setLinkEmbedded(link_logline->linkEmbedded()); time=time.addMSecs(length); } // // Apply Leading Event Values // if(logline!=NULL) { logline->setGraceTime(grace_time); logline->setTimeType(time_type); logline->setTransType(trans_type); } // // Clear Leading Event Values // time_type=RDLogLine::Relative; trans_type=event_default_transtype; grace_time=-1; } delete q; // // Mark Events as Used // sql=QString("update IMPORTER_LINES set ")+ "EVENT_USED=\"Y\" where "+ "STATION_NAME=\""+RDEscapeString(event_station->name())+"\" && "+ QString().sprintf("PROCESS_ID=%u && ",getpid())+ QString().sprintf("(START_HOUR=%d)&&",start_start_hour)+ QString().sprintf("(START_SECS>=%d)&&",start_start_secs/1000)+ QString().sprintf("(START_SECS<=%d)&&",end_start_secs/1000)+ "(EVENT_USED=\"N\")"; q=new RDSqlQuery(sql); delete q; // // Autofill // QTime end_time=link_logline->startTime(RDLogLine::Logged). addMSecs(link_logline->linkLength()); if(event_use_autofill&&(event_start_time<=time)) { QTime fill_start_time=time; sql=QString("select ")+ "AUTOFILLS.CART_NUMBER,"+ // 00 "CART.FORCED_LENGTH "+ // 01 "from AUTOFILLS left join CART "+ "on AUTOFILLS.CART_NUMBER=CART.NUMBER where "+ "(AUTOFILLS.SERVICE=\""+RDEscapeString(svcname)+"\")&&"+ QString().sprintf("(CART.FORCED_LENGTH<=%d)&&",time.msecsTo(end_time))+ "(CART.FORCED_LENGTH>0) "+ "order by CART.FORCED_LENGTH desc"; q=new RDSqlQuery(sql); bool fit=true; while(fit) { fit=false; while(q->next()&&(fill_start_time<=time)) { if((time.addMSecs(q->value(1).toInt())<=end_time)&& (time.addMSecs(q->value(1).toInt())>time)) { e->insert(e->size(),1); logline=e->logLine(e->size()-1); logline->setId(e->nextId()); logline->setStartTime(RDLogLine::Logged,time); logline->setType(RDLogLine::Cart); logline->setSource(event_src); logline->setTransType(trans_type); logline->setGraceTime(grace_time); logline->setCartNumber(q->value(0).toUInt()); logline->setTimeType(time_type); logline->setEventLength(event_length); logline->setLinkEventName(event_name); logline->setLinkStartTime(link_logline->linkStartTime()); logline->setLinkLength(link_logline->linkLength()); logline->setLinkStartSlop(link_logline->linkStartSlop()); logline->setLinkEndSlop(link_logline->linkEndSlop()); logline->setLinkId(link_logline->linkId()); logline->setLinkEmbedded(false); time=time.addMSecs(q->value(1).toInt()); time_type=RDLogLine::Relative; trans_type=event_default_transtype; grace_time=-1; q->seek(-1); fit=true; } } } delete q; } // // Fill Check // if(event_autofill_slop>=0) { int slop=QTime().msecsTo(end_time)-QTime().msecsTo(time); if(abs(slop)>=event_autofill_slop) { if(slop>0) { *errors+=QString(" ")+time.toString("hh:mm:ss")+ " -- \""+event_name+"\" "+QObject::tr("is underscheduled by")+" "+ QTime().addMSecs(slop).toString("hh:mm:ss")+".\n"; } else { *errors+=QString(" ")+time.toString("hh:mm:ss")+ " -- \""+event_name+"\" "+QObject::tr("is overscheduled by")+" "+ QTime().addMSecs(-slop).toString("hh:mm:ss")+".\n"; } } } return false; } QString RDEventLine::propertiesText() const { QString ret; QString sql=QString("select ")+ "NAME,"+ // 00 "COLOR,"+ // 01 "PREPOSITION,"+ // 02 "FIRST_TRANS_TYPE,"+ // 03 "TIME_TYPE,"+ // 04 "GRACE_TIME,"+ // 05 "USE_AUTOFILL,"+ // 06 "IMPORT_SOURCE,"+ // 07 "NESTED_EVENT "+ // 08 "from EVENTS where "+ "NAME=\""+RDEscapeString(event_name)+"\""; RDSqlQuery *q=new RDSqlQuery(sql); if(q->first()) { ret=RDEventLine:: propertiesText(q->value(2).toInt(), (RDLogLine::TransType)q->value(3).toUInt(), (RDLogLine::TimeType)q->value(4).toUInt(), q->value(5).toInt(), RDBool(q->value(6).toString()), (RDEventLine::ImportSource)q->value(7).toUInt(), !q->value(8).toString().isEmpty()); } delete q; return ret; } QString RDEventLine::propertiesText(int prepos_msec, RDLogLine::TransType first_trans, RDLogLine::TimeType time_type, int grace_msec, bool autofill, RDEventLine::ImportSource import_src, bool inline_tfc) { QString ret=""; QString str; if(prepos_msec>=0) { ret+=QObject::tr("Cue")+ "(-"+QTime(0,0,0).addMSecs(prepos_msec).toString("mm:ss")+"), "; } if(time_type==RDLogLine::Hard) { switch(grace_msec) { case 0: ret+=QObject::tr("Timed(Start), "); break; case -1: ret+=QObject::tr("Timed(MakeNext), "); break; default: ret+=", "+QObject::tr("Timed(Wait)")+" "+ QTime(0,0,0).addMSecs(grace_msec).toString("mm:ss")+", "; break; } } if(autofill) { ret+=QObject::tr("Fill")+", "; } switch(import_src) { case RDEventLine::Traffic: ret+=QObject::tr("Traffic, "); break; case RDEventLine::Music: ret+=QObject::tr("Music, "); break; case RDEventLine::Scheduler: ret+=QObject::tr("Scheduler, "); break; default: break; } if(inline_tfc) { ret+=QObject::tr("Inline Traffic, "); } return ret.left(ret.length()-2); } int RDEventLine::GetLength(unsigned cartnum,int def_length) { RDCart *cart=new RDCart(cartnum); if(!cart->exists()) { delete cart; return def_length; } int length=cart->forcedLength(); delete cart; return length; }