Database changes for Nexus integration

This commit is contained in:
Patrick Linstruth 2019-09-11 12:01:40 -07:00
parent 75ee836325
commit d1874b868a
11 changed files with 302 additions and 70 deletions

View File

@ -28,6 +28,8 @@ USAGE_CODE int(11) 0=Feature, 1=Theme Open,
FORCED_LENGTH int(10) Playout this length, 0 = don't timeshift FORCED_LENGTH int(10) Playout this length, 0 = don't timeshift
AVERAGE_LENGTH int(10) AVERAGE_LENGTH int(10)
LENGTH_DEVIATION int(10) Maximum variation of underlying cuts LENGTH_DEVIATION int(10) Maximum variation of underlying cuts
MINIMUM_TALK_LENGTH int(10) Minimum talk length of underlying cuts
MAXIMUM_TALK_LENGTH int(10) Maximum talk length of underlying cuts
AVERAGE_SEGUE_LENGTH int(10) AVERAGE_SEGUE_LENGTH int(10)
AVERAGE_HOOK_LENGTH int(10) AVERAGE_HOOK_LENGTH int(10)
CUT_QUANTITY int(10) > 1 for rotators CUT_QUANTITY int(10) > 1 for rotators

View File

@ -0,0 +1,13 @@
NEXUS_FIELDS Table Layout for Rivendell
The NEXUS_FIELDS table contains mappings between Rivendell database rows
and MusicMaster Nexus fields.
FIELD NAME TYPE REMARKS
--------------------------------------------------------------------------
ID int(11) Primary Key
STATION varchar(255) Nexus Station (Database)
RD_NAME varchar(255) Rivendell Name
NEXUS_NAME varchar(255) MusicMaster Field Name
NEXUS_ID int(11) MusicMaster Field ID

View File

@ -0,0 +1,12 @@
NEXUS_QUEUE Table Layout for Rivendell
The NEXUS_QUEUE table holds notifications that could not be sent
to a MusicMaster Nexus server.
FIELD NAME TYPE REMARKS
--------------------------------------------------------------------------
ID int(11) Primary Key
NOTIFICATION varchar(255)
ERROR varchar(255)
CREATED timestamp

View File

@ -0,0 +1,12 @@
NEXUS_SERVER Table Layout for Rivendell
The NEXUS_SERVER table holds data concerning integration with
a MusicMaster Nexus server.
FIELD NAME TYPE REMARKS
--------------------------------------------------------------------------
NUMBER int(10) unsigned
ENABLED enum('N','Y')
ADDRESS varchar(50)
PORT int(11)
STATION_NAME varchar(64)

View File

@ -0,0 +1,14 @@
NEXUS_STATIONS Table Layout for Rivendell
The NEXUS_STATIONS table contains mappings and other information
between Rivendell and MusicMaster Nexus.
FIELD NAME TYPE REMARKS
--------------------------------------------------------------------------
STATION varchar(255) Nexus Station (Database)
CATEGORY varchar(10) Default MusicMaster Category
AUTO_MERGE enum('N','Y') Auto Merge MusicMaster Schedules
RD_SERVICE varchar(10) Rivendell Service
RD_GROUP_NAME varchar(10) Default Rivendell Group
RD_SCHED_CODE varchar(11) Default Rivendell Scheduler Code

View File

