2015-02-22 Fred Gleason <fredg@paravelsystems.com>

* Fixed a bug in 'lib/rdlivewire.cpp' that caused long LWRP
	messages to be truncated.
	* Refactored parser code in 'lib/rdlivewire.cpp' for greater
	robustness.
	* Fixed a bug in 'rdadmin/view_node_info.cpp' that caused
	slots to be sorted in incorrect order.
	* Renamed the 'STREAMING' column to 'ACTIVE' in
	'rdadmin/view_node_info.cpp'.
This commit is contained in:
Fred Gleason
2015-02-22 21:20:32 -05:00
parent 741dc183da
commit 482aebf204
5 changed files with 235 additions and 215 deletions

View File

@@ -14780,3 +14780,12 @@
* Fixed a regression in 'rdairplay/log_play.cpp' that caused * Fixed a regression in 'rdairplay/log_play.cpp' that caused
the 'Play Tail' button to start from an incorrect position when the 'Play Tail' button to start from an incorrect position when
non-zero Start Marker position was set for the cut. non-zero Start Marker position was set for the cut.
2015-02-22 Fred Gleason <fredg@paravelsystems.com>
* Fixed a bug in 'lib/rdlivewire.cpp' that caused long LWRP
messages to be truncated.
* Refactored parser code in 'lib/rdlivewire.cpp' for greater
robustness.
* Fixed a bug in 'rdadmin/view_node_info.cpp' that caused
slots to be sorted in incorrect order.
* Renamed the 'STREAMING' column to 'ACTIVE' in
'rdadmin/view_node_info.cpp'.

View File

