1
0
mirror of https://github.com/ElvishArtisan/rivendell.git synced 2025-06-19 17:40:20 +02:00

2015-09-05 Fred Gleason <fredg@paravelsystems.com>

* Refactored caed(8) to use virtual inheritance for audio
	subsystem drivers.
	* Reimplemented the HPI driver in 'cae/driver_hpi.cpp' and
	'cae/driver_hpi.h'.
This commit is contained in:
Fred Gleason 2015-09-05 18:12:29 -04:00
parent 4de09b9eaf
commit c1f86bbde1
13 changed files with 1217 additions and 1389 deletions

@ -14873,3 +14873,8 @@
'rdadmin/edit_rdlogedit.cpp' and 'rdadmin/edit_rdlogedit.h'. 'rdadmin/edit_rdlogedit.cpp' and 'rdadmin/edit_rdlogedit.h'.
* Added PCM24 support for voice tracking in * Added PCM24 support for voice tracking in
'rdlogedit/voice_tracker.cpp'. 'rdlogedit/voice_tracker.cpp'.
2015-09-05 Fred Gleason <fredg@paravelsystems.com>
* Refactored caed(8) to use virtual inheritance for audio
subsystem drivers.
* Reimplemented the HPI driver in 'cae/driver_hpi.cpp' and
'cae/driver_hpi.h'.

@ -2,9 +2,7 @@
## ##
## Core Audio Engine Makefile.am for Rivendell ## Core Audio Engine Makefile.am for Rivendell
## ##
## Copyright 2002-2006 Fred Gleason <fredg@paravelsystems.com> ## Copyright 2002-2015 Fred Gleason <fredg@paravelsystems.com>
##
## $Id: Makefile.am,v 1.33.8.1 2012/11/29 01:37:34 cvs Exp $
## ##
## This program is free software; you can redistribute it and/or modify ## 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 ## it under the terms of the GNU General Public License version 2 as
@ -32,13 +30,18 @@ moc_%.cpp: %.h
bin_PROGRAMS = caed bin_PROGRAMS = caed
dist_caed_SOURCES = cae.cpp cae.h\ dist_caed_SOURCES = cae.cpp cae.h\
cae_alsa.cpp\ ## cae_alsa.cpp\
cae_hpi.cpp\ ## cae_hpi.cpp\
cae_jack.cpp\ ## cae_jack.cpp\
cae_socket.cpp cae_socket.h cae_socket.cpp cae_socket.h\
driver.cpp driver.h\
driver_hpi.cpp driver_hpi.h\
driverfactory.cpp driverfactory.h
nodist_caed_SOURCES = moc_cae.cpp\ nodist_caed_SOURCES = moc_cae.cpp\
moc_cae_socket.cpp moc_cae_socket.cpp\
moc_driver.cpp\
moc_driver_hpi.cpp
caed_LDADD = @LIB_RDLIBS@\ caed_LDADD = @LIB_RDLIBS@\
@LIBALSA@\ @LIBALSA@\

File diff suppressed because it is too large Load Diff

