2023-09-15 Fred Gleason <fredg@paravelsystems.com>

* Added a 'Set Timeout' ['TO'] CAE command.
	* Added a 'Touch' ['TH'] CAE command.

Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
Fred Gleason
2023-09-15 11:52:18 -04:00
parent c8e6dd62e8
commit c6b18468f1
11 changed files with 565 additions and 586 deletions

View File

@@ -24421,3 +24421,6 @@
* Implemented the modified 'Set Audio Passthrough Level' ['AL'] CAE * Implemented the modified 'Set Audio Passthrough Level' ['AL'] CAE
command. command.
* Implemented the new 'Update Audio Ports' ['AP'] CAE command. * Implemented the new 'Update Audio Ports' ['AP'] CAE command.
2023-09-15 Fred Gleason <fredg@paravelsystems.com>
* Added a 'Set Timeout' ['TO'] CAE command.
* Added a 'Touch' ['TH'] CAE command.

View File

@@ -1,4 +1,4 @@
## automake.am ## Makefile.am
## ##
## Core Audio Engine Makefile.am for Rivendell ## Core Audio Engine Makefile.am for Rivendell
## ##
@@ -31,6 +31,7 @@ sbin_PROGRAMS = caed
dist_caed_SOURCES = cae.cpp cae.h\ dist_caed_SOURCES = cae.cpp cae.h\
cae_server.cpp cae_server.h\ cae_server.cpp cae_server.h\
connection.cpp connection.h\
driver.cpp driver.h\ driver.cpp driver.h\
driver_alsa.cpp driver_alsa.h\ driver_alsa.cpp driver_alsa.h\
driver_hpi.cpp driver_hpi.h\ driver_hpi.cpp driver_hpi.h\
@@ -39,6 +40,7 @@ dist_caed_SOURCES = cae.cpp cae.h\
nodist_caed_SOURCES = moc_cae.cpp\ nodist_caed_SOURCES = moc_cae.cpp\
moc_cae_server.cpp\ moc_cae_server.cpp\
moc_connection.cpp\
moc_driver.cpp\ moc_driver.cpp\
moc_driver_alsa.cpp\ moc_driver_alsa.cpp\
moc_driver_hpi.cpp\ moc_driver_hpi.cpp\

View File

