2021-08-18 Fred Gleason <fredg@paravelsystems.com>

* Refactored the HPI driver in caed(8) to use virtual inheritance.
	* Disabled JACK driver support in caed(8).
	* Disabled ALSA driver support in caed(8).

Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
Fred Gleason 2021-08-18 11:14:41 -04:00
parent 13f2d5c0ca
commit 6ed4643fc1
16 changed files with 1380 additions and 853 deletions

View File

@ -22304,3 +22304,7 @@
2021-08-17 Fred Gleason <fredg@paravelsystems.com>
* Fixed a regression in rdlogmanager(1) that caused it to attempt to
open an X11 connection even when invoked in CLI mode.
2021-08-18 Fred Gleason <fredg@paravelsystems.com>
* Refactored the HPI driver in caed(8) to use virtual inheritance.
* Disabled JACK driver support in caed(8).
* Disabled ALSA driver support in caed(8).

View File

@ -2,7 +2,7 @@
##
## Core Audio Engine Makefile.am for Rivendell
##
## Copyright 2002-2020 Fred Gleason <fredg@paravelsystems.com>
## Copyright 2002-2021 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,15 @@ dist_caed_SOURCES = cae.cpp cae.h\
cae_alsa.cpp\
cae_hpi.cpp\
cae_jack.cpp\
cae_server.cpp cae_server.h
cae_server.cpp cae_server.h\
caedriver.cpp caedriver.h\
caedriverfactory.cpp caedriverfactory.h\
hpidriver.cpp hpidriver.h
nodist_caed_SOURCES = moc_cae.cpp\
moc_cae_server.cpp
moc_cae_server.cpp\
moc_caedriver.cpp\
moc_hpidriver.cpp
caed_LDADD = @LIB_RDLIBS@\
@LIBALSA@\

File diff suppressed because it is too large Load Diff

View File