@ -2,9 +2,7 @@
// //
// The Core Audio Engine component of Rivendell // The Core Audio Engine component of Rivendell
// //
// (C) Copyright 2002-2004 Fred Gleason <fredg@paravelsystems.com> // (C) Copyright 2002-2015 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: cae.h,v 1.79.4.4 2012/11/30 16:14:58 cvs Exp $
// //
// This program is free software; you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License version 2 as
@ -28,6 +26,8 @@
#include <pthread.h> #include <pthread.h>
#include <stdint.h> #include <stdint.h>
#include <vector>
#include <soundtouch/SoundTouch.h> #include <soundtouch/SoundTouch.h>
#include <qobject.h> #include <qobject.h>
@ -40,7 +40,7 @@
#include <rdwavefile.h> #include <rdwavefile.h>
#include <rdsocket.h> #include <rdsocket.h>
/*
#ifdef HPI #ifdef HPI
#include <rdhpisoundcard.h> #include <rdhpisoundcard.h>
#include <rdhpiplaystream.h> #include <rdhpiplaystream.h>
@ -69,7 +69,7 @@ struct alsa_format {
#ifdef JACK #ifdef JACK
#include <jack/jack.h> #include <jack/jack.h>
#endif // JACK #endif // JACK
*/
#ifdef HAVE_TWOLAME #ifdef HAVE_TWOLAME
#include <twolame.h> #include <twolame.h>
#endif // HAVE_TWOLAME #endif // HAVE_TWOLAME
@ -81,6 +81,8 @@ struct alsa_format {
#include <rdconfig.h> #include <rdconfig.h>
#include <rdstation.h> #include <rdstation.h>
#include "driver.h"
// //
// Debug Options // Debug Options
// //
@ -151,7 +153,7 @@ class MainObject : public QObject
int argnum[CAE_MAX_CONNECTIONS]; int argnum[CAE_MAX_CONNECTIONS];
int argptr[CAE_MAX_CONNECTIONS]; int argptr[CAE_MAX_CONNECTIONS];
bool auth[CAE_MAX_CONNECTIONS]; bool auth[CAE_MAX_CONNECTIONS];
RDStation::AudioDriver cae_driver[RD_MAX_CARDS]; // RDStation::AudioDriver cae_driver[RD_MAX_CARDS];
int record_owner[RD_MAX_CARDS][RD_MAX_STREAMS]; int record_owner[RD_MAX_CARDS][RD_MAX_STREAMS];
int record_length[RD_MAX_CARDS][RD_MAX_STREAMS]; int record_length[RD_MAX_CARDS][RD_MAX_STREAMS];
int record_threshold[RD_MAX_CARDS][RD_MAX_STREAMS]; int record_threshold[RD_MAX_CARDS][RD_MAX_STREAMS];
@ -167,51 +169,12 @@ class MainObject : public QObject
int owner; int owner;
} play_handle[256]; } play_handle[256];
int next_play_handle; int next_play_handle;
std::vector<Driver *> cae_drivers;
//
// HPI Driver
//
private:
void hpiInit(RDStation *station);
void hpiFree();
QString hpiVersion();
bool hpiLoadPlayback(int card,QString wavename,int *stream);
bool hpiUnloadPlayback(int card,int stream);
bool hpiPlaybackPosition(int card,int stream,unsigned pos);
bool hpiPlay(int card,int stream,int length,int speed,bool pitch,
bool rates);
bool hpiStopPlayback(int card,int stream);
bool hpiTimescaleSupported(int card);
bool hpiLoadRecord(int card,int port,int coding,int chans,int samprate,
int bitrate,QString wavename);
bool hpiUnloadRecord(int card,int stream,unsigned *len);
bool hpiRecord(int card,int stream,int length,int thres);
bool hpiStopRecord(int card,int stream);
bool hpiSetClockSource(int card,int src);
bool hpiSetInputVolume(int card,int stream,int level);
bool hpiSetOutputVolume(int card,int stream,int port,int level);
bool hpiFadeOutputVolume(int card,int stream,int port,int level,int length);
bool hpiSetInputLevel(int card,int port,int level);
bool hpiSetOutputLevel(int card,int port,int level);
bool hpiSetInputMode(int card,int stream,int mode);
bool hpiSetOutputMode(int card,int stream,int mode);
bool hpiSetInputVoxLevel(int card,int stream,int level);
bool hpiSetInputType(int card,int port,int type);
bool hpiGetInputStatus(int card,int port);
bool hpiGetInputMeters(int card,int port,short levels[2]);
bool hpiGetOutputMeters(int card,int port,short levels[2]);
bool hpiGetStreamOutputMeters(int card,int stream,short levels[2]);
bool hpiSetPassthroughLevel(int card,int in_port,int out_port,int level);
void hpiGetOutputPosition(int card,unsigned *pos);
#ifdef HPI
RDHPISoundCard *sound_card;
RDHPIRecordStream *record[RD_MAX_CARDS][RD_MAX_STREAMS];
RDHPIPlayStream *play[RD_MAX_CARDS][RD_MAX_STREAMS];
#endif // HPI
// //
// JACK Driver // JACK Driver
// //
/*
private slots: private slots:
void jackStopTimerData(int stream); void jackStopTimerData(int stream);
void jackFadeTimerData(int stream); void jackFadeTimerData(int stream);
@ -285,10 +248,11 @@ class MainObject : public QObject
int jack_clock_phase; int jack_clock_phase;
unsigned jack_samples_recorded[RD_MAX_STREAMS]; unsigned jack_samples_recorded[RD_MAX_STREAMS];
#endif // JACK #endif // JACK
*/
// //
// ALSA Driver // ALSA Driver
// //
/*
private slots: private slots:
void alsaStopTimerData(int cardstream); void alsaStopTimerData(int cardstream);
void alsaFadeTimerData(int cardstream); void alsaFadeTimerData(int cardstream);
@ -340,6 +304,7 @@ class MainObject : public QObject
short alsa_output_volume_db[RD_MAX_CARDS][RD_MAX_PORTS][RD_MAX_STREAMS]; short alsa_output_volume_db[RD_MAX_CARDS][RD_MAX_PORTS][RD_MAX_STREAMS];
short alsa_passthrough_volume_db[RD_MAX_CARDS][RD_MAX_PORTS][RD_MAX_PORTS]; short alsa_passthrough_volume_db[RD_MAX_CARDS][RD_MAX_PORTS][RD_MAX_PORTS];
short *alsa_wave_buffer; short *alsa_wave_buffer;
uint8_t *alsa_wave24_buffer;
RDWaveFile *alsa_record_wave[RD_MAX_CARDS][RD_MAX_STREAMS]; RDWaveFile *alsa_record_wave[RD_MAX_CARDS][RD_MAX_STREAMS];
RDWaveFile *alsa_play_wave[RD_MAX_CARDS][RD_MAX_STREAMS]; RDWaveFile *alsa_play_wave[RD_MAX_CARDS][RD_MAX_STREAMS];
int alsa_offset[RD_MAX_CARDS][RD_MAX_STREAMS]; int alsa_offset[RD_MAX_CARDS][RD_MAX_STREAMS];
@ -352,7 +317,7 @@ class MainObject : public QObject
int alsa_fade_port[RD_MAX_CARDS][RD_MAX_STREAMS]; int alsa_fade_port[RD_MAX_CARDS][RD_MAX_STREAMS];
unsigned alsa_samples_recorded[RD_MAX_CARDS][RD_MAX_STREAMS]; unsigned alsa_samples_recorded[RD_MAX_CARDS][RD_MAX_STREAMS];
#endif // ALSA #endif // ALSA
*/
bool CheckLame(); bool CheckLame();
// //

