2019-05-29 Fred Gleason <fredg@paravelsystems.com>

* Refactored caed(8) to eliminated arbitrary limit on number of
	client connections.
This commit is contained in:
Fred Gleason 2019-05-29 18:00:58 -04:00
parent f6fa420cfd
commit c7b6322bc6
10 changed files with 1925 additions and 1534 deletions

View File

@ -18696,3 +18696,6 @@
2019-05-24 Fred Gleason <fredg@paravelsystems.com>
* Fixed a regression in rdgpimon(1) that caused GPIO status
to fail to be displayed in the status widgets.
2019-05-29 Fred Gleason <fredg@paravelsystems.com>
* Refactored caed(8) to eliminated arbitrary limit on number of
client connections.

View File

@ -2,7 +2,7 @@
##
## Core Audio Engine Makefile.am for Rivendell
##
## Copyright 2002-2006,2016 Fred Gleason <fredg@paravelsystems.com>
## Copyright 2002-2019 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
@ -33,10 +33,10 @@ dist_caed_SOURCES = cae.cpp cae.h\
cae_alsa.cpp\
cae_hpi.cpp\
cae_jack.cpp\
cae_socket.cpp cae_socket.h
cae_server.cpp cae_server.h
nodist_caed_SOURCES = moc_cae.cpp\
moc_cae_socket.cpp
moc_cae_server.cpp
caed_LDADD = @LIB_RDLIBS@\
@LIBALSA@\

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
//
// The Core Audio Engine component of Rivendell
//
// (C) Copyright 2002-2015 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2002-2019 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
@ -18,7 +18,6 @@
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef CAE_H
#define CAE_H
@ -31,13 +30,11 @@
#include <qobject.h>
#include <qstring.h>
#include <q3socketdevice.h>
#include <q3serversocket.h>
#include <qsignalmapper.h>
#include <qtimer.h>
#include <q3process.h>
#include <rdwavefile.h>
#include <rdsocket.h>
#ifdef HPI
#include <rdhpisoundcard.h>
@ -79,6 +76,8 @@ struct alsa_format {
#include <rdconfig.h>
#include <rdstation.h>
#include "cae_server.h"
#ifndef HAVE_SRC_CONV
void src_int_to_float_array (const int *in, float *out, int len);
void src_float_to_int_array (const float *in, int *out, int len);
@ -101,37 +100,64 @@ void src_float_to_int_array (const float *in, int *out, int len);
void SigHandler(int signum);
extern RDConfig *rd_config;
class MainObject : public QObject
{
Q_OBJECT
public:
MainObject(QObject *parent=0,const char *name=0);
~MainObject();
public slots:
void newConnection(int fd);
private slots:
void socketData(int);
void socketKill(int);
void loadPlaybackData(int id,unsigned card,const QString &name);
void unloadPlaybackData(int id,unsigned handle);
void playPositionData(int id,unsigned handle,unsigned pos);
void playData(int id,unsigned handle,unsigned length,unsigned speed,
unsigned pitch_flag);
void stopPlaybackData(int id,unsigned handle);
void timescalingSupportData(int id,unsigned card);
void loadRecordingData(int id,unsigned card,unsigned port,unsigned coding,
unsigned channels,unsigned samprate,unsigned bitrate,
const QString &name);
void unloadRecordingData(int id,unsigned card,unsigned stream);
void recordData(int id,unsigned card,unsigned stream,unsigned len,
int threshold_level);
void stopRecordingData(int id,unsigned card,unsigned stream);
void setInputVolumeData(int id,unsigned card,unsigned stream,int level);
void setOutputVolumeData(int id,unsigned card,unsigned stream,unsigned port,
int level);
void fadeOutputVolumeData(int id,unsigned card,unsigned stream,unsigned port,
int level,unsigned length);
void setInputLevelData(int id,unsigned card,unsigned stream,int level);
void setOutputLevelData(int id,unsigned card,unsigned port,int level);
void setInputModeData(int id,unsigned card,unsigned stream,unsigned mode);
void setOutputModeData(int id,unsigned card,unsigned stream,unsigned mode);
void setInputVoxLevelData(int id,unsigned card,unsigned stream,int level);
void setInputTypeData(int id,unsigned card,unsigned port,unsigned type);
void getInputStatusData(int id,unsigned card,unsigned port);
void setAudioPassthroughLevelData(int id,unsigned card,unsigned input,
unsigned output,int level);
void setClockSourceData(int id,unsigned card,int input);
void setOutputStatusFlagData(int id,unsigned card,unsigned port,
unsigned stream,bool state);
void openRtpCaptureChannelData(int id,unsigned card,unsigned port,
uint16_t udp_port,unsigned samprate,
unsigned chans);
void jackConnectPortsData(int id,const QString &out_name,
const QString &in_name);
void jackDisconnectPortsData(int id,const QString &out_name,
const QString &in_name);
void meterEnableData(int id,uint16_t udp_port,const QList<unsigned> &cards);
void statePlayUpdate(int card,int stream,int state);
void stateRecordUpdate(int card,int stream,int state);
void updateMeters();
void connectionDroppedData(int id);
private:
void InitProvisioning() const;
void InitMixers();
void ParseCommand(int);
void DispatchCommand(int);
void KillSocket(int);
void BroadcastCommand(const char *);
void EchoCommand(int,const char *);
void EchoArgs(int,const char);
bool CheckDaemon(QString);
pid_t GetPid(QString pidfile);
int GetNextHandle();
int GetHandle(int ch,int *card,int *stream);
int GetHandle(int card,int stream);
void ProbeCaps(RDStation *station);
void ClearDriverEntries(RDStation *station);
@ -144,16 +170,9 @@ class MainObject : public QObject
void SendMeterUpdate(const QString &msg,int conn_id);
bool debug;
unsigned system_sample_rate;
CaeServer *cae_server;
Q_INT16 tcp_port;
Q3ServerSocket *server;
Q3SocketDevice *meter_socket;
RDSocket *socket[CAE_MAX_CONNECTIONS];
Q_UINT16 meter_port[CAE_MAX_CONNECTIONS];
char args[CAE_MAX_CONNECTIONS][CAE_MAX_ARGS][CAE_MAX_LENGTH];
int istate[CAE_MAX_CONNECTIONS];
int argnum[CAE_MAX_CONNECTIONS];
int argptr[CAE_MAX_CONNECTIONS];
bool auth[CAE_MAX_CONNECTIONS];
RDStation::AudioDriver cae_driver[RD_MAX_CARDS];
int record_owner[RD_MAX_CARDS][RD_MAX_STREAMS];
int record_length[RD_MAX_CARDS][RD_MAX_STREAMS];
@ -164,7 +183,6 @@ class MainObject : public QObject
bool play_pitch[RD_MAX_CARDS][RD_MAX_STREAMS];
bool port_status[RD_MAX_CARDS][RD_MAX_PORTS];
bool output_status_flag[RD_MAX_CARDS][RD_MAX_PORTS][RD_MAX_STREAMS];
bool update_meters[RD_MAX_CARDS][CAE_MAX_CONNECTIONS];
struct {
int card;
int stream;

543
cae/cae_server.cpp Normal file
View File

@ -0,0 +1,543 @@
// cae_server.cpp
//
// Network server for caed(8).
//
// (C) Copyright 2019 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 <ctype.h>
#include <stdio.h>
#include <qbytearray.h>
#include <qstringlist.h>
#include "cae_server.h"
CaeServerConnection::CaeServerConnection(QTcpSocket *sock)
{
socket=sock;
authenticated=false;
accum="";
meter_port=0;
for(int i=0;i<RD_MAX_CARDS;i++) {
meters_enabled[i]=false;
}
}
CaeServerConnection::~CaeServerConnection()
{
socket->deleteLater();
}
CaeServer::CaeServer(RDConfig *config,QObject *parent)
: QObject(parent)
{
cae_config=config;
cae_server=new QTcpServer(this);
connect(cae_server,SIGNAL(newConnection()),this,SLOT(newConnectionData()));
cae_ready_read_mapper=new QSignalMapper(this);
connect(cae_ready_read_mapper,SIGNAL(mapped(int)),
this,SLOT(readyReadData(int)));
cae_connection_closed_mapper=new QSignalMapper(this);
connect(cae_connection_closed_mapper,SIGNAL(mapped(int)),
this,SLOT(connectionClosedData(int)));
}
QList<int> CaeServer::connectionIds() const
{
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();
}
uint16_t CaeServer::peerPort(int id) const
{
return cae_connections[id]->socket->peerPort();
}
uint16_t CaeServer::meterPort(int id) const
{
return cae_connections[id]->meter_port;
}
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];
}
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 cae_server->listen(addr,port);
}
void CaeServer::sendCommand(const QString &cmd)
{
for(QMap<int,CaeServerConnection *>::const_iterator it=
cae_connections.begin();it!=cae_connections.end();it++) {
if(it.value()->authenticated) {
sendCommand(it.key(),cmd);
}
}
}
void CaeServer::sendCommand(int id,const QString &cmd)
{
// syslog(LOG_DEBUG,"sending [%d]: %s",id,(const char *)cmd.toUtf8());
cae_connections.value(id)->socket->write(cmd.toAscii());
}
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);
syslog(LOG_DEBUG,"added connection %d",sock->socketDescriptor());
}
void CaeServer::readyReadData(int id)
{
QByteArray data=cae_connections.value(id)->socket->readAll();
for(int i=0;i<data.size();i++) {
char c=0xFF&data[i];
if(c=='!') {
ProcessCommand(id,cae_connections.value(id)->accum);
}
else {
if(isalnum(0xFF&data[i])||(c=='_')||(c==' ')) {
cae_connections.value(id)->accum+=0xFF&data[i];
}
}
}
}
void CaeServer::connectionClosedData(int id)
{
emit connectionDropped(id);
cae_connections.value(id)->socket->disconnect();
delete cae_connections.value(id);
cae_connections.remove(id);
syslog(LOG_DEBUG,"removed connection %d",id);
}
void CaeServer::ProcessCommand(int id,const QString &cmd)
{
CaeServerConnection *conn=cae_connections.value(id);
QStringList f0=cmd.split(" ",QString::SkipEmptyParts);
bool ok=false;
// syslog(LOG_DEBUG,"receiving [%d]: %s",id,(const char *)cmd.toUtf8());
cae_connections.value(id)->accum="";
//
// Unpriviledged Commands
//
if(f0.at(0)=="DC") {
connectionClosedData(id);
return;
}
if(f0.at(0)=="PW") {
if((f0.size()==2)&&(f0.at(1)==cae_config->password())) {
conn->authenticated=true;
sendCommand(id,"PW +!");
}
else {
conn->authenticated=false;
sendCommand(id,"PW -!");
}
return;
}
//
// Priviledged Commands
// Authentication required to execute these!
//
if(!conn->authenticated) {
return;
}
bool was_processed=false;
if((f0.at(0)=="LP")&&(f0.size()==3)) { // Load Playback
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
emit loadPlaybackReq(id,card,f0.at(2));
was_processed=true;
}
}
if((f0.at(0)=="UP")&&(f0.size()==2)) { // Unload Playback
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
emit unloadPlaybackReq(id,card);
was_processed=true;
}
}
if((f0.at(0)=="PP")&&(f0.size()==3)) { // Play Position
unsigned handle=f0.at(1).toUInt(&ok);
if(ok) {
unsigned pos=f0.at(2).toUInt(&ok);
if(ok) {
emit playPositionReq(id,handle,pos);
was_processed=true;
}
}
}
if((f0.at(0)=="PY")&&(f0.size()==5)) { // Play
unsigned handle=f0.at(1).toUInt(&ok);
if(ok) {
unsigned len=f0.at(2).toUInt(&ok);
if(ok) {
unsigned speed=f0.at(3).toUInt(&ok);
if(ok) {
unsigned pitch=f0.at(4).toUInt(&ok);
if(ok) {
emit playReq(id,handle,len,speed,pitch);
was_processed=true;
}
}
}
}
}
if((f0.at(0)=="SP")&&(f0.size()==2)) { // Stop Playback
unsigned handle=f0.at(1).toUInt(&ok);
if(ok) {
emit stopPlaybackReq(id,handle);
was_processed=true;
}
}
if((f0.at(0)=="TS")&&(f0.size()==2)) { // Timescaling Support
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
emit timescalingSupportReq(id,card);
was_processed=true;
}
}
if((f0.at(0)=="LR")&&(f0.size()==8)) { // Load Recording
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned port=f0.at(2).toUInt(&ok);
if(ok&&(port<RD_MAX_PORTS)) {
unsigned coding=f0.at(3).toUInt(&ok);
if(ok&&(coding<5)) {
unsigned chans=f0.at(4).toUInt(&ok);
if(ok&&(chans<=2)) {
unsigned samprate=f0.at(5).toUInt(&ok);
if(ok) {
unsigned bitrate=f0.at(6).toUInt(&ok);
if(ok) {
emit loadRecordingReq(id,card,port,coding,chans,samprate,
bitrate,f0.at(7));
was_processed=true;
}
}
}
}
}
}
}
if((f0.at(0)=="UR")&&(f0.size()==3)) { // Unload Recording
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned stream=f0.at(2).toUInt(&ok);
if(ok&&(stream<RD_MAX_STREAMS)) {
emit unloadRecordingReq(id,card,stream);
was_processed=true;
}
}
}
if((f0.at(0)=="RD")&&(f0.size()==5)) { // Record
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned stream=f0.at(2).toUInt(&ok);
if(ok&&(stream<RD_MAX_STREAMS)) {
if(ok) {
unsigned len=f0.at(3).toUInt(&ok);
if(ok) {
int thres=f0.at(4).toInt(&ok);
if(ok) {
emit recordReq(id,card,stream,len,thres);
was_processed=true;
}
}
}
}
}
}
if((f0.at(0)=="SR")&&(f0.size()==3)) { // Stop Recording
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned stream=f0.at(2).toUInt(&ok);
if(ok&&(stream<RD_MAX_STREAMS)) {
if(ok) {
emit stopRecordingReq(id,card,stream);
was_processed=true;
}
}
}
}
if((f0.at(0)=="IV")&&(f0.size()==4)) { // Set Input Volume
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned stream=f0.at(2).toUInt(&ok);
if(ok&&(stream<RD_MAX_STREAMS)) {
if(ok) {
int level=f0.at(3).toInt(&ok);
if(ok) {
emit setInputVolumeReq(id,card,stream,level);
was_processed=true;
}
}
}
}
}
if((f0.at(0)=="OV")&&(f0.size()==5)) { // Set Output Volume
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned stream=f0.at(2).toUInt(&ok);
if(ok&&(stream<RD_MAX_STREAMS)) {
if(ok) {
unsigned port=f0.at(3).toUInt(&ok);
if(ok&&(port<RD_MAX_PORTS)) {
int level=f0.at(4).toInt(&ok);
if(ok) {
emit setOutputVolumeReq(id,card,stream,port,level);
was_processed=true;
}
}
}
}
}
}
if((f0.at(0)=="FV")&&(f0.size()==6)) { // Fade Output Volume
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned stream=f0.at(2).toUInt(&ok);
if(ok&&(stream<RD_MAX_STREAMS)) {
if(ok) {
unsigned port=f0.at(3).toUInt(&ok);
if(ok&&(port<RD_MAX_PORTS)) {
int level=f0.at(4).toInt(&ok);
if(ok) {
int len=f0.at(5).toUInt(&ok);
if(ok) {
emit fadeOutputVolumeReq(id,card,stream,port,level,len);
was_processed=true;
}
}
}
}
}
}
}
if((f0.at(0)=="IL")&&(f0.size()==4)) { // Set Input Level
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned port=f0.at(2).toUInt(&ok);
if(ok&&(port<RD_MAX_PORTS)) {
int level=f0.at(3).toInt(&ok);
if(ok) {
emit setInputLevelReq(id,card,port,level);
was_processed=true;
}
}
}
}
if((f0.at(0)=="OL")&&(f0.size()==4)) { // Set Output Level
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned port=f0.at(2).toUInt(&ok);
if(ok&&(port<RD_MAX_PORTS)) {
int level=f0.at(3).toInt(&ok);
if(ok) {
emit setOutputLevelReq(id,card,port,level);
was_processed=true;
}
}
}
}
if((f0.at(0)=="IM")&&(f0.size()==4)) { // Set Input Mode
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned port=f0.at(2).toUInt(&ok);
if(ok&&(port<RD_MAX_PORTS)) {
unsigned mode=f0.at(3).toUInt(&ok);
if(ok&&(mode<=3)) {
emit setInputModeReq(id,card,port,mode);
was_processed=true;
}
}
}
}
if((f0.at(0)=="OM")&&(f0.size()==4)) { // Set Output Mode
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned port=f0.at(2).toUInt(&ok);
if(ok&&(port<RD_MAX_PORTS)) {
unsigned mode=f0.at(3).toUInt(&ok);
if(ok&&(mode<=3)) {
emit setOutputModeReq(id,card,port,mode);
was_processed=true;
}
}
}
}
if((f0.at(0)=="IX")&&(f0.size()==4)) { // Set Input Vox Level
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned stream=f0.at(2).toUInt(&ok);
if(ok&&(stream<RD_MAX_STREAMS)) {
int level=f0.at(3).toInt(&ok);
if(ok) {
emit setInputVoxLevelReq(id,card,stream,level);
was_processed=true;
}
}
}
}
if((f0.at(0)=="IT")&&(f0.size()==4)) { // Set Input Type
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned port=f0.at(2).toUInt(&ok);
if(ok&&(port<RD_MAX_PORTS)) {
int type=f0.at(3).toInt(&ok);
if(ok&&(type<=1)) {
emit setInputTypeReq(id,card,port,type);
was_processed=true;
}
}
}
}
if((f0.at(0)=="IS")&&(f0.size()==3)) { // Get Input Status
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned port=f0.at(2).toUInt(&ok);
if(ok&&(port<RD_MAX_PORTS)) {
emit getInputStatusReq(id,card,port);
was_processed=true;
}
}
}
if((f0.at(0)=="AL")&&(f0.size()==5)) { // Set Audio Passthrough Level
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned input=f0.at(2).toUInt(&ok);
if(ok&&(input<RD_MAX_PORTS)) {
unsigned output=f0.at(2).toUInt(&ok);
if(ok&&(output<RD_MAX_PORTS)) {
int level=f0.at(3).toUInt(&ok);
if(ok) {
emit setAudioPassthroughLevelReq(id,card,input,output,level);
was_processed=true;
}
}
}
}
}
if((f0.at(0)=="CS")&&(f0.size()==3)) { // Set Clock Source
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned input=f0.at(2).toUInt(&ok);
if(ok&&(input<RD_MAX_PORTS)) {
emit setClockSourceReq(id,card,input);
was_processed=true;
}
}
}
if((f0.at(0)=="OS")&&(f0.size()==5)) { // Set Output Status Flag
unsigned card=f0.at(1).toUInt(&ok);
if(ok&&(card<RD_MAX_CARDS)) {
unsigned port=f0.at(2).toUInt(&ok);
if(ok&&(port<RD_MAX_PORTS)) {
unsigned stream=f0.at(3).toUInt(&ok);
if(ok&&(stream<RD_MAX_STREAMS)) {
emit setOutputStatusFlagReq(id,card,port,stream,f0.at(4)=="1");
was_processed=true;
}
}
}
}
if((f0.at(0)=="JC")&&(f0.size()==3)) { // Connect Jack Ports
emit jackConnectPortsReq(id,f0.at(1),f0.at(2));
was_processed=true;
}
if((f0.at(0)=="JD")&&(f0.size()==3)) { // Disconnect Jack Ports
emit jackDisconnectPortsReq(id,f0.at(1),f0.at(2));
was_processed=true;
}
if((f0.at(0)=="ME")&&(f0.size()>=3)) { // Meter Enable
uint16_t udp_port=0xFFFF&f0.at(1).toUInt(&ok);
if(ok) {
QList<unsigned> cards;
for(int i=2;i<f0.size();i++) {
cards.push_back(f0.at(i).toUInt());
}
emit meterEnableReq(id,udp_port,cards);
was_processed=true;
}
}
if(!was_processed) { // Send generic error response
sendCommand(id,f0.join(" ")+"-!");
}
}