@ -74,6 +74,7 @@ struct alsa_format {
#include <rdconfig.h>
#include <rdstation.h>
#include "caedriver.h"
#include "cae_server.h"
#ifndef HAVE_SRC_CONV
@ -96,7 +97,7 @@ void src_float_to_int_array (const float *in, int *out, int len);
// Function Prototypes
//
void SigHandler(int signum);
extern RDConfig *rd_config;
//extern RDConfig *rd_config;
class MainObject : public QObject
{
@ -183,12 +184,19 @@ class MainObject : public QObject
int owner;
} play_handle[256];
int next_play_handle;
RDStation *cae_station;
// RDStation *cae_station;
//
// New Stuff
//
CaeDriver *GetDriver(unsigned card) const;
QList<CaeDriver *> d_drivers;
//
// HPI Driver
//
private:
/*
void hpiInit(RDStation *station);
void hpiFree();
QString hpiVersion();
@ -225,6 +233,7 @@ class MainObject : public QObject
RDHPIRecordStream *record[RD_MAX_CARDS][RD_MAX_STREAMS];
RDHPIPlayStream *play[RD_MAX_CARDS][RD_MAX_STREAMS];
#endif // HPI
*/
//
// JACK Driver

View File

@ -69,14 +69,13 @@ void *AlsaCaptureCallback(void *ptr)
while(!alsa_format->exiting) {
int s=snd_pcm_readi(alsa_format->pcm,alsa_format->card_buffer,
rd_config->alsaPeriodSize()/(alsa_format->periods*2));
rda->config()->alsaPeriodSize()/(alsa_format->periods*2));
if(((snd_pcm_state(alsa_format->pcm)!=SND_PCM_STATE_RUNNING)&&
(!alsa_format->exiting))||(s<0)) {
snd_pcm_drop (alsa_format->pcm);
snd_pcm_prepare(alsa_format->pcm);
RDApplication::syslog(rd_config,LOG_DEBUG,
"****** ALSA Capture Xrun - Card: %d ******",
alsa_format->card);
rda->syslog(LOG_DEBUG,"****** ALSA Capture Xrun - Card: %d ******",
alsa_format->card);
}
else {
switch(alsa_format->format) {
@ -512,11 +511,11 @@ void *AlsaPlayCallback(void *ptr)
int s=snd_pcm_writei(alsa_format->pcm,alsa_format->card_buffer,n);
if(s!=n) {
if(s<0) {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"*** alsa error %d: %s",-s,snd_strerror(s));
}
else {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"period size mismatch - wrote %d",s);
}
}
@ -524,7 +523,7 @@ void *AlsaPlayCallback(void *ptr)
(!alsa_format->exiting)) {
snd_pcm_drop (alsa_format->pcm);
snd_pcm_prepare(alsa_format->pcm);
RDApplication::syslog(rd_config,LOG_DEBUG,
rda->syslog(LOG_DEBUG,
"****** ALSA Playout Xrun - Card: %d ******",
alsa_format->card);
}
@ -537,7 +536,7 @@ void *AlsaPlayCallback(void *ptr)
void MainObject::AlsaInitCallback()
{
int avg_periods=
(330*system_sample_rate)/(1000*rd_config->alsaPeriodSize());
(330*system_sample_rate)/(1000*rda->config()->alsaPeriodSize());
for(int i=0;i<RD_MAX_CARDS;i++) {
for(int j=0;j<RD_MAX_PORTS;j++) {
alsa_recording[i][j]=false;
@ -604,7 +603,7 @@ void MainObject::alsaFadeTimerData(int cardstream)
alsa_fade_timer[card][stream]->stop();
}
}
RDApplication::syslog(rd_config,LOG_DEBUG,"FadeLevel: %d",level);
rda->syslog(LOG_DEBUG,"FadeLevel: %d",level);
alsaSetOutputVolume(card,stream,alsa_fade_port[card][stream],level);
#endif // ALSA
}
@ -726,7 +725,7 @@ void MainObject::alsaInit(RDStation *station)
if(cae_driver[i]==RDStation::Alsa) {
station->setCardDriver(i,RDStation::Alsa);
if(snd_ctl_open(&snd_ctl,dev.toUtf8(),0)<0) {
RDApplication::syslog(rd_config,LOG_INFO,
rda->syslog(LOG_INFO,
"no control device found for %s",
dev.toUtf8().constData());
station->setCardName(i,tr("ALSA Device")+" "+dev);
@ -784,14 +783,14 @@ bool MainObject::alsaLoadPlayback(int card,QString wavename,int *stream)
{
#ifdef ALSA
if(alsa_play_format[card].exiting||((*stream=GetAlsaOutputStream(card))<0)) {
RDApplication::syslog(rd_config,LOG_DEBUG,
rda->syslog(LOG_DEBUG,
"alsaLoadPlayback(%s) GetAlsaOutputStream():%d < 0",
(const char *)wavename.toUtf8(),*stream);
return false;
}
alsa_play_wave[card][*stream]=new RDWaveFile(wavename);
if(!alsa_play_wave[card][*stream]->openWave()) {
RDApplication::syslog(rd_config,LOG_DEBUG,
rda->syslog(LOG_DEBUG,
"alsaLoadPlayback(%s) openWave() failed to open file",
(const char *)wavename.toUtf8());
delete alsa_play_wave[card][*stream];
@ -810,7 +809,7 @@ bool MainObject::alsaLoadPlayback(int card,QString wavename,int *stream)
break;
default:
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"alsaLoadPlayback(%s) getFormatTag()%d || getBistsPerSample()%d failed",
(const char *)wavename.toUtf8(),
alsa_play_wave[card][*stream]->getFormatTag(),
@ -998,7 +997,7 @@ bool MainObject::alsaLoadRecord(int card,int stream,int coding,int chans,
break;
default:
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"requested unsupported channel count %d, card: %d, stream: %d",
chans,card,stream);
delete alsa_record_wave[card][stream];
@ -1026,7 +1025,7 @@ bool MainObject::alsaLoadRecord(int card,int stream,int coding,int chans,
break;
default:
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"requested invalid audio encoding %d, card: %d, stream: %d",
coding,card,stream);
delete alsa_record_wave[card][stream];
@ -1040,8 +1039,8 @@ bool MainObject::alsaLoadRecord(int card,int stream,int coding,int chans,
alsa_record_wave[card][stream]=NULL;
return false;
}
RDCheckExitCode(rd_config,"alsaLoadRecord() chown",
chown(wavename.toUtf8(),rd_config->uid(),rd_config->gid()));
RDCheckExitCode(rda->config(),"alsaLoadRecord() chown",
chown(wavename.toUtf8(),rda->config()->uid(),rda->config()->gid()));
alsa_input_channels[card][stream]=chans;
alsa_record_ring[card][stream]=new RDRingBuffer(RINGBUFFER_SIZE);
alsa_record_ring[card][stream]->reset();
@ -1367,7 +1366,7 @@ bool MainObject::AlsaStartCaptureDevice(QString &dev,int card,snd_pcm_t *pcm)
snd_pcm_hw_params_alloca(&hwparams);
snd_pcm_hw_params_any(pcm,hwparams);
RDApplication::syslog(rd_config,LOG_INFO,"Starting ALSA Capture Device %s:",
rda->syslog(LOG_INFO,"Starting ALSA Capture Device %s:",
(const char *)dev.toUtf8());
//
@ -1375,9 +1374,9 @@ bool MainObject::AlsaStartCaptureDevice(QString &dev,int card,snd_pcm_t *pcm)
//
if(snd_pcm_hw_params_test_access(pcm,hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED)<0) {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" Interleaved access not supported,");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" aborting initialization of device.");
return false;
}
@ -1388,18 +1387,18 @@ bool MainObject::AlsaStartCaptureDevice(QString &dev,int card,snd_pcm_t *pcm)
//
if(snd_pcm_hw_params_test_format(pcm,hwparams,SND_PCM_FORMAT_S32_LE)==0) {
alsa_capture_format[card].format=SND_PCM_FORMAT_S32_LE;
RDApplication::syslog(rd_config,LOG_INFO," Format = 32 bit little-endian");
rda->syslog(LOG_INFO," Format = 32 bit little-endian");
}
else {
if(snd_pcm_hw_params_test_format(pcm,hwparams,SND_PCM_FORMAT_S16_LE)==0) {
alsa_capture_format[card].format=SND_PCM_FORMAT_S16_LE;
RDApplication::syslog(rd_config,LOG_INFO,
rda->syslog(LOG_INFO,
" Format = 16 bit little-endian");
}
else {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" Neither 16 nor 32 bit little-endian formats available,");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" aborting initialization of device.");
return false;
}
@ -1418,57 +1417,57 @@ bool MainObject::AlsaStartCaptureDevice(QString &dev,int card,snd_pcm_t *pcm)
snd_pcm_hw_params_set_rate_near(pcm,hwparams,&sr,&dir);
if((sr<(system_sample_rate-RD_ALSA_SAMPLE_RATE_TOLERANCE))||
(sr>(system_sample_rate+RD_ALSA_SAMPLE_RATE_TOLERANCE))) {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" Asked for sample rate %u, got %u",
system_sample_rate,sr);
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" Sample rate unsupported by device");
return false;
}
alsa_capture_format[card].sample_rate=sr;
RDApplication::syslog(rd_config,LOG_INFO," SampleRate = %u",sr);
rda->syslog(LOG_INFO," SampleRate = %u",sr);
//
// Channels
//
if(rd_config->alsaChannelsPerPcm()<0) {
if(rda->config()->alsaChannelsPerPcm()<0) {
alsa_capture_format[card].channels=RD_DEFAULT_CHANNELS*RD_MAX_PORTS;
}
else {
alsa_capture_format[card].channels=rd_config->alsaChannelsPerPcm();
alsa_capture_format[card].channels=rda->config()->alsaChannelsPerPcm();
}
snd_pcm_hw_params_set_channels_near(pcm,hwparams,
&alsa_capture_format[card].channels);
alsa_play_format[card].capture_channels=alsa_capture_format[card].channels;
RDApplication::syslog(rd_config,LOG_INFO," Aggregate Channels = %u",
rda->syslog(LOG_INFO," Aggregate Channels = %u",
alsa_capture_format[card].channels);
//
// Buffer Size
//
alsa_capture_format[card].periods=rd_config->alsaPeriodQuantity();
alsa_capture_format[card].periods=rda->config()->alsaPeriodQuantity();
snd_pcm_hw_params_set_periods_near(pcm,hwparams,
&alsa_capture_format[card].periods,&dir);
RDApplication::syslog(rd_config,LOG_INFO,
rda->syslog(LOG_INFO,
" Periods = %u",alsa_capture_format[card].periods);
alsa_capture_format[card].buffer_size=
alsa_capture_format[card].periods*rd_config->alsaPeriodSize();
alsa_capture_format[card].periods*rda->config()->alsaPeriodSize();
snd_pcm_hw_params_set_buffer_size_near(pcm,hwparams,
&alsa_capture_format[card].buffer_size);
RDApplication::syslog(rd_config,LOG_INFO," BufferSize = %u frames",
rda->syslog(LOG_INFO," BufferSize = %u frames",
(unsigned)alsa_capture_format[card].buffer_size);
//
// Fire It Up
//
if((err=snd_pcm_hw_params(pcm,hwparams))<0) {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" Device Error: %s,",snd_strerror(err));
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" aborting initialization of device.");
return false;
}
RDApplication::syslog(rd_config,LOG_INFO," Device started successfully");
rda->syslog(LOG_INFO," Device started successfully");
switch(alsa_capture_format[card].format) {
case SND_PCM_FORMAT_S16_LE:
alsa_capture_format[card].card_buffer_size=
@ -1496,9 +1495,9 @@ bool MainObject::AlsaStartCaptureDevice(QString &dev,int card,snd_pcm_t *pcm)
//
snd_pcm_sw_params_alloca(&swparams);
snd_pcm_sw_params_current(pcm,swparams);
snd_pcm_sw_params_set_avail_min(pcm,swparams,rd_config->alsaPeriodSize());
snd_pcm_sw_params_set_avail_min(pcm,swparams,rda->config()->alsaPeriodSize());
if((err=snd_pcm_sw_params(pcm,swparams))<0) {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"ALSA Device %s: %s",(const char *)dev.toUtf8(),
snd_strerror(err));
return false;
@ -1534,7 +1533,7 @@ bool MainObject::AlsaStartPlayDevice(QString &dev,int card,snd_pcm_t *pcm)
snd_pcm_hw_params_alloca(&hwparams);
snd_pcm_hw_params_any(pcm,hwparams);
RDApplication::syslog(rd_config,LOG_INFO,"Starting ALSA Play Device %s:",
rda->syslog(LOG_INFO,"Starting ALSA Play Device %s:",
(const char *)dev.toUtf8());
//
@ -1542,9 +1541,9 @@ bool MainObject::AlsaStartPlayDevice(QString &dev,int card,snd_pcm_t *pcm)
//
if(snd_pcm_hw_params_test_access(pcm,hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED)<0) {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" Interleaved access not supported,");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" aborting initialization of device.");
return false;
}
@ -1555,18 +1554,18 @@ bool MainObject::AlsaStartPlayDevice(QString &dev,int card,snd_pcm_t *pcm)
//
if(snd_pcm_hw_params_test_format(pcm,hwparams,SND_PCM_FORMAT_S32_LE)==0) {
alsa_play_format[card].format=SND_PCM_FORMAT_S32_LE;
RDApplication::syslog(rd_config,LOG_INFO," Format = 32 bit little-endian");
rda->syslog(LOG_INFO," Format = 32 bit little-endian");
}
else {
if(snd_pcm_hw_params_test_format(pcm,hwparams,SND_PCM_FORMAT_S16_LE)==0) {
alsa_play_format[card].format=SND_PCM_FORMAT_S16_LE;
RDApplication::syslog(rd_config,LOG_INFO,
rda->syslog(LOG_INFO,
" Format = 16 bit little-endian");
}
else {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" Neither 16 nor 32 bit little-endian formats available,");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" aborting initialization of device.");
return false;
}
@ -1580,55 +1579,55 @@ bool MainObject::AlsaStartPlayDevice(QString &dev,int card,snd_pcm_t *pcm)
snd_pcm_hw_params_set_rate_near(pcm,hwparams,&sr,&dir);
if((sr<(system_sample_rate-RD_ALSA_SAMPLE_RATE_TOLERANCE))||
(sr>(system_sample_rate+RD_ALSA_SAMPLE_RATE_TOLERANCE))) {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" Asked for sample rate %u, got %u",
system_sample_rate,sr);
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" Sample rate unsupported by device");
return false;
}
alsa_play_format[card].sample_rate=sr;
RDApplication::syslog(rd_config,LOG_INFO," SampleRate = %u",sr);
rda->syslog(LOG_INFO," SampleRate = %u",sr);
//
// Channels
//
if(rd_config->alsaChannelsPerPcm()<0) {
if(rda->config()->alsaChannelsPerPcm()<0) {
alsa_play_format[card].channels=RD_DEFAULT_CHANNELS*RD_MAX_PORTS;
}
else {
alsa_play_format[card].channels=rd_config->alsaChannelsPerPcm();
alsa_play_format[card].channels=rda->config()->alsaChannelsPerPcm();
}
snd_pcm_hw_params_set_channels_near(pcm,hwparams,
&alsa_play_format[card].channels);
RDApplication::syslog(rd_config,LOG_INFO," Aggregate Channels = %u",
rda->syslog(LOG_INFO," Aggregate Channels = %u",
alsa_play_format[card].channels);
//
// Buffer Size
//
alsa_play_format[card].periods=rd_config->alsaPeriodQuantity();
alsa_play_format[card].periods=rda->config()->alsaPeriodQuantity();
snd_pcm_hw_params_set_periods_near(pcm,hwparams,
&alsa_play_format[card].periods,&dir);
RDApplication::syslog(rd_config,LOG_INFO,
rda->syslog(LOG_INFO,
" Periods = %u",alsa_play_format[card].periods);
alsa_play_format[card].buffer_size=
alsa_play_format[card].periods*rd_config->alsaPeriodSize();
alsa_play_format[card].periods*rda->config()->alsaPeriodSize();
snd_pcm_hw_params_set_buffer_size_near(pcm,hwparams,
&alsa_play_format[card].buffer_size);
RDApplication::syslog(rd_config,LOG_INFO," BufferSize = %u frames",
rda->syslog(LOG_INFO," BufferSize = %u frames",
(unsigned)alsa_play_format[card].buffer_size);
//
// Fire It Up
//
if((err=snd_pcm_hw_params(pcm,hwparams))<0) {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
" Device Error: %s,",snd_strerror(err));
RDApplication::syslog(rd_config,LOG_ERR,
rda->syslog(LOG_ERR,
" aborting initialization of device.");
return false;
}
RDApplication::syslog(rd_config,LOG_INFO," Device started successfully");
rda->syslog(LOG_INFO," Device started successfully");
switch(alsa_play_format[card].format) {
case SND_PCM_FORMAT_S16_LE:
alsa_play_format[card].card_buffer_size=
@ -1655,9 +1654,9 @@ bool MainObject::AlsaStartPlayDevice(QString &dev,int card,snd_pcm_t *pcm)
//
snd_pcm_sw_params_alloca(&swparams);
snd_pcm_sw_params_current(pcm,swparams);
snd_pcm_sw_params_set_avail_min(pcm,swparams,rd_config->alsaPeriodSize());
snd_pcm_sw_params_set_avail_min(pcm,swparams,rda->config()->alsaPeriodSize());
if((err=snd_pcm_sw_params(pcm,swparams))<0) {
RDApplication::syslog(rd_config,LOG_WARNING,"ALSA Device %s: %s",
rda->syslog(LOG_WARNING,"ALSA Device %s: %s",
(const char *)dev.toUtf8(),snd_strerror(err));
return false;
}
@ -1748,7 +1747,7 @@ void MainObject::WriteAlsaBuffer(int card,int stream,int16_t *buffer,unsigned le
alsa_record_wave[card][stream]->writeWave(mpeg,s);
}
else {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"TwoLAME encode error, card: %d, stream: %d",
card,stream);
}

View File

@ -25,7 +25,7 @@
#include <rddebug.h>
#include "cae.h"
/*
void MainObject::hpiInit(RDStation *station)
{
#ifdef HPI
@ -529,3 +529,4 @@ bool MainObject::hpiSetPassthroughLevel(int card,int in_port,int out_port,
return false;
#endif // HPI
}
*/

View File

@ -436,23 +436,23 @@ void MainObject::jackClientStartData()
"`DESCRIPTION`,"+ // 00
"`COMMAND_LINE` "+ // 01
"from `JACK_CLIENTS` where "+
"`STATION_NAME`='"+RDEscapeString(rd_config->stationName())+"'";
"`STATION_NAME`='"+RDEscapeString(rda->config()->stationName())+"'";
RDSqlQuery *q=new RDSqlQuery(sql);
while(q->next()) {
QString cmd=RDDateDecode(q->value(1).toString(),QDate::currentDate(),
cae_station,rd_config,
rd_config->provisioningServiceName(rd_config->stationName()));
rda->station(),rda->config(),
rda->config()->provisioningServiceName(rda->config()->stationName()));
QStringList args=cmd.split(" ",QString::SkipEmptyParts);
QString program=args.at(0);
args.removeFirst();
jack_clients.push_back(new QProcess(this));
jack_clients.back()->start(program,args);
if(jack_clients.back()->waitForStarted()) {
RDApplication::syslog(rd_config,LOG_INFO,"started JACK Client \"%s\"",
rda->syslog(LOG_INFO,"started JACK Client \"%s\"",
(const char *)q->value(0).toString().toUtf8());
}
else {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"failed to start JACK Client \"%s\" [%s]",
(const char *)q->value(0).toString().toUtf8(),
(const char *)q->value(1).toString().toUtf8());
@ -482,7 +482,7 @@ void MainObject::jackInit(RDStation *station)
}
}
if(jack_card==RD_MAX_CARDS) {
RDApplication::syslog(rd_config,LOG_INFO,"no more RD cards available");
rda->syslog(LOG_INFO,"no more RD cards available");
return;
}
QString name=QString().sprintf("rivendell_%d",jack_card);
@ -499,16 +499,16 @@ void MainObject::jackInit(RDStation *station)
QProcess *proc=new QProcess(this);
proc->start(program,args);
if(proc->waitForStarted()) {
RDApplication::syslog(rd_config,LOG_INFO,"JACK server started");
rda->syslog(LOG_INFO,"JACK server started");
}
else {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"failed to start JACK server");
}
sleep(1);
}
else {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"could not start JACK server: no command line specified");
}
}
@ -528,70 +528,70 @@ void MainObject::jackInit(RDStation *station)
if(jack_client==NULL) {
if((jackstat&JackInvalidOption)!=0) {
fprintf (stderr, "invalid or unsupported JACK option\n");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"invalid or unsupported JACK option");
}
if((jackstat&JackServerError)!=0) {
fprintf (stderr, "communication error with the JACK server\n");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"communication error with the JACK server");
}
if((jackstat&JackNoSuchClient)!=0) {
fprintf (stderr, "requested JACK client does not exist\n");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"requested JACK client does not exist");
}
if((jackstat&JackLoadFailure)!=0) {
fprintf (stderr, "unable to load internal JACK client\n");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"unable to load internal JACK client");
}
if((jackstat&JackInitFailure)!=0) {
fprintf (stderr, "unable to initialize JACK client\n");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"unable to initialize JACK client");
}
if((jackstat&JackShmFailure)!=0) {
fprintf (stderr, "unable to access JACK shared memory\n");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"unable to access JACK shared memory");
}
if((jackstat&JackVersionError)!=0) {
fprintf (stderr, "JACK protocol version mismatch\n");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"JACK protocol version mismatch");
}
if((jackstat&JackServerStarted)!=0) {
fprintf (stderr, "JACK server started\n");
RDApplication::syslog(rd_config,LOG_WARNING,"JACK server started");
rda->syslog(LOG_WARNING,"JACK server started");
}
if((jackstat&JackServerFailed)!=0) {
fprintf (stderr, "unable to communication with JACK server\n");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"unable to communicate with JACK server");
}
if((jackstat&JackNameNotUnique)!=0) {
fprintf (stderr, "JACK client name not unique\n");
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"JACK client name not unique");
}
if((jackstat&JackFailure)!=0) {
fprintf (stderr, "JACK general failure\n");
RDApplication::syslog(rd_config,LOG_WARNING,"JACK general failure");
rda->syslog(LOG_WARNING,"JACK general failure");
}
jack_card=-1;
fprintf (stderr, "no connection to JACK server\n");
RDApplication::syslog(rd_config,LOG_WARNING,"no connection to JACK server");
rda->syslog(LOG_WARNING,"no connection to JACK server");
return;
}
jack_connected=true;
@ -603,7 +603,7 @@ void MainObject::jackInit(RDStation *station)
#else
jack_on_shutdown(jack_client,JackShutdown,0);
#endif // HAVE_JACK_INFO_SHUTDOWN
RDApplication::syslog(rd_config,LOG_INFO,"connected to JACK server");
rda->syslog(LOG_INFO,"connected to JACK server");
//
// Start JACK Clients
@ -722,7 +722,7 @@ void MainObject::jackInit(RDStation *station)
jack_sample_rate=jack_get_sample_rate(jack_client);
if(jack_sample_rate!=system_sample_rate) {
fprintf (stderr,"JACK sample rate mismatch!\n");
RDApplication::syslog(rd_config,LOG_WARNING,"JACK sample rate mismatch!");
rda->syslog(LOG_WARNING,"JACK sample rate mismatch!");
}
jack_activated=true;
cae_driver[jack_card]=RDStation::Jack;
@ -751,14 +751,14 @@ bool MainObject::jackLoadPlayback(int card,QString wavename,int *stream)
{
#ifdef JACK
if((*stream=GetJackOutputStream())<0) {
RDApplication::syslog(rd_config,LOG_DEBUG,
rda->syslog(LOG_DEBUG,
"jackLoadPlayback(%s) GetJackOutputStream():%d <0",
(const char *)wavename.toUtf8(),*stream);
return false;
}
jack_play_wave[*stream]=new RDWaveFile(wavename);
if(!jack_play_wave[*stream]->openWave()) {
RDApplication::syslog(rd_config,LOG_DEBUG,
rda->syslog(LOG_DEBUG,
"jackLoadPlayback(%s) openWave() failed to open file",
(const char *)wavename.toUtf8());
delete jack_play_wave[*stream];
@ -777,7 +777,7 @@ bool MainObject::jackLoadPlayback(int card,QString wavename,int *stream)
break;
default:
RDApplication::syslog(rd_config,LOG_DEBUG,
rda->syslog(LOG_DEBUG,
"jackLoadPlayback(%s) getFormatTag()%d || getBistsPerSample()%d failed",
(const char *) wavename.toUtf8(),
jack_play_wave[*stream]->getFormatTag(),
@ -972,7 +972,7 @@ bool MainObject::jackLoadRecord(int card,int stream,int coding,int chans,
break;
default:
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"requested unsupported channel count %d, card: %d, stream: %d",
chans,card,stream);
delete jack_record_wave[stream];
@ -1000,7 +1000,7 @@ bool MainObject::jackLoadRecord(int card,int stream,int coding,int chans,
break;
default:
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"requested invalid audio encoding %d, card: %d, stream: %d",
coding,card,stream);
delete jack_record_wave[stream];
@ -1014,8 +1014,8 @@ bool MainObject::jackLoadRecord(int card,int stream,int coding,int chans,
jack_record_wave[stream]=NULL;
return false;
}
RDCheckExitCode(rd_config,"jackLoadRecord() chown",
chown(wavename.toUtf8(),rd_config->uid(),rd_config->gid()));
RDCheckExitCode(rda->config(),"jackLoadRecord() chown",
chown(wavename.toUtf8(),rda->config()->uid(),rda->config()->gid()));
jack_input_channels[stream]=chans;
jack_record_ring[stream]=new RDRingBuffer(RINGBUFFER_SIZE);
jack_record_ring[stream]->reset();
@ -1477,7 +1477,7 @@ void MainObject::WriteJackBuffer(int stream,jack_default_audio_sample_t *buffer,
jack_record_wave[stream]->writeWave(mpeg,s);
}
else {
RDApplication::syslog(rd_config,LOG_WARNING,
rda->syslog(LOG_WARNING,
"TwoLAME encode error, card: %d, stream: %d",jack_card,stream);
}
}
@ -1681,7 +1681,7 @@ void MainObject::JackSessionSetup()
QString dest=profile->stringValue("JackSession",dest_tag,"",&dest_ok);
while(src_ok&&dest_ok) {
if(jack_connect(jack_client,src.toUtf8(),dest.toUtf8())!=0) {
RDApplication::syslog(rd_config,LOG_WARNING,"unable to connect %s to %s",
rda->syslog(LOG_WARNING,"unable to connect %s to %s",
(const char *)src.toUtf8(),(const char *)dest.toUtf8());
}
count++;

View File

@ -217,6 +217,7 @@ void CaeServer::connectionClosedData(int id)
bool CaeServer::ProcessCommand(int id,const QString &cmd)
{
printf("CaeServer::ProcessCommand(%d,'%s')\n",id,cmd.toUtf8().constData());
CaeServerConnection *conn=cae_connections.value(id);
bool ok=false;
QString cmdstr=cmd;

65
cae/caedriver.cpp Normal file
View File

@ -0,0 +1,65 @@
// caedriver.cpp
//
// Abstract base class for caed(8) audio driver implementations.
//
// (C) Copyright 2021 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 "caedriver.h"
CaeDriver::CaeDriver(RDStation::AudioDriver type,QObject *parent)
: QObject(parent)
{
d_driver_type=type;
}
RDStation::AudioDriver CaeDriver::driverType() const
{
return d_driver_type;
}
bool CaeDriver::hasCard(int cardnum) const
{
return d_cards.contains(cardnum);
}
void CaeDriver::statePlayUpdate(int card,int stream,int state)
{
emit playStateChanged(card,stream,state);
}
void CaeDriver::stateRecordUpdate(int card,int stream,int state)
{
emit recordStateChanged(card,stream,state);
}
void CaeDriver::addCard(unsigned cardnum)
{
if(d_cards.contains(cardnum)) {
rda->syslog(LOG_WARNING,
"%s driver attempted to register card %u multiple times",
RDStation::audioDriverText(d_driver_type).toUtf8().constData(),
cardnum);
}
else {
d_cards.push_back(cardnum);
}
}

90
cae/caedriver.h Normal file
View File

@ -0,0 +1,90 @@
// caedriver.h
//
// Abstract base class for caed(8) audio driver implementations.
//
// (C) Copyright 2021 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 CAEDRIVER_H
#define CAEDRIVER_H
#include <QList>
#include <QObject>
#include <rdapplication.h>
class CaeDriver : public QObject
{
Q_OBJECT
public:
CaeDriver(RDStation::AudioDriver type,QObject *parent=0);
RDStation::AudioDriver driverType() const;
bool hasCard(int cardnum) const;
virtual QString version() const=0;
virtual bool initialize(unsigned *next_cardnum)=0;;
virtual void updateMeters()=0;
public:
virtual bool loadPlayback(int card,QString wavename,int *stream)=0;
virtual bool unloadPlayback(int card,int stream)=0;
virtual bool playbackPosition(int card,int stream,unsigned pos)=0;
virtual bool play(int card,int stream,int length,int speed,bool pitch,
bool rates)=0;
virtual bool stopPlayback(int card,int stream)=0;
virtual bool timescaleSupported(int card)=0;
virtual bool loadRecord(int card,int port,int coding,int chans,int samprate,
int bitrate,QString wavename)=0;
virtual bool unloadRecord(int card,int stream,unsigned *len)=0;
virtual bool record(int card,int stream,int length,int thres)=0;
virtual bool stopRecord(int card,int stream)=0;
virtual bool setClockSource(int card,int src)=0;
virtual bool setInputVolume(int card,int stream,int level)=0;
virtual bool setOutputVolume(int card,int stream,int port,int level)=0;
virtual bool fadeOutputVolume(int card,int stream,int port,int level,
int length)=0;
virtual bool setInputLevel(int card,int port,int level)=0;
virtual bool setOutputLevel(int card,int port,int level)=0;
virtual bool setInputMode(int card,int stream,int mode)=0;
virtual bool setOutputMode(int card,int stream,int mode)=0;
virtual bool setInputVoxLevel(int card,int stream,int level)=0;
virtual bool setInputType(int card,int port,int type)=0;
virtual bool getInputStatus(int card,int port)=0;
virtual bool getInputMeters(int card,int port,short levels[2])=0;
virtual bool getOutputMeters(int card,int port,short levels[2])=0;
virtual bool getStreamOutputMeters(int card,int stream,short levels[2])=0;
virtual bool setPassthroughLevel(int card,int in_port,int out_port,
int level)=0;
virtual void getOutputPosition(int card,unsigned *pos)=0;
signals:
void playStateChanged(int card,int stream,int state);
void recordStateChanged(int card,int stream,int state);
protected slots:
void statePlayUpdate(int card,int stream,int state);
void stateRecordUpdate(int card,int stream,int state);
protected:
void addCard(unsigned cardnum);
RDConfig *config() const;
private:
RDStation::AudioDriver d_driver_type;
QList<unsigned> d_cards;
};
#endif // CAEDRIVER_H

43
cae/caedriverfactory.cpp Normal file
View File

@ -0,0 +1,43 @@
// caedriverfactory.xpp
//
// Create CaeDriver instances.
//
// (C) Copyright 2021 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 "caedriverfactory.h"
#include "hpidriver.h"
CaeDriver *CaeDriverFactory(RDStation::AudioDriver dvr,QObject *parent)
{
CaeDriver *ret=NULL;
printf("HERE1\n");
switch(dvr) {
case RDStation::Hpi:
printf("HERE2\n");
ret=new HpiDriver(parent);
break;
case RDStation::Jack:
case RDStation::Alsa:
case RDStation::None:
printf("HERE3\n");
break;
}
printf("HERE4: %p\n",ret);
return ret;
}

33
cae/caedriverfactory.h Normal file
View File

@ -0,0 +1,33 @@
// caedriverfactory.h
//
// Create CaeDriver instances.
//
// (C) Copyright 2021 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 CAEDRIVERFACTORY_H
#define CAEDRIVERFACTORY_H
#include <QObject>
#include <rdstation.h>
#include "caedriver.h"
CaeDriver *CaeDriverFactory(RDStation::AudioDriver dvr,QObject *parent=0);
#endif // CAEDRIVERFACTORY_H

567
cae/hpidriver.cpp Normal file
View File

@ -0,0 +1,567 @@
// hpidriver.cpp
//
// caed(8) driver for AudioScience HPI audio devices.
//
// (C) Copyright 2021 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 <rdconf.h>
#include "hpidriver.h"
HpiDriver::HpiDriver(QObject *parent)
: CaeDriver(RDStation::Hpi,parent)
{
#ifdef HPI
for(int i=0;i<RD_MAX_CARDS;i++) {
for(int j=0;j<RD_MAX_STREAMS;j++) {
d_record_streams[i][j]=NULL;
d_play_streams[i][j]=NULL;
}
}
d_sound_card=new RDHPISoundCard(rda->config(),this);
#endif // HPI
}
HpiDriver::~HpiDriver()
{
#ifdef HPI
for(int i=0;i<RD_MAX_CARDS;i++) {
for(int j=0;j<RD_MAX_STREAMS;j++) {
if(d_record_streams[i][j]!=NULL) {
delete d_record_streams[i][j];
}
if(d_play_streams[i][j]!=NULL) {
delete d_play_streams[i][j];
}
}
}
delete d_sound_card;
#endif // HPI
}
QString HpiDriver::version() const
{
#ifdef HPI
if(d_sound_card==NULL) {
return tr("not active");
}
RDHPIInformation *info=d_sound_card->hpiInformation(0);
if(info->hpiVersion()==0) {
return tr("not active");
}
return QString().sprintf("%d.%02d.%02d",info->hpiMajorVersion(),
info->hpiMinorVersion(),info->hpiPointVersion());
#else
return tr("not enabled");
#endif // HPI
}
bool HpiDriver::initialize(unsigned *next_cardnum)
{
#ifdef HPI
d_sound_card->setFadeProfile(RD_FADE_TYPE);
for(int i=0;i<d_sound_card->getCardQuantity();i++) {
rda->station()->setCardDriver(i,RDStation::Hpi);
rda->station()->setCardName(i,d_sound_card->getCardDescription(i));
rda->station()->setCardInputs(i,d_sound_card->getCardInputPorts(i));
rda->station()->setCardOutputs(i,d_sound_card->getCardOutputPorts(i));
addCard(*next_cardnum);
(*next_cardnum)++;
}
return d_sound_card->getCardQuantity()>0;
#else
return false;
#endif // HPI
}
void HpiDriver::updateMeters()
{
#ifdef HPI
#endif // HPI
}
bool HpiDriver::loadPlayback(int card,QString wavename,int *stream)
{
#ifdef HPI
RDHPIPlayStream *playstream=new RDHPIPlayStream(d_sound_card);
playstream->setCard(card);
if(playstream->openWave(wavename)!=RDHPIPlayStream::Ok) {
rda->syslog(LOG_DEBUG,"hpiLoadPlayback(%s) openWave() failed to open file",
wavename.toUtf8().constData());
delete playstream;
return false;
}
*stream=playstream->getStream();
d_play_streams[card][*stream]=playstream;
connect(d_play_streams[card][*stream],SIGNAL(stateChanged(int,int,int)),
this,SLOT(statePlayUpdate(int,int,int)));
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::unloadPlayback(int card,int stream)
{
#ifdef HPI
if(d_play_streams[card][stream]==NULL) {
return false;
}
if(d_play_streams[card][stream]->getState()==RDHPIPlayStream::Playing) {
d_play_streams[card][stream]->pause();
}
d_play_streams[card][stream]->disconnect();
d_play_streams[card][stream]->closeWave();
delete d_play_streams[card][stream];
d_play_streams[card][stream]=NULL;
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::playbackPosition(int card,int stream,unsigned pos)
{
#ifdef HPI
if(d_play_streams[card][stream]==NULL) {
return false;
}
return d_play_streams[card][stream]->
setPosition((unsigned)((double)d_play_streams[card][stream]->
getSamplesPerSec()*(double)pos/1000.0));
#else
return false;
#endif // HPI
}
bool HpiDriver::play(int card,int stream,int length,int speed,bool pitch,
bool rates)
{
#ifdef HPI
if(d_play_streams[card][stream]==NULL) {
return false;
}
if(!d_play_streams[card][stream]->setSpeed(speed,pitch,rates)) {
return false;
}
d_play_streams[card][stream]->setPlayLength(length);
return d_play_streams[card][stream]->play();
#else
return false;
#endif // HPI
}
bool HpiDriver::stopPlayback(int card,int stream)
{
#ifdef HPI
if(d_play_streams[card][stream]==NULL) {
return false;
}
d_play_streams[card][stream]->pause();
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::timescaleSupported(int card)
{
#ifdef HPI
return d_sound_card->haveTimescaling(card);
#else
return false;
#endif // HPI
}
bool HpiDriver::loadRecord(int card,int port,int coding,int chans,int samprate,
int bitrate,QString wavename)
{
#ifdef HPI
d_record_streams[card][port]=new RDHPIRecordStream(d_sound_card);
connect(d_record_streams[card][port],SIGNAL(stateChanged(int,int,int)),
this,SLOT(stateRecordUpdate(int,int,int)));
d_record_streams[card][port]->setCard(card);
d_record_streams[card][port]->setStream(port);
d_record_streams[card][port]->nameWave(wavename);
d_record_streams[card][port]->setChannels(chans);
d_record_streams[card][port]->setSamplesPerSec(samprate);
if(coding==0) { // PCM16
d_record_streams[card][port]->setFormatTag(WAVE_FORMAT_PCM);
d_record_streams[card][port]->setBitsPerSample(16);
}
if((coding==1)||(coding==2)) { // MPEG-1
d_record_streams[card][port]->setFormatTag(WAVE_FORMAT_MPEG);
d_record_streams[card][port]->setHeadLayer(coding);
d_record_streams[card][port]->setHeadBitRate(bitrate);
d_record_streams[card][port]->setMextChunk(true);
switch(chans) {
case 1:
d_record_streams[card][port]->setHeadMode(ACM_MPEG_SINGLECHANNEL);
break;
case 2:
d_record_streams[card][port]->setHeadMode(ACM_MPEG_STEREO);
break;
default:
delete d_record_streams[card][port];
d_record_streams[card][port]=NULL;
return false;
}
d_record_streams[card][port]->setHeadFlags(ACM_MPEG_ID_MPEG1);
}
if(coding==4) { // PCM24
d_record_streams[card][port]->setFormatTag(WAVE_FORMAT_PCM);
d_record_streams[card][port]->setBitsPerSample(24);
}
if(coding>4) {
delete d_record_streams[card][port];
d_record_streams[card][port]=NULL;
return false;
}
d_record_streams[card][port]->setBextChunk(true);
d_record_streams[card][port]->setCartChunk(true);
d_record_streams[card][port]->setLevlChunk(true);
if(d_record_streams[card][port]->createWave()!=RDHPIRecordStream::Ok) {
delete d_record_streams[card][port];
d_record_streams[card][port]=NULL;
return false;
}
RDCheckExitCode(rda->config(),"hpiLoadRecord() chown",
chown(wavename.toUtf8(),rda->config()->uid(),rda->config()->gid()));
if(!d_record_streams[card][port]->recordReady()) {
delete d_record_streams[card][port];
d_record_streams[card][port]=NULL;
return false;
}
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::unloadRecord(int card,int port,unsigned *len)
{
#ifdef HPI
if(d_record_streams[card][port]==NULL) {
return false;
}
if(d_record_streams[card][port]->getState()==RDHPIRecordStream::Recording) {
d_record_streams[card][port]->pause();
}
d_record_streams[card][port]->disconnect();
*len=d_record_streams[card][port]->samplesRecorded();
d_record_streams[card][port]->closeWave();
delete d_record_streams[card][port];
d_record_streams[card][port]=NULL;
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::record(int card,int port,int length,int thres)
{
#ifdef HPI
if(d_record_streams[card][port]==NULL) {
return false;
}
if(thres!=0) {
if(d_record_streams[card][port]->haveInputVOX()) {
d_record_streams[card][port]->setInputVOX(thres);
}
else {
return false;
}
}
d_record_streams[card][port]->setRecordLength(length);
d_record_streams[card][port]->record();
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::stopRecord(int card,int port)
{
#ifdef HPI
if(d_record_streams[card][port]==NULL) {
return false;
}
d_record_streams[card][port]->pause();
d_record_streams[card][port]->setInputVOX(-10000);
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::setClockSource(int card,int src)
{
#ifdef HPI
return d_sound_card->setClockSource(card,(RDHPISoundCard::ClockSource)src);
#else
return false;
#endif // HPI
}
bool HpiDriver::setInputVolume(int card,int stream,int level)
{
#ifdef HPI
d_sound_card->setInputVolume(card,stream,level);
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::setOutputVolume(int card,int stream,int port,int level)
{
#ifdef HPI
d_sound_card->setOutputVolume(card,stream,port,level);
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::fadeOutputVolume(int card,int stream,int port,int level,
int length)
{
#ifdef HPI
d_sound_card->fadeOutputVolume(card,stream,port,level,length);
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::setInputLevel(int card,int port,int level)
{
#ifdef HPI
d_sound_card->setInputLevel(card,port,level);
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::setOutputLevel(int card,int port,int level)
{
#ifdef HPI
d_sound_card->setOutputLevel(card,port,level);
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::setInputMode(int card,int stream,int mode)
{
#ifdef HPI
switch(mode) {
case 0:
d_sound_card->setInputMode(card,stream,RDHPISoundCard::Normal);
break;
case 1:
d_sound_card->setInputMode(card,stream,RDHPISoundCard::Swap);
break;
case 2:
d_sound_card->setInputMode(card,stream,RDHPISoundCard::LeftOnly);
break;
case 3:
d_sound_card->setInputMode(card,stream,RDHPISoundCard::RightOnly);
break;
default:
return false;
}
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::setOutputMode(int card,int stream,int mode)
{
#ifdef HPI
switch(mode) {
case 0:
d_sound_card->setOutputMode(card,stream,RDHPISoundCard::Normal);
break;
case 1:
d_sound_card->setOutputMode(card,stream,RDHPISoundCard::Swap);
break;
case 2:
d_sound_card->setOutputMode(card,stream,RDHPISoundCard::LeftOnly);
break;
case 3:
d_sound_card->setOutputMode(card,stream,RDHPISoundCard::RightOnly);
break;
default:
return false;
}
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::setInputVoxLevel(int card,int stream,int level)
{
#ifdef HPI
d_sound_card->setInputStreamVOX(card,stream,level);
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::setInputType(int card,int port,int type)
{
#ifdef HPI
switch(type) {
case 0:
d_sound_card->setInputPortMux(card,port,RDHPISoundCard::LineIn);
break;
case 1:
d_sound_card->setInputPortMux(card,port,RDHPISoundCard::AesEbuIn);
break;
default:
return false;
}
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::getInputStatus(int card,int port)
{
#ifdef HPI
return d_sound_card->getInputPortError(card,port)==0;
#else
return false;
#endif // HPI
}
bool HpiDriver::getInputMeters(int card,int port,short levels[2])
{
#ifdef HPI
return d_sound_card->inputStreamMeter(card,port,levels);
#else
return false;
#endif // HPI
}
bool HpiDriver::getOutputMeters(int card,int port,short levels[2])
{
#ifdef HPI
return d_sound_card->outputPortMeter(card,port,levels);
#else
return false;
#endif // HPI
}
bool HpiDriver::getStreamOutputMeters(int card,int stream,short levels[2])
{
#ifdef HPI
return d_sound_card->outputStreamMeter(card,stream,levels);
#else
return false;
#endif // HPI
}
bool HpiDriver::setPassthroughLevel(int card,int in_port,int out_port,int level)
{
#ifdef HPI
return d_sound_card->setPassthroughVolume(card,in_port,out_port,level);
#else
return false;
#endif // HPI
}
void HpiDriver::getOutputPosition(int card,unsigned *pos)
{
#ifdef HPI
for(int i=0;i<RD_MAX_STREAMS;i++) {
if(d_play_streams[card][i]==NULL) {
pos[i]=0;
}
else {
pos[i]=
1000*(unsigned long long)d_play_streams[card][i]->currentPosition()/
d_play_streams[card][i]->getSamplesPerSec();
}
}
#endif // HPI
}

83
cae/hpidriver.h Normal file
View File

@ -0,0 +1,83 @@
// hpidriver.h
//
// caed(8) driver for AudioScience HPI audio devices.
//
// (C) Copyright 2021 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 HPIDRIVER_H
#define HPIDRIVER_H
#include <rdconfig.h>
#include "caedriver.h"
#ifdef HPI
#include <rdhpisoundcard.h>
#include <rdhpiplaystream.h>
#include <rdhpirecordstream.h>
#endif // HPI
class HpiDriver : public CaeDriver
{
Q_OBJECT
public:
HpiDriver(QObject *parent=0);
~HpiDriver();
QString version() const;
bool initialize(unsigned *next_cardnum);
void updateMeters();
bool loadPlayback(int card,QString wavename,int *stream);
bool unloadPlayback(int card,int stream);
bool playbackPosition(int card,int stream,unsigned pos);
bool play(int card,int stream,int length,int speed,bool pitch,
bool rates);
bool stopPlayback(int card,int stream);
bool timescaleSupported(int card);
bool loadRecord(int card,int port,int coding,int chans,int samprate,
int bitrate,QString wavename);
bool unloadRecord(int card,int port,unsigned *len);
bool record(int card,int port,int length,int thres);
bool stopRecord(int card,int port);
bool setClockSource(int card,int src);
bool setInputVolume(int card,int stream,int level);
bool setOutputVolume(int card,int stream,int port,int level);
bool fadeOutputVolume(int card,int stream,int port,int level,
int length);
bool setInputLevel(int card,int port,int level);
bool setOutputLevel(int card,int port,int level);
bool setInputMode(int card,int stream,int mode);
bool setOutputMode(int card,int stream,int mode);
bool setInputVoxLevel(int card,int stream,int level);
bool setInputType(int card,int port,int type);
bool getInputStatus(int card,int port);
bool getInputMeters(int card,int port,short levels[2]);
bool getOutputMeters(int card,int port,short levels[2]);
bool getStreamOutputMeters(int card,int stream,short levels[2]);
bool setPassthroughLevel(int card,int in_port,int out_port,
int level);
void getOutputPosition(int card,unsigned *pos);
private:
#ifdef HPI
RDHPISoundCard *d_sound_card;
RDHPIRecordStream *d_record_streams[RD_MAX_CARDS][RD_MAX_STREAMS];
RDHPIPlayStream *d_play_streams[RD_MAX_CARDS][RD_MAX_STREAMS];
#endif // HPI
};
#endif // HPIDRIVER_H

View File

@ -1992,6 +1992,30 @@ void RDStation::remove(const QString &name)
}
QString RDStation::audioDriverText(RDStation::AudioDriver dvr)
{
QString ret=QObject::tr("Unknown");
switch(dvr) {
case RDStation::None:
ret=QObject::tr("None");
break;
case RDStation::Hpi:
ret=QObject::tr("AudioScience HPI");
break;
case RDStation::Jack:
ret=QObject::tr("JACK Audio Connection Kit");
break;
case RDStation::Alsa:
ret=QObject::tr("Advance Linux Sound Architecture (ALSA)");
break;
}
return ret;
}
void RDStation::SetRow(const QString &param,const QString &value) const
{
QString sql;

View File

@ -117,6 +117,7 @@ class RDStation
const QString &exemplar="",
const QHostAddress &hostaddr=QHostAddress());
static void remove(const QString &name);
static QString audioDriverText(AudioDriver dvr);
private:
void SetRow(const QString &param,const QString &value) const;