@@ -145,12 +145,14 @@ MainObject::MainObject(QObject *parent)
// Server Front End // Server Front End
// //
cae_server=new CaeServer(this); cae_server=new CaeServer(this);
if(!cae_server->listen(QHostAddress::Any,CAED_TCP_PORT)) { if(!cae_server->bind(QHostAddress::Any,CAED_TCP_PORT)) {
rda->syslog(LOG_ERR,"caed: failed to bind port %d",CAED_TCP_PORT); rda->syslog(LOG_ERR,"caed: failed to bind port %d",CAED_TCP_PORT);
exit(1); exit(1);
} }
connect(cae_server,SIGNAL(connectionDropped(int)), // connect(cae_server,SIGNAL(connectionDropped(int)),
this,SLOT(connectionDroppedData(int))); // this,SLOT(connectionDroppedData(int)));
connect(cae_server,SIGNAL(connectionClosed(const SessionId &)),
this,SLOT(connectionClosedData(const SessionId &)));
connect(cae_server,SIGNAL(playPositionReq(const SessionId &,int)), connect(cae_server,SIGNAL(playPositionReq(const SessionId &,int)),
this,SLOT(playPositionData(const SessionId &,int))); this,SLOT(playPositionData(const SessionId &,int)));
connect(cae_server,SIGNAL(startPlaybackReq(const SessionId &,const QString &, connect(cae_server,SIGNAL(startPlaybackReq(const SessionId &,const QString &,
@@ -159,7 +161,6 @@ MainObject::MainObject(QObject *parent)
unsigned,unsigned,int,int,int))); unsigned,unsigned,int,int,int)));
connect(cae_server,SIGNAL(playStopReq(const SessionId &)), connect(cae_server,SIGNAL(playStopReq(const SessionId &)),
this,SLOT(stopPlaybackData(const SessionId &))); this,SLOT(stopPlaybackData(const SessionId &)));
/*
connect(cae_server,SIGNAL(loadPlaybackReq(int,unsigned,const QString &)), connect(cae_server,SIGNAL(loadPlaybackReq(int,unsigned,const QString &)),
this,SLOT(loadPlaybackData(int,unsigned,const QString &))); this,SLOT(loadPlaybackData(int,unsigned,const QString &)));
connect(cae_server,SIGNAL(unloadPlaybackReq(int,unsigned)), connect(cae_server,SIGNAL(unloadPlaybackReq(int,unsigned)),
@@ -198,6 +199,7 @@ MainObject::MainObject(QObject *parent)
unsigned,int,unsigned)), unsigned,int,unsigned)),
this,SLOT(fadeOutputVolumeData(int,unsigned,unsigned, this,SLOT(fadeOutputVolumeData(int,unsigned,unsigned,
unsigned,int,unsigned))); unsigned,int,unsigned)));
/*
connect(cae_server,SIGNAL(setInputLevelReq(int,unsigned,unsigned,int)), connect(cae_server,SIGNAL(setInputLevelReq(int,unsigned,unsigned,int)),
this,SLOT(setInputLevelData(int,unsigned,unsigned,int))); this,SLOT(setInputLevelData(int,unsigned,unsigned,int)));
connect(cae_server,SIGNAL(setOutputLevelReq(int,unsigned,unsigned,int)), connect(cae_server,SIGNAL(setOutputLevelReq(int,unsigned,unsigned,int)),
@@ -236,11 +238,11 @@ MainObject::MainObject(QObject *parent)
this, this,
SLOT(openRtpCaptureChannelData(int,unsigned,unsigned,uint16_t, SLOT(openRtpCaptureChannelData(int,unsigned,unsigned,uint16_t,
unsigned,unsigned))); unsigned,unsigned)));
*/
connect(cae_server,SIGNAL(meterEnableReq(const QHostAddress &,uint16_t, connect(cae_server,SIGNAL(meterEnableReq(const QHostAddress &,uint16_t,
const QList<unsigned> &)), const QList<unsigned> &)),
this,SLOT(meterEnableData(const QHostAddress &,uint16_t, this,SLOT(meterEnableData(const QHostAddress &,uint16_t,
const QList<unsigned> &))); const QList<unsigned> &)));
*/
signal(SIGHUP,SigHandler); signal(SIGHUP,SigHandler);
signal(SIGINT,SigHandler); signal(SIGINT,SigHandler);
signal(SIGTERM,SigHandler); signal(SIGTERM,SigHandler);
@@ -412,7 +414,7 @@ void MainObject::startPlaybackData(const SessionId &sid,const QString &cutname,
sess->setStartPosition(start_pos); sess->setStartPosition(start_pos);
sess->setEndPosition(end_pos); sess->setEndPosition(end_pos);
sess->setSpeed(speed); sess->setSpeed(speed);
cae_sessions[sid]=sess; cae_play_sessions[sid]=sess;
rda->syslog(LOG_DEBUG,"playback started - session: %s card: %d port: %d stream: %d filename: %s", rda->syslog(LOG_DEBUG,"playback started - session: %s card: %d port: %d stream: %d filename: %s",
sid.dump().toUtf8().constData(),cardnum,portnum,streamnum, sid.dump().toUtf8().constData(),cardnum,portnum,streamnum,
@@ -428,7 +430,7 @@ void MainObject::playPositionData(const SessionId &sid,int position)
// //
// Find the session // Find the session
// //
if((sess=cae_sessions.value(sid))==NULL) { if((sess=cae_play_sessions.value(sid))==NULL) {
rda->syslog(LOG_WARNING, rda->syslog(LOG_WARNING,
"attempting to position non-existent session - session: %s", "attempting to position non-existent session - session: %s",
sid.dump().toUtf8().constData()); sid.dump().toUtf8().constData());
@@ -449,8 +451,7 @@ void MainObject::playPositionData(const SessionId &sid,int position)
sid.dump().toUtf8().constData(),position); sid.dump().toUtf8().constData(),position);
return; return;
} }
cae_server->sendCommand(sid,QString::asprintf("PP %d %d %d", cae_server->sendCommand(sid,QString::asprintf("PP %d %d",
sid.processId(),
sid.serialNumber(), sid.serialNumber(),
position)); position));
rda->syslog(LOG_DEBUG,"play position succeeded - session: %s position: %d", rda->syslog(LOG_DEBUG,"play position succeeded - session: %s position: %d",
@@ -460,45 +461,23 @@ void MainObject::playPositionData(const SessionId &sid,int position)
void MainObject::stopPlaybackData(const SessionId &sid) void MainObject::stopPlaybackData(const SessionId &sid)
{ {
//
// Maintainer's Note:
// *Do not* call this from an iterator! Use StopPlayout() instead.
//
Session *sess=NULL; Session *sess=NULL;
Driver *dvr=NULL;
// //
// Find the session // Find the session
// //
if((sess=cae_sessions.value(sid))==NULL) { if((sess=cae_play_sessions.value(sid))==NULL) {
rda->syslog(LOG_WARNING, rda->syslog(LOG_WARNING,
"attempting to stop playing non-existent session - session: %s", "attempting to stop playing non-existent session - session: %s",
sid.dump().toUtf8().constData()); sid.dump().toUtf8().constData());
return; return;
} }
// StopPlayout(sess);
// Find the card
//
if((dvr=GetDriver(sess->cardNumber()))==NULL) {
rda->syslog(LOG_WARNING,"no such card - session: %s card: %d",
sid.dump().toUtf8().constData(),sess->cardNumber());
return;
}
//
// Stop Transport
//
if(!dvr->stopPlayback(sess->cardNumber(),sess->streamNumber())) {
rda->syslog(LOG_WARNING,
"stop playback failed - session: %s",
sid.dump().toUtf8().constData());
}
//
// Unload
//
if(!dvr->unloadPlayback(sess->cardNumber(),sess->streamNumber())) {
rda->syslog(LOG_WARNING,
"unload playback failed - session: %s",
sid.dump().toUtf8().constData());
}
// //
// Delete session // Delete session
@@ -506,7 +485,7 @@ void MainObject::stopPlaybackData(const SessionId &sid)
QString msg=QString::asprintf("stopped playback - session: %s", QString msg=QString::asprintf("stopped playback - session: %s",
sid.dump().toUtf8().constData()); sid.dump().toUtf8().constData());
delete sess; delete sess;
cae_sessions.remove(sid); cae_play_sessions.remove(sid);
rda->syslog(LOG_DEBUG,"%s",msg.toUtf8().constData()); rda->syslog(LOG_DEBUG,"%s",msg.toUtf8().constData());
} }
@@ -1263,19 +1242,14 @@ void MainObject::openRtpCaptureChannelData(int id,unsigned card,unsigned port,
{ {
} }
/*
void MainObject::meterEnableData(const QHostAddress &addr,uint16_t udp_port, void MainObject::meterEnableData(const QHostAddress &addr,uint16_t udp_port,
const QList<unsigned> &cards) const QList<unsigned> &cards)
{ {
/*
QString cmd=QString::asprintf("ME %u",0xFFFF&udp_port); QString cmd=QString::asprintf("ME %u",0xFFFF&udp_port);
for(int i=0;i<cards.size();i++) { for(int i=0;i<cards.size();i++) {
cmd+=QString::asprintf(" %u",cards.at(i)); cmd+=QString::asprintf(" %u",cards.at(i));
} }
if((udp_port<0)||(udp_port>0xFFFF)) {
cae_server->sendCommand(id,cmd+" -!");
return;
}
cae_server->setMeterPort(id,udp_port); cae_server->setMeterPort(id,udp_port);
for(int i=0;i<cards.size();i++) { for(int i=0;i<cards.size();i++) {
if((cards.at(i)<0)||(cards.at(i)>=RD_MAX_CARDS)) { if((cards.at(i)<0)||(cards.at(i)>=RD_MAX_CARDS)) {
@@ -1285,31 +1259,55 @@ void MainObject::meterEnableData(const QHostAddress &addr,uint16_t udp_port,
cae_server->setMetersEnabled(id,cards.at(i),true); cae_server->setMetersEnabled(id,cards.at(i),true);
} }
cae_server->sendCommand(id,cmd+" +!"); // cae_server->sendCommand(id,cmd+" +!");
SendMeterOutputStatusUpdate(); SendMeterOutputStatusUpdate();
*/
} }
*/
/*
void MainObject::connectionDroppedData(int id) void MainObject::connectionDroppedData(int id)
{ {
KillSocket(id); KillSocket(id);
} }
*/
void MainObject::connectionClosedData(const SessionId &sid)
{
rda->syslog(LOG_DEBUG,"cleaning up sessions from %s",
sid.dump().toUtf8().constData());
//
// Clean up active play sessions
//
QMutableMapIterator<SessionId,Session *> it(cae_play_sessions);
while(it.hasNext()) {
it.next();
if(it.key().belongsTo(sid)) {
StopPlayout(it.value());
delete it.value();
it.remove();
}
}
//
// Clean up active record sessions
//
// FIXME: Implement this!
}
void MainObject::statePlayUpdate(int card,int stream,int state) void MainObject::statePlayUpdate(int card,int stream,int state)
{ {
if(state==0) { // Stopped if(state==0) { // Stopped
for(QMap<SessionId,Session *>::iterator it=cae_sessions.begin(); for(QMap<SessionId,Session *>::iterator it=cae_play_sessions.begin();
it!=cae_sessions.end();it++) { it!=cae_play_sessions.end();it++) {
if((it.value()->cardNumber()==card)&& if((it.value()->cardNumber()==card)&&
(it.value()->streamNumber()==stream)) { (it.value()->streamNumber()==stream)) {
cae_server-> cae_server->
sendCommand(it.key(),QString::asprintf("SP %d %d", sendCommand(it.key(),QString::asprintf("SP %d",
it.key().processId(),
it.key().serialNumber())); it.key().serialNumber()));
delete it.value(); delete it.value();
cae_sessions.remove(it.key()); cae_play_sessions.remove(it.key());
return; return;
} }
} }
@@ -1431,6 +1429,40 @@ void MainObject::updateMeters()
} }
void MainObject::StopPlayout(Session *sess)
{
Driver *dvr=NULL;
//
// Find the card
//
if((dvr=GetDriver(sess->cardNumber()))==NULL) {
rda->syslog(LOG_WARNING,"no such card - session: %s card: %d",
sess->sessionId().dump().toUtf8().constData(),
sess->cardNumber());
return;
}
//
// Stop Transport
//
if(!dvr->stopPlayback(sess->cardNumber(),sess->streamNumber())) {
rda->syslog(LOG_WARNING,
"stop playback failed - session: %s",
sess->sessionId().dump().toUtf8().constData());
}
//
// Unload
//
if(!dvr->unloadPlayback(sess->cardNumber(),sess->streamNumber())) {
rda->syslog(LOG_WARNING,
"unload playback failed - session: %s",
sess->sessionId().dump().toUtf8().constData());
}
}
void MainObject::InitProvisioning() const void MainObject::InitProvisioning() const
{ {
QString sql; QString sql;
@@ -1513,7 +1545,7 @@ void MainObject::InitMixers()
} }
} }
/*
void MainObject::KillSocket(int ch) void MainObject::KillSocket(int ch)
{ {
for(int i=0;i<RD_MAX_CARDS;i++) { for(int i=0;i<RD_MAX_CARDS;i++) {
@@ -1556,7 +1588,7 @@ void MainObject::KillSocket(int ch)
} }
} }
} }
*/
pid_t MainObject::GetPid(QString pidfile) pid_t MainObject::GetPid(QString pidfile)
{ {
@@ -1832,15 +1864,15 @@ void MainObject::FreeMadDecoder(int card,int stream)
void MainObject::SendMeterLevelUpdate(const QString &type,int cardnum, void MainObject::SendMeterLevelUpdate(const QString &type,int cardnum,
int portnum,short levels[]) int portnum,short levels[])
{ {
QList<int> ids=cae_server->connectionIds(); for(QMap<SessionId,Session *>::const_iterator it=cae_play_sessions.begin();
it!=cae_play_sessions.end();it++) {
for(int l=0;l<ids.size();l++) { if((it.value()->cardNumber()==cardnum)&&(it.value()->meterPort()>0)&&
if((cae_server->meterPort(ids.at(l))>0)&& (it.value()->metersEnabled())) {
cae_server->metersEnabled(ids.at(l),cardnum)) {
SendMeterUpdate(QString::asprintf("ML %s %d %d %d %d", SendMeterUpdate(QString::asprintf("ML %s %d %d %d %d",
type.toUtf8().constData(), type.toUtf8().constData(),
cardnum,portnum,levels[0],levels[1]), cardnum,portnum,levels[0],levels[1]),
ids.at(l)); it.value());
} }
} }
} }
@@ -1849,13 +1881,13 @@ void MainObject::SendMeterLevelUpdate(const QString &type,int cardnum,
void MainObject::SendStreamMeterLevelUpdate(int cardnum,int streamnum, void MainObject::SendStreamMeterLevelUpdate(int cardnum,int streamnum,
short levels[]) short levels[])
{ {
QList<int> ids=cae_server->connectionIds(); for(QMap<SessionId,Session *>::const_iterator it=cae_play_sessions.begin();
it!=cae_play_sessions.end();it++) {
for(int l=0;l<ids.size();l++) { if((it.value()->cardNumber()==cardnum)&&(it.value()->meterPort()>0)&&
if((cae_server->meterPort(ids.at(l))>0)&& (it.value()->metersEnabled())) {
cae_server->metersEnabled(ids.at(l),cardnum)) {
SendMeterUpdate(QString::asprintf("MO %d %d %d %d", SendMeterUpdate(QString::asprintf("MO %d %d %d %d",
cardnum,streamnum,levels[0],levels[1]),ids.at(l)); cardnum,streamnum,levels[0],levels[1]),
it.value());
} }
} }
} }
@@ -1863,14 +1895,13 @@ void MainObject::SendStreamMeterLevelUpdate(int cardnum,int streamnum,
void MainObject::SendMeterPositionUpdate(int cardnum,unsigned pos[]) void MainObject::SendMeterPositionUpdate(int cardnum,unsigned pos[])
{ {
QList<int> ids=cae_server->connectionIds();
for(unsigned k=0;k<RD_MAX_STREAMS;k++) { for(unsigned k=0;k<RD_MAX_STREAMS;k++) {
for(int l=0;l<ids.size();l++) { for(QMap<SessionId,Session *>::const_iterator it=cae_play_sessions.begin();
if((cae_server->meterPort(ids.at(l))>0)&& it!=cae_play_sessions.end();it++) {
cae_server->metersEnabled(ids.at(l),cardnum)) { if((it.value()->cardNumber()==cardnum)&&(it.value()->meterPort()>0)&&
(it.value()->metersEnabled())) {
SendMeterUpdate(QString::asprintf("MP %d %d %d",cardnum,k,pos[k]), SendMeterUpdate(QString::asprintf("MP %d %d %d",cardnum,k,pos[k]),
ids.at(l)); it.value());
} }
} }
} }
@@ -1879,17 +1910,17 @@ void MainObject::SendMeterPositionUpdate(int cardnum,unsigned pos[])
void MainObject::SendMeterOutputStatusUpdate() void MainObject::SendMeterOutputStatusUpdate()
{ {
QList<int> ids=cae_server->connectionIds(); for(int i=0;i<RD_MAX_CARDS;i++) {
for(unsigned i=0;i<RD_MAX_CARDS;i++) {
if(GetDriver(i)!=NULL) { if(GetDriver(i)!=NULL) {
for(unsigned j=0;j<RD_MAX_PORTS;j++) { for(unsigned j=0;j<RD_MAX_PORTS;j++) {
for(unsigned k=0;k<RD_MAX_STREAMS;k++) { for(unsigned k=0;k<RD_MAX_STREAMS;k++) {
for(int l=0;l<ids.size();l++) { for(QMap<SessionId,Session *>::const_iterator it=cae_play_sessions.begin();
if((cae_server->meterPort(ids.at(l))>0)&& it!=cae_play_sessions.end();it++) {
cae_server->metersEnabled(ids.at(l),i)) { if((it.value()->cardNumber()==i)&&
(it.value()->meterPort()>0)&&(it.value()->metersEnabled())) {
SendMeterUpdate(QString::asprintf("MS %d %d %d %d",i,j,k, SendMeterUpdate(QString::asprintf("MS %d %d %d %d",i,j,k,
output_status_flag[i][j][k]),ids.at(l)); output_status_flag[i][j][k]),
it.value());
} }
} }
} }
@@ -1901,21 +1932,22 @@ void MainObject::SendMeterOutputStatusUpdate()
void MainObject::SendMeterOutputStatusUpdate(int card,int port,int stream) void MainObject::SendMeterOutputStatusUpdate(int card,int port,int stream)
{ {
QList<int> ids=cae_server->connectionIds(); for(QMap<SessionId,Session *>::const_iterator it=cae_play_sessions.begin();
it!=cae_play_sessions.end();it++) {
for(int l=0;l<ids.size();l++) { if((it.value()->streamNumber()==stream)&&(it.value()->meterPort()>0)&&
if((cae_server->meterPort(ids.at(l))>0)&& (it.value()->metersEnabled())) {
cae_server->metersEnabled(ids.at(l),card)) {
SendMeterUpdate(QString::asprintf("MS %d %d %d %d",card,port,stream, SendMeterUpdate(QString::asprintf("MS %d %d %d %d",card,port,stream,
output_status_flag[card][port][stream]),ids.at(l)); output_status_flag[card][port][stream]),
it.value());
} }
} }
} }
void MainObject::SendMeterUpdate(const QString &msg,int conn_id)
void MainObject::SendMeterUpdate(const QString &msg,Session *sess)
{ {
meter_socket->writeDatagram(msg.toUtf8(),cae_server->peerAddress(conn_id), meter_socket->writeDatagram(msg.toUtf8(),sess->sessionId().address(),
cae_server->meterPort(conn_id)); sess->meterPort());
} }

View File

@@ -47,8 +47,8 @@
#include <rdconfig.h> #include <rdconfig.h>
#include <rdstation.h> #include <rdstation.h>
#include "driver.h"
#include "cae_server.h" #include "cae_server.h"
#include "driver.h"
#ifndef HAVE_SRC_CONV #ifndef HAVE_SRC_CONV
void src_int_to_float_array (const int *in, float *out, int len); void src_int_to_float_array (const int *in, float *out, int len);
@@ -123,17 +123,20 @@ class MainObject : public QObject
void openRtpCaptureChannelData(int id,unsigned card,unsigned port, void openRtpCaptureChannelData(int id,unsigned card,unsigned port,
uint16_t udp_port,unsigned samprate, uint16_t udp_port,unsigned samprate,
unsigned chans); unsigned chans);
void meterEnableData(const QHostAddress &addr,uint16_t udp_port, // void meterEnableData(const QHostAddress &addr,uint16_t udp_port,
const QList<unsigned> &cards); // const QList<unsigned> &cards);
void statePlayUpdate(int card,int stream,int state); void statePlayUpdate(int card,int stream,int state);
void stateRecordUpdate(int card,int stream,int state); void stateRecordUpdate(int card,int stream,int state);
void updateMeters(); void updateMeters();
void connectionDroppedData(int id); // void connectionDroppedData(int id);
void connectionClosedData(const SessionId &sid);
private: private:
void StopPlayout(Session *sess);
void InitProvisioning() const; void InitProvisioning() const;
void InitMixers(); void InitMixers();
void KillSocket(int); // void KillSocket(int);
bool CheckDaemon(QString); bool CheckDaemon(QString);
pid_t GetPid(QString pidfile); pid_t GetPid(QString pidfile);
int GetNextHandle(); int GetNextHandle();
@@ -146,7 +149,8 @@ class MainObject : public QObject
void SendMeterPositionUpdate(int cardnum,unsigned pos[]); void SendMeterPositionUpdate(int cardnum,unsigned pos[]);
void SendMeterOutputStatusUpdate(); void SendMeterOutputStatusUpdate();
void SendMeterOutputStatusUpdate(int card,int port,int stream); void SendMeterOutputStatusUpdate(int card,int port,int stream);
void SendMeterUpdate(const QString &msg,int conn_id); // void SendMeterUpdate(const QString &msg,int conn_id);
void SendMeterUpdate(const QString &msg,Session *sess);
Driver *GetDriver(unsigned card) const; Driver *GetDriver(unsigned card) const;
void MakeDriver(unsigned *next_card,RDStation::AudioDriver type); void MakeDriver(unsigned *next_card,RDStation::AudioDriver type);
QList<Driver *> d_drivers; QList<Driver *> d_drivers;
@@ -171,7 +175,7 @@ class MainObject : public QObject
} play_handle[256]; } play_handle[256];
int next_play_handle; int next_play_handle;
QMap<SessionId,Session *> cae_sessions; QMap<SessionId,Session *> cae_play_sessions;
private: private:
bool CheckLame(); bool CheckLame();

View File

@@ -42,60 +42,7 @@ CaeServer::CaeServer(QObject *parent)
} }
QList<int> CaeServer::connectionIds() const bool CaeServer::bind(const QHostAddress &addr,uint16_t port)
{
QList<int> ret;
/*
for(QMap<int,CaeServerConnection *>::const_iterator it=
cae_connections.begin();it!=cae_connections.end();it++) {
ret.push_back(it.key());
}
*/
return ret;
}
QHostAddress CaeServer::peerAddress(int id) const
{
// return cae_connections[id]->socket->peerAddress();
return QHostAddress();
}
uint16_t CaeServer::peerPort(int id) const
{
// return cae_connections[id]->socket->peerPort();
return 0;
}
uint16_t CaeServer::meterPort(int id) const
{
// return cae_connections[id]->meter_port;
return 0;
}
void CaeServer::setMeterPort(int id,uint16_t port)
{
// cae_connections[id]->meter_port=port;
}
bool CaeServer::metersEnabled(int id,unsigned card) const
{
// return cae_connections[id]->meters_enabled[card];
return false;
}
void CaeServer::setMetersEnabled(int id,unsigned card,bool state)
{
// cae_connections[id]->meters_enabled[card]=state;
}
bool CaeServer::listen(const QHostAddress &addr,uint16_t port)
{ {
return d_server_socket->bind(port); return d_server_socket->bind(port);
} }
@@ -124,26 +71,6 @@ void CaeServer::sendCommand(const SessionId &dest,const QString &cmd)
} }
void CaeServer::newConnectionData()
{/*
QTcpSocket *sock=cae_server->nextPendingConnection();
cae_connection_closed_mapper->setMapping(sock,sock->socketDescriptor());
connect(sock,SIGNAL(disconnected()),cae_connection_closed_mapper,SLOT(map()));
cae_ready_read_mapper->setMapping(sock,sock->socketDescriptor());
connect(sock,SIGNAL(readyRead()),cae_ready_read_mapper,SLOT(map()));
cae_connections[sock->socketDescriptor()]=new CaeServerConnection(sock);
RDApplication::syslog(cae_config,LOG_DEBUG,
"added connection %d [%s:%u]",sock->socketDescriptor(),
sock->peerAddress().toString().toUtf8().constData(),
0xFFFF&sock->peerPort());
*/
}
void CaeServer::readyReadData() void CaeServer::readyReadData()
{ {
QNetworkDatagram dgram=d_server_socket->receiveDatagram(1500); QNetworkDatagram dgram=d_server_socket->receiveDatagram(1500);
@@ -152,9 +79,20 @@ void CaeServer::readyReadData()
} }
void CaeServer::connectionExpiredData(const SessionId &sid)
{
Connection *conn=cae_connections.value(sid);
if(conn!=NULL) {
conn->deleteLater();
cae_connections.remove(sid);
emit connectionClosed(sid);
}
}
/*
void CaeServer::connectionClosedData(int id) void CaeServer::connectionClosedData(int id)
{ {
/*
QString logmsg= QString logmsg=
QString::asprintf("removed connection %d [%s:%u]", QString::asprintf("removed connection %d [%s:%u]",
id, id,
@@ -175,9 +113,8 @@ void CaeServer::connectionClosedData(int id)
cae_connections.remove(id); cae_connections.remove(id);
RDApplication::syslog(cae_config,priority,"%s",logmsg.toUtf8().constData()); RDApplication::syslog(cae_config,priority,"%s",logmsg.toUtf8().constData());
*/
} }
*/
bool CaeServer::ProcessCommand(const QHostAddress &src_addr,uint16_t src_port, bool CaeServer::ProcessCommand(const QHostAddress &src_addr,uint16_t src_port,
const QString &cmd) const QString &cmd)
@@ -185,7 +122,6 @@ bool CaeServer::ProcessCommand(const QHostAddress &src_addr,uint16_t src_port,
bool was_processed=false; bool was_processed=false;
bool ok=false; bool ok=false;
QStringList f0=cmd.split(" ",QString::SkipEmptyParts); QStringList f0=cmd.split(" ",QString::SkipEmptyParts);
pid_t pid;
unsigned serial; unsigned serial;
QString cutname; QString cutname;
unsigned cardnum; unsigned cardnum;
@@ -200,34 +136,61 @@ bool CaeServer::ProcessCommand(const QHostAddress &src_addr,uint16_t src_port,
int coding; int coding;
int channels; int channels;
int bitrate; int bitrate;
int interval;
SessionId origin(src_addr,src_port); SessionId origin(src_addr,src_port);
//
// Connection Management
//
if((f0.at(0)=="TO")&&(f0.size()==2)) { // Set Timeout
interval=f0.at(1).toInt(&ok);
if(ok&&(interval>=0)) {
Connection *conn=cae_connections.value(origin);
if(conn==NULL) {
conn=new Connection(origin,this);
connect(conn,SIGNAL(connectionExpired(const SessionId &)),
this,SLOT(connectionExpiredData(const SessionId &)));
cae_connections[origin]=conn;
}
conn->setTimeout(interval);
was_processed=true;
}
}
if((f0.at(0)=="TH")&&(f0.size()==1)) { // Touch
Connection *conn=cae_connections.value(origin);
if(conn==NULL) {
rda->syslog(LOG_WARNING,"%s attempted to touch non-existent connection",
origin.dump().toUtf8().constData());
}
else {
conn->touch();
}
was_processed=true;
}
// //
// Playback Operations // Playback Operations
// //
if((f0.at(0)=="PY")&&(f0.size()==9)) { // Start Playback if((f0.at(0)=="PY")&&(f0.size()==8)) { // Start Playback
pid=f0.at(1).toUInt(&ok); serial=f0.at(1).toUInt(&ok);
if(ok&&(pid>0)) { if(ok) {
origin.setProcessId(pid); origin.setSerialNumber(serial);
serial=f0.at(2).toUInt(&ok); cutname=f0.at(2);
if(ok) { if(cutname.length()==10) {
origin.setSerialNumber(serial); cardnum=f0.at(3).toUInt(&ok);
cutname=f0.at(3); if(ok&&(cardnum<RD_MAX_CARDS)) {
if(cutname.length()==10) { portnum=f0.at(4).toInt(&ok);
cardnum=f0.at(4).toUInt(&ok); if(ok&&(portnum<RD_MAX_PORTS)) {
if(ok&&(cardnum<RD_MAX_CARDS)) { start_pos=f0.at(5).toInt(&ok);
portnum=f0.at(5).toInt(&ok); if(ok&&(start_pos>=0)) {
if(ok&&(portnum<RD_MAX_PORTS)) { end_pos=f0.at(6).toInt(&ok);
start_pos=f0.at(6).toInt(&ok); if(ok&&(end_pos>=0)&&(end_pos>=start_pos)) {
if(ok&&(start_pos>=0)) { speed=f0.at(7).toInt(&ok);
end_pos=f0.at(7).toInt(&ok); if(ok&&(speed>0)) {
if(ok&&(end_pos>=0)&&(end_pos>=start_pos)) { emit startPlaybackReq(origin,cutname,cardnum,portnum,
speed=f0.at(8).toInt(&ok); start_pos,end_pos,speed);
if(ok&&(speed>0)) { was_processed=true;
emit startPlaybackReq(origin,cutname,cardnum,portnum,
start_pos,end_pos,speed);
was_processed=true;
}
} }
} }
} }
@@ -237,122 +200,94 @@ bool CaeServer::ProcessCommand(const QHostAddress &src_addr,uint16_t src_port,
} }
} }
if((f0.at(0)=="PP")&&(f0.size()==4)) { // Play Position if((f0.at(0)=="PP")&&(f0.size()==3)) { // Play Position
pid=f0.at(1).toUInt(&ok); serial=f0.at(1).toUInt(&ok);
if(ok&&(pid>0)) { if(ok) {
origin.setProcessId(pid); origin.setSerialNumber(serial);
serial=f0.at(2).toUInt(&ok); position=f0.at(2).toInt(&ok);
if(ok&&(position>=0)) {
emit playPositionReq(origin,position);
was_processed=true;
}
}
}
if((f0.at(0)=="PE")&&(f0.size()==2)) { // Pause Playback
serial=f0.at(1).toUInt(&ok);
if(ok) {
origin.setSerialNumber(serial);
emit playPauseReq(origin);
was_processed=true;
}
}
if((f0.at(0)=="PR")&&(f0.size()==2)) { // Resume Playback
serial=f0.at(1).toUInt(&ok);
if(ok) {
origin.setSerialNumber(serial);
emit playResumeReq(origin);
was_processed=true;
}
}
if((f0.at(0)=="SP")&&(f0.size()==2)) { // Stop Playback
serial=f0.at(1).toUInt(&ok);
if(ok) {
origin.setSerialNumber(serial);
emit playStopReq(origin);
was_processed=true;
}
}
if((f0.at(0)=="OV")&&(f0.size()==3)) { // Set Output Volume
serial=f0.at(1).toUInt(&ok);
if(ok) {
origin.setSerialNumber(serial);
level=f0.at(2).toInt(&ok);
if(ok) { if(ok) {
origin.setSerialNumber(serial); emit playSetOutputVolumeReq(origin,level);
position=f0.at(3).toInt(&ok); was_processed=true;
if(ok&&(position>=0)) { }
emit playPositionReq(origin,position); }
}
if((f0.at(0)=="FV")&&(f0.size()==4)) { // Fade Output Volume
serial=f0.at(1).toUInt(&ok);
if(ok) {
origin.setSerialNumber(serial);
level=f0.at(2).toInt(&ok);
if(ok) {
length=f0.at(3).toInt(&ok);
if(ok&&length>=0) {
emit playFadeOutputVolumeReq(origin,level,length);
was_processed=true; was_processed=true;
} }
} }
} }
} }
if((f0.at(0)=="PE")&&(f0.size()==3)) { // Pause Playback
pid=f0.at(1).toUInt(&ok);
if(ok&&(pid>0)) {
origin.setProcessId(pid);
serial=f0.at(2).toUInt(&ok);
if(ok) {
origin.setSerialNumber(serial);
emit playPauseReq(origin);
was_processed=true;
}
}
}
if((f0.at(0)=="PR")&&(f0.size()==3)) { // Resume Playback
pid=f0.at(1).toUInt(&ok);
if(ok&&(pid>0)) {
origin.setProcessId(pid);
serial=f0.at(2).toUInt(&ok);
if(ok) {
origin.setSerialNumber(serial);
emit playResumeReq(origin);
was_processed=true;
}
}
}
if((f0.at(0)=="SP")&&(f0.size()==3)) { // Stop Playback
pid=f0.at(1).toUInt(&ok);
if(ok&&(pid>0)) {
origin.setProcessId(pid);
serial=f0.at(2).toUInt(&ok);
if(ok) {
origin.setSerialNumber(serial);
emit playStopReq(origin);
was_processed=true;
}
}
}
if((f0.at(0)=="OV")&&(f0.size()==4)) { // Set Output Volume
pid=f0.at(1).toUInt(&ok);
if(ok&&(pid>0)) {
origin.setProcessId(pid);
serial=f0.at(2).toUInt(&ok);
if(ok) {
origin.setSerialNumber(serial);
level=f0.at(3).toInt(&ok);
if(ok) {
emit playSetOutputVolumeReq(origin,level);
was_processed=true;
}
}
}
}
if((f0.at(0)=="FV")&&(f0.size()==5)) { // Fade Output Volume
pid=f0.at(1).toUInt(&ok);
if(ok&&(pid>0)) {
origin.setProcessId(pid);
serial=f0.at(2).toUInt(&ok);
if(ok) {
origin.setSerialNumber(serial);
level=f0.at(3).toInt(&ok);
if(ok) {
length=f0.at(4).toInt(&ok);
if(ok&&length>=0) {
emit playFadeOutputVolumeReq(origin,level,length);
was_processed=true;
}
}
}
}
}
// //
// Record Operations // Record Operations
// //
if((f0.at(0)=="LR")&&(f0.size()==10)) { // Cue Recording if((f0.at(0)=="LR")&&(f0.size()==8)) { // Cue Recording
pid=f0.at(1).toUInt(&ok); serial=f0.at(1).toUInt(&ok);
if(ok&&(pid>0)) { if(ok) {
origin.setProcessId(pid); origin.setSerialNumber(serial);
serial=f0.at(2).toUInt(&ok); cutname=f0.at(2);
if(ok) { if(cutname.length()==10) {
origin.setSerialNumber(serial); cardnum=f0.at(3).toUInt(&ok);
cutname=f0.at(3); if(ok&&(cardnum<RD_MAX_CARDS)) {
if(cutname.length()==10) { portnum=f0.at(4).toInt(&ok);
cardnum=f0.at(4).toUInt(&ok); if(ok&&(portnum<RD_MAX_PORTS)) {
if(ok&&(cardnum<RD_MAX_CARDS)) { coding=f0.at(5).toInt(&ok);
portnum=f0.at(5).toInt(&ok); if(ok&&(coding>=0)&&(coding<=4)) {
if(ok&&(portnum<RD_MAX_PORTS)) { channels=f0.at(6).toInt(&ok);
coding=f0.at(6).toInt(&ok); if(ok&&(channels>0)) {
if(ok&&(coding>=0)&&(coding<=4)) { bitrate=f0.at(7).toInt(&ok);
channels=f0.at(7).toInt(&ok); if(ok&&(bitrate>=0)) {
if(ok&&(channels>0)) { emit recordCueReq(origin,cutname,cardnum,portnum,
bitrate=f0.at(8).toInt(&ok); coding,channels,bitrate);
if(ok&&(bitrate>=0)) { was_processed=true;
emit recordCueReq(origin,cutname,cardnum,portnum,
coding,channels,bitrate);
was_processed=true;
}
} }
} }
} }
@@ -362,54 +297,46 @@ bool CaeServer::ProcessCommand(const QHostAddress &src_addr,uint16_t src_port,
} }
} }
if((f0.at(0)=="RD")&&(f0.size()==5)) { // Start Recording if((f0.at(0)=="RD")&&(f0.size()==4)) { // Start Recording
pid=f0.at(1).toUInt(&ok); serial=f0.at(1).toUInt(&ok);
if(ok&&(pid>0)) { if(ok) {
origin.setProcessId(pid); origin.setSerialNumber(serial);
serial=f0.at(2).toUInt(&ok); length=f0.at(2).toInt(&ok);
if(ok) { if(ok&&(length>=0)) {
origin.setSerialNumber(serial); threshold=f0.at(3).toInt(&ok);
length=f0.at(3).toInt(&ok); if(ok&&(threshold<=0)) {
if(ok&&(length>=0)) { emit recordStartReq(origin,length,threshold);
threshold=f0.at(4).toInt(&ok); was_processed=true;
if(ok&&(threshold<=0)) {
emit recordStartReq(origin,length,threshold);
was_processed=true;
}
} }
} }
} }
} }
if((f0.at(0)=="RC")&&(f0.size()==11)) { // Cue and Start Recording if((f0.at(0)=="RC")&&(f0.size()==10)) { // Cue and Start Recording
pid=f0.at(1).toUInt(&ok); serial=f0.at(1).toUInt(&ok);
if(ok&&(pid>0)) { if(ok) {
origin.setProcessId(pid); origin.setSerialNumber(serial);
serial=f0.at(2).toUInt(&ok); cutname=f0.at(2);
if(ok) { if(cutname.length()==10) {
origin.setSerialNumber(serial); cardnum=f0.at(3).toUInt(&ok);
cutname=f0.at(3); if(ok&&(cardnum<RD_MAX_CARDS)) {
if(cutname.length()==10) { portnum=f0.at(4).toInt(&ok);
cardnum=f0.at(4).toUInt(&ok); if(ok&&(portnum<RD_MAX_PORTS)) {
if(ok&&(cardnum<RD_MAX_CARDS)) { coding=f0.at(5).toInt(&ok);
portnum=f0.at(5).toInt(&ok); if(ok&&(coding>=0)&&(coding<=4)) {
if(ok&&(portnum<RD_MAX_PORTS)) { channels=f0.at(6).toInt(&ok);
coding=f0.at(6).toInt(&ok); if(ok&&(channels>0)) {
if(ok&&(coding>=0)&&(coding<=4)) { bitrate=f0.at(7).toInt(&ok);
channels=f0.at(7).toInt(&ok); if(ok&&(bitrate>=0)) {
if(ok&&(channels>0)) { length=f0.at(8).toInt(&ok);
bitrate=f0.at(8).toInt(&ok); if(ok&&(length>=0)) {
if(ok&&(bitrate>=0)) { threshold=f0.at(9).toInt(&ok);
length=f0.at(9).toInt(&ok); if(ok&&(threshold<=0)) {
if(ok&&(length>=0)) { emit recordCueAndStartReq(origin,cutname,
threshold=f0.at(10).toInt(&ok); cardnum,portnum,
if(ok&&(threshold<=0)) { coding,channels,bitrate,
emit recordCueAndStartReq(origin,cutname, length,threshold);
cardnum,portnum, was_processed=true;
coding,channels,bitrate,
length,threshold);
was_processed=true;
}
} }
} }
} }
@@ -421,16 +348,12 @@ bool CaeServer::ProcessCommand(const QHostAddress &src_addr,uint16_t src_port,
} }
} }
if((f0.at(0)=="SR")&&(f0.size()==3)) { // Stop Recording if((f0.at(0)=="SR")&&(f0.size()==2)) { // Stop Recording
pid=f0.at(1).toUInt(&ok); serial=f0.at(1).toUInt(&ok);
if(ok&&(pid>0)) { if(ok) {
origin.setProcessId(pid); origin.setSerialNumber(serial);
serial=f0.at(2).toUInt(&ok); emit recordStopReq(origin);
if(ok) { was_processed=true;
origin.setSerialNumber(serial);
emit recordStopReq(origin);
was_processed=true;
}
} }
} }
@@ -483,10 +406,6 @@ bool CaeServer::ProcessCommand(const QHostAddress &src_addr,uint16_t src_port,
// //
// Meter Commands // Meter Commands
// //
/*
* This needs to die!
* Replace with multicast meter system.
*
if(f0.at(0)=="ME") { // Meter Enable if(f0.at(0)=="ME") { // Meter Enable
if(f0.size()>2) { // So we don't warn if no cards are specified if(f0.size()>2) { // So we don't warn if no cards are specified
uint16_t udp_port=0xFFFF&f0.at(1).toUInt(&ok); uint16_t udp_port=0xFFFF&f0.at(1).toUInt(&ok);
@@ -500,7 +419,6 @@ bool CaeServer::ProcessCommand(const QHostAddress &src_addr,uint16_t src_port,
} }
was_processed=true; was_processed=true;
} }
*/
if(!was_processed) { if(!was_processed) {
rda->syslog(LOG_WARNING, rda->syslog(LOG_WARNING,

View File

@@ -31,6 +31,7 @@
#include <rdconfig.h> #include <rdconfig.h>
#include "connection.h"
#include "session.h" #include "session.h"
class CaeServer : public QObject class CaeServer : public QObject
@@ -38,23 +39,19 @@ class CaeServer : public QObject
Q_OBJECT; Q_OBJECT;
public: public:
CaeServer(QObject *parent=0); CaeServer(QObject *parent=0);
QList<int> connectionIds() const;
QHostAddress peerAddress(int id) const;
uint16_t peerPort(int id) const;
uint16_t meterPort(int id) const;
void setMeterPort(int id,uint16_t port);
bool metersEnabled(int id,unsigned card) const; bool metersEnabled(int id,unsigned card) const;
void setMetersEnabled(int id,unsigned card,bool state); void setMetersEnabled(int id,unsigned card,bool state);
bool listen(const QHostAddress &addr,uint16_t port); bool bind(const QHostAddress &addr,uint16_t port);
void sendCommand(const QString &cmd); void sendCommand(const QString &cmd);
void sendCommand(const SessionId &dest,const QString &cmd); void sendCommand(const SessionId &dest,const QString &cmd);
signals: signals:
void connectionDropped(int id); // void connectionDropped(int id);
// //
// New Signals // New Signals
// //
void connectionClosed(const SessionId &sid);
void startPlaybackReq(const SessionId &sid,const QString &cutname, void startPlaybackReq(const SessionId &sid,const QString &cutname,
unsigned cardnum,unsigned portnum, unsigned cardnum,unsigned portnum,
int start_pos,int end_pos,int speed); int start_pos,int end_pos,int speed);
@@ -111,13 +108,14 @@ class CaeServer : public QObject
const QList<unsigned> &cards); const QList<unsigned> &cards);
private slots: private slots:
void newConnectionData();
void readyReadData(); void readyReadData();
void connectionClosedData(int id); void connectionExpiredData(const SessionId &sid);
// void connectionClosedData(int id);
private: private:
bool ProcessCommand(const QHostAddress &src_addr,uint16_t src_port, bool ProcessCommand(const QHostAddress &src_addr,uint16_t src_port,
const QString &cmd); const QString &cmd);
QMap<SessionId,Connection *> cae_connections;
QSignalMapper *cae_ready_read_mapper; QSignalMapper *cae_ready_read_mapper;
QUdpSocket *d_server_socket; QUdpSocket *d_server_socket;
}; };

83
cae/connection.cpp Normal file
View File

@@ -0,0 +1,83 @@
// connection.cpp
//
// UDP connection context for CAE protocol commands
//
// (C) Copyright 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
// 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 "connection.h"
Connection::Connection(const SessionId &sid,QObject *parent)
: QObject(parent)
{
d_session_id=sid;
d_interval=0;
d_timer=new QTimer(this);
d_timer->setSingleShot(true);
connect(d_timer,SIGNAL(timeout()),this,SLOT(timerData()));
}
Connection::~Connection()
{
delete d_timer;
}
SessionId Connection::sessionId() const
{
return d_session_id;
}
QString Connection::dump() const
{
return d_session_id.dump();
}
bool Connection::operator!=(const Connection &other) const
{
return (other.d_session_id.address()!=d_session_id.address())||
(other.d_session_id.port()!=d_session_id.port());
}
bool Connection::operator<(const Connection &other) const
{
return other.d_session_id<d_session_id;
}
void Connection::setTimeout(int msecs)
{
d_interval=msecs;
touch();
}
void Connection::touch()
{
d_timer->stop();
d_timer->start(d_interval);
}
void Connection::timerData()
{
emit connectionExpired(d_session_id);
}

60
cae/connection.h Normal file
View File

@@ -0,0 +1,60 @@
// connection.h
//
// UDP connection context for CAE protocol commands
//
// (C) Copyright 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
// 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 CONNECTION_H
#define CONNECTION_H
#include <stdint.h>
#include <QHostAddress>
#include <QObject>
#include <QTimer>
#include "session.h"
class Connection : public QObject
{
Q_OBJECT;
public:
Connection(const SessionId &sid,QObject *parent);
~Connection();
SessionId sessionId() const;
QString dump() const;
bool operator!=(const Connection &other) const;
bool operator<(const Connection &other) const;
signals:
void connectionExpired(const SessionId &sid);
public slots:
void setTimeout(int msecs);
void touch();
private slots:
void timerData();
private:
SessionId d_session_id;
QTimer *d_timer;
int d_interval;
};
#endif // SESSION_H

View File

@@ -20,19 +20,16 @@
#include "session.h" #include "session.h"
SessionId::SessionId(const QHostAddress &addr,uint16_t port,int pid,int serial) SessionId::SessionId(const QHostAddress &src_addr,uint16_t src_port,int serial)
{ {
d_address=addr; d_address=src_addr;
d_port=port; d_port=src_port;
d_process_id=pid;
d_serial_number=serial; d_serial_number=serial;
} }
SessionId::SessionId() SessionId::SessionId()
{ {
d_port=0;
d_process_id=0;
d_serial_number=0; d_serial_number=0;
} }
@@ -49,18 +46,6 @@ uint16_t SessionId::port() const
} }
int SessionId::processId() const
{
return d_process_id;
}
void SessionId::setProcessId(int pid)
{
d_process_id=pid;
}
int SessionId::serialNumber() const int SessionId::serialNumber() const
{ {
return d_serial_number; return d_serial_number;
@@ -75,31 +60,41 @@ void SessionId::setSerialNumber(int serial)
QString SessionId::dump() const QString SessionId::dump() const
{ {
return address().toString()+ return QString::asprintf("%s:%d:%d",d_address.toString().toUtf8().constData(),
QString::asprintf(":%d:%d:%d",0xFFFF&port(),processId(),serialNumber()); 0xFFFF&d_port,d_serial_number);
}
bool SessionId::belongsTo(const SessionId &other) const
{
return ((other.d_address==d_address)&&(other.d_port==d_port));
}
bool SessionId::operator!=(const SessionId &other) const
{
return (other.d_address!=d_address)||(other.d_port!=d_port)||
(other.d_serial_number!=d_serial_number);
} }
bool SessionId::operator<(const SessionId &other) const bool SessionId::operator<(const SessionId &other) const
{ {
if(other.d_address!=d_address) { if(other.d_address.toIPv4Address()!=d_address.toIPv4Address()) {
return other.d_address.toIPv4Address()<d_address.toIPv4Address(); return other.d_address.toIPv4Address()<d_address.toIPv4Address();
} }
if(other.d_port!=d_port) { if(other.d_port!=d_port) {
return other.d_port<d_port; return other.d_port<d_port;
} }
if(other.d_process_id!=d_process_id) {
return other.d_process_id<d_process_id;
}
return other.d_serial_number<d_serial_number; return other.d_serial_number<d_serial_number;
} }
Session::Session(const QHostAddress &addr,uint16_t port,int pid,int serial) Session::Session(const QHostAddress &addr,uint16_t port,int serial)
{ {
d_session_id=SessionId(addr,port,pid,serial); d_session_id=SessionId(addr,port,serial);
d_card_number=-1; d_card_number=-1;
d_port_number=-1; d_port_number=-1;
@@ -128,6 +123,24 @@ Session::Session(const SessionId &sid)
d_meters_enabled=false; d_meters_enabled=false;
} }
/*
Session::Session(const Connection &conn)
{
d_session_id=SessionId(conn);
d_session_id=sid;
d_card_number=-1;
d_port_number=-1;
d_stream_number=-1;
d_start_position=-1;
d_end_position=-1;
d_speed=100000;
d_meter_port=0;
d_meters_enabled=false;
}
*/
SessionId Session::sessionId() const SessionId Session::sessionId() const
{ {

View File

@@ -28,21 +28,20 @@
class SessionId class SessionId
{ {
public: public:
SessionId(const QHostAddress &addr,uint16_t port,int pid=0,int serial=0); SessionId(const QHostAddress &src_addr,uint16_t src_port,int serial=0);
SessionId(); SessionId();
QHostAddress address() const; QHostAddress address() const;
uint16_t port() const; uint16_t port() const;
int processId() const;
void setProcessId(int pid);
int serialNumber() const; int serialNumber() const;
void setSerialNumber(int serial); void setSerialNumber(int serial);
QString dump() const; QString dump() const;
bool belongsTo(const SessionId &other) const;
bool operator!=(const SessionId &other) const;
bool operator<(const SessionId &other) const; bool operator<(const SessionId &other) const;
private: private:
QHostAddress d_address; QHostAddress d_address;
uint16_t d_port; uint16_t d_port;
int d_process_id;
int d_serial_number; int d_serial_number;
}; };
@@ -52,7 +51,7 @@ class SessionId
class Session class Session
{ {
public: public:
Session(const QHostAddress &addr,uint16_t port,int pid,int serial); Session(const QHostAddress &addr,uint16_t port,int serial=0);
Session(const SessionId &sid); Session(const SessionId &sid);
SessionId sessionId() const; SessionId sessionId() const;
int cardNumber() const; int cardNumber() const;

View File

@@ -142,6 +142,54 @@
</sect2> </sect2>
</sect1> </sect1>
<sect1 xml:id="sect.connection_management">
<title>Connection Management</title>
<para>
<sect2 xml:id="sect.connection_management.commands">
<title>Commands</title>
<sect3 xml:id="sect.connection_management.commands.set_timeout">
<title>Set Timeout</title>
<para>
Set the timeout interval for the connection.
</para>
<para>
<userinput>
TO
<replaceable>interval</replaceable>
</userinput>
</para>
<variablelist>
<varlistentry>
<term><replaceable>interval</replaceable></term>
<listitem>
<para>
When set to a non-zero value, the client must send a
<link linkend="sect.connection_management.commands.touch">
Touch message
</link>
at an interval of least that many milliseconds, otherwise
the engine will clear the connection, releasing all associated
resources.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect3>
<sect3 xml:id="sect.connection_management.commands.touch">
<title>Touch</title>
<para>
Keep connection alive.
</para>
<para>
<userinput>
TH
</userinput>
</para>
</sect3>
</sect2>
</para>
</sect1>
<sect1 xml:id="sect.playback_operations"> <sect1 xml:id="sect.playback_operations">
<title>Playback Operations</title> <title>Playback Operations</title>
<sect2 xml:id="sect.playback_operations.commands"> <sect2 xml:id="sect.playback_operations.commands">
@@ -156,7 +204,6 @@
<para> <para>
<userinput> <userinput>
PY PY
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
<replaceable>cut-name</replaceable> <replaceable>cut-name</replaceable>
<replaceable>card-num</replaceable> <replaceable>card-num</replaceable>
@@ -167,15 +214,6 @@
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
An integer value, giving the process ID of the process
originating the command.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -183,7 +221,7 @@
An integer value, giving the serial number of the command. An integer value, giving the serial number of the command.
This can be any 32 bit positive integer value, but This can be any 32 bit positive integer value, but
<emphasis>must</emphasis> be unique within the scope of the <emphasis>must</emphasis> be unique within the scope of the
process originating the command! connection sending the command!
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@@ -249,24 +287,11 @@
<para> <para>
<userinput> <userinput>
PP PP
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
<replaceable>position</replaceable> <replaceable>position</replaceable>
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
Integer value. Should be the same value as that used in the prior
<link linkend="sect.playback_operations.commands.start_playback">
<command>Start Playback</command>
</link>
operation.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -302,23 +327,10 @@
<para> <para>
<userinput> <userinput>
PE PE
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
Integer value. Should be the same value as that used in the prior
<link linkend="sect.playback_operations.commands.start_playback">
<command>Start Playback</command>
</link>
operation.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -343,23 +355,10 @@
<para> <para>
<userinput> <userinput>
PR PR
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
Integer value. Should be the same value as that used in the prior
<link linkend="sect.playback_operations.commands.start_playback">
<command>Start Playback</command>
</link>
operation.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -384,23 +383,10 @@
<para> <para>
<userinput> <userinput>
SP SP
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
Integer value. Should be the same value as that used in the prior
<link linkend="sect.playback_operations.commands.start_playback">
<command>Start Playback</command>
</link>
operation.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -424,24 +410,11 @@
<para> <para>
<userinput> <userinput>
OV OV
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
<replaceable>level</replaceable> <replaceable>level</replaceable>
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
Integer value. Should be the same value as that used in the prior
<link linkend="sect.playback_operations.commands.start_playback">
<command>Start Playback</command>
</link>
operation.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -475,25 +448,12 @@
<para> <para>
<userinput> <userinput>
FV FV
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
<replaceable>level</replaceable> <replaceable>level</replaceable>
<replaceable>length</replaceable> <replaceable>length</replaceable>
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
Integer value. Should be the same value as that used in the prior
<link linkend="sect.playback_operations.commands.start_playback">
<command>Start Playback</command>
</link>
operation.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -540,23 +500,10 @@
<para> <para>
<userinput> <userinput>
SP SP
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
Integer value. The same value as that used in the prior
<link linkend="sect.playback_operations.commands.start_playback">
<command>Start Playback</command>
</link>
operation.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -580,24 +527,11 @@
<para> <para>
<userinput> <userinput>
PP PP
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
<replaceable>position</replaceable> <replaceable>position</replaceable>
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
Integer value. The same value as that used in the prior
<link linkend="sect.playback_operations.commands.start_playback">
<command>Start Playback</command>
</link>
operation.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -640,7 +574,6 @@
<para> <para>
<userinput> <userinput>
LR LR
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
<replaceable>cut-name</replaceable> <replaceable>cut-name</replaceable>
<replaceable>card-num</replaceable> <replaceable>card-num</replaceable>
@@ -651,15 +584,6 @@
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
An integer value, giving the process ID of the process
originating the command.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -667,7 +591,7 @@
An integer value, giving the serial number of the command. An integer value, giving the serial number of the command.
This can be any 32 bit positive integer value, but This can be any 32 bit positive integer value, but
<emphasis>must</emphasis> be unique within the scope of the <emphasis>must</emphasis> be unique within the scope of the
process originating the command! connection sending the command!
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@@ -749,25 +673,12 @@
<para> <para>
<userinput> <userinput>
RD RD
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
<replaceable>length</replaceable> <replaceable>length</replaceable>
<replaceable>threshold</replaceable> <replaceable>threshold</replaceable>
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
Integer value. The same value as that used in the prior
<link linkend="sect.record_operations.commands.cue_recording">
<command>Cue Recording</command>
</link>
operation.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -813,7 +724,6 @@
<para> <para>
<userinput> <userinput>
RC RC
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
<replaceable>cut-name</replaceable> <replaceable>cut-name</replaceable>
<replaceable>card-num</replaceable> <replaceable>card-num</replaceable>
@@ -826,15 +736,6 @@
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
An integer value, giving the process ID of the process
originating the command.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -842,7 +743,7 @@
An integer value, giving the serial number of the command. An integer value, giving the serial number of the command.
This can be any 32 bit positive integer value, but This can be any 32 bit positive integer value, but
<emphasis>must</emphasis> be unique within the scope of the <emphasis>must</emphasis> be unique within the scope of the
process originating the command! connection sending the command!
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@@ -941,27 +842,10 @@
<para> <para>
<userinput> <userinput>
SR SR
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
</userinput> </userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
Integer value. The same value as that used in the prior
<link linkend="sect.record_operations.commands.cue_recording">
<command>Cue Recording</command>
</link>
or
<link linkend="sect.record_operations.commands.cue_and_start_recording">
<command>Cue and Start Recording</command>
</link>
operation.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>
@@ -994,28 +878,11 @@
<para> <para>
<computeroutput> <computeroutput>
RS RS
<replaceable>pid</replaceable>
<replaceable>serial</replaceable> <replaceable>serial</replaceable>
<replaceable>state</replaceable> <replaceable>state</replaceable>
</computeroutput> </computeroutput>
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term><replaceable>pid</replaceable></term>
<listitem>
<para>
Integer value. The same value as that used in the prior
<link linkend="sect.record_operations.commands.cue_recording">
<command>Cue Recording</command>
</link>
or
<link linkend="sect.record_operations.commands.cue_and_start_recording">
<command>Cue and Start Recording</command>
</link>
operation.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>serial</replaceable></term> <term><replaceable>serial</replaceable></term>
<listitem> <listitem>