From edd8221b6f23053e7ea131bbfaa6b6bf3b29b933 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Mon, 11 Jul 2016 14:01:30 -0400 Subject: [PATCH] 2016-07-11 Fred Gleason * Added rdxml_parse_test(1) in 'tests/'. * Added a RDCart::readXml()' method in 'lib/rdcart.cpp' and 'lib/rdcart.h'. * Fixed a typo in the 'averageSegueLength' field in the 'RDCart::xml()' method in 'lib/rdcart.cpp'. * Removed the 'validity' field from the output of the 'RDCart::xml()' method in 'lib/rdcart.cpp'. * Removed the 'validity' and 'localCounter' fields from the output of the 'RDCut::xml()' method in 'lib/rdcut.cpp'. --- .gitignore | 1 + ChangeLog | 10 + lib/librd_cs.ts | 36 +++ lib/librd_de.ts | 36 +++ lib/librd_es.ts | 36 +++ lib/librd_fr.ts | 36 +++ lib/librd_nb.ts | 36 +++ lib/librd_nn.ts | 36 +++ lib/librd_pt_BR.ts | 36 +++ lib/rdcart.cpp | 312 ++++++++++++++++++++- lib/rdcart.h | 3 + lib/rdcut.cpp | 2 - lib/rdwavedata.cpp | 543 ++++++++++++++++++++++++++++++++++++- lib/rdwavedata.h | 93 ++++++- lib/rdwavedata_dialog.cpp | 2 +- tests/Makefile.am | 4 + tests/rdxml_parse_test.cpp | 108 ++++++++ tests/rdxml_parse_test.h | 35 +++ 18 files changed, 1351 insertions(+), 14 deletions(-) create mode 100644 tests/rdxml_parse_test.cpp create mode 100644 tests/rdxml_parse_test.h diff --git a/.gitignore b/.gitignore index 316b998a..6aafb08a 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,7 @@ tests/audio_export_test tests/audio_import_test tests/audio_peaks_test tests/datedecode_test +tests/rdxml_parse_test tests/reserve_carts_test tests/sas_switch_torture tests/sas_torture diff --git a/ChangeLog b/ChangeLog index f610a79a..68ead922 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15268,3 +15268,13 @@ dialog heirarchy correctly. 2016-07-07 Fred Gleason * Incremented the package version to 2.14.1int00. +2016-07-11 Fred Gleason + * Added rdxml_parse_test(1) in 'tests/'. + * Added a RDCart::readXml()' method in 'lib/rdcart.cpp' and + 'lib/rdcart.h'. + * Fixed a typo in the 'averageSegueLength' field in the 'RDCart::xml()' + method in 'lib/rdcart.cpp'. + * Removed the 'validity' field from the output of the 'RDCart::xml()' + method in 'lib/rdcart.cpp'. + * Removed the 'validity' and 'localCounter' fields from the output + of the 'RDCut::xml()' method in 'lib/rdcut.cpp'. diff --git a/lib/librd_cs.ts b/lib/librd_cs.ts index 5ff7ac39..921a72b9 100644 --- a/lib/librd_cs.ts +++ b/lib/librd_cs.ts @@ -431,6 +431,42 @@ Cut Log + + unknown + + + + feature + + + + open + + + + close + + + + theme + + + + background + + + + promo + + + + cold + + + + fade + + RDAddCart diff --git a/lib/librd_de.ts b/lib/librd_de.ts index 7df19df7..f10c3c04 100644 --- a/lib/librd_de.ts +++ b/lib/librd_de.ts @@ -427,6 +427,42 @@ Cut Log + + unknown + + + + feature + + + + open + + + + close + + + + theme + + + + background + + + + promo + + + + cold + + + + fade + + RDAddCart diff --git a/lib/librd_es.ts b/lib/librd_es.ts index bf393e07..e7a139be 100644 --- a/lib/librd_es.ts +++ b/lib/librd_es.ts @@ -427,6 +427,42 @@ Cut Log + + unknown + + + + feature + + + + open + + + + close + + + + theme + + + + background + + + + promo + + + + cold + + + + fade + + RDAddCart diff --git a/lib/librd_fr.ts b/lib/librd_fr.ts index 002cfc8b..33a4ed57 100644 --- a/lib/librd_fr.ts +++ b/lib/librd_fr.ts @@ -413,6 +413,42 @@ Cut Log + + unknown + + + + feature + + + + open + + + + close + + + + theme + + + + background + + + + promo + + + + cold + + + + fade + + RDAddCart diff --git a/lib/librd_nb.ts b/lib/librd_nb.ts index 80b607b5..552b66ae 100644 --- a/lib/librd_nb.ts +++ b/lib/librd_nb.ts @@ -427,6 +427,42 @@ Cut Log + + unknown + + + + feature + + + + open + + + + close + + + + theme + + + + background + + + + promo + + + + cold + + + + fade + + RDAddCart diff --git a/lib/librd_nn.ts b/lib/librd_nn.ts index 80b607b5..552b66ae 100644 --- a/lib/librd_nn.ts +++ b/lib/librd_nn.ts @@ -427,6 +427,42 @@ Cut Log + + unknown + + + + feature + + + + open + + + + close + + + + theme + + + + background + + + + promo + + + + cold + + + + fade + + RDAddCart diff --git a/lib/librd_pt_BR.ts b/lib/librd_pt_BR.ts index 80ae5ec8..cddf3787 100644 --- a/lib/librd_pt_BR.ts +++ b/lib/librd_pt_BR.ts @@ -427,6 +427,42 @@ Cut Log + + unknown + + + + feature + + + + open + + + + close + + + + theme + + + + background + + + + promo + + + + cold + + + + fade + + RDAddCart diff --git a/lib/rdcart.cpp b/lib/rdcart.cpp index 84e4749b..d5b988fd 100644 --- a/lib/rdcart.cpp +++ b/lib/rdcart.cpp @@ -879,7 +879,7 @@ void RDCart::getMetadata(RDWaveData *data) const data->setConductor(q->value(10).toString()); data->setTmciSongId(q->value(11).toString()); data->setBeatsPerMinute(q->value(12).toUInt()); - data->setUsageCode(q->value(13).toUInt()); + data->setUsageCode((RDWaveData::UsageCode)q->value(13).toUInt()); data->setSchedCodes(schedCodesList()); data->setMetadataFound(true); } @@ -983,6 +983,35 @@ QString RDCart::xml(bool include_cuts,RDSettings *settings,int cutnum) const RDCut *cut; QStringList mlist; + sql=QString("select ")+ + "TYPE,"+ // 00 + "GROUP_NAME,"+ // 01 + "TITLE,"+ // 02 + "ARTIST,"+ // 03 + "ALBUM,"+ // 04 + "YEAR,"+ // 05 + "LABEL,"+ // 06 + "CLIENT,"+ // 07 + "AGENCY,"+ // 08 + "PUBLISHER,"+ // 09 + "COMPOSER,"+ // 10 + "USER_DEFINED,"+ // 11 + "USAGE_CODE,"+ // 12 + "FORCED_LENGTH,"+ // 13 + "AVERAGE_LENGTH,"+ // 14 + "LENGTH_DEVIATION,"+ // 15 + "AVERAGE_SEGUE_LENGTH,"+ // 16 + "AVERAGE_HOOK_LENGTH,"+ // 17 + "CUT_QUANTITY,"+ // 18 + "LAST_CUT_PLAYED,"+ // 19 + "VALIDITY,"+ // 20 + "ENFORCE_LENGTH,"+ // 21 + "ASYNCRONOUS,"+ // 22 + "OWNER,"+ // 23 + "METADATA_DATETIME,"+ // 24 + "CONDUCTOR "+ // 25 + QString().sprintf("from CART where NUMBER=%u",cart_number); + /* sql=QString().sprintf("select TYPE,GROUP_NAME,TITLE,ARTIST,ALBUM,YEAR,\ LABEL,CLIENT,AGENCY,PUBLISHER,COMPOSER,USER_DEFINED,\ USAGE_CODE,FORCED_LENGTH,AVERAGE_LENGTH,\ @@ -991,6 +1020,7 @@ QString RDCart::xml(bool include_cuts,RDSettings *settings,int cutnum) const VALIDITY,\ ENFORCE_LENGTH,ASYNCRONOUS,OWNER,METADATA_DATETIME \ from CART where NUMBER=%u",cart_number); + */ q=new RDSqlQuery(sql); if(q->first()) { ret+="\n"; @@ -1017,6 +1047,7 @@ QString RDCart::xml(bool include_cuts,RDSettings *settings,int cutnum) const ret+=" "+RDXmlField("agency",q->value(8).toString()); ret+=" "+RDXmlField("publisher",q->value(9).toString()); ret+=" "+RDXmlField("composer",q->value(10).toString()); + ret+=" "+RDXmlField("conductor",q->value(25).toString()); ret+=" "+RDXmlField("userDefined",q->value(11).toString()); ret+=" "+RDXmlField("usageCode",q->value(12).toInt()); ret+=" "+RDXmlField("forcedLength", @@ -1025,13 +1056,12 @@ QString RDCart::xml(bool include_cuts,RDSettings *settings,int cutnum) const RDGetTimeLength(q->value(14).toUInt(),true)); ret+=" "+RDXmlField("lengthDeviation", RDGetTimeLength(q->value(15).toUInt(),true)); - ret+=" "+RDXmlField("averageSegueLenth", + ret+=" "+RDXmlField("averageSegueLength", RDGetTimeLength(q->value(16).toUInt(),true)); ret+=" "+RDXmlField("averageHookLength", RDGetTimeLength(q->value(17).toUInt(),true)); ret+=" "+RDXmlField("cutQuantity",q->value(18).toUInt()); ret+=" "+RDXmlField("lastCutPlayed",q->value(19).toUInt()); - ret+=" "+RDXmlField("validity",q->value(20).toUInt()); ret+=" "+RDXmlField("enforceLength",RDBool(q->value(21).toString())); ret+=" "+RDXmlField("asyncronous",RDBool(q->value(22).toString())); ret+=" "+RDXmlField("owner",q->value(23).toString()); @@ -1549,6 +1579,282 @@ void RDCart::removePending(RDStation *station,RDUser *user,RDConfig *config) } +unsigned RDCart::readXml(std::vector *data,const QString &xml) +{ + // + // HACK! HACK! HACK! HACK! HACK! + // + // This is totally ad-hoc and will likely break horribly for XML that + // deviates the least bit from that generated by Rivendell's own xml() + // methods. + // + // Slated to be put out of its misery as soon as we get a Real XML Parser. + // + int istate=0; + RDWaveData cartdata; + RDSettings *settings=NULL; + QStringList f0=f0.split("\n",xml); + + for(unsigned i=0;i") { + istate=1; + } + break; + + case 1: // Cart-level objects + if(f0[i].contains("")) { + cartdata.setCartNumber(GetXmlValue("number",f0[i]).toUInt()); + } + if(f0[i].contains("")) { + cartdata.setCategory(GetXmlValue("groupName",f0[i]).toString()); + } + if(f0[i].contains("")) { + cartdata.setTitle(GetXmlValue("title",f0[i]).toString()); + } + if(f0[i].contains("<artist>")) { + cartdata.setArtist(GetXmlValue("artist",f0[i]).toString()); + } + if(f0[i].contains("<album>")) { + cartdata.setAlbum(GetXmlValue("album",f0[i]).toString()); + } + if(f0[i].contains("<label>")) { + cartdata.setLabel(GetXmlValue("label",f0[i]).toString()); + } + if(f0[i].contains("<client>")) { + cartdata.setClient(GetXmlValue("client",f0[i]).toString()); + } + if(f0[i].contains("<agency>")) { + cartdata.setAgency(GetXmlValue("agency",f0[i]).toString()); + } + if(f0[i].contains("<composer>")) { + cartdata.setComposer(GetXmlValue("composer",f0[i]).toString()); + } + if(f0[i].contains("<publisher>")) { + cartdata.setPublisher(GetXmlValue("publisher",f0[i]).toString()); + } + if(f0[i].contains("<conductor>")) { + cartdata.setConductor(GetXmlValue("conductor",f0[i]).toString()); + } + if(f0[i].contains("<userDefined>")) { + cartdata.setUserDefined(GetXmlValue("userDefined",f0[i]).toString()); + } + if(f0[i].contains("<year>")) { + cartdata.setReleaseYear(GetXmlValue("year",f0[i]).toInt()); + } + if(f0[i].contains("<forcedLength>")) { + cartdata. + setForcedLength(RDSetTimeLength(GetXmlValue("forcedLength",f0[i]). + toString())); + } + if(f0[i].contains("<averageLength>")) { + cartdata. + setAverageLength(RDSetTimeLength(GetXmlValue("averageLength",f0[i]). + toString())); + } + if(f0[i].contains("<lengthDeviation>")) { + cartdata.setLengthDeviation(RDSetTimeLength(GetXmlValue("lengthDeviation",f0[i]). + toString())); + } + if(f0[i].contains("<averageHookLength>")) { + cartdata. + setAverageHookLength(RDSetTimeLength(GetXmlValue("averageHookLength",f0[i]). + toString())); + } + if(f0[i].contains("<averageSegueLength>")) { + cartdata. + setAverageSegueLength(RDSetTimeLength(GetXmlValue("averageSegueLength",f0[i]). + toString())); + } + if(f0[i].contains("<cutQuantity>")) { + cartdata.setCutQuantity(GetXmlValue("cutQuantity",f0[i]).toInt()); + } + if(f0[i].contains("<lastCutPlayed>")) { + cartdata.setLastCutPlayed(GetXmlValue("lastCutPlayed",f0[i]).toInt()); + } + if(f0[i].contains("<enforceLength>")) { + cartdata.setEnforceLength(GetXmlValue("enforceLength",f0[i]).toBool()); + } + if(f0[i].contains("<asyncronous>")) { + cartdata.setAsyncronous(GetXmlValue("asyncronous",f0[i]).toBool()); + } + if(f0[i].contains("<owner>")) { + cartdata.setOwner(GetXmlValue("owner",f0[i]).toString()); + } + if(f0[i].contains("<metadataDatetime>")) { + cartdata.setMetadataDatetime(GetXmlValue("metadataDatetime",f0[i]). + toDateTime()); + } + + if(f0[i]=="</cart>") { + istate=0; + } + + if(f0[i]=="<cutList>") { + data->push_back(RDWaveData()); + data->back()=cartdata; + istate=2; + } + break; + + case 2: // Cut List + if(f0[i]=="<cut>") { // Start of new cut + data->push_back(RDWaveData()); + data->back()=cartdata; + settings=new RDSettings(); + istate=3; + } + if(f0[i]=="</cutList>") { // End of cut + istate=1; + } + break; + + case 3: // Cut Object + if(f0[i].contains("<description>")) { + data->back().setDescription(GetXmlValue("description",f0[i]).toString()); + } + if(f0[i].contains("<cutNumber>")) { + data->back().setCutNumber(GetXmlValue("cutNumber",f0[i]).toInt()); + } + if(f0[i].contains("<cutName>")) { + data->back().setCutName(GetXmlValue("cutName",f0[i]).toString()); + } + if(f0[i].contains("<evergreen>")) { + data->back().setEvergreen(GetXmlValue("evergreen",f0[i]).toBool()); + } + if(f0[i].contains("<outcue>")) { + data->back().setOutCue(GetXmlValue("outcue",f0[i]).toString()); + } + if(f0[i].contains("<isrc>")) { + data->back().setIsrc(GetXmlValue("isrc",f0[i]).toString()); + } + if(f0[i].contains("<isci>")) { + data->back().setIsci(GetXmlValue("isci",f0[i]).toString()); + } + if(f0[i].contains("<length>")) { + data->back().setLength(GetXmlValue("length",f0[i]).toInt()); + } + if(f0[i].contains("<originName>")) { + data->back().setOriginator(GetXmlValue("originName",f0[i]).toString()); + } + if(f0[i].contains("<originDatetime>")) { + data->back().setOriginationDate(GetXmlValue("originDatetime",f0[i]). + toDateTime().date()); + data->back().setOriginationTime(GetXmlValue("originDatetime",f0[i]). + toDateTime().time()); + } + if(f0[i].contains("<playCounter>")) { + data->back().setPlayCounter(GetXmlValue("playCounter",f0[i]).toInt()); + } + if(f0[i].contains("<startDatetime>")) { + data->back().setStartDate(GetXmlValue("startDatetime",f0[i]). + toDateTime().date()); + data->back().setStartTime(GetXmlValue("startDatetime",f0[i]). + toDateTime().time()); + } + if(f0[i].contains("<endDatetime>")) { + data->back().setEndDate(GetXmlValue("endDatetime",f0[i]). + toDateTime().date()); + data->back().setEndTime(GetXmlValue("endDatetime",f0[i]). + toDateTime().time()); + } + if(f0[i].contains("<lastPlayDatetime>")) { + data->back().setLastPlayDatetime(GetXmlValue("lastPlayDatetime",f0[i]). + toDateTime()); + } + if(f0[i].contains("<codingFormat>")) { + settings->setFormat((RDSettings::Format)GetXmlValue("codingFormat",f0[i]). + toUInt()); + } + if(f0[i].contains("<sampleRate>")) { + settings->setSampleRate(GetXmlValue("sampleRate",f0[i]).toUInt()); + } + if(f0[i].contains("<bitRate>")) { + settings->setBitRate(GetXmlValue("bitRate",f0[i]).toUInt()); + } + if(f0[i].contains("<channels>")) { + settings->setChannels(GetXmlValue("channels",f0[i]).toUInt()); + } + if(f0[i].contains("<playGain>")) { + data->back().setPlayGain(GetXmlValue("playGain",f0[i]).toInt()); + } + if(f0[i].contains("<startPoint>")) { + data->back().setStartPos(GetXmlValue("startPoint",f0[i]).toInt()); + } + if(f0[i].contains("<endPoint>")) { + data->back().setEndPos(GetXmlValue("endPoint",f0[i]).toInt()); + } + if(f0[i].contains("<segueStartPoint>")) { + data->back().setSegueStartPos(GetXmlValue("segueStartPoint",f0[i]). + toInt()); + } + if(f0[i].contains("<segueEndPoint>")) { + data->back().setSegueEndPos(GetXmlValue("segueEndPoint",f0[i]).toInt()); + } + if(f0[i].contains("<segueGain>")) { + data->back().setSegueGain(GetXmlValue("segueGain",f0[i]).toInt()); + } + if(f0[i].contains("<talkStartPoint>")) { + data->back().setIntroStartPos(GetXmlValue("talkStartPoint",f0[i]). + toInt()); + } + if(f0[i].contains("<talkEndPoint>")) { + data->back().setIntroEndPos(GetXmlValue("talkEndPoint",f0[i]).toInt()); + } + if(f0[i].contains("<hookStartPoint>")) { + data->back().setHookStartPos(GetXmlValue("hookStartPoint",f0[i]). + toInt()); + } + if(f0[i].contains("<hookEndPoint>")) { + data->back().setHookEndPos(GetXmlValue("hookEndPoint",f0[i]).toInt()); + } + if(f0[i].contains("<fadeupPoint>")) { + data->back().setFadeUpPos(GetXmlValue("fadeupPoint",f0[i]).toInt()); + } + if(f0[i].contains("<fadedownPoint>")) { + data->back().setFadeDownPos(GetXmlValue("fadedownPoint",f0[i]).toInt()); + } + + if(f0[i]=="</cut>") { // End of cut + data->back().setAudioSettings(*settings); + delete settings; + settings=NULL; + istate=2; + } + break; + } + } + + // printf("DUMP:\n%s\n",(const char *)cartdata.dump()); + + return data->size(); +} + + +QVariant RDCart::GetXmlValue(const QString &tag,const QString &line) +{ + bool ok=false; + QString value=line; + value=value.remove("<"+tag+">").remove("</"+tag+">"); + + value.toUInt(&ok); + if(ok) { + return QVariant(value.toUInt()); + } + value.toInt(&ok); + if(ok) { + return QVariant(value.toInt()); + } + + return QVariant(value); +} + + QString RDCart::GetNextCut(RDSqlQuery *q) const { QString cutname; diff --git a/lib/rdcart.h b/lib/rdcart.h index cee59d58..af4e2765 100644 --- a/lib/rdcart.h +++ b/lib/rdcart.h @@ -20,6 +20,7 @@ #include <qdatetime.h> #include <qstringlist.h> +#include <qvariant.h> #include <rdconfig.h> #include <rdwavedata.h> @@ -158,8 +159,10 @@ class RDCart static bool removeCutAudio(RDStation *station,RDUser *user,unsigned cart_num, const QString &cutname,RDConfig *config); static void removePending(RDStation *station,RDUser *user,RDConfig *config); + static unsigned readXml(std::vector<RDWaveData> *data,const QString &xml); private: + static QVariant GetXmlValue(const QString &tag,const QString &line); QString GetNextCut(RDSqlQuery *q) const; int GetNextFreeCut() const; RDCut::Validity ValidateCut(RDSqlQuery *q,bool enforce_length, diff --git a/lib/rdcut.cpp b/lib/rdcut.cpp index 61882c13..2b5abc73 100644 --- a/lib/rdcut.cpp +++ b/lib/rdcut.cpp @@ -1226,8 +1226,6 @@ QString RDCut::xml(RDSettings *settings) const ret+=" "+RDXmlField("weight",q->value(19).toUInt()); ret+=" "+RDXmlField("lastPlayDatetime",q->value(20).toDateTime()); ret+=" "+RDXmlField("playCounter",q->value(21).toUInt()); - ret+=" "+RDXmlField("localCounter",q->value(22).toUInt()); - ret+=" "+RDXmlField("validity",q->value(23).toUInt()); if(settings==NULL) { ret+=" "+RDXmlField("codingFormat",q->value(24).toUInt()); ret+=" "+RDXmlField("sampleRate",q->value(25).toUInt()); diff --git a/lib/rdwavedata.cpp b/lib/rdwavedata.cpp index 273fe216..a04d5cf1 100644 --- a/lib/rdwavedata.cpp +++ b/lib/rdwavedata.cpp @@ -17,8 +17,10 @@ // License along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// +#include <qobject.h> + +#include <rdconf.h> #include <rdwavedata.h> RDWaveData::RDWaveData() @@ -39,6 +41,54 @@ void RDWaveData::setMetadataFound(bool state) } +unsigned RDWaveData::cartNumber() const +{ + return data_cart_number; +} + + +void RDWaveData::setCartNumber(unsigned cartnum) +{ + data_cart_number=cartnum; +} + + +int RDWaveData::cutNumber() const +{ + return data_cut_number; +} + + +void RDWaveData::setCutNumber(int cutnum) +{ + data_cut_number=cutnum; +} + + +QString RDWaveData::cutName() const +{ + return data_cutname; +} + + +void RDWaveData::setCutName(const QString &str) +{ + data_cutname=str; +} + + +RDWaveData::CartType RDWaveData::cartType() const +{ + return data_cart_type; +} + + +void RDWaveData::setCartType(RDWaveData::CartType type) +{ + data_cart_type=type; +} + + QString RDWaveData::title() const { return data_title; @@ -159,13 +209,13 @@ void RDWaveData::setPublisher(const QString &str) } -int RDWaveData::usageCode() const +RDWaveData::UsageCode RDWaveData::usageCode() const { return data_usage_code; } -void RDWaveData::setUsageCode(int code) +void RDWaveData::setUsageCode(RDWaveData::UsageCode code) { data_usage_code=code; } @@ -387,6 +437,198 @@ void RDWaveData::setEndType(RDWaveData::EndType type) } +int RDWaveData::forcedLength() const +{ + return data_forced_length; +} + + +void RDWaveData::setForcedLength(int msecs) +{ + data_forced_length=msecs; +} + + +int RDWaveData::averageLength() const +{ + return data_average_length; +} + + +void RDWaveData::setAverageLength(int msecs) +{ + data_average_length=msecs; +} + + +int RDWaveData::lengthDeviation() const +{ + return data_length_deviation; +} + + +void RDWaveData::setLengthDeviation(int msecs) +{ + data_length_deviation=msecs; +} + + +int RDWaveData::averageSegueLength() const +{ + return data_average_segue_length; +} + + +void RDWaveData::setAverageSegueLength(int msecs) +{ + data_average_segue_length=msecs; +} + + +int RDWaveData::averageHookLength() const +{ + return data_average_hook_length; +} + + +void RDWaveData::setAverageHookLength(int msecs) +{ + data_average_hook_length=msecs; +} + + +int RDWaveData::cutQuantity() const +{ + return data_cut_quantity; +} + + +void RDWaveData::setCutQuantity(int n) +{ + data_cut_quantity=n; +} + + +int RDWaveData::lastCutPlayed() const +{ + return data_last_cut_played; +} + + +void RDWaveData::setLastCutPlayed(int cutnum) +{ + data_last_cut_played=cutnum; +} + + +QDateTime RDWaveData::lastPlayDatetime() const +{ + return data_last_play_datetime; +} + + +void RDWaveData::setLastPlayDatetime(const QDateTime &dt) +{ + data_last_play_datetime=dt; +} + + +int RDWaveData::length() const +{ + return data_length; +} + + +void RDWaveData::setLength(int msecs) +{ + data_length=msecs; +} + + +bool RDWaveData::enforceLength() const +{ + return data_enforce_length; +} + + +void RDWaveData::setEnforceLength(bool state) +{ + data_enforce_length=state; +} + + +bool RDWaveData::asyncronous() const +{ + return data_asyncronous; +} + + +void RDWaveData::setAsyncronous(bool state) +{ + data_asyncronous=state; +} + + +QString RDWaveData::owner() const +{ + return data_owner; +} + + +void RDWaveData::setOwner(const QString &str) +{ + data_owner=str; +} + + +QDateTime RDWaveData::metadataDatetime() const +{ + return data_metadata_datetime; +} + + +void RDWaveData::setMetadataDatetime(const QDateTime &dt) +{ + data_metadata_datetime=dt; +} + + +bool RDWaveData::dayOfWeek(int dow) const +{ + return data_day_of_week[dow-1]; +} + + +void RDWaveData::setDayOfWeek(int dow,bool state) +{ + data_day_of_week[dow-1]=state; +} + + +int RDWaveData::weight() const +{ + return data_weight; +} + + +void RDWaveData::setWeight(int weight) +{ + data_weight=weight; +} + + +bool RDWaveData::evergreen() const +{ + return data_evergreen; +} + + +void RDWaveData::setEvergreen(bool state) +{ + data_evergreen=state; +} + + int RDWaveData::introStartPos() const { return data_intro_start_pos; @@ -435,6 +677,18 @@ void RDWaveData::setSegueEndPos(int msec) } +int RDWaveData::segueGain() const +{ + return data_segue_gain; +} + + +void RDWaveData::setSegueGain(int lvl) +{ + data_segue_gain=lvl; +} + + int RDWaveData::startPos() const { return data_start_pos; @@ -627,9 +881,189 @@ void RDWaveData::setDaypartEndTime(const QTime &time) } +unsigned RDWaveData::playCounter() const +{ + return data_play_counter; +} + + +void RDWaveData::setPlayCounter(unsigned count) +{ + data_play_counter=count; +} + + +RDSettings RDWaveData::audioSettings() const +{ + return data_settings; +} + + +void RDWaveData::setAudioSettings(const RDSettings &settings) +{ + data_settings=settings; +} + + +int RDWaveData::playGain() const +{ + return data_play_gain; +} + + +void RDWaveData::setPlayGain(int lvl) +{ + data_play_gain=lvl; +} + + +QString RDWaveData::dump() const +{ + QString ret=""; + + // + // Cart-level attributes + // + ret+=QString().sprintf("cartNumber: %06u\n",cartNumber()); + ret+="cartType: "+RDWaveData::cartTypeText(cartType())+"\n"; + ret+="category: "+category()+"\n"; + ret+="title: "+title()+"\n"; + ret+="artist: "+artist()+"\n"; + ret+="album: "+album()+"\n"; + ret+="label: "+label()+"\n"; + ret+="agency: "+agency()+"\n"; + ret+="client: "+client()+"\n"; + ret+="composer: "+composer()+"\n"; + ret+="publisher: "+publisher()+"\n"; + ret+="conductor: "+conductor()+"\n"; + ret+="userDefined: "+userDefined()+"\n"; + if(releaseYear()>0) { + ret+=QString().sprintf("year: %d\n",releaseYear()); + } + else { + ret+="year:\n"; + } + ret+="usageCode: "+RDWaveData::usageText(usageCode())+"\n"; + ret+="forcedLength: "+RDGetTimeLength(forcedLength(),true,true)+"\n"; + ret+="averageLength: "+RDGetTimeLength(averageLength(),true,true)+"\n"; + ret+="lengthDeviation: "+RDGetTimeLength(lengthDeviation(),true,true)+"\n"; + ret+= + "averageSegueLength: "+RDGetTimeLength(averageSegueLength(),true,true)+"\n"; + ret+="averageHookLength: "+RDGetTimeLength(averageHookLength(),true,true)+"\n"; + ret+=QString().sprintf("cutQuantity: %d\n",cutQuantity()); + ret+=QString().sprintf("lastCutPlayed: %d\n",lastCutPlayed()); + if(enforceLength()) { + ret+="enforceLength: true\n"; + } + else { + ret+="enforceLength: false\n"; + } + if(asyncronous()) { + ret+="asyncronous: true\n"; + } + else { + ret+="asyncronous: false\n"; + } + ret+="owner: "+owner()+"\n"; + ret+="metadataDatetime: "+ + metadataDatetime().toString("yyyy-MM-dd hh:mm:ss")+"\n"; + + // + // Cut-level attributes + // + ret+="cutName: "+cutName()+"\n"; + ret+=QString().sprintf("cutNumber: %d\n",cutNumber()); + ret+="description: "+description()+"\n"; + ret+="outcue: "+outCue()+"\n"; + if(evergreen()) { + ret+="evergreen: true\n"; + } + else { + ret+="evergreen: false\n"; + } + ret+="isrc: "+isrc()+"\n"; + ret+="isci: "+isci()+"\n"; + ret+=QString().sprintf("length: %d\n",length()); + ret+="originator: "+originator()+"\n"; + ret+="originationDate: "+originationDate().toString("yyyy-MM-dd")+"\n"; + ret+="originationTime: "+originationTime().toString("hh:mm:ss")+"\n"; + ret+="startDate: "; + if(startDate().isValid()) { + ret+=startDate().toString("yyyy-MM-dd"); + } + ret+="\n"; + ret+="startTime: "; + if(startDate().isValid()&&startTime().isValid()) { + ret+=startTime().toString("hh:mm:ss"); + } + ret+="\n"; + ret+="endDate: "; + if(endDate().isValid()) { + ret+=endDate().toString("yyyy-MM-dd"); + } + ret+="\n"; + ret+="endTime: "; + if(endDate().isValid()&&endTime().isValid()) { + ret+=endTime().toString("hh:mm:ss"); + } + ret+="\n"; + for(int i=1;i<8;i++) { + if(dayOfWeek(i)) { + ret+=QDate::longDayName(i)+": true\n"; + } + else { + ret+=QDate::longDayName(i)+": false\n"; + } + } + ret+="daypartStartTime: "; + if(daypartStartTime().isValid()&&(daypartStartTime()!=daypartEndTime())) { + ret+=daypartStartTime().toString("hh:mm:ss"); + } + ret+="\n"; + ret+="daypartEndTime: "; + if(daypartEndTime().isValid()&&(daypartStartTime()!=daypartEndTime())) { + ret+=daypartEndTime().toString("hh:mm:ss"); + } + ret+="\n"; + ret+="lastPlayDatetime: "; + if(lastPlayDatetime().isValid()) { + ret+=lastPlayDatetime().toString("yyyy-MM-dd hh:mm:ss"); + } + ret+="\n"; + ret+=QString().sprintf("weight: %d\n",weight()); + ret+=QString().sprintf("playCounter: %d\n",playCounter()); + ret+=QString().sprintf("audioSettings::format: %u\n", + audioSettings().format()); + ret+=QString().sprintf("audioSettings::sampleRate: %u\n", + audioSettings().sampleRate()); + ret+=QString().sprintf("audioSettings::bitRate: %u\n", + audioSettings().bitRate()); + ret+=QString().sprintf("audioSettings::channels: %u\n", + audioSettings().channels()); + ret+=QString().sprintf("playGain: %d\n",playGain()); + ret+=QString().sprintf("startPos: %d\n",startPos()); + ret+=QString().sprintf("endPos: %d\n",endPos()); + ret+=QString().sprintf("segueStartPos: %d\n",segueStartPos()); + ret+=QString().sprintf("segueEndPos: %d\n",segueEndPos()); + ret+=QString().sprintf("segueGain: %d\n",segueGain()); + ret+=QString().sprintf("introStartPos: %d\n",introStartPos()); + ret+=QString().sprintf("introEndPos: %d\n",introEndPos()); + ret+=QString().sprintf("hookStartPos: %d\n",hookStartPos()); + ret+=QString().sprintf("hookEndPos: %d\n",hookEndPos()); + ret+=QString().sprintf("fadeUpPos: %d\n",fadeUpPos()); + ret+=QString().sprintf("fadeDownPos: %d\n",fadeDownPos()); + ret+="\n"; + + return ret; +} + void RDWaveData::clear() { data_metadata_found=false; + data_cart_number=0; + data_cart_type=RDWaveData::AudioType; + data_cut_number=0; + data_cutname=""; data_title=""; data_artist=""; data_album=""; @@ -640,7 +1074,7 @@ void RDWaveData::clear() data_agency=""; data_composer=""; data_publisher=""; - data_usage_code=0; + data_usage_code=RDWaveData::UsageFeature; data_sched_codes.clear(); data_licensing_organization=""; data_copyright_notice=""; @@ -657,11 +1091,33 @@ void RDWaveData::clear() data_isci=""; data_mcn=""; data_out_cue=""; + data_release_year=0; data_end_type=RDWaveData::UnknownEnd; + + data_length=0; + data_forced_length=-1; + data_average_length=-1; + data_length_deviation=0; + data_average_segue_length=0; + data_average_hook_length=0; + data_cut_quantity=0; + data_last_cut_played=0; + data_last_play_datetime=QDateTime(); + data_enforce_length=false; + data_asyncronous=false; + data_owner=""; + data_metadata_datetime=QDateTime(); + + for(int i=0;i<7;i++) { + data_day_of_week[i]=true; + } + data_weight=1; + data_evergreen=false; data_intro_start_pos=-1; data_intro_end_pos=-1; data_segue_start_pos=-1; data_segue_end_pos=-1; + data_segue_gain=-3000; data_start_pos=-1; data_end_pos=-1; data_hook_start_pos=-1; @@ -678,4 +1134,83 @@ void RDWaveData::clear() data_end_time=QTime(); data_daypart_start_time=QTime(); data_daypart_end_time=QTime(); + data_play_counter=0; + data_play_gain=0; +} + + +QString RDWaveData::endTypeText(EndType type) +{ + QString ret=QObject::tr("unknown"); + + switch(type) { + case UnknownEnd: + ret=QObject::tr("unknown"); + break; + + case ColdEnd: + ret=QObject::tr("cold"); + break; + + case FadeEnd: + ret=QObject::tr("fade"); + break; + } + + return ret; +} + + +QString RDWaveData::cartTypeText(CartType type) +{ + QString ret=QObject::tr("unknown"); + + switch(type) { + case RDWaveData::AudioType: + ret="audio"; + break; + + case RDWaveData::MacroType: + ret="macro"; + break; + } + + return ret; +} + + +QString RDWaveData::usageText(UsageCode code) +{ + QString ret=QObject::tr("unknown"); + + switch(code) { + case UsageFeature: + ret=QObject::tr("feature"); + break; + + case UsageOpen: + ret=QObject::tr("open"); + break; + + case UsageClose: + ret=QObject::tr("close"); + break; + + case UsageTheme: + ret=QObject::tr("theme"); + break; + + case UsageBackground: + ret=QObject::tr("background"); + break; + + case UsagePromo: + ret=QObject::tr("promo"); + break; + + case UsageLast: + break; + } + + return ret; } diff --git a/lib/rdwavedata.h b/lib/rdwavedata.h index 257f8d59..d0c94187 100644 --- a/lib/rdwavedata.h +++ b/lib/rdwavedata.h @@ -25,13 +25,26 @@ #include <qstringlist.h> #include <qdatetime.h> +#include <rdsettings.h> + class RDWaveData { public: enum EndType {UnknownEnd='N',ColdEnd='C',FadeEnd='F'}; + enum CartType {AudioType=0,MacroType=1}; + enum UsageCode {UsageFeature=0,UsageOpen=1,UsageClose=2,UsageTheme=3, + UsageBackground=4,UsagePromo=5,UsageLast=6}; RDWaveData(); bool metadataFound() const; void setMetadataFound(bool state); + unsigned cartNumber() const; + void setCartNumber(unsigned cartnum); + int cutNumber() const; + void setCutNumber(int cutnum); + QString cutName() const; + void setCutName(const QString &str); + CartType cartType() const; + void setCartType(CartType type); QString title() const; void setTitle(const QString &str); QString artist() const; @@ -52,8 +65,8 @@ class RDWaveData void setComposer(const QString &str); QString publisher() const; void setPublisher(const QString &str); - int usageCode() const; - void setUsageCode(int code); + UsageCode usageCode() const; + void setUsageCode(UsageCode code); QStringList schedCodes() const; void setSchedCodes(const QStringList &codes); QString licensingOrganization() const; @@ -90,6 +103,40 @@ class RDWaveData void setOutCue(const QString &str); RDWaveData::EndType endType() const; void setEndType(RDWaveData::EndType type); + + int forcedLength() const; + void setForcedLength(int msecs); + int averageLength() const; + void setAverageLength(int msecs); + int lengthDeviation() const; + void setLengthDeviation(int msecs); + int averageSegueLength() const; + void setAverageSegueLength(int msecs); + int averageHookLength() const; + void setAverageHookLength(int msecs); + int cutQuantity() const; + void setCutQuantity(int n); + int lastCutPlayed() const; + void setLastCutPlayed(int cutnum); + QDateTime lastPlayDatetime() const; + void setLastPlayDatetime(const QDateTime &dt); + int length() const; + void setLength(int msecs); + bool enforceLength() const; + void setEnforceLength(bool state); + bool asyncronous() const; + void setAsyncronous(bool state); + QString owner() const; + void setOwner(const QString &str); + QDateTime metadataDatetime() const; + void setMetadataDatetime(const QDateTime &dt); + + bool dayOfWeek(int dow) const; + void setDayOfWeek(int dow,bool state); + int weight() const; + void setWeight(int weight); + bool evergreen() const; + void setEvergreen(bool state); int introStartPos() const; void setIntroStartPos(int msec); int introEndPos() const; @@ -98,6 +145,8 @@ class RDWaveData void setSegueStartPos(int msec); int segueEndPos() const; void setSegueEndPos(int msec); + int segueGain() const; + void setSegueGain(int lvl); int startPos() const; void setStartPos(int msec); int endPos() const; @@ -130,10 +179,24 @@ class RDWaveData void setDaypartStartTime(const QTime &time); QTime daypartEndTime() const; void setDaypartEndTime(const QTime &time); + unsigned playCounter() const; + void setPlayCounter(unsigned count); + RDSettings audioSettings() const; + void setAudioSettings(const RDSettings &settings); + int playGain() const; + void setPlayGain(int lvl); + QString dump() const; void clear(); + static QString endTypeText(EndType type); + static QString cartTypeText(CartType type); + static QString usageText(UsageCode code); private: bool data_metadata_found; + unsigned data_cart_number; + CartType data_cart_type; + int data_cut_number; + QString data_cutname; QString data_title; QString data_artist; QString data_album; @@ -144,7 +207,7 @@ class RDWaveData QString data_agency; QString data_composer; QString data_publisher; - int data_usage_code; + UsageCode data_usage_code; QStringList data_sched_codes; QString data_licensing_organization; QString data_copyright_notice; @@ -162,11 +225,30 @@ class RDWaveData QString data_isci; QString data_mcn; QString data_out_cue; - RDWaveData::EndType data_end_type; + EndType data_end_type; + + int data_length; + int data_forced_length; + int data_average_length; + int data_length_deviation; + int data_average_segue_length; + int data_average_hook_length; + int data_cut_quantity; + int data_last_cut_played; + QDateTime data_last_play_datetime; + bool data_enforce_length; + bool data_asyncronous; + QString data_owner; + QDateTime data_metadata_datetime; + + bool data_evergreen; + bool data_day_of_week[7]; + int data_weight; int data_intro_start_pos; int data_intro_end_pos; int data_segue_start_pos; int data_segue_end_pos; + int data_segue_gain; int data_start_pos; int data_end_pos; int data_hook_start_pos; @@ -188,6 +270,9 @@ class RDWaveData QTime data_end_time; QTime data_daypart_start_time; QTime data_daypart_end_time; + unsigned data_play_counter; + RDSettings data_settings; + int data_play_gain; }; diff --git a/lib/rdwavedata_dialog.cpp b/lib/rdwavedata_dialog.cpp index bd8b574e..0121a943 100644 --- a/lib/rdwavedata_dialog.cpp +++ b/lib/rdwavedata_dialog.cpp @@ -254,7 +254,7 @@ void RDWaveDataDialog::okData() else { wave_data->setReleaseYear(wave_year_edit->text().toInt()); } - wave_data->setUsageCode(wave_usage_box->currentItem()); + wave_data->setUsageCode((RDWaveData::UsageCode)wave_usage_box->currentItem()); wave_data->setTmciSongId(wave_songid_edit->text()); wave_data->setBeatsPerMinute(wave_bpm_spin->value()); wave_data->setAlbum(wave_album_edit->text()); diff --git a/tests/Makefile.am b/tests/Makefile.am index 9f2ad1f0..b2f89c11 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -33,6 +33,7 @@ noinst_PROGRAMS = audio_convert_test\ audio_import_test\ audio_peaks_test\ datedecode_test\ + rdxml_parse_test\ reserve_carts_test\ sas_switch_torture\ sas_torture\ @@ -56,6 +57,9 @@ audio_peaks_test_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ dist_datedecode_test_SOURCES = datedecode_test.cpp datedecode_test.h datedecode_test_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ +dist_rdxml_parse_test_SOURCES = rdxml_parse_test.cpp rdxml_parse_test.h +rdxml_parse_test_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ + dist_reserve_carts_test_SOURCES = reserve_carts_test.cpp reserve_carts_test.h reserve_carts_test_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ diff --git a/tests/rdxml_parse_test.cpp b/tests/rdxml_parse_test.cpp new file mode 100644 index 00000000..23e9522b --- /dev/null +++ b/tests/rdxml_parse_test.cpp @@ -0,0 +1,108 @@ +// rdxml_parse_test.cpp +// +// Test the Rivendell RDXML parser routines. +// +// (C) Copyright 2016 Fred Gleason <fredg@paravelsystems.com> +// +// 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 <stdlib.h> +#include <stdio.h> + +#include <vector> + +#include <qapplication.h> +#include <qfile.h> + +#include <rdcart.h> +#include <rdcmd_switch.h> +#include <rdwavedata.h> + +#include "rdxml_parse_test.h" + +MainObject::MainObject(QObject *parent) + :QObject(parent) +{ + QString filename=""; + QFile *file=NULL; + QString line; + QString xml=""; + + // + // Read Command Options + // + RDCmdSwitch *cmd= + new RDCmdSwitch(qApp->argc(),qApp->argv(),"rdxml_parse_test", + RDXML_PARSE_TEST_USAGE); + for(unsigned i=0;i<cmd->keys();i++) { + if(cmd->key(i)=="--filename") { + filename=cmd->value(i); + cmd->setProcessed(i,true); + } + if(!cmd->processed(i)) { + fprintf(stderr,"rdxml_parse_test: unknown option \"%s\"\n", + (const char *)cmd->value(i)); + exit(256); + } + } + if(filename.isEmpty()) { + fprintf(stderr,"rdxml_parse_test: --filename= must be specified\n"); + exit(256); + } + + // + // Read File + // + file=new QFile(filename); + if(!file->open(IO_ReadOnly)) { + fprintf(stderr,"rdxml_parse_test: unable to open \"%s\"\n", + (const char *)filename); + exit(256); + } + while(file->readLine(line,1024)>=0) { + xml+=line; + } + file->close(); + + // + // Parse + // + std::vector<RDWaveData> data; + int n=RDCart::readXml(&data,xml); + + if(n<1) { + fprintf(stderr,"rdxml_parse_test: no data found\n"); + exit(256); + } + printf("*** CART DATA ***\n"); + printf("%s\n",(const char *)data[0].dump()); + printf("\n"); + + for(unsigned i=1;i<data.size();i++) { + printf("*** CUT %u DATA ***\n",i); + printf("%s\n",(const char *)data[i].dump()); + printf("\n"); + } + + exit(0); +} + + +int main(int argc,char *argv[]) +{ + QApplication a(argc,argv,false); + new MainObject(); + return a.exec(); +} diff --git a/tests/rdxml_parse_test.h b/tests/rdxml_parse_test.h new file mode 100644 index 00000000..3ea1a40f --- /dev/null +++ b/tests/rdxml_parse_test.h @@ -0,0 +1,35 @@ +// rdxml_parse_test.h +// +// Test the Rivendell RDXML parser routines. +// +// (C) Copyright 2016 Fred Gleason <fredg@paravelsystems.com> +// +// 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. +// + +#ifndef RDXML_PARSE_TEST_H +#define RDXML_PARSE_TEST_H + +#include <qobject.h> + +#define RDXML_PARSE_TEST_USAGE "--filename=<input-file>\n\n" + +class MainObject : public QObject +{ + public: + MainObject(QObject *parent=0); +}; + + +#endif // RDXML_PARSE_TEST_H