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:
parent
4de09b9eaf
commit
c1f86bbde1
@ -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@\
|
||||||
|
951
cae/cae.cpp
951
cae/cae.cpp
File diff suppressed because it is too large
Load Diff
63
cae/cae.h
63
cae/cae.h
@ -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
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
541
cae/cae_hpi.cpp
541
cae/cae_hpi.cpp
@ -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
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
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
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
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
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
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
|
Loading…
x
Reference in New Issue
Block a user