@ -2,9 +2,7 @@
// //
// The ALSA Driver for the Core Audio Engine component of Rivendell // The ALSA Driver for the Core Audio Engine component of Rivendell
// //
// (C) Copyright 2002-2004 Fred Gleason <fredg@paravelsystems.com> // (C) Copyright 2002-2015 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: cae_alsa.cpp,v 1.48.6.5 2013/06/26 23:18:40 cvs Exp $
// //
// This program is free software; you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License version 2 as
@ -19,7 +17,7 @@
// License along with this program; if not, write to the Free Software // License along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// //
/*
#include <math.h> #include <math.h>
#include <signal.h> #include <signal.h>
@ -717,6 +715,7 @@ void MainObject::alsaInit(RDStation *station)
// //
AlsaInitCallback(); AlsaInitCallback();
alsa_wave_buffer=new int16_t[RINGBUFFER_SIZE]; alsa_wave_buffer=new int16_t[RINGBUFFER_SIZE];
alsa_wave24_buffer=new uint8_t[RINGBUFFER_SIZE];
//alsa_resample_buffer=new int16_t[2*RINGBUFFER_SIZE]; //alsa_resample_buffer=new int16_t[2*RINGBUFFER_SIZE];
// //
@ -1527,11 +1526,11 @@ bool MainObject::AlsaStartCaptureDevice(QString &dev,int card,snd_pcm_t *pcm)
// Start the Callback // Start the Callback
// //
pthread_attr_init(&pthread_attr); pthread_attr_init(&pthread_attr);
/*
if(use_realtime) { // if(use_realtime) {
pthread_attr_setschedpolicy(&pthread_attr,SCHED_FIFO); // pthread_attr_setschedpolicy(&pthread_attr,SCHED_FIFO);
} // }
*/
alsa_capture_format[card].exiting = false; alsa_capture_format[card].exiting = false;
pthread_create(&alsa_capture_format[card].thread,&pthread_attr, pthread_create(&alsa_capture_format[card].thread,&pthread_attr,
AlsaCaptureCallback,&alsa_capture_format[card]); AlsaCaptureCallback,&alsa_capture_format[card]);
@ -1682,11 +1681,11 @@ bool MainObject::AlsaStartPlayDevice(QString &dev,int card,snd_pcm_t *pcm)
// Start the Callback // Start the Callback
// //
pthread_attr_init(&pthread_attr); pthread_attr_init(&pthread_attr);
/*
if(use_realtime) { // if(use_realtime) {
pthread_attr_setschedpolicy(&pthread_attr,SCHED_FIFO); // pthread_attr_setschedpolicy(&pthread_attr,SCHED_FIFO);
} // }
*/
alsa_play_format[card].exiting = false; alsa_play_format[card].exiting = false;
pthread_create(&alsa_play_format[card].thread,&pthread_attr, pthread_create(&alsa_play_format[card].thread,&pthread_attr,
AlsaPlayCallback,&alsa_play_format[card]); AlsaPlayCallback,&alsa_play_format[card]);
@ -1776,6 +1775,34 @@ void MainObject::FillAlsaOutputStream(int card,int stream)
(double)alsa_play_wave[card][stream]->getSamplesPerSec(); (double)alsa_play_wave[card][stream]->getSamplesPerSec();
switch(alsa_play_wave[card][stream]->getFormatTag()) { switch(alsa_play_wave[card][stream]->getFormatTag()) {
case WAVE_FORMAT_PCM: case WAVE_FORMAT_PCM:
switch(alsa_play_wave[card][stream]->getBitsPerSample()) {
case 16: // PCM16
free=(int)((double)free/ratio)/(2*alsa_output_channels[card][stream])*
(2*alsa_output_channels[card][stream]);
n=alsa_play_wave[card][stream]->readWave(alsa_wave_buffer,free);
if(n!=free) {
alsa_eof[card][stream]=true;
alsa_stop_timer[card][stream]->stop();
}
break;
case 24: // PCM24
free=(int)((double)free/ratio)/(6*alsa_output_channels[card][stream])*
(6*alsa_output_channels[card][stream]);
n=alsa_play_wave[card][stream]->readWave(alsa_wave24_buffer,free);
for(int i=0;i<(n/3);i++) {
for(int j=0;j<2;j++) {
((uint8_t *)alsa_wave_buffer)[2*i+j]=alsa_wave24_buffer[3*i+j+1];
}
}
if(n!=free) {
alsa_eof[card][stream]=true;
alsa_stop_timer[card][stream]->stop();
}
break;
}
break;
case WAVE_FORMAT_VORBIS: case WAVE_FORMAT_VORBIS:
free=(int)((double)free/ratio)/(2*alsa_output_channels[card][stream])* free=(int)((double)free/ratio)/(2*alsa_output_channels[card][stream])*
(2*alsa_output_channels[card][stream]); (2*alsa_output_channels[card][stream]);
@ -1880,3 +1907,4 @@ void MainObject::AlsaClock()
} }
#endif // ALSA #endif // ALSA
} }
*/

