diff --git a/ChangeLog b/ChangeLog index 48770d36..621dd593 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24417,3 +24417,5 @@ 2023-10-05 Fred Gleason * Fixed a regression in rdairplay(1) and rdpanel(1) that caused extraneous buttons to appear when resizing the sound panel. +2023-10-06 Fred Gleason + * Added a 'SoundPanel Buttons' notification. diff --git a/docs/apis/notification.xml b/docs/apis/notification.xml index 7c3c2fd1..49b6fcf0 100644 --- a/docs/apis/notification.xml +++ b/docs/apis/notification.xml @@ -369,6 +369,73 @@ + + + SoundPanel Buttons [<command>rdairplay</command><manvolnum>1</manvolnum>] + + SoundPanel Button Fields + + + + + + Field + Value + + + Database Field + PANELS.ID + + + Type + PANEL_BUTTON + + + Id Data Type + Integer + + + RDNotification::Type Value + RDNotification::PanelButtonType [8] + + + +
+
+ + + Extended SoundPanel Buttons [<command>rdpanel</command><manvolnum>1</manvolnum>] + + SoundPanel Button Fields + + + + + + Field + Value + + + Database Field + EXTENDED_PANELS.ID + + + Type + EXTENDED_PANEL_BUTTON + + + Id Data Type + Integer + + + RDNotification::Type Value + RDNotification::ExtendedPanelButtonType [9] + + + +
+
+ diff --git a/lib/rdnotification.cpp b/lib/rdnotification.cpp index b4de38b1..44ff92bf 100644 --- a/lib/rdnotification.cpp +++ b/lib/rdnotification.cpp @@ -81,6 +81,8 @@ bool RDNotification::isValid() const bool RDNotification::read(const QString &str) { + printf("RDNotification::read(%s)\n",str.toUtf8().constData()); + notify_type=RDNotification::NullType; notify_action=RDNotification::NoAction; notify_id=QVariant(); @@ -123,6 +125,11 @@ bool RDNotification::read(const QString &str) notify_id=QVariant(args[3]); break; + case RDNotification::PanelButtonType: + case RDNotification::ExtendedPanelButtonType: + notify_id=QVariant(args[3].toInt()); + break; + case RDNotification::NullType: case RDNotification::LastType: break; @@ -182,6 +189,11 @@ QString RDNotification::write() const ret+=notify_id.toString(); break; + case RDNotification::PanelButtonType: + case RDNotification::ExtendedPanelButtonType: + ret+=QString::asprintf("%d",notify_id.toInt()); + break; + case RDNotification::NullType: case RDNotification::LastType: break; @@ -251,6 +263,14 @@ QString RDNotification::typeString(RDNotification::Type type) ret="FEED"; break; + case RDNotification::PanelButtonType: + ret="PANEL_BUTTON"; + break; + + case RDNotification::ExtendedPanelButtonType: + ret="EXTENDED_PANEL_BUTTON"; + break; + case RDNotification::NullType: case RDNotification::LastType: break; diff --git a/lib/rdnotification.h b/lib/rdnotification.h index 44e2d10b..bb992382 100644 --- a/lib/rdnotification.h +++ b/lib/rdnotification.h @@ -28,7 +28,8 @@ class RDNotification { public: enum Type {NullType=0,CartType=1,LogType=2,PypadType=3,DropboxType=4, - CatchEventType=5,FeedItemType=6,FeedType=7,LastType=8}; + CatchEventType=5,FeedItemType=6,FeedType=7, + PanelButtonType=8,ExtendedPanelButtonType=9,LastType=10}; enum Action {NoAction=0,AddAction=1,DeleteAction=2,ModifyAction=3, LastAction=4}; RDNotification(Type type,Action action,const QVariant &id); diff --git a/lib/rdpanel_button.cpp b/lib/rdpanel_button.cpp index e94d10d2..0a23cb50 100644 --- a/lib/rdpanel_button.cpp +++ b/lib/rdpanel_button.cpp @@ -30,6 +30,7 @@ RDPanelButton::RDPanelButton(int row,int col,RDStation *station,bool flash, QWidget *parent) : RDPushButton(parent) { + button_db_id=-1; button_row=row; button_col=col; button_station=station; @@ -51,6 +52,7 @@ void RDPanelButton::clear() button_color=Qt::lightGray; button_default_color=Qt::lightGray; setCart(0); + button_db_id=-1; button_deck=-1; button_output=-1; button_play_deck=NULL; @@ -81,6 +83,18 @@ int RDPanelButton::column() const } +int RDPanelButton::dbId() const +{ + return button_db_id; +} + + +void RDPanelButton::setDbId(int id) +{ + button_db_id=id; +} + + QString RDPanelButton::text() const { return button_text; diff --git a/lib/rdpanel_button.h b/lib/rdpanel_button.h index d141e50e..2520fad4 100644 --- a/lib/rdpanel_button.h +++ b/lib/rdpanel_button.h @@ -40,6 +40,8 @@ class RDPanelButton : public RDPushButton void clear(); int row() const; int column() const; + int dbId() const; + void setDbId(int id); QString text() const; void setText(const QString &text); QString outputText() const; @@ -131,6 +133,7 @@ class RDPanelButton : public RDPushButton RDLogLine::StartSource button_start_source; int button_row; int button_col; + int button_db_id; int button_move_count; bool button_allow_drags; }; diff --git a/lib/rdsound_panel.cpp b/lib/rdsound_panel.cpp index 19b9639f..eac86d1c 100644 --- a/lib/rdsound_panel.cpp +++ b/lib/rdsound_panel.cpp @@ -157,6 +157,8 @@ RDSoundPanel::RDSoundPanel(int station_panels,int user_panels,bool flash, // connect(rda->ripc(),SIGNAL(onairFlagChanged(bool)), this,SLOT(onairFlagChangedData(bool))); + connect(rda->ripc(),SIGNAL(notificationReceived(RDNotification *)), + this,SLOT(notificationReceivedData(RDNotification *))); // // Load Panel Names @@ -933,6 +935,60 @@ void RDSoundPanel::onairFlagChangedData(bool state) } +void RDSoundPanel::notificationReceivedData(RDNotification *notify) +{ + printf("notificationReceivedData()\n"); + + RDPanelButton *button=NULL; + QString sql; + RDSqlQuery *q=NULL; + + if(((notify->type()==RDNotification::PanelButtonType)&& + (panel_tablename=="`PANELS`"))|| + ((notify->type()==RDNotification::ExtendedPanelButtonType)&& + (panel_tablename=="`EXTENDED_PANELS`"))) { + sql=ButtonSqlFields()+ + " where "+ + panel_tablename+QString::asprintf(".`ID`=%d",notify->id().toInt()); + printf("SQL: %s\n",sql.toUtf8().constData()); + q=new RDSqlQuery(sql); + if(q->first()) { + RDAirPlayConf::PanelType ptype= + (RDAirPlayConf::PanelType)q->value(10).toInt(); + if((q->value(1).toString()==rda->station()->name())&& + (ptype==RDAirPlayConf::StationPanel)) { + if(panel_arrays.value("").size()>q->value(2).toInt()) { + if((button=panel_arrays.value("").at(q->value(2).toInt())-> + panelButton(q->value(3).toInt(),q->value(4).toInt()))!=NULL) { + if(!button->isActive()) { + ApplyButtonFields(button,q); + } + } + } + } + if((ptype==RDAirPlayConf::UserPanel)&& + (panel_arrays.contains(q->value(1).toString()))) { + if(panel_arrays.value(q->value(1).toString()).size()> + q->value(2).toInt()) { + if((button=panel_arrays.value(q->value(1).toString()). + at(q->value(2).toInt())->panelButton(q->value(3).toInt(),q->value(4).toInt()))!=NULL) { + if(!button->isActive()) { + ApplyButtonFields(button,q); + } + } + } + } + } + else { + rda->syslog(LOG_WARNING, + "received update for non-existent panel button [id: %d]", + notify->id().toInt()); + } + delete q; + } +} + + void RDSoundPanel::resizeEvent(QResizeEvent *e) { // int w=size().width(); @@ -1277,6 +1333,8 @@ void RDSoundPanel::StopButton(RDPlayDeck *deck) void RDSoundPanel::UpdatePanels(const QString &username) { + printf("UpdatePanel(\"%s\")\n",username.toUtf8().constData()); + QString owner=username; RDAirPlayConf::PanelType type=RDAirPlayConf::UserPanel; int max_panels=panel_user_panels; @@ -1309,18 +1367,7 @@ void RDSoundPanel::UpdatePanels(const QString &username) // // Update button attributes // - QString sql=QString("select ")+ - panel_tablename+".`PANEL_NO`,"+ // 00 - panel_tablename+".`ROW_NO`,"+ // 01 - panel_tablename+".`COLUMN_NO`,"+ // 02 - panel_tablename+".`LABEL`,"+ // 03 - panel_tablename+".`CART`,"+ // 04 - panel_tablename+".`DEFAULT_COLOR`,"+ // 05 - "`CART`.`FORCED_LENGTH`,"+ // 06 - "`CART`.`AVERAGE_HOOK_LENGTH`,"+ // 07 - "`CART`.`TYPE` "+ // 08 - "from "+panel_tablename+" "+ // 09 - "left join `CART` on "+panel_tablename+".`CART`=`CART`.`NUMBER` "+ + QString sql=ButtonSqlFields()+ "where "+panel_tablename+QString::asprintf(".`TYPE`=%d && ",type)+ panel_tablename+".`OWNER`='"+RDEscapeString(owner)+"' && "+ panel_tablename+QString::asprintf(".`PANEL_NO`<%d ",max_panels)+ @@ -1330,38 +1377,10 @@ void RDSoundPanel::UpdatePanels(const QString &username) panel_tablename+".`ROW_NO`"; RDSqlQuery *q=new RDSqlQuery(sql); while(q->next()) { - RDPanelButton *button=panel_arrays.value(username).at(q->value(0).toInt())-> - panelButton(q->value(1).toInt(),q->value(2).toInt()); + RDPanelButton *button=panel_arrays.value(username).at(q->value(2).toInt())-> + panelButton(q->value(3).toInt(),q->value(4).toInt()); if(!button->isActive()) { - button->setText(q->value(3).toString()); - button->setCart(q->value(4).toInt()); - button->setLength(false,q->value(6).toInt()); - button->setLength(true,q->value(7).toInt()); - if((panel_playmode_box!=NULL)&&(panel_playmode_box->currentIndex()==1)&& - (q->value(7).toUInt()>0)) { - button->setActiveLength(q->value(7).toInt()); - } - else { - if(q->value(8).toInt()==RDCart::Macro) { - button->setActiveLength(q->value(6).toInt()); - } - else { - if(q->value(6).toInt()>0) { - button->setActiveLength(q->value(6).toInt()); - } - else { - button->setActiveLength(-1); - } - } - } - if(q->value(5).toString().isEmpty()) { - button->setColor(palette().color(QPalette::Background)); - button->setDefaultColor(palette().color(QPalette::Background)); - } - else { - button->setColor(QColor(q->value(5).toString())); - button->setDefaultColor(QColor(q->value(5).toString())); - } + ApplyButtonFields(button,q); } } delete q; @@ -1385,13 +1404,15 @@ void RDSoundPanel::ShowPanel(RDAirPlayConf::PanelType type,int offset) void RDSoundPanel::SaveButton(RDAirPlayConf::PanelType type, - int panel,int row,int col) + int panel,int row,int col) { QString sql; QString sql1; RDSqlQuery *q; QString owner; QString username; + RDNotification *notify=NULL; + if(type==RDAirPlayConf::UserPanel) { username=rda->user()->name(); } @@ -1412,37 +1433,37 @@ void RDSoundPanel::SaveButton(RDAirPlayConf::PanelType type, // // Determine if the button exists // - sql=QString("select `LABEL` from ")+panel_tablename+" where "+ + sql=QString("select ")+ + "`ID` "+ // 00 + "from "+panel_tablename+" where "+ QString::asprintf("`TYPE`=%d && ",type)+ "`OWNER`='"+RDEscapeString(owner)+"' && "+ QString::asprintf("`PANEL_NO`=%d && ",panel)+ QString::asprintf("`ROW_NO`=%d && ",row)+ QString::asprintf("`COLUMN_NO`=%d",col); q=new RDSqlQuery(sql); - if(q->size()>0) { + if(q->first()) { // // If so, update the record // - delete q; sql1=QString("update ")+panel_tablename+" set "+ "`LABEL`='"+RDEscapeString(button->text())+"',"+ QString::asprintf("`CART`=%d,",button->cart())+ "`DEFAULT_COLOR`='"+button->defaultColor().name()+"' where "+ - QString::asprintf("(`TYPE`=%d)&&",type)+ - "(`OWNER`='"+RDEscapeString(owner)+"')&&"+ - QString::asprintf("(`PANEL_NO`=%d)&&",panel)+ - QString::asprintf("(`ROW_NO`=%d)&&",row)+ - QString::asprintf("(`COLUMN_NO`=%d)",col); - q=new RDSqlQuery(sql1); - if(q->isActive()) { - delete q; - return; + QString::asprintf("`ID`=%d",q->value(0).toInt()); + RDSqlQuery::apply(sql1); + if(panel_tablename=="`PANELS`") { + notify=new RDNotification(RDNotification::PanelButtonType, + RDNotification::ModifyAction, + q->value(0).toInt()); + } + else { + notify=new RDNotification(RDNotification::ExtendedPanelButtonType, + RDNotification::ModifyAction, + q->value(0).toInt()); } - delete q; } else { - delete q; - // // Otherwise, insert a new one // @@ -1461,8 +1482,22 @@ void RDSoundPanel::SaveButton(RDAirPlayConf::PanelType type, "'"+RDEscapeString(button->text())+"',"+ QString::asprintf("%d,",button->cart())+ "'"+RDEscapeString(button->defaultColor().name())+"')"; - RDSqlQuery::apply(sql1); + int new_id=RDSqlQuery::run(sql1).toInt(); + + if(panel_tablename=="`PANELS`") { + notify=new RDNotification(RDNotification::PanelButtonType, + RDNotification::AddAction, + new_id); + } + else { + notify=new RDNotification(RDNotification::ExtendedPanelButtonType, + RDNotification::AddAction, + new_id); + } } + rda->ripc()->sendNotification(*notify); + delete notify; + delete q; } @@ -1673,31 +1708,34 @@ void RDSoundPanel::Paused(int id) void RDSoundPanel::Stopped(int id) { - if(panel_active_buttons[id]==NULL) { + RDPanelButton *button=panel_active_buttons[id]; + + if(button==NULL) { LogLine(QString::asprintf("Invalid ID=%d in RDSoundPanel::Stopped()", id)); return; } - LogTraffic(panel_active_buttons[id]); + LogTraffic(button); ClearChannel(id); - if(panel_active_buttons[id]->pauseWhenFinished()) { - panel_active_buttons[id]->setState(true); - panel_active_buttons[id]->setColor(RDPANEL_PAUSED_BACKGROUND_COLOR); - panel_active_buttons[id]->resetCounter(); + if(button->pauseWhenFinished()) { + button->setState(true); + button->setColor(RDPANEL_PAUSED_BACKGROUND_COLOR); + button->resetCounter(); } else { - panel_active_buttons[id]->setState(false); - panel_active_buttons[id]->setHookMode(panel_playmode_box->currentIndex()==1); + button->setState(false); + button->setHookMode(panel_playmode_box->currentIndex()==1); } - disconnect(this,SIGNAL(tick()),panel_active_buttons[id],SLOT(tickClock())); - panel_active_buttons[id]->playDeck()->disconnect(); - delete panel_active_buttons[id]->playDeck(); - panel_active_buttons[id]->setPlayDeck(NULL); - if(!panel_active_buttons[id]->pauseWhenFinished()) { - panel_active_buttons[id]->reset(); + disconnect(this,SIGNAL(tick()),button,SLOT(tickClock())); + button->playDeck()->disconnect(); + delete button->playDeck(); + button->setPlayDeck(NULL); + if(!button->pauseWhenFinished()) { + button->reset(); } - panel_active_buttons[id]->setDuckVolume(0); + button->setDuckVolume(0); panel_active_buttons[id]=NULL; + UpdateButton(button); LogLine(QString::asprintf("Playout stopped: id=%d",id)); } @@ -1749,3 +1787,72 @@ RDPanelButton *RDSoundPanel::GetVisibleButton(int row,int col) const { return NULL; } + + +QString RDSoundPanel::ButtonSqlFields() const +{ + QString sql=QString("select ")+ + panel_tablename+".`ID`,"+ // 00 + panel_tablename+".`OWNER`,"+ // 01 + panel_tablename+".`PANEL_NO`,"+ // 02 + panel_tablename+".`ROW_NO`,"+ // 03 + panel_tablename+".`COLUMN_NO`,"+ // 04 + panel_tablename+".`LABEL`,"+ // 05 + panel_tablename+".`CART`,"+ // 06 + panel_tablename+".`DEFAULT_COLOR`,"+ // 07 + "`CART`.`FORCED_LENGTH`,"+ // 08 + "`CART`.`AVERAGE_HOOK_LENGTH`,"+ // 09 + "`CART`.`TYPE` "+ // 10 + "from "+panel_tablename+" "+ + "left join `CART` on "+panel_tablename+".`CART`=`CART`.`NUMBER` "; + + return sql; +} + + +void RDSoundPanel::ApplyButtonFields(RDPanelButton *button,RDSqlQuery *q) +{ + button->setDbId(q->value(0).toInt()); + button->setText(q->value(5).toString()); + button->setCart(q->value(6).toInt()); + button->setLength(false,q->value(8).toInt()); + button->setLength(true,q->value(9).toInt()); + if((panel_playmode_box!=NULL)&&(panel_playmode_box->currentIndex()==1)&& + (q->value(9).toUInt()>0)) { + button->setActiveLength(q->value(9).toInt()); + } + else { + if(q->value(10).toInt()==RDCart::Macro) { + button->setActiveLength(q->value(7).toInt()); + } + else { + if(q->value(8).toInt()>0) { + button->setActiveLength(q->value(8).toInt()); + } + else { + button->setActiveLength(-1); + } + } + } + if(q->value(7).toString().isEmpty()) { + button->setColor(palette().color(QPalette::Background)); + button->setDefaultColor(palette().color(QPalette::Background)); + } + else { + button->setColor(QColor(q->value(7).toString())); + button->setDefaultColor(QColor(q->value(7).toString())); + } +} + + +void RDSoundPanel::UpdateButton(RDPanelButton *button) +{ + QString sql=ButtonSqlFields()+"where "+ + panel_tablename+QString::asprintf(".`ID`=%d",button->dbId()); + + RDSqlQuery *q=new RDSqlQuery(sql); + if(q->first()) { + ApplyButtonFields(button,q); + } + delete q; +} diff --git a/lib/rdsound_panel.h b/lib/rdsound_panel.h index 990ea65d..2902029f 100644 --- a/lib/rdsound_panel.h +++ b/lib/rdsound_panel.h @@ -118,6 +118,7 @@ class RDSoundPanel : public RDWidget void timescalingSupportedData(int card,bool state); void panelSetupData(); void onairFlagChangedData(bool state); + void notificationReceivedData(RDNotification *notify); protected: void resizeEvent(QResizeEvent *e); @@ -152,6 +153,9 @@ class RDSoundPanel : public RDWidget QString PanelTag(int index); QString PanelOwner(RDAirPlayConf::PanelType type); RDPanelButton *GetVisibleButton(int row,int col) const; + QString ButtonSqlFields() const; + void ApplyButtonFields(RDPanelButton *button,RDSqlQuery *q); + void UpdateButton(RDPanelButton *button); QMap > panel_arrays; RDButtonPanel *panel_current_panel; RDComboBox *panel_selector_box;