mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-12-05 16:20:14 +01:00
2023-09-28 Fred Gleason <fredg@paravelsystems.com>
* Added a 'RDJsonEscape(const QString &str)' function in 'lib/rdweb.cpp' and 'lib/rdweb.h'. * Added a '--dump-panel-updates' switch to rdpanel(1). * Added a rdpanel(1) man page. Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
@@ -24399,3 +24399,8 @@
|
||||
2023-09-27 Fred Gleason <fredg@paravelsystems.com>
|
||||
* Fixed a bug in 'RDSoundPanel' that threw a segfault when adding
|
||||
a new button to a User panel.
|
||||
2023-09-28 Fred Gleason <fredg@paravelsystems.com>
|
||||
* Added a 'RDJsonEscape(const QString &str)' function in
|
||||
'lib/rdweb.cpp' and 'lib/rdweb.h'.
|
||||
* Added a '--dump-panel-updates' switch to rdpanel(1).
|
||||
* Added a rdpanel(1) man page.
|
||||
|
||||
@@ -81,6 +81,9 @@ all-local: rdadmin.1\
|
||||
rdmetadata.1\
|
||||
rdmetadata.html\
|
||||
rdmetadata.pdf\
|
||||
rdpanel.1\
|
||||
rdpanel.html\
|
||||
rdpanel.pdf\
|
||||
rdrender.1\
|
||||
rdrender.html\
|
||||
rdrender.pdf\
|
||||
@@ -112,6 +115,7 @@ man_MANS = rdadmin.1\
|
||||
rdlogmanager.1\
|
||||
rdmarkerset.8\
|
||||
rdmetadata.1\
|
||||
rdpanel.1\
|
||||
rdrender.1\
|
||||
rmlsend.1\
|
||||
rdservice.8\
|
||||
@@ -168,6 +172,10 @@ EXTRA_DIST = exitcodes.xml\
|
||||
rdmetadata.html\
|
||||
rdmetadata.pdf\
|
||||
rdmetadata.xml\
|
||||
rdpanel.1\
|
||||
rdpanel.html\
|
||||
rdpanel.pdf\
|
||||
rdpanel.xml\
|
||||
rdrender.1\
|
||||
rdrender.html\
|
||||
rdrender.pdf\
|
||||
|
||||
70
docs/manpages/rdpanel.xml
Normal file
70
docs/manpages/rdpanel.xml
Normal file
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<refentry id="stdin" xmlns="http://docbook.org/ns/docbook" version="5.0">
|
||||
<!--
|
||||
Header
|
||||
-->
|
||||
<refmeta>
|
||||
<refentrytitle>rdpanel</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class='source'>September 2023</refmiscinfo>
|
||||
<refmiscinfo class='manual'>Linux Audio Manual</refmiscinfo>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>rdpanel</refname>
|
||||
<refpurpose>
|
||||
Module for stand-alone sound panel
|
||||
</refpurpose>
|
||||
</refnamediv>
|
||||
<info>
|
||||
<author>
|
||||
<personname>
|
||||
<firstname>Fred</firstname>
|
||||
<surname>Gleason</surname>
|
||||
<email>fredg@paravelsystems.com</email>
|
||||
</personname>
|
||||
<contrib>Application Author</contrib>
|
||||
</author>
|
||||
</info>
|
||||
|
||||
<!--
|
||||
Body
|
||||
-->
|
||||
<refsynopsisdiv id='synopsis'>
|
||||
<cmdsynopsis>
|
||||
<command>rdpanel</command>
|
||||
<arg choice='opt'><replaceable>OPTIONS</replaceable></arg>
|
||||
<sbr/>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1 id='description'>
|
||||
<title>Description</title>
|
||||
<para>
|
||||
The <command>rdpanel</command><manvolnum>1</manvolnum> modules provides
|
||||
a single, stand-alone "cart wall" application that allows
|
||||
users to play carts by means of a single button press.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id='options'>
|
||||
<title>Options</title>
|
||||
<variablelist remap='TP'>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--dump-panel-updates</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
When this option is given,
|
||||
<command>rdpanel</command><manvolnum>1</manvolnum> will print
|
||||
a dump of the currently loaded sound panel configuration to
|
||||
standard output each time the Rivendell user logged into the system
|
||||
is changed.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
@@ -23,9 +23,12 @@
|
||||
#include <rdbutton_panel.h>
|
||||
#include <rdbutton_dialog.h>
|
||||
|
||||
RDButtonPanel::RDButtonPanel(RDAirPlayConf::PanelType type,QWidget *parent)
|
||||
RDButtonPanel::RDButtonPanel(RDAirPlayConf::PanelType type,int number,
|
||||
QWidget *parent)
|
||||
: RDWidget(parent)
|
||||
{
|
||||
panel_number=number;
|
||||
|
||||
for(int i=0;i<PANEL_MAX_BUTTON_ROWS;i++) {
|
||||
for(int j=0;j<PANEL_MAX_BUTTON_COLUMNS;j++) {
|
||||
panel_button[i][j]=
|
||||
@@ -76,6 +79,24 @@ QSizePolicy RDButtonPanel::sizePolicy() const
|
||||
}
|
||||
|
||||
|
||||
int RDButtonPanel::number() const
|
||||
{
|
||||
return panel_number;
|
||||
}
|
||||
|
||||
|
||||
QString RDButtonPanel::title() const
|
||||
{
|
||||
return panel_title;
|
||||
}
|
||||
|
||||
|
||||
void RDButtonPanel::setTitle(const QString &str)
|
||||
{
|
||||
panel_title=str;
|
||||
}
|
||||
|
||||
|
||||
RDPanelButton *RDButtonPanel::panelButton(int row,int col) const
|
||||
{
|
||||
return panel_button[row][col];
|
||||
@@ -209,3 +230,41 @@ void RDButtonPanel::clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString RDButtonPanel::json(int padding,bool final) const
|
||||
{
|
||||
QString ret;
|
||||
|
||||
//
|
||||
// Get Button Count
|
||||
//
|
||||
int count=0;
|
||||
for(int i=0;i<PANEL_MAX_BUTTON_ROWS;i++) {
|
||||
for(int j=0;j<PANEL_MAX_BUTTON_COLUMNS;j++) {
|
||||
if(!panel_button[i][j]->isEmpty()) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret+=RDJsonPadding(padding)+"\"panel\": {\r\n";
|
||||
ret+=RDJsonField("number",panel_number,4+padding);
|
||||
ret+=RDJsonField("title",panel_title,4+padding,count==0);
|
||||
|
||||
for(int i=0;i<PANEL_MAX_BUTTON_ROWS;i++) {
|
||||
for(int j=0;j<PANEL_MAX_BUTTON_COLUMNS;j++) {
|
||||
if(!panel_button[i][j]->isEmpty()) {
|
||||
count--;
|
||||
ret+=panel_button[i][j]->json(4+padding,count==0);
|
||||
}
|
||||
}
|
||||
}
|
||||
ret+=RDJsonPadding(padding)+"}";
|
||||
if(!final) {
|
||||
ret+=",";
|
||||
}
|
||||
ret+="\r\n";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <rduser.h>
|
||||
#include <rdpanel_button.h>
|
||||
#include <rdbutton_dialog.h>
|
||||
#include <rdweb.h>
|
||||
#include <rdwidget.h>
|
||||
|
||||
//
|
||||
@@ -43,10 +44,13 @@
|
||||
class RDButtonPanel : public RDWidget
|
||||
{
|
||||
public:
|
||||
RDButtonPanel(RDAirPlayConf::PanelType type,QWidget *parent);
|
||||
RDButtonPanel(RDAirPlayConf::PanelType type,int number,QWidget *parent);
|
||||
~RDButtonPanel();
|
||||
QSize sizeHint() const;
|
||||
QSizePolicy sizePolicy() const;
|
||||
int number() const;
|
||||
QString title() const;
|
||||
void setTitle(const QString &str);
|
||||
RDPanelButton *panelButton(int row,int col) const;
|
||||
void setActionMode(RDAirPlayConf::ActionMode mode);
|
||||
void setAllowDrags(bool state);
|
||||
@@ -54,8 +58,11 @@ class RDButtonPanel : public RDWidget
|
||||
void hide();
|
||||
void show();
|
||||
void clear();
|
||||
QString json(int padding=0,bool final=false) const;
|
||||
|
||||
private:
|
||||
int panel_number;
|
||||
QString panel_title;
|
||||
RDPanelButton *panel_button[PANEL_MAX_BUTTON_ROWS][PANEL_MAX_BUTTON_COLUMNS];
|
||||
};
|
||||
|
||||
|
||||
@@ -323,6 +323,45 @@ int RDPanelButton::duckVolume() const
|
||||
}
|
||||
|
||||
|
||||
bool RDPanelButton::isEmpty() const
|
||||
{
|
||||
return button_cart==0;
|
||||
}
|
||||
|
||||
|
||||
QString RDPanelButton::json(int padding,bool final)
|
||||
{
|
||||
QString ret;
|
||||
|
||||
ret+=RDJsonPadding(padding)+"\"button\": {\r\n";
|
||||
ret+=RDJsonField("column",button_col,4+padding);
|
||||
ret+=RDJsonField("row",button_row,4+padding);
|
||||
if(isEmpty()) {
|
||||
ret+=RDJsonNullField("cart",4+padding);
|
||||
ret+=RDJsonNullField("defaultColor",4+padding);
|
||||
ret+=RDJsonNullField("length",4+padding);
|
||||
ret+=RDJsonNullField("hookLength",4+padding);
|
||||
ret+=RDJsonNullField("label",4+padding,true);
|
||||
}
|
||||
else {
|
||||
ret+=RDJsonField("cart",button_cart,4+padding);
|
||||
ret+=RDJsonField("defaultColor",button_default_color.name(),4+padding);
|
||||
ret+=RDJsonField("length",RDGetTimeLength(button_length[0],true,false),
|
||||
4+padding);
|
||||
ret+=RDJsonField("hookLength",RDGetTimeLength(button_length[1],true,false),
|
||||
4+padding);
|
||||
ret+=RDJsonField("label",button_text,4+padding,true);
|
||||
}
|
||||
ret+=RDJsonPadding(padding)+"}";
|
||||
if(!final) {
|
||||
ret+=",";
|
||||
}
|
||||
ret+="\r\n";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void RDPanelButton::tickClock()
|
||||
{
|
||||
int msecs;
|
||||
|
||||
@@ -21,8 +21,9 @@
|
||||
#ifndef RDPANEL_BUTTON_H
|
||||
#define RDPANEL_BUTTON_H
|
||||
|
||||
#include <rdpushbutton.h>
|
||||
#include <rdplay_deck.h>
|
||||
#include <rdpushbutton.h>
|
||||
#include <rdweb.h>
|
||||
|
||||
#define RDPANEL_BUTTON_MARGIN 5
|
||||
|
||||
@@ -70,6 +71,8 @@ class RDPanelButton : public RDPushButton
|
||||
void setDuckVolume(int lvel);
|
||||
void setAllowDrags(bool state);
|
||||
void resetCounter();
|
||||
bool isEmpty() const;
|
||||
QString json(int padding=0,bool final=false);
|
||||
|
||||
signals:
|
||||
void cartDropped(int row,int col,unsigned cartnum,const QColor &color,
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "rdlog_line.h"
|
||||
#include "rdmacro.h"
|
||||
#include "rdsound_panel.h"
|
||||
#include "rdweb.h"
|
||||
|
||||
RDSoundPanel::RDSoundPanel(int station_panels,int user_panels,bool flash,
|
||||
const QString &caption,const QString &label_template,
|
||||
@@ -35,6 +36,7 @@ RDSoundPanel::RDSoundPanel(int station_panels,int user_panels,bool flash,
|
||||
RDCartDialog *cart_dialog,QWidget *parent)
|
||||
: RDWidget(parent)
|
||||
{
|
||||
panel_dump_panel_updates=false;
|
||||
panel_playmode_box=NULL;
|
||||
panel_button_columns=PANEL_MAX_BUTTON_COLUMNS;
|
||||
panel_button_rows=PANEL_MAX_BUTTON_ROWS;
|
||||
@@ -235,6 +237,18 @@ QSizePolicy RDSoundPanel::sizePolicy() const
|
||||
}
|
||||
|
||||
|
||||
bool RDSoundPanel::dumpPanelUpdates() const
|
||||
{
|
||||
return panel_dump_panel_updates;
|
||||
}
|
||||
|
||||
|
||||
void RDSoundPanel::setDumpPanelUpdates(bool state)
|
||||
{
|
||||
panel_dump_panel_updates=state;
|
||||
}
|
||||
|
||||
|
||||
int RDSoundPanel::card(int outnum) const
|
||||
{
|
||||
return panel_card[outnum];
|
||||
@@ -476,6 +490,45 @@ RDAirPlayConf::PanelType RDSoundPanel::currentType() const
|
||||
}
|
||||
|
||||
|
||||
QString RDSoundPanel::json(const QString &owner,int padding,bool final) const
|
||||
{
|
||||
QString ret;
|
||||
QList<RDButtonPanel *> panels=panel_panels.value(owner);
|
||||
|
||||
ret+=RDJsonPadding(padding)+"\"array\": {\r\n";
|
||||
ret+=RDJsonField("owner",owner,4+padding);
|
||||
|
||||
for(int i=0;i<(panels.size()-1);i++) {
|
||||
ret+=panels.at(i)->json(4+padding);
|
||||
}
|
||||
if(panels.size()>0) {
|
||||
ret+=panels.last()->json(4+padding,true);
|
||||
}
|
||||
|
||||
ret+=RDJsonPadding(padding)+"}";
|
||||
if(!final) {
|
||||
ret+=",";
|
||||
}
|
||||
ret+="\r\n";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
QString RDSoundPanel::json(int padding) const
|
||||
{
|
||||
QString ret;
|
||||
|
||||
int count=0;
|
||||
for(QMap<QString,QList<RDButtonPanel *> >::const_iterator it=panel_panels.
|
||||
begin();it!=panel_panels.end();it++) {
|
||||
ret+=json(it.key(),4,++count==panel_panels.size());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void RDSoundPanel::setButton(RDAirPlayConf::PanelType type,int panel,
|
||||
int row,int col,unsigned cartnum,
|
||||
const QString &title)
|
||||
@@ -558,6 +611,9 @@ void RDSoundPanel::changeUser()
|
||||
{
|
||||
panel_config_panels=rda->user()->configPanels();
|
||||
UpdatePanels(rda->user()->name());
|
||||
if(panel_dump_panel_updates) {
|
||||
printf("{\r\n%s}\r\n",json(4).toUtf8().constData());
|
||||
}
|
||||
|
||||
//
|
||||
// Remove Old Panel Names
|
||||
@@ -1421,7 +1477,7 @@ void RDSoundPanel::UpdatePanels(const QString &username)
|
||||
list=panel_panels.value(username);
|
||||
}
|
||||
for(int i=panel_panels.value(username).size();i<size;i++) {
|
||||
RDButtonPanel *panel=new RDButtonPanel(type,this);
|
||||
RDButtonPanel *panel=new RDButtonPanel(type,i,this);
|
||||
for(int j=0;j<PANEL_MAX_BUTTON_COLUMNS;j++) {
|
||||
for(int k=0;k<PANEL_MAX_BUTTON_ROWS;k++) {
|
||||
RDPanelButton *button=panel->panelButton(k,j);
|
||||
|
||||
@@ -55,6 +55,8 @@ class RDSoundPanel : public RDWidget
|
||||
~RDSoundPanel();
|
||||
QSize sizeHint() const;
|
||||
QSizePolicy sizePolicy() const;
|
||||
bool dumpPanelUpdates() const;
|
||||
void setDumpPanelUpdates(bool state);
|
||||
int card(int outnum) const;
|
||||
void setCard(int outnum,int card);
|
||||
int port(int outnum) const;
|
||||
@@ -84,6 +86,8 @@ class RDSoundPanel : public RDWidget
|
||||
void setPauseEnabled(bool state);
|
||||
int currentNumber() const;
|
||||
RDAirPlayConf::PanelType currentType() const;
|
||||
QString json(const QString &owner,int padding=0,bool final=false) const;
|
||||
QString json(int padding=0) const;
|
||||
|
||||
public slots:
|
||||
void setButton(RDAirPlayConf::PanelType type,int panel,int row,int col,
|
||||
@@ -197,6 +201,7 @@ class RDSoundPanel : public RDWidget
|
||||
bool panel_onair_flag;
|
||||
QTimer *panel_scan_timer;
|
||||
QString panel_caption;
|
||||
bool panel_dump_panel_updates;
|
||||
};
|
||||
|
||||
#endif // RDSOUND_PANEL_H
|
||||
|
||||
@@ -206,6 +206,39 @@ QString RDJsonPadding(int padding)
|
||||
}
|
||||
|
||||
|
||||
QString RDJsonEscape(const QString &str)
|
||||
{
|
||||
QString ret;
|
||||
|
||||
for(int i=0;i<str.length();i++) {
|
||||
QChar c=str.at(i);
|
||||
switch(c.category()) {
|
||||
case QChar::Other_Control:
|
||||
ret+=QString::asprintf("\\u%04X",c.unicode());
|
||||
break;
|
||||
|
||||
default:
|
||||
switch(c.unicode()) {
|
||||
case 0x22: // Quote
|
||||
ret+="\\\"";
|
||||
break;
|
||||
|
||||
case 0x5C: // Backslash
|
||||
ret+="\\\\";
|
||||
break;
|
||||
|
||||
default:
|
||||
ret+=c;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
QString RDJsonNullField(const QString &name,int padding,bool final)
|
||||
{
|
||||
QString comma=",";
|
||||
@@ -269,6 +302,8 @@ QString RDJsonField(const QString &name,const QString &value,int padding,
|
||||
comma="";
|
||||
}
|
||||
|
||||
ret=RDJsonEscape(value);
|
||||
/*
|
||||
for(int i=0;i<value.length();i++) {
|
||||
QChar c=value.at(i);
|
||||
switch(c.category()) {
|
||||
@@ -293,6 +328,7 @@ QString RDJsonField(const QString &name,const QString &value,int padding,
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return RDJsonPadding(padding)+"\""+name+"\": \""+ret+"\""+comma+"\r\n";
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ extern QString RDXmlField(const QString &tag);
|
||||
extern QString RDXmlEscape(const QString &str);
|
||||
extern QString RDXmlUnescape(const QString &str);
|
||||
extern QString RDJsonPadding(int padding);
|
||||
extern QString RDJsonEscape(const QString &str);
|
||||
extern QString RDJsonNullField(const QString &name,int padding=0,
|
||||
bool final=false);
|
||||
extern QString RDJsonField(const QString &name,bool value,int padding=0,
|
||||
|
||||
@@ -42,7 +42,7 @@ RDCartDialog *panel_cart_dialog;
|
||||
MainWidget::MainWidget(RDConfig *c,QWidget *parent)
|
||||
: RDMainWindow("rdpanel",c)
|
||||
{
|
||||
// QPixmap panel_skin_pixmap;
|
||||
bool dump_panel_updates=false;
|
||||
QString err_msg;
|
||||
|
||||
//
|
||||
@@ -64,11 +64,15 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
|
||||
// Read Command Options
|
||||
//
|
||||
for(unsigned i=0;i<rda->cmdSwitch()->keys();i++) {
|
||||
if(rda->cmdSwitch()->key(i)=="--dump-panel-updates") {
|
||||
dump_panel_updates=true;
|
||||
rda->cmdSwitch()->setProcessed(i,true);
|
||||
}
|
||||
if(!rda->cmdSwitch()->processed(i)) {
|
||||
QMessageBox::critical(this,"RDPanel - "+tr("Error"),
|
||||
tr("Unknown command option")+": "+
|
||||
rda->cmdSwitch()->key(i));
|
||||
exit(2);
|
||||
exit(RDCoreApplication::ExitInvalidOption);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +133,7 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
|
||||
"RDPanel",
|
||||
rda->panelConf()->buttonLabelTemplate(),true,
|
||||
panel_player,panel_cart_dialog,this);
|
||||
panel_panel->setDumpPanelUpdates(dump_panel_updates);
|
||||
panel_panel->setPauseEnabled(rda->panelConf()->panelPauseEnabled());
|
||||
panel_panel->setCard(0,rda->panelConf()->card(RDAirPlayConf::SoundPanel1Channel));
|
||||
panel_panel->setPort(0,rda->panelConf()->port(RDAirPlayConf::SoundPanel1Channel));
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// A Dedicated Cart Wall Utility for Rivendell.
|
||||
//
|
||||
// (C) Copyright 2002-2021 Fred Gleason <fredg@paravelsystems.com>
|
||||
// (C) Copyright 2002-2023 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
|
||||
|
||||
@@ -468,6 +468,7 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%{_mandir}/man1/rdimport.1.gz
|
||||
%{_mandir}/man1/rdlogmanager.1.gz
|
||||
%{_mandir}/man1/rdmetadata.1.gz
|
||||
%{_mandir}/man1/rdpanel.1.gz
|
||||
%{_mandir}/man1/rdrender.1.gz
|
||||
%{_mandir}/man1/rmlsend.1.gz
|
||||
%{_mandir}/man1/rdsinglestart.1.gz
|
||||
|
||||
Reference in New Issue
Block a user