@ -1,541 +0,0 @@
// cae_hpi.cpp
//
// The HPI Driver for the Core Audio Engine component of Rivendell
//
// (C) Copyright 2002-2004 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: cae_hpi.cpp,v 1.38.6.2 2012/11/30 16:14:58 cvs Exp $
//
// 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 <cae.h>
#include <rddebug.h>
void MainObject::hpiInit(RDStation *station)
{
#ifdef HPI
for(int i=0;i<RD_MAX_CARDS;i++) {
for(int j=0;j<RD_MAX_STREAMS;j++) {
record[i][j]=NULL;
play[i][j]=NULL;
}
}
sound_card=new RDHPISoundCard(this,"sound_card");
sound_card->setFadeProfile(RD_FADE_TYPE);
for(int i=0;i<sound_card->getCardQuantity();i++) {
cae_driver[i]=RDStation::Hpi;
station->setCardDriver(i,RDStation::Hpi);
station->setCardName(i,sound_card->getCardDescription(i));
station->setCardInputs(i,sound_card->getCardInputPorts(i));
station->setCardOutputs(i,sound_card->getCardOutputPorts(i));
}
#endif // HPI
}
void MainObject::hpiFree()
{
#ifdef HPI
#endif // HPI
}
QString MainObject::hpiVersion()
{
#ifdef HPI
if(sound_card==NULL) {
return QString("not active");
}
RDHPIInformation *info=sound_card->hpiInformation(0);
if(info->hpiVersion()==0) {
return QString("not active");
}
return QString().sprintf("%d.%02d.%02d",info->hpiMajorVersion(),
info->hpiMinorVersion(),info->hpiPointVersion());
#else
return QString("not enabled");
#endif // HPI
}
bool MainObject::hpiLoadPlayback(int card,QString wavename,int *stream)
{
#ifdef HPI
RDHPIPlayStream *playstream=new RDHPIPlayStream(sound_card);
playstream->setCard(card);
if(playstream->openWave(wavename)!=RDHPIPlayStream::Ok) {
LogLine(RDConfig::LogNotice,QString().sprintf(
"Error: hpiLoadPlayback(%s) openWave() failed to open file",
(const char *) wavename) );
delete playstream;
return false;
}
*stream=playstream->getStream();
play[card][*stream]=playstream;
connect(play[card][*stream],SIGNAL(stateChanged(int,int,int)),
this,SLOT(statePlayUpdate(int,int,int)));
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiUnloadPlayback(int card,int stream)
{
#ifdef HPI
if(play[card][stream]==NULL) {
return false;
}
if(play[card][stream]->getState()==RDHPIPlayStream::Playing) {
play[card][stream]->pause();
}
play[card][stream]->disconnect();
play[card][stream]->closeWave();
delete play[card][stream];
play[card][stream]=NULL;
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiPlaybackPosition(int card,int stream,unsigned pos)
{
#ifdef HPI
if(play[card][stream]==NULL) {
return false;
}
return play[card][stream]->
setPosition((unsigned)((double)play[card][stream]->getSamplesPerSec()*
(double)pos/1000.0));
#else
return false;
#endif // HPI
}
bool MainObject::hpiPlay(int card,int stream,int length,int speed,bool pitch,
bool rates)
{
#ifdef HPI
if(play[card][stream]==NULL) {
return false;
}
if(!play[card][stream]->setSpeed(speed,pitch,rates)) {
return false;
}
play[card][stream]->setPlayLength(length);
return play[card][stream]->play();
#else
return false;
#endif // HPI
}
bool MainObject::hpiStopPlayback(int card,int stream)
{
#ifdef HPI
if(play[card][stream]==NULL) {
return false;
}
play[card][stream]->pause();
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiTimescaleSupported(int card)
{
#ifdef HPI
return sound_card->haveTimescaling(card);
#else
return false;
#endif // HPI
}
bool MainObject::hpiLoadRecord(int card,int stream,int coding,int chans,
int samprate,int bitrate,QString wavename)
{
#ifdef HPI
syslog(LOG_NOTICE,"card: %d coding: %d\n",card,coding);
record[card][stream]=new RDHPIRecordStream(sound_card);
connect(record[card][stream],SIGNAL(stateChanged(int,int,int)),
this,SLOT(stateRecordUpdate(int,int,int)));
record[card][stream]->setCard(card);
record[card][stream]->setStream(stream);
record[card][stream]->nameWave(wavename);
record[card][stream]->setChannels(chans);
record[card][stream]->setSamplesPerSec(samprate);
if(coding==0) { // PCM16
record[card][stream]->setFormatTag(WAVE_FORMAT_PCM);
record[card][stream]->setBitsPerSample(16);
}
if((coding==1)||(coding==2)) { // MPEG-1
record[card][stream]->setFormatTag(WAVE_FORMAT_MPEG);
record[card][stream]->setHeadLayer(coding);
record[card][stream]->setHeadBitRate(bitrate);
record[card][stream]->setMextChunk(true);
switch(chans) {
case 1:
record[card][stream]->setHeadMode(ACM_MPEG_SINGLECHANNEL);
break;
case 2:
record[card][stream]->setHeadMode(ACM_MPEG_STEREO);
break;
default:
delete record[card][stream];
record[card][stream]=NULL;
return false;
}
record[card][stream]->setHeadFlags(ACM_MPEG_ID_MPEG1);
}
if(coding==4) { // PCM24
record[card][stream]->setFormatTag(WAVE_FORMAT_PCM);
record[card][stream]->setBitsPerSample(24);
}
if(coding>4) {
delete record[card][stream];
record[card][stream]=NULL;
return false;
}
record[card][stream]->setBextChunk(true);
record[card][stream]->setCartChunk(true);
record[card][stream]->setLevlChunk(true);
if(record[card][stream]->createWave()!=RDHPIRecordStream::Ok) {
delete record[card][stream];
record[card][stream]=NULL;
return false;
}
chown((const char *)wavename,rd_config->uid(),rd_config->gid());
if(!record[card][stream]->recordReady()) {
delete record[card][stream];
record[card][stream]=NULL;
return false;
}
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiUnloadRecord(int card,int stream,unsigned *len)
{
#ifdef HPI
if(record[card][stream]==NULL) {
return false;
}
if(record[card][stream]->getState()==RDHPIRecordStream::Recording) {
record[card][stream]->pause();
}
record[card][stream]->disconnect();
*len=record[card][stream]->samplesRecorded();
record[card][stream]->closeWave();
delete record[card][stream];
record[card][stream]=NULL;
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiRecord(int card,int stream,int length,int thres)
{
#ifdef HPI
if(record[card][stream]==NULL) {
return false;
}
if(thres!=0) {
if(record[card][stream]->haveInputVOX()) {
record[card][stream]->setInputVOX(thres);
}
else {
return false;
}
}
record[card][stream]->setRecordLength(length);
record[card][stream]->record();
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiStopRecord(int card,int stream)
{
#ifdef HPI
if(record[card][stream]==NULL) {
return false;
}
record[card][stream]->pause();
record[card][stream]->setInputVOX(-10000);
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiSetClockSource(int card,int src)
{
#ifdef HPI
return sound_card->setClockSource(card,(RDHPISoundCard::ClockSource)src);
#else
return false;
#endif // HPI
}
bool MainObject::hpiSetInputVolume(int card,int stream,int level)
{
#ifdef HPI
sound_card->setInputVolume(card,stream,level);
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiSetOutputVolume(int card,int stream,int port,int level)
{
#ifdef HPI
sound_card->setOutputVolume(card,stream,port,level);
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiFadeOutputVolume(int card,int stream,int port,int level,
int length)
{
#ifdef HPI
sound_card->fadeOutputVolume(card,stream,port,level,length);
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiSetInputLevel(int card,int port,int level)
{
#ifdef HPI
sound_card->setInputLevel(card,port,level);
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiSetOutputLevel(int card,int port,int level)
{
#ifdef HPI
sound_card->setOutputLevel(card,port,level);
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiSetInputMode(int card,int stream,int mode)
{
#ifdef HPI
switch(mode) {
case 0:
sound_card->setInputMode(card,stream,RDHPISoundCard::Normal);
break;
case 1:
sound_card->setInputMode(card,stream,RDHPISoundCard::Swap);
break;
case 2:
sound_card->setInputMode(card,stream,RDHPISoundCard::LeftOnly);
break;
case 3:
sound_card->setInputMode(card,stream,RDHPISoundCard::RightOnly);
break;
default:
return false;
}
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiSetOutputMode(int card,int stream,int mode)
{
#ifdef HPI
switch(mode) {
case 0:
sound_card->setOutputMode(card,stream,RDHPISoundCard::Normal);
break;
case 1:
sound_card->setOutputMode(card,stream,RDHPISoundCard::Swap);
break;
case 2:
sound_card->setOutputMode(card,stream,RDHPISoundCard::LeftOnly);
break;
case 3:
sound_card->setOutputMode(card,stream,RDHPISoundCard::RightOnly);
break;
default:
return false;
}
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiSetInputVoxLevel(int card,int stream,int level)
{
#ifdef HPI
sound_card->setInputStreamVOX(card,stream,level);
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiSetInputType(int card,int port,int type)
{
#ifdef HPI
switch(type) {
case 0:
sound_card->setInputPortMux(card,port,RDHPISoundCard::LineIn);
break;
case 1:
sound_card->setInputPortMux(card,port,RDHPISoundCard::AesEbuIn);
break;
default:
return false;
}
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiGetInputStatus(int card,int port)
{
#ifdef HPI
if(sound_card->getInputPortError(card,port)!=0) {
return false;
}
return true;
#else
return false;
#endif // HPI
}
bool MainObject::hpiGetInputMeters(int card,int port,short levels[2])
{
#ifdef HPI
return sound_card->inputStreamMeter(card,port,levels);
#else
return false;
#endif // HPI
}
bool MainObject::hpiGetOutputMeters(int card,int port,short levels[2])
{
#ifdef HPI
if(rd_config->useStreamMeters()) {
//
// This is UGLY, but needed to semi-support cards (like the ASI4215)
// that lack output port metering.
//
for(int i=0;i<RD_MAX_STREAMS;i++) {
if(sound_card->getOutputVolume(card,i,port)>-10000) {
return sound_card->outputStreamMeter(card,i,levels);
}
}
levels[0]=-10000;
levels[1]=-10000;
return true;
}
return sound_card->outputPortMeter(card,port,levels);
#else
return false;
#endif // HPI
}
bool MainObject::hpiGetStreamOutputMeters(int card,int stream,short levels[2])
{
#ifdef HPI
return sound_card->outputStreamMeter(card,stream,levels);
#else
return false;
#endif // HPI
}
void MainObject::hpiGetOutputPosition(int card,unsigned *pos)
{
#ifdef HPI
for(int i=0;i<RD_MAX_STREAMS;i++) {
if(play[card][i]==NULL) {
pos[i]=0;
}
else {
pos[i]=1000*(unsigned long long)play[card][i]->currentPosition()/
play[card][i]->getSamplesPerSec();
}
}
#endif // HPI
return;
}
bool MainObject::hpiSetPassthroughLevel(int card,int in_port,int out_port,
int level)
{
#ifdef HPI
return sound_card->setPassthroughVolume(card,in_port,out_port,level);
#else
return false;
#endif // HPI
}

@ -17,7 +17,7 @@
// License along with this program; if not, write to the Free Software // License along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// //
/*
#include <math.h> #include <math.h>
#include <samplerate.h> #include <samplerate.h>
@ -961,29 +961,6 @@ bool MainObject::jackLoadRecord(int card,int stream,int coding,int chans,
jack_ready[stream]=true; jack_ready[stream]=true;
return true; return true;
/*
if ((stream <0) || (stream >=RD_MAX_PORTS)){
return false;
}
jack_record_wave[stream]=new RDWaveFile(wavename);
jack_record_wave[stream]->setFormatTag(WAVE_FORMAT_PCM);
jack_record_wave[stream]->setChannels(chans);
jack_record_wave[stream]->setSamplesPerSec(samprate);
jack_record_wave[stream]->setBitsPerSample(16);
jack_record_wave[stream]->setBextChunk(true);
jack_record_wave[stream]->setLevlChunk(true);
if(!jack_record_wave[stream]->createWave()) {
delete jack_record_wave[stream];
jack_record_wave[stream]=NULL;
return false;
}
chown((const char *)wavename,rd_config->uid(),rd_config->gid());
jack_input_channels[stream]=chans;
jack_record_ring[stream]=new RDRingBuffer(RINGBUFFER_SIZE);
jack_record_ring[stream]->reset();
jack_ready[stream]=true;
return true;
*/
#else #else
return false; return false;
#endif // JACK #endif // JACK
@ -1656,3 +1633,5 @@ void MainObject::JackSessionSetup()
delete profile; delete profile;
#endif // JACK #endif // JACK
} }
*/

123
cae/driver.cpp Normal file

@ -0,0 +1,123 @@
// driver.cpp
//
// Abstract base class for CAE audio drivers.
//
// (C) Copyright 2002-2015 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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <qdatetime.h>
#include "driver.h"
Driver::Driver(Driver::Type type,RDStation *station,RDConfig *config,
QObject *parent)
: QObject(parent)
{
dvr_type=type;
dvr_station=station;
dvr_config=config;
}
Driver::~Driver()
{
}
Driver::Type Driver::type() const
{
return dvr_type;
}
bool Driver::connectPorts(const QString &out,const QString &in)
{
return false;
}
bool Driver::disconnectPorts(const QString &out,const QString &in)
{
return false;
}
RDStation *Driver::station()
{
return dvr_station;
}
RDConfig *Driver::config()
{
return dvr_config;
}
void Driver::logLine(RDConfig::LogPriority prio,const QString &line)
{
FILE *file;
dvr_config->log("caed",prio,line);
if(dvr_config->caeLogfile().isEmpty()) {
return;
}
QDateTime current=QDateTime::currentDateTime();
file=fopen(dvr_config->caeLogfile(),"a");
if(file==NULL) {
return;
}
chmod(dvr_config->caeLogfile(),S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
fprintf(file,"%02d/%02d/%4d - %02d:%02d:%02d.%03d : %s\n",
current.date().month(),
current.date().day(),
current.date().year(),
current.time().hour(),
current.time().minute(),
current.time().second(),
current.time().msec(),
(const char *)line);
fclose(file);
}
QString Driver::typeText(Driver::Type type)
{
QString ret=tr("Unknown");
switch(type) {
case Driver::Alsa:
ret=tr("Advanced Linux Sound Architecture");
break;
case Driver::Hpi:
ret=tr("AudioScience HPI");
break;
case Driver::Jack:
ret=tr("JACK Audio Connection Kit");
break;
}
return ret;
}

94
cae/driver.h Normal file

@ -0,0 +1,94 @@
// driver.h
//
// Abstract base class for CAE audio drivers.
//
// (C) Copyright 2002-2015 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 DRIVER_H
#define DRIVER_H
#include <qstring.h>
#include <qobject.h>
#include <rdconfig.h>
#include <rdstation.h>
class Driver : public QObject
{
Q_OBJECT
public:
enum Type {Hpi=0,Alsa=1,Jack=2};
Driver(Driver::Type type,RDStation *station,RDConfig *config,
QObject *parent=0);
~Driver();
Driver::Type type() const;
virtual QString version()=0;
virtual QString cardName(int card)=0;
virtual int inputs(int card)=0;
virtual int outputs(int card)=0;
virtual int start(int next_card)=0;
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 stream,int coding,int chans,int samprate,
int bitrate,QString wavename)=0;
virtual bool record(int card,int stream,int length,int thres)=0;
virtual bool stopRecord(int card,int stream)=0;
virtual bool unloadRecord(int card,int stream,unsigned *len)=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;
virtual bool connectPorts(const QString &out,const QString &in);
virtual bool disconnectPorts(const QString &out,const QString &in);
static QString typeText(Driver::Type type);
signals:
void playStateChanged(int card,int stream,int state);
void recordStateChanged(int card,int stream,int state);
protected:
RDStation *station();
RDConfig *config();
void logLine(RDConfig::LogPriority prio,const QString &line);
private:
Driver::Type dvr_type;
RDStation *dvr_station;
RDConfig *dvr_config;
};
#endif // DRIVER_H

566
cae/driver_hpi.cpp Normal file

@ -0,0 +1,566 @@
// driver_hpi.cpp
//
// CAE driver for AudioScience HPI devices
//
// (C) Copyright 2002-2015 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 "driver_hpi.h"
HpiDriver::HpiDriver(RDStation *station,RDConfig *config,QObject *parent)
: Driver(Driver::Hpi,station,config,parent)
{
#ifdef HPI
for(int i=0;i<RD_MAX_CARDS;i++) {
for(int j=0;j<RD_MAX_STREAMS;j++) {
hpi_record[i][j]=NULL;
hpi_play[i][j]=NULL;
}
}
hpi_sound_card=new RDHPISoundCard(this);
hpi_sound_card->setFadeProfile(RD_FADE_TYPE);
for(int i=0;i<hpi_sound_card->getCardQuantity();i++) {
station->setCardDriver(i,RDStation::Hpi);
station->setCardName(i,hpi_sound_card->getCardDescription(i));
station->setCardInputs(i,hpi_sound_card->getCardInputPorts(i));
station->setCardOutputs(i,hpi_sound_card->getCardOutputPorts(i));
}
#endif // HPI
}
HpiDriver::~HpiDriver()
{
}
QString HpiDriver::version()
{
#ifdef HPI
if(hpi_sound_card==NULL) {
return QString("not active");
}
RDHPIInformation *info=hpi_sound_card->hpiInformation(0);
if(info->hpiVersion()==0) {
return QString("not active");
}
return QString().sprintf("%d.%02d.%02d",info->hpiMajorVersion(),
info->hpiMinorVersion(),info->hpiPointVersion());
#else
return QString("not enabled");
#endif // HPI
}
QString HpiDriver::cardName(int card)
{
return hpi_sound_card->getCardDescription(card);
}
int HpiDriver::inputs(int card)
{
return hpi_sound_card->getCardInputPorts(card);
}
int HpiDriver::outputs(int card)
{
return hpi_sound_card->getCardOutputPorts(card);
}
int HpiDriver::start(int next_card)
{
return hpi_sound_card->getCardQuantity();
}
bool HpiDriver::loadPlayback(int card,QString wavename,int *stream)
{
#ifdef HPI
RDHPIPlayStream *playstream=new RDHPIPlayStream(hpi_sound_card);
playstream->setCard(card);
if(playstream->openWave(wavename)!=RDHPIPlayStream::Ok) {
logLine(RDConfig::LogNotice,QString().sprintf(
"Error: hpiLoadPlayback(%s) openWave() failed to open file",
(const char *) wavename) );
delete playstream;
return false;
}
*stream=playstream->getStream();
hpi_play[card][*stream]=playstream;
connect(hpi_play[card][*stream],SIGNAL(stateChanged(int,int,int)),
this,SLOT(playStateChangedData(int,int,int)));
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::unloadPlayback(int card,int stream)
{
#ifdef HPI
if(hpi_play[card][stream]==NULL) {
return false;
}
if(hpi_play[card][stream]->getState()==RDHPIPlayStream::Playing) {
hpi_play[card][stream]->pause();
}
hpi_play[card][stream]->disconnect();
hpi_play[card][stream]->closeWave();
delete hpi_play[card][stream];
hpi_play[card][stream]=NULL;
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::playbackPosition(int card,int stream,unsigned pos)
{
#ifdef HPI
if(hpi_play[card][stream]==NULL) {
return false;
}
return hpi_play[card][stream]->
setPosition((unsigned)((double)hpi_play[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(hpi_play[card][stream]==NULL) {
return false;
}
if(!hpi_play[card][stream]->setSpeed(speed,pitch,rates)) {
return false;
}
hpi_play[card][stream]->setPlayLength(length);
return hpi_play[card][stream]->play();
#else
return false;
#endif // HPI
}
bool HpiDriver::stopPlayback(int card,int stream)
{
#ifdef HPI
if(hpi_play[card][stream]==NULL) {
return false;
}
hpi_play[card][stream]->pause();
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::timescaleSupported(int card)
{
#ifdef HPI
return hpi_sound_card->haveTimescaling(card);
#else
return false;
#endif // HPI
}
bool HpiDriver::loadRecord(int card,int stream,int coding,int chans,
int samprate,int bitrate,QString wavename)
{
#ifdef HPI
hpi_record[card][stream]=new RDHPIRecordStream(hpi_sound_card);
connect(hpi_record[card][stream],SIGNAL(stateChanged(int,int,int)),
this,SLOT(recordStateChangedData(int,int,int)));
hpi_record[card][stream]->setCard(card);
hpi_record[card][stream]->setStream(stream);
hpi_record[card][stream]->nameWave(wavename);
hpi_record[card][stream]->setChannels(chans);
hpi_record[card][stream]->setSamplesPerSec(samprate);
if(coding==0) { // PCM16
hpi_record[card][stream]->setFormatTag(WAVE_FORMAT_PCM);
hpi_record[card][stream]->setBitsPerSample(16);
}
if((coding==1)||(coding==2)) { // MPEG-1
hpi_record[card][stream]->setFormatTag(WAVE_FORMAT_MPEG);
hpi_record[card][stream]->setHeadLayer(coding);
hpi_record[card][stream]->setHeadBitRate(bitrate);
hpi_record[card][stream]->setMextChunk(true);
switch(chans) {
case 1:
hpi_record[card][stream]->setHeadMode(ACM_MPEG_SINGLECHANNEL);
break;
case 2:
hpi_record[card][stream]->setHeadMode(ACM_MPEG_STEREO);
break;
default:
delete hpi_record[card][stream];
hpi_record[card][stream]=NULL;
return false;
}
hpi_record[card][stream]->setHeadFlags(ACM_MPEG_ID_MPEG1);
}
if(coding==4) { // PCM24
hpi_record[card][stream]->setFormatTag(WAVE_FORMAT_PCM);
hpi_record[card][stream]->setBitsPerSample(24);
}
if(coding>4) {
delete hpi_record[card][stream];
hpi_record[card][stream]=NULL;
return false;
}
hpi_record[card][stream]->setBextChunk(true);
hpi_record[card][stream]->setCartChunk(true);
hpi_record[card][stream]->setLevlChunk(true);
if(hpi_record[card][stream]->createWave()!=RDHPIRecordStream::Ok) {
delete hpi_record[card][stream];
hpi_record[card][stream]=NULL;
return false;
}
chown((const char *)wavename,config()->uid(),config()->gid());
if(!hpi_record[card][stream]->recordReady()) {
delete hpi_record[card][stream];
hpi_record[card][stream]=NULL;
return false;
}
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::record(int card,int stream,int length,int thres)
{
#ifdef HPI
if(hpi_record[card][stream]==NULL) {
return false;
}
if(thres!=0) {
if(hpi_record[card][stream]->haveInputVOX()) {
hpi_record[card][stream]->setInputVOX(thres);
}
else {
return false;
}
}
hpi_record[card][stream]->setRecordLength(length);
hpi_record[card][stream]->record();
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::stopRecord(int card,int stream)
{
#ifdef HPI
if(hpi_record[card][stream]==NULL) {
return false;
}
hpi_record[card][stream]->pause();
hpi_record[card][stream]->setInputVOX(-10000);
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::unloadRecord(int card,int stream,unsigned *len)
{
#ifdef HPI
if(hpi_record[card][stream]==NULL) {
return false;
}
if(hpi_record[card][stream]->getState()==RDHPIRecordStream::Recording) {
hpi_record[card][stream]->pause();
}
hpi_record[card][stream]->disconnect();
*len=hpi_record[card][stream]->samplesRecorded();
hpi_record[card][stream]->closeWave();
delete hpi_record[card][stream];
hpi_record[card][stream]=NULL;
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::setClockSource(int card,int src)
{
#ifdef HPI
return hpi_sound_card->setClockSource(card,(RDHPISoundCard::ClockSource)src);
#else
return false;
#endif // HPI
}
bool HpiDriver::setInputVolume(int card,int stream,int level)
{
#ifdef HPI
hpi_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
hpi_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
hpi_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
hpi_sound_card->setInputLevel(card,port,level);
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::setOutputLevel(int card,int port,int level)
{
#ifdef HPI
hpi_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:
hpi_sound_card->setInputMode(card,stream,RDHPISoundCard::Normal);
break;
case 1:
hpi_sound_card->setInputMode(card,stream,RDHPISoundCard::Swap);
break;
case 2:
hpi_sound_card->setInputMode(card,stream,RDHPISoundCard::LeftOnly);
break;
case 3:
hpi_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:
hpi_sound_card->setOutputMode(card,stream,RDHPISoundCard::Normal);
break;
case 1:
hpi_sound_card->setOutputMode(card,stream,RDHPISoundCard::Swap);
break;
case 2:
hpi_sound_card->setOutputMode(card,stream,RDHPISoundCard::LeftOnly);
break;
case 3:
hpi_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
hpi_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:
hpi_sound_card->setInputPortMux(card,port,RDHPISoundCard::LineIn);
break;
case 1:
hpi_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
if(hpi_sound_card->getInputPortError(card,port)!=0) {
return false;
}
return true;
#else
return false;
#endif // HPI
}
bool HpiDriver::getInputMeters(int card,int port,short levels[2])
{
#ifdef HPI
return hpi_sound_card->inputStreamMeter(card,port,levels);
#else
return false;
#endif // HPI
}
bool HpiDriver::getOutputMeters(int card,int port,short levels[2])
{
#ifdef HPI
if(config()->useStreamMeters()) {
//
// This is UGLY, but needed to semi-support cards (like the ASI4215)
// that lack output port metering.
//
for(int i=0;i<RD_MAX_STREAMS;i++) {
if(hpi_sound_card->getOutputVolume(card,i,port)>-10000) {
return hpi_sound_card->outputStreamMeter(card,i,levels);
}
}
levels[0]=-10000;
levels[1]=-10000;
return true;
}
return hpi_sound_card->outputPortMeter(card,port,levels);
#else
return false;
#endif // HPI
}
bool HpiDriver::getStreamOutputMeters(int card,int stream,short levels[2])
{
#ifdef HPI
return hpi_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 hpi_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(hpi_play[card][i]==NULL) {
pos[i]=0;
}
else {
pos[i]=1000*(unsigned long long)hpi_play[card][i]->currentPosition()/
hpi_play[card][i]->getSamplesPerSec();
}
}
#endif // HPI
}
void HpiDriver::playStateChangedData(int card,int stream,int state)
{
emit playStateChanged(card,stream,state);
}
void HpiDriver::recordStateChangedData(int card,int stream,int state)
{
emit recordStateChanged(card,stream,state);
}

86
cae/driver_hpi.h Normal file

@ -0,0 +1,86 @@
// driver_hpi.h
//
// CAE driver for AudioScience HPI devices
//
// (C) Copyright 2002-2015 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 DRIVER_HPI_H
#define DRIVER_HPI_H
#include <rd.h>
#ifdef HPI
#include <rdhpiplaystream.h>
#include <rdhpirecordstream.h>
#include <rdhpisoundcard.h>
#endif // HPI
#include "driver.h"
class HpiDriver : public Driver
{
Q_OBJECT
public:
HpiDriver(RDStation *station,RDConfig *config,QObject *parent=0);
~HpiDriver();
QString version();
QString cardName(int card);
int inputs(int card);
int outputs(int card);
int start(int next_card);
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 stream,int coding,int chans,int samprate,
int bitrate,QString wavename);
bool record(int card,int stream,int length,int thres);
bool stopRecord(int card,int stream);
bool unloadRecord(int card,int stream,unsigned *len);
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 slots:
void playStateChangedData(int card,int stream,int state);
void recordStateChangedData(int card,int stream,int state);
private:
#ifdef HPI
RDHPISoundCard *hpi_sound_card;
RDHPIRecordStream *hpi_record[RD_MAX_CARDS][RD_MAX_STREAMS];
RDHPIPlayStream *hpi_play[RD_MAX_CARDS][RD_MAX_STREAMS];
#endif // HPI
};
#endif // DRIVER_HPI_H

45
cae/driverfactory.cpp Normal file

@ -0,0 +1,45 @@
// driverfactory.cpp
//
// Instantiate CAE audio drivers
//
// (C) Copyright 2015 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 "driver_hpi.h"
#include "driverfactory.h"
Driver *DriverFactory(Driver::Type type,RDStation *station,RDConfig *config,
QObject *parent)
{
Driver *dvr=NULL;
switch(type) {
case Driver::Alsa:
break;
case Driver::Hpi:
#ifdef HPI
dvr=new HpiDriver(station,config,parent);
#endif // HPI
break;
case Driver::Jack:
break;
}
return dvr;
}

30
cae/driverfactory.h Normal file

@ -0,0 +1,30 @@
// driverfactory.h
//
// Instantiate CAE audio drivers
//
// (C) Copyright 2015 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 DRIVERFACTORY_H
#define DRIVERFACTORY_H
#include "driver.h"
Driver *DriverFactory(Driver::Type type,RDStation *station,RDConfig *config,
QObject *parent=0);
#endif // DRIVERFACTORY_H