119
cae/cae_server.h Normal file
View File

@ -0,0 +1,119 @@
// cae_server.h
//
// Network server for caed(8).
//
// (C) Copyright 2019 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 CAE_SERVER_H
#define CAE_SERVER_H
#include <stdint.h>
#include <qlist.h>
#include <qmap.h>
#include <qobject.h>
#include <qsignalmapper.h>
#include <qtcpserver.h>
#include <qtcpsocket.h>
#include <rdconfig.h>
class CaeServerConnection
{
public:
CaeServerConnection(QTcpSocket *sock);
~CaeServerConnection();
QTcpSocket *socket;
bool authenticated;
QString accum;
uint16_t meter_port;
bool meters_enabled[RD_MAX_CARDS];
};
class CaeServer : public QObject
{
Q_OBJECT;
public:
CaeServer(RDConfig *config,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;
void setMetersEnabled(int id,unsigned card,bool state);
bool listen(const QHostAddress &addr,uint16_t port);
void sendCommand(const QString &cmd);
void sendCommand(int id,const QString &cmd);
signals:
void connectionDropped(int id);
void loadPlaybackReq(int id,unsigned card,const QString &name);
void unloadPlaybackReq(int id,unsigned handle);
void playPositionReq(int id,unsigned handle,unsigned pos);
void playReq(int id,unsigned handle,unsigned length,unsigned speed,unsigned pitch_flag);
void stopPlaybackReq(int id,unsigned handle);
void timescalingSupportReq(int id,unsigned card);
void loadRecordingReq(int id,unsigned card,unsigned port,unsigned coding,
unsigned channels,unsigned samprate,unsigned bitrate,
const QString &name);
void unloadRecordingReq(int id,unsigned card,unsigned stream);
void recordReq(int id,unsigned card,unsigned stream,unsigned len,
int threshold_level);
void stopRecordingReq(int id,unsigned card,unsigned stream);
void setInputVolumeReq(int id,unsigned card,unsigned stream,int level);
void setOutputVolumeReq(int id,unsigned card,unsigned stream,unsigned port,
int level);
void fadeOutputVolumeReq(int id,unsigned card,unsigned stream,unsigned port,
int level,unsigned length);
void setInputLevelReq(int id,unsigned card,unsigned port,int level);
void setOutputLevelReq(int id,unsigned card,unsigned port,int level);
void setInputModeReq(int id,unsigned card,unsigned stream,unsigned mode);
void setOutputModeReq(int id,unsigned card,unsigned stream,unsigned mode);
void setInputVoxLevelReq(int id,unsigned card,unsigned stream,int level);
void setInputTypeReq(int id,unsigned card,unsigned port,unsigned type);
void getInputStatusReq(int id,unsigned card,unsigned port);
void setAudioPassthroughLevelReq(int id,unsigned card,unsigned input,
unsigned output,int level);
void setClockSourceReq(int id,unsigned card,int input);
void setOutputStatusFlagReq(int id,unsigned card,unsigned port,
unsigned stream,bool state);
void openRtpCaptureChannelReq(int id,unsigned card,unsigned port,uint16_t udp_port,
unsigned samprate,unsigned chans);
void jackConnectPortsReq(int id,const QString &out_name,const QString &in_name);
void jackDisconnectPortsReq(int id,const QString &out_name,const QString &in_name);
void meterEnableReq(int id,uint16_t udp_port,const QList<unsigned> &cards);
private slots:
void newConnectionData();
void readyReadData(int id);
void connectionClosedData(int id);
private:
void ProcessCommand(int id,const QString &cmd);
QMap<int,CaeServerConnection *> cae_connections;
QTcpServer *cae_server;
QSignalMapper *cae_ready_read_mapper;
QSignalMapper *cae_connection_closed_mapper;
RDConfig *cae_config;
};
#endif // CAE_SERVER_H

View File

@ -1,53 +0,0 @@
// socket.cpp
//
// The Core Audio Engine component of Rivendell
//
// (C) Copyright 2002,2016 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 <qapplication.h>
#include <qobject.h>
#include <q3serversocket.h>
#include <qhostaddress.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <math.h>
#include <cae.h>
#include <cae_socket.h>
CaeSocket::CaeSocket(Q_UINT16 port,int backlog,QObject *parent,
const char *name)
: Q3ServerSocket(port,0,parent,name)
{
}
CaeSocket::CaeSocket(const QHostAddress &address,Q_UINT16 port,int backlog,
QObject *parent,const char *name)
: Q3ServerSocket(address,port,0,parent,name)
{
}
void CaeSocket::newConnection(int fd)
{
emit connection(fd);
}

View File

@ -1,48 +0,0 @@
// cae_socket.h
//
// The Core Audio Engine component of Rivendell
//
// (C) Copyright 2002,2016 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 SOCKET_H
#define SOCKET_H
#include <qobject.h>
#include <qstring.h>
#include <q3serversocket.h>
#include <qhostaddress.h>
class CaeSocket : public Q3ServerSocket
{
Q_OBJECT
public:
CaeSocket(Q_UINT16 port,int backlog=0,QObject *parent=0,
const char *name=0);
CaeSocket(const QHostAddress &address,Q_UINT16 port,int backlog=0,
QObject *parent=0,const char *name=0);
void newConnection(int socket);
signals:
void connection(int);
private:
Q3ServerSocket *socket;
};
#endif

View File

@ -2,7 +2,7 @@
//
// System-Wide Values for Rivendell
//
// (C) Copyright 2002-2018 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2002-2019 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
@ -365,7 +365,6 @@
#define CAE_MAX_ARGS 10
#define CAE_MAX_LENGTH 256
#define CAE_POLL_INTERVAL 50
#define CAE_MAX_CONNECTIONS 128
/*
* Default Sample Rate

View File

@ -541,7 +541,6 @@ void RDCae::DispatchCommand(RDCmdCache *cmd)
for(int i=0;i<RD_MAX_CARDS;i++) {
for(int j=0;j<RD_MAX_STREAMS;j++) {
if(cae_handle[i][j]==handle) {
//emit playPositionChanged(handle,cae_output_positions[i][j]);
emit playPositionChanged(handle,pos);
}
}