@@ -30,6 +30,49 @@
#include <rd.h> #include <rd.h>
#include <rdlivewire.h> #include <rdlivewire.h>
AString::AString()
: QString()
{
}
AString::AString(const AString &lhs)
: QString(lhs)
{
}
AString::AString(const QString &lhs)
: QString(lhs)
{
}
QStringList AString::split(const QString &sep,const QString &esc) const
{
if(esc.isEmpty()) {
return QStringList::split(sep,*this);
}
QStringList list;
bool escape=false;
QChar e=esc.at(0);
list.push_back(QString());
for(unsigned i=0;i<length();i++) {
if(at(i)==e) {
escape=!escape;
}
else {
if((!escape)&&(mid(i,1)==sep)) {
list.push_back(QString());
}
else {
list.back()+=at(i);
}
}
}
return list;
}
RDLiveWire::RDLiveWire(unsigned id,QObject *parent,const char *name) RDLiveWire::RDLiveWire(unsigned id,QObject *parent,const char *name)
: QObject(parent,name) : QObject(parent,name)
@@ -344,7 +387,9 @@ void RDLiveWire::readyReadData()
{ {
char buf[RD_LIVEWIRE_MAX_CMD_LENGTH]; char buf[RD_LIVEWIRE_MAX_CMD_LENGTH];
int n=live_socket->readBlock(buf,RD_LIVEWIRE_MAX_CMD_LENGTH); int n;
while((n=live_socket->readBlock(buf,RD_LIVEWIRE_MAX_CMD_LENGTH))>0) {
buf[n]=0; buf[n]=0;
for(int i=0;i<n;i++) { for(int i=0;i<n;i++) {
if(buf[i]=='\n') { if(buf[i]=='\n') {
@@ -363,6 +408,7 @@ void RDLiveWire::readyReadData()
} }
} }
} }
}
void RDLiveWire::errorData(int err) void RDLiveWire::errorData(int err)
@@ -532,48 +578,51 @@ void RDLiveWire::DespatchCommand(const QString &cmd)
void RDLiveWire::ReadVersion(const QString &cmd) void RDLiveWire::ReadVersion(const QString &cmd)
{ {
int ptr=0; QStringList f0;
QString tag; QStringList f1;
QString value;
if(!live_connected) { if(!live_connected) {
while((ptr=ParseString(cmd,ptr,&tag,&value))>=0) { f0=AString(cmd).split(" ","\"");
if(tag=="LWRP") { for(unsigned i=0;i<f0.size();i++) {
live_protocol_version=value; f1=f1.split(":",f0[i]);
if(f1.size()==2) {
if(f1[0]=="LWRP") {
live_protocol_version=f1[1];
} }
if(tag=="DEVN") { if(f1[0]=="DEVN") {
live_device_name=value; live_device_name=f1[1];
} }
if(tag=="SYSV") { if(f1[0]=="SYSV") {
live_system_version=value; live_system_version=f1[1];
} }
if(tag=="NSRC") { if(f1[0]=="NSRC") {
int delimiter=value.find("/"); int delimiter=f1[1].find("/");
if(delimiter<0) { if(delimiter<0) {
live_sources=value.toInt(); live_sources=f1[1].toInt();
} }
else { else {
live_sources=value.left(delimiter).toInt(); live_sources=f1[1].left(delimiter).toInt();
live_channels=value.right(value.length()-delimiter-1).toInt(); live_channels=f1[1].right(f1[1].length()-delimiter-1).toInt();
} }
if(live_sources>0) { if(live_sources>0) {
live_socket->writeBlock("SRC\r\n",5); live_socket->writeBlock("SRC\r\n",5);
} }
} }
if(tag=="NDST") { if(f1[0]=="NDST") {
int delimiter=value.find("/"); int delimiter=f1[1].find("/");
if(delimiter<0) { if(delimiter<0) {
live_destinations=value.toInt(); live_destinations=f1[1].toInt();
} }
else { else {
live_destinations=value.left(delimiter).toInt(); live_destinations=f1[1].left(delimiter).toInt();
live_channels=value.right(value.length()-delimiter-1).toInt(); live_channels=f1[1].right(f1[1].length()-delimiter-1).toInt();
} }
if(live_destinations>0) { if(live_destinations>0) {
live_socket->writeBlock("DST\r\n",5); live_socket->writeBlock("DST\r\n",5);
} }
} }
if(tag=="NGPI") { if(f1[0]=="NGPI") {
live_gpis=value.toInt(); live_gpis=f1[1].toInt();
QSignalMapper *mapper=new QSignalMapper(this,"gpi_mapper"); QSignalMapper *mapper=new QSignalMapper(this,"gpi_mapper");
connect(mapper,SIGNAL(mapped(int)),this,SLOT(gpiTimeoutData(int))); connect(mapper,SIGNAL(mapped(int)),this,SLOT(gpiTimeoutData(int)));
for(int i=0;i<live_gpis;i++) { for(int i=0;i<live_gpis;i++) {
@@ -594,8 +643,8 @@ void RDLiveWire::ReadVersion(const QString &cmd)
live_gpi_initialized=true; live_gpi_initialized=true;
} }
} }
if(tag=="NGPO") { if(f1[0]=="NGPO") {
live_gpos=value.toInt(); live_gpos=f1[1].toInt();
QSignalMapper *mapper=new QSignalMapper(this,"gpo_mapper"); QSignalMapper *mapper=new QSignalMapper(this,"gpo_mapper");
connect(mapper,SIGNAL(mapped(int)),this,SLOT(gpoTimeoutData(int))); connect(mapper,SIGNAL(mapped(int)),this,SLOT(gpoTimeoutData(int)));
for(int i=0;i<live_gpos;i++) { for(int i=0;i<live_gpos;i++) {
@@ -611,6 +660,7 @@ void RDLiveWire::ReadVersion(const QString &cmd)
connect(live_gpo_timers.back(),SIGNAL(timeout()),mapper,SLOT(map())); connect(live_gpo_timers.back(),SIGNAL(timeout()),mapper,SLOT(map()));
} }
} }
}
if(!live_gpo_initialized) { if(!live_gpo_initialized) {
live_socket->writeBlock("CFG GPO\r\n",9); live_socket->writeBlock("CFG GPO\r\n",9);
live_socket->writeBlock("ADD GPO\r\n",9); live_socket->writeBlock("ADD GPO\r\n",9);
@@ -638,46 +688,44 @@ void RDLiveWire::ReadVersion(const QString &cmd)
void RDLiveWire::ReadSources(const QString &cmd) void RDLiveWire::ReadSources(const QString &cmd)
{ {
// printf("SOURCES: %s\n",(const char *)cmd);
int ptr=0;
QString tag;
QString value;
RDLiveWireSource *src=new RDLiveWireSource();
QHostAddress addr; QHostAddress addr;
QStringList f1;
int offset=cmd.find(" "); RDLiveWireSource *src=new RDLiveWireSource();
src->setSlotNumber(cmd.left(offset).toInt()); QStringList f0=AString(cmd).split(" ","\"");
ptr=offset+1; src->setSlotNumber(f0[0].toInt());
while((ptr=ParseString(cmd,ptr,&tag,&value))>=0) { for(unsigned i=1;i<f0.size();i++) {
if(tag=="PSNM") { f1=f1.split(":",f0[i]);
src->setPrimaryName(value); if(f1.size()==2) {
if(f1[0]=="PSNM") {
src->setPrimaryName(f1[1]);
} }
if(tag=="LABL") { if(f1[0]=="LABL") {
src->setLabelName(value); src->setLabelName(f1[1]);
} }
if(tag=="FASM") { if(f1[0]=="FASM") {
// ???? // ????
} }
if(tag=="RTPE") { if(f1[0]=="RTPE") {
src->setRtpEnabled(value.toInt()); src->setRtpEnabled(f1[1].toInt());
} }
if(tag=="RTPA") { if(f1[0]=="RTPA") {
addr.setAddress(value); addr.setAddress(f1[1]);
src->setStreamAddress(addr); src->setStreamAddress(addr);
} }
if(tag=="INGN") { if(f1[0]=="INGN") {
src->setInputGain(value.toInt()); src->setInputGain(f1[1].toInt());
} }
if(tag=="SHAB") { if(f1[0]=="SHAB") {
src->setShareable(value.toInt()); src->setShareable(f1[1].toInt());
} }
if(tag=="NCHN") { if(f1[0]=="NCHN") {
src->setChannels(value.toInt()); src->setChannels(f1[1].toInt());
} }
if(tag=="RTPP") { if(f1[0]=="RTPP") {
// ???? // ????
} }
} }
}
emit sourceChanged(live_id,src); emit sourceChanged(live_id,src);
delete src; delete src;
} }
@@ -685,31 +733,30 @@ void RDLiveWire::ReadSources(const QString &cmd)
void RDLiveWire::ReadDestinations(const QString &cmd) void RDLiveWire::ReadDestinations(const QString &cmd)
{ {
int ptr=0;
QString tag;
QString value;
RDLiveWireDestination *dst=new RDLiveWireDestination();
QHostAddress addr; QHostAddress addr;
QStringList f1;
int offset=cmd.find(" "); RDLiveWireDestination *dst=new RDLiveWireDestination();
dst->setSlotNumber(cmd.left(offset).toInt()); QStringList f0=AString(cmd).split(" ","\"");
ptr=offset+1; dst->setSlotNumber(f0[0].toInt());
while((ptr=ParseString(cmd,ptr,&tag,&value))>=0) { for(unsigned i=1;i<f0.size();i++) {
if(tag=="NAME") { f1=f1.split(":",f0[i]);
dst->setPrimaryName(value); if(f1.size()==2) {
if(f1[0]=="NAME") {
dst->setPrimaryName(f1[1]);
} }
if(tag=="ADDR") { if(f1[0]=="ADDR") {
addr.setAddress(value); addr.setAddress(f1[1]);
dst->setStreamAddress(addr); dst->setStreamAddress(addr);
} }
if(tag=="NCHN") { if(f1[0]=="NCHN") {
dst->setChannels(value.toInt()); dst->setChannels(f1[1].toInt());
} }
if(tag=="LOAD") { if(f1[0]=="LOAD") {
dst->setLoad((RDLiveWireDestination::Load)value.toInt()); dst->setOutputGain((RDLiveWireDestination::Load)f1[1].toInt());
}
if(f1[0]=="OUGN") {
dst->setOutputGain(f1[1].toInt());
} }
if(tag=="OUGN") {
dst->setOutputGain(value.toInt());
} }
} }
emit destinationChanged(live_id,dst); emit destinationChanged(live_id,dst);
@@ -769,17 +816,16 @@ void RDLiveWire::ReadGpos(const QString &cmd)
void RDLiveWire::ReadGpioConfig(const QString &cmd) void RDLiveWire::ReadGpioConfig(const QString &cmd)
{ {
// printf("GpioConfig: %s\n",(const char *)cmd); QStringList f0;
int ptr=0; QStringList f1;
QString tag;
QString value; f0=AString(cmd).split(" ","\"");
int offset=cmd.find(" "); int slot=f0[0].toInt()-1;
int slot=cmd.left(offset).toInt()-1; for(unsigned i=1;i<f0.size();i++) {
QString str=cmd.right(cmd.length()-offset-1).lower(); f1=f1.split(":",f0[i]);
ptr=offset+1; if(f1.size()==2) {
while((ptr=ParseString(cmd,ptr,&tag,&value))>=0) { if(f1[0]=="SRCA") {
if(tag=="SRCA") { int chan=PruneUrl(f1[1]).toInt();
int chan=PruneUrl(value).toInt();
for(unsigned i=0;i<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;i++) { for(unsigned i=0;i<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;i++) {
live_gpi_channels[slot][i]=chan*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+i; live_gpi_channels[slot][i]=chan*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+i;
live_gpo_channels[slot][i]=chan*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+i; live_gpo_channels[slot][i]=chan*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+i;
@@ -788,55 +834,6 @@ void RDLiveWire::ReadGpioConfig(const QString &cmd)
} }
} }
} }
int RDLiveWire::ParseString(const QString &str,int ptr,
QString *tag,QString *value) const
{
int len=(int)str.length();
bool quote_mode=false;
if(ptr>=len) {
return -1;
}
*tag="";
*value="";
//
// Get Tag
//
for(int i=ptr;i<len;i++) {
if(str[i]==':') {
ptr=i+1;
i=len;
}
else {
(*tag)+=str[i];
}
}
//
// Get Value
//
for(int i=ptr;i<len;i++) {
if(str[i]=='\"') {
quote_mode=!quote_mode;
}
else {
if((str[i]==' ')&&(!quote_mode)) {
ptr=i+1;
return ptr;
}
else {
(*value)+=str[i];
}
}
if(i==(len-1)) {
ptr=i+1;
return ptr;
}
}
return ptr;
} }

View File

@@ -25,8 +25,10 @@
#include <vector> #include <vector>
#include <qstring.h>
#include <qobject.h> #include <qobject.h>
#include <qsocket.h> #include <qsocket.h>
#include <qstringlist.h>
#include <qtimer.h> #include <qtimer.h>
#include <rd.h> #include <rd.h>
@@ -38,6 +40,16 @@
#define RDLIVEWIRE_RECONNECT_MIN_INTERVAL 5000 #define RDLIVEWIRE_RECONNECT_MIN_INTERVAL 5000
#define RDLIVEWIRE_RECONNECT_MAX_INTERVAL 30000 #define RDLIVEWIRE_RECONNECT_MAX_INTERVAL 30000
class AString : public QString
{
public:
AString();
AString(const AString &lhs);
AString(const QString &lhs);
QStringList split(const QString &sep,const QString &esc="") const;
};
class RDLiveWire : public QObject class RDLiveWire : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -98,8 +110,6 @@ class RDLiveWire : public QObject
void ReadGpis(const QString &cmd); void ReadGpis(const QString &cmd);
void ReadGpos(const QString &cmd); void ReadGpos(const QString &cmd);
void ReadGpioConfig(const QString &cmd); void ReadGpioConfig(const QString &cmd);
int ParseString(const QString &str,int ptr,QString *tag,
QString *value) const;
QString PruneUrl(const QString &str); QString PruneUrl(const QString &str);
void ResetConnection(); void ResetConnection();
int GetHoldoff(); int GetHoldoff();

View File

@@ -20,6 +20,8 @@
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// //
#include <stdio.h>
#include <rd.h> #include <rd.h>
#include <rdlivewiresource.h> #include <rdlivewiresource.h>

View File

@@ -193,7 +193,7 @@ ViewNodeInfo::ViewNodeInfo(QWidget *parent,const char *name)
view_sources_view->setColumnAlignment(1,Qt::AlignCenter); view_sources_view->setColumnAlignment(1,Qt::AlignCenter);
view_sources_view->addColumn(tr("NAME")); view_sources_view->addColumn(tr("NAME"));
view_sources_view->setColumnAlignment(2,Qt::AlignLeft); view_sources_view->setColumnAlignment(2,Qt::AlignLeft);
view_sources_view->addColumn(tr("STREAMING")); view_sources_view->addColumn(tr("ACTIVE"));
view_sources_view->setColumnAlignment(3,Qt::AlignCenter); view_sources_view->setColumnAlignment(3,Qt::AlignCenter);
view_sources_view->addColumn(tr("SHAREABLE")); view_sources_view->addColumn(tr("SHAREABLE"));
view_sources_view->setColumnAlignment(4,Qt::AlignCenter); view_sources_view->setColumnAlignment(4,Qt::AlignCenter);
@@ -217,6 +217,7 @@ ViewNodeInfo::ViewNodeInfo(QWidget *parent,const char *name)
view_destinations_view->setItemMargin(5); view_destinations_view->setItemMargin(5);
view_destinations_view->addColumn(tr("#")); view_destinations_view->addColumn(tr("#"));
view_destinations_view->setColumnAlignment(0,Qt::AlignCenter); view_destinations_view->setColumnAlignment(0,Qt::AlignCenter);
view_destinations_view->setColumnSortType(0,RDListView::LineSort);
view_destinations_view->addColumn(tr("CHAN")); view_destinations_view->addColumn(tr("CHAN"));
view_destinations_view->setColumnAlignment(1,Qt::AlignCenter); view_destinations_view->setColumnAlignment(1,Qt::AlignCenter);
view_destinations_view->addColumn(tr("NAME")); view_destinations_view->addColumn(tr("NAME"));
@@ -326,7 +327,7 @@ void ViewNodeInfo::closeData()
void ViewNodeInfo::WriteSourceItem(RDLiveWireSource *src,RDListViewItem *item) void ViewNodeInfo::WriteSourceItem(RDLiveWireSource *src,RDListViewItem *item)
{ {
item->setLine(src->slotNumber());
item->setText(1,QString().sprintf("%05d",src->channelNumber())); item->setText(1,QString().sprintf("%05d",src->channelNumber()));
item->setText(2,src->primaryName()); item->setText(2,src->primaryName());
if(src->rtpEnabled()) { if(src->rtpEnabled()) {
@@ -349,6 +350,7 @@ void ViewNodeInfo::WriteSourceItem(RDLiveWireSource *src,RDListViewItem *item)
void ViewNodeInfo::WriteDestinationItem(RDLiveWireDestination *dst, void ViewNodeInfo::WriteDestinationItem(RDLiveWireDestination *dst,
RDListViewItem *item) RDListViewItem *item)
{ {
item->setLine(dst->slotNumber());
item-> item->
setText(1,QString().sprintf("%05u",view_base_output+dst->slotNumber()-1)); setText(1,QString().sprintf("%05u",view_base_output+dst->slotNumber()-1));
item->setText(2,dst->primaryName()); item->setText(2,dst->primaryName());