@ -253,12 +253,7 @@ int RDCart::year() const
void RDCart::setYear(int year) void RDCart::setYear(int year)
{ {
if((year>0)&&(year<10000)) { SetRow("YEAR",QString().sprintf("%04d-01-01",year));
SetRow("YEAR",QString().sprintf("%04d-01-01",year));
}
else {
SetRow("YEAR");
}
metadata_changed=true; metadata_changed=true;
} }
@ -619,6 +614,32 @@ void RDCart::setAverageLength(unsigned length) const
} }
unsigned RDCart::minimumTalkLength() const
{
return RDGetSqlValue("CART","NUMBER",cart_number,
"MINIMUM_TALK_LENGTH").toUInt();
}
void RDCart::setMinimumTalkLength(unsigned length) const
{
SetRow("MINIMUM_TALK_LENGTH",length);
}
unsigned RDCart::maximumTalkLength() const
{
return RDGetSqlValue("CART","NUMBER",cart_number,
"MAXIMUM_TALK_LENGTH").toUInt();
}
void RDCart::setMaximumTalkLength(unsigned length) const
{
SetRow("MAXIMUM_TALK_LENGTH",length);
}
unsigned RDCart::averageSegueLength() const unsigned RDCart::averageSegueLength() const
{ {
return RDGetSqlValue("CART","NUMBER",cart_number, return RDGetSqlValue("CART","NUMBER",cart_number,
@ -1016,6 +1037,8 @@ void RDCart::updateLength(bool enforce_length,unsigned length)
long long total=0; long long total=0;
long long segue_total=0; long long segue_total=0;
long long hook_total=0; long long hook_total=0;
long long min_talk_len=LLONG_MAX;
long long max_talk_len=0;
unsigned weight_total=0; unsigned weight_total=0;
unsigned weight = 0; unsigned weight = 0;
QDateTime end_date; QDateTime end_date;
@ -1025,7 +1048,8 @@ void RDCart::updateLength(bool enforce_length,unsigned length)
QString sql=QString(). QString sql=QString().
sprintf("select LENGTH,SEGUE_START_POINT,SEGUE_END_POINT,START_POINT,\ sprintf("select LENGTH,SEGUE_START_POINT,SEGUE_END_POINT,START_POINT,\
SUN,MON,TUE,WED,THU,FRI,SAT,START_DAYPART,END_DAYPART,\ SUN,MON,TUE,WED,THU,FRI,SAT,START_DAYPART,END_DAYPART,\
HOOK_START_POINT,HOOK_END_POINT,WEIGHT,END_DATETIME \ HOOK_START_POINT,HOOK_END_POINT,WEIGHT,END_DATETIME,\
TALK_START_POINT,TALK_END_POINT \
from CUTS where (CUT_NAME like \"%06d%%\")&&(LENGTH>0)", from CUTS where (CUT_NAME like \"%06d%%\")&&(LENGTH>0)",
cart_number); cart_number);
RDSqlQuery *q=new RDSqlQuery(sql); RDSqlQuery *q=new RDSqlQuery(sql);
@ -1047,6 +1071,12 @@ void RDCart::updateLength(bool enforce_length,unsigned length)
segue_total+=(q->value(1).toInt()-q->value(3).toInt()) * weight; segue_total+=(q->value(1).toInt()-q->value(3).toInt()) * weight;
} }
hook_total+=(q->value(14).toUInt()-q->value(13).toUInt()) * weight; hook_total+=(q->value(14).toUInt()-q->value(13).toUInt()) * weight;
if(min_talk_len>q->value(18).toUInt()-q->value(17).toUInt()) {
min_talk_len=q->value(18).toUInt()-q->value(17).toUInt();
}
if(max_talk_len<q->value(18).toUInt()-q->value(17).toUInt()) {
max_talk_len=q->value(18).toUInt()-q->value(17).toUInt();
}
weight_total += weight; weight_total += weight;
} }
if(weight_total>0) { if(weight_total>0) {
@ -1065,6 +1095,8 @@ void RDCart::updateLength(bool enforce_length,unsigned length)
setForcedLength(0); setForcedLength(0);
} }
} }
setMinimumTalkLength(min_talk_len);
setMaximumTalkLength(max_talk_len);
setCutQuantity(q->size()); setCutQuantity(q->size());
delete q; delete q;
@ -1355,61 +1387,63 @@ QString RDCart::xmlSql(bool include_cuts)
"CART.LENGTH_DEVIATION,"+ // 16 "CART.LENGTH_DEVIATION,"+ // 16
"CART.AVERAGE_SEGUE_LENGTH,"+ // 17 "CART.AVERAGE_SEGUE_LENGTH,"+ // 17
"CART.AVERAGE_HOOK_LENGTH,"+ // 18 "CART.AVERAGE_HOOK_LENGTH,"+ // 18
"CART.CUT_QUANTITY,"+ // 19 "CART.MINIMUM_TALK_LENGTH,"+ // 19
"CART.LAST_CUT_PLAYED,"+ // 20 "CART.MAXIMUM_TALK_LENGTH,"+ // 20
"CART.VALIDITY,"+ // 21 "CART.CUT_QUANTITY,"+ // 21
"CART.ENFORCE_LENGTH,"+ // 22 "CART.LAST_CUT_PLAYED,"+ // 22
"CART.ASYNCRONOUS,"+ // 23 "CART.VALIDITY,"+ // 23
"CART.OWNER,"+ // 24 "CART.ENFORCE_LENGTH,"+ // 24
"CART.METADATA_DATETIME,"+ // 25 "CART.ASYNCRONOUS,"+ // 25
"CART.CONDUCTOR,"+ // 26 "CART.OWNER,"+ // 26
"CART.MACROS,"+ // 27 "CART.METADATA_DATETIME,"+ // 27
"CART.SONG_ID "; // 28 "CART.CONDUCTOR,"+ // 28
"CART.MACROS,"+ // 29
"CART.SONG_ID "; // 30
if(include_cuts) { if(include_cuts) {
sql+=QString(",")+ sql+=QString(",")+
"CUTS.CUT_NAME,"+ // 29 "CUTS.CUT_NAME,"+ // 31
"CUTS.EVERGREEN,"+ // 30 "CUTS.EVERGREEN,"+ // 32
"CUTS.DESCRIPTION,"+ // 31 "CUTS.DESCRIPTION,"+ // 33
"CUTS.OUTCUE,"+ // 32 "CUTS.OUTCUE,"+ // 34
"CUTS.ISRC,"+ // 33 "CUTS.ISRC,"+ // 35
"CUTS.ISCI,"+ // 34 "CUTS.ISCI,"+ // 36
"CUTS.LENGTH,"+ // 35 "CUTS.LENGTH,"+ // 37
"CUTS.ORIGIN_DATETIME,"+ // 36 "CUTS.ORIGIN_DATETIME,"+ // 38
"CUTS.START_DATETIME,"+ // 37 "CUTS.START_DATETIME,"+ // 39
"CUTS.END_DATETIME,"+ // 38 "CUTS.END_DATETIME,"+ // 40
"CUTS.SUN,"+ // 39 "CUTS.SUN,"+ // 41
"CUTS.MON,"+ // 40 "CUTS.MON,"+ // 42
"CUTS.TUE,"+ // 41 "CUTS.TUE,"+ // 43
"CUTS.WED,"+ // 42 "CUTS.WED,"+ // 44
"CUTS.THU,"+ // 43 "CUTS.THU,"+ // 45
"CUTS.FRI,"+ // 44 "CUTS.FRI,"+ // 46
"CUTS.SAT,"+ // 45 "CUTS.SAT,"+ // 47
"CUTS.START_DAYPART,"+ // 46 "CUTS.START_DAYPART,"+ // 48
"CUTS.END_DAYPART,"+ // 47 "CUTS.END_DAYPART,"+ // 49
"CUTS.ORIGIN_NAME,"+ // 48 "CUTS.ORIGIN_NAME,"+ // 50
"CUTS.ORIGIN_LOGIN_NAME,"+ // 49 "CUTS.ORIGIN_LOGIN_NAME,"+ // 51
"CUTS.SOURCE_HOSTNAME,"+ // 50 "CUTS.SOURCE_HOSTNAME,"+ // 52
"CUTS.WEIGHT,"+ // 51 "CUTS.WEIGHT,"+ // 53
"CUTS.LAST_PLAY_DATETIME,"+ // 52 "CUTS.LAST_PLAY_DATETIME,"+ // 54
"CUTS.PLAY_COUNTER,"+ // 53 "CUTS.PLAY_COUNTER,"+ // 55
"CUTS.LOCAL_COUNTER,"+ // 54 "CUTS.LOCAL_COUNTER,"+ // 56
"CUTS.VALIDITY,"+ // 55 "CUTS.VALIDITY,"+ // 57
"CUTS.CODING_FORMAT,"+ // 56 "CUTS.CODING_FORMAT,"+ // 58
"CUTS.SAMPLE_RATE,"+ // 57 "CUTS.SAMPLE_RATE,"+ // 59
"CUTS.BIT_RATE,"+ // 58 "CUTS.BIT_RATE,"+ // 60
"CUTS.CHANNELS,"+ // 59 "CUTS.CHANNELS,"+ // 61
"CUTS.PLAY_GAIN,"+ // 60 "CUTS.PLAY_GAIN,"+ // 62
"CUTS.START_POINT,"+ // 61 "CUTS.START_POINT,"+ // 63
"CUTS.END_POINT,"+ // 62 "CUTS.END_POINT,"+ // 64
"CUTS.FADEUP_POINT,"+ // 63 "CUTS.FADEUP_POINT,"+ // 65
"CUTS.FADEDOWN_POINT,"+ // 64 "CUTS.FADEDOWN_POINT,"+ // 66
"CUTS.SEGUE_START_POINT,"+ // 65 "CUTS.SEGUE_START_POINT,"+ // 67
"CUTS.SEGUE_END_POINT,"+ // 66 "CUTS.SEGUE_END_POINT,"+ // 68
"CUTS.SEGUE_GAIN,"+ // 67 "CUTS.SEGUE_GAIN,"+ // 69
"CUTS.HOOK_START_POINT,"+ // 68 "CUTS.HOOK_START_POINT,"+ // 70
"CUTS.HOOK_END_POINT,"+ // 69 "CUTS.HOOK_END_POINT,"+ // 71
"CUTS.TALK_START_POINT,"+ // 70 "CUTS.TALK_START_POINT,"+ // 72
"CUTS.TALK_END_POINT "+ // 71 "CUTS.TALK_END_POINT "+ // 73
"from CART left join CUTS "+ "from CART left join CUTS "+
"on CART.NUMBER=CUTS.CART_NUMBER "; "on CART.NUMBER=CUTS.CART_NUMBER ";
} }
@ -1465,18 +1499,22 @@ QString RDCart::xml(RDSqlQuery *q,bool include_cuts,
"0"+RDGetTimeLength(q->value(17).toUInt(),true)); "0"+RDGetTimeLength(q->value(17).toUInt(),true));
xml+=" "+RDXmlField("averageHookLength", xml+=" "+RDXmlField("averageHookLength",
"0"+RDGetTimeLength(q->value(18).toUInt(),true)); "0"+RDGetTimeLength(q->value(18).toUInt(),true));
xml+=" "+RDXmlField("cutQuantity",q->value(19).toUInt()); xml+=" "+RDXmlField("minimumTalkLength",
xml+=" "+RDXmlField("lastCutPlayed",q->value(20).toUInt()); "0"+RDGetTimeLength(q->value(19).toUInt(),true));
xml+=" "+RDXmlField("enforceLength",RDBool(q->value(22).toString())); xml+=" "+RDXmlField("maximumTalkLength",
xml+=" "+RDXmlField("asyncronous",RDBool(q->value(23).toString())); "0"+RDGetTimeLength(q->value(20).toUInt(),true));
xml+=" "+RDXmlField("owner",q->value(24).toString()); xml+=" "+RDXmlField("cutQuantity",q->value(21).toUInt());
xml+=" "+RDXmlField("metadataDatetime",q->value(25).toDateTime()); xml+=" "+RDXmlField("lastCutPlayed",q->value(22).toUInt());
xml+=" "+RDXmlField("songId",q->value(28).toString()); xml+=" "+RDXmlField("enforceLength",RDBool(q->value(24).toString()));
xml+=" "+RDXmlField("asyncronous",RDBool(q->value(25).toString()));
xml+=" "+RDXmlField("owner",q->value(26).toString());
xml+=" "+RDXmlField("metadataDatetime",q->value(27).toDateTime());
xml+=" "+RDXmlField("songId",q->value(30).toString());
switch((RDCart::Type)q->value(1).toInt()) { switch((RDCart::Type)q->value(1).toInt()) {
case RDCart::Audio: case RDCart::Audio:
if(include_cuts) { if(include_cuts) {
cartnum=q->value(0).toUInt(); cartnum=q->value(0).toUInt();
if(q->value(29).toString().isEmpty()) { if(q->value(31).toString().isEmpty()) {
xml+=" <cutList/>\n"; xml+=" <cutList/>\n";
} }
else { else {
@ -1497,7 +1535,7 @@ QString RDCart::xml(RDSqlQuery *q,bool include_cuts,
break; break;
case RDCart::Macro: case RDCart::Macro:
mlist=q->value(27).toString().split("!"); mlist=q->value(29).toString().split("!");
if(mlist.size()==0) { if(mlist.size()==0) {
xml+=" <macroList/>\n"; xml+=" <macroList/>\n";
} }
@ -1845,6 +1883,18 @@ unsigned RDCart::readXml(std::vector<RDWaveData> *data,const QString &xml)
toString())); toString()));
cartdata.setMetadataFound(true); cartdata.setMetadataFound(true);
} }
if(f0[i].contains("<minimumTalkLength>")) {
cartdata.
setMinimumTalkLength(RDSetTimeLength(GetXmlValue("minimumTalkLength",f0[i]).
toString()));
cartdata.setMetadataFound(true);
}
if(f0[i].contains("<maximumTalkLength>")) {
cartdata.
setMaximumTalkLength(RDSetTimeLength(GetXmlValue("maximumTalkLength",f0[i]).
toString()));
cartdata.setMetadataFound(true);
}
if(f0[i].contains("<cutQuantity>")) { if(f0[i].contains("<cutQuantity>")) {
cartdata.setCutQuantity(GetXmlValue("cutQuantity",f0[i]).toInt()); cartdata.setCutQuantity(GetXmlValue("cutQuantity",f0[i]).toInt());
cartdata.setMetadataFound(true); cartdata.setMetadataFound(true);

View File

@ -99,6 +99,10 @@ class RDCart
unsigned calculateAverageLength(unsigned *max_dev=0) const; unsigned calculateAverageLength(unsigned *max_dev=0) const;
unsigned averageLength() const; unsigned averageLength() const;
void setAverageLength(unsigned length) const; void setAverageLength(unsigned length) const;
unsigned minimumTalkLength() const;
void setMinimumTalkLength(unsigned length) const;
unsigned maximumTalkLength() const;
void setMaximumTalkLength(unsigned length) const;
unsigned averageSegueLength() const; unsigned averageSegueLength() const;
void setAverageSegueLength(unsigned length) const; void setAverageSegueLength(unsigned length) const;
unsigned averageHookLength() const; unsigned averageHookLength() const;

View File

@ -485,6 +485,29 @@ void RDWaveData::setLengthDeviation(int msecs)
} }
int RDWaveData::minimumTalkLength() const
{
return data_minimum_talk_length;
}
void RDWaveData::setMinimumTalkLength(int msecs)
{
data_minimum_talk_length=msecs;
}
int RDWaveData::maximumTalkLength() const
{
return data_maximum_talk_length;
}
void RDWaveData::setMaximumTalkLength(int msecs)
{
data_maximum_talk_length=msecs;
}
int RDWaveData::averageSegueLength() const int RDWaveData::averageSegueLength() const
{ {
return data_average_segue_length; return data_average_segue_length;

View File

@ -111,6 +111,10 @@ class RDWaveData
void setAverageLength(int msecs); void setAverageLength(int msecs);
int lengthDeviation() const; int lengthDeviation() const;
void setLengthDeviation(int msecs); void setLengthDeviation(int msecs);
int minimumTalkLength() const;
void setMinimumTalkLength(int msecs);
int maximumTalkLength() const;
void setMaximumTalkLength(int msecs);
int averageSegueLength() const; int averageSegueLength() const;
void setAverageSegueLength(int msecs); void setAverageSegueLength(int msecs);
int averageHookLength() const; int averageHookLength() const;
@ -237,6 +241,8 @@ class RDWaveData
int data_forced_length; int data_forced_length;
int data_average_length; int data_average_length;
int data_length_deviation; int data_length_deviation;
int data_minimum_talk_length;
int data_maximum_talk_length;
int data_average_segue_length; int data_average_segue_length;
int data_average_hook_length; int data_average_hook_length;
int data_cut_quantity; int data_cut_quantity;

View File

@ -157,7 +157,7 @@ void MainObject::InitializeSchemaMap() {
global_version_map["2.18"]=272; global_version_map["2.18"]=272;
global_version_map["2.19"]=275; global_version_map["2.19"]=275;
global_version_map["3.0"]=308; global_version_map["3.0"]=308;
global_version_map["3.1"]=309; global_version_map["3.1"]=310;
} }

View File

@ -9749,6 +9749,102 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg)
WriteSchemaVersion(++cur_schema); WriteSchemaVersion(++cur_schema);
} }
if((cur_schema<310)&&(set_schema>cur_schema)) {
sql="alter table CART add column MINIMUM_TALK_LENGTH int unsigned default 0 after AVERAGE_HOOK_LENGTH";
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
sql="alter table CART add column MAXIMUM_TALK_LENGTH int unsigned default 0 after MINIMUM_TALK_LENGTH";
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
sql=QString("create table if not exists NEXUS_FIELDS (")+
"STATION varchar(255) NOT NULL,"+
"RD_NAME varchar(255),"+
"NEXUS_NAME varchar(255),"+
"NEXUS_ID int(11))"+
" charset utf8mb4 collate utf8mb4_general_ci"+
db_table_create_postfix;
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
sql=QString("create table if not exists NEXUS_QUEUE (")+
"ID int auto_increment not null primary key,"+
"NOTIFICATION varchar(255),"+
"ERROR varchar(255),"+
"CREATED timestamp default current_timestamp)"+
" charset utf8mb4 collate utf8mb4_general_ci"+
db_table_create_postfix;
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
sql=QString("create table if not exists NEXUS_SERVER (")+
"ENABLED enum('N','Y') default 'N',"+
"ADDRESS varchar(50) NOT NULL,"+
"PORT int(11) NOT NULL DEFAULT 8080,"+
"STATION_NAME varchar(64))"+
" charset utf8mb4 collate utf8mb4_general_ci"+
db_table_create_postfix;
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
sql=QString("create table if not exists NEXUS_STATIONS (")+
"STATION varchar(255) not null,"+
"CATEGORY varchar(10) not null,"+
"AUTO_MERGE enum('N','Y') default 'N',"+
"RD_SERVICE varchar(10) not null,"+
"RD_GROUP_NAME varchar(10) not null,"+
"RD_SCHED_CODE varchar(11) not null)"+
" charset utf8mb4 collate utf8mb4_general_ci"+
db_table_create_postfix;
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
q=new RDSqlQuery("select NAME from SERVICES",false);
while(q->next()) {
sql=QString("insert into NEXUS_STATIONS set ")+
"RD_SERVICE=\""+RDEscapeString(q->value(0).toString())+"\"";
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
}
delete q;
sql=QString("insert into IMPORT_TEMPLATES set ")+
"NAME='MusicMaster Nexus',"+
"HOURS_OFFSET=0,"+
"HOURS_LENGTH=2,"+
"MINUTES_OFFSET=3,"+
"MINUTES_LENGTH=2,"+
"SECONDS_OFFSET=6,"+
"SECONDS_LENGTH=2,"+
"DATA_OFFSET=10,"+
"DATA_LENGTH=6,"+
"CART_OFFSET=20,"+
"CART_LENGTH=6,"+
"TITLE_OFFSET=30,"+
"TITLE_LENGTH=60,"+
"LEN_HOURS_OFFSET=0,"+
"LEN_HOURS_LENGTH=0,"+
"LEN_MINUTES_OFFSET=95,"+
"LEN_MINUTES_LENGTH=2,"+
"LEN_SECONDS_OFFSET=98,"+
"LEN_SECONDS_LENGTH=2,"+
"EVENT_ID_OFFSET=101,"+
"EVENT_ID_LENGTH=10";
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
length_update_required=true;
WriteSchemaVersion(++cur_schema);
}
// NEW SCHEMA UPDATES GO HERE... // NEW SCHEMA UPDATES GO HERE...