mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-05-29 07:02:34 +02:00
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:
parent
f6fa420cfd
commit
c7b6322bc6
@ -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.
|
||||
|
@ -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@\
|
||||
|
2613
cae/cae.cpp
2613
cae/cae.cpp
File diff suppressed because it is too large
Load Diff
70
cae/cae.h
70
cae/cae.h
@ -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
543
cae/cae_server.cpp
Normal 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
119
cae/cae_server.h
Normal 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
|
@ -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);
|
||||
}
|
@ -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
|
3
lib/rd.h
3
lib/rd.h
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user