some work on the new audioOutput layer

git-svn-id: https://svn.musicpd.org/mpd/trunk@2277 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
Warren Dukes 2004-10-20 16:05:13 +00:00
parent 4951f9f809
commit 608ac668db
4 changed files with 95 additions and 139 deletions

View File

@ -14,6 +14,7 @@ mpd_inputPlugins = \
mpd_headers = \
ack.h \
audio.h \
audioOutput.h \
buffer2array.h \
charConv.h \
command.h \
@ -55,6 +56,8 @@ mpd_SOURCES = \
$(mpd_headers) \
$(mpd_inputPlugins) \
audio.c \
audioOutput.c \
audioOutput_ao.c \
buffer2array.c \
charConv.c \
command.c \

View File

@ -28,16 +28,30 @@ AudioOutput * newAudioOutput(char * name) {
if(findInList(audioOutputPluginList, name, &data)) {
AudioOutputPlugin * plugin = (AudioOutputPlugin *) data;
ret = malloc(sizeof(AudioOutput));
ret->initConfigFunc = plugin->initConfigFunc;
ret->finishConfigFunc = plugin->finishConfigFunc;
ret->initDriverFunc = plugin->initDriverFunc;
ret->finishDriverFunc = plugin->initDriverFunc;
ret->openDeviceFunc = plugin->openDeviceFunc;
ret->playFunc = plugin->playFunc;
ret->closeDeviceFunc = plugin->closeDeviceFunc;
plugin->initDriverFunc(ret);
}
return ret;
}
void closeAudioOutput(AudioOutput * audioOutput);
int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat) {
return audioOutput->openDeviceFunc(audioOutput, audioFormat);
}
int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size) {
return audioOutput->playFunc(audioOutput, playChunk, size);
}
void closeAudioOutput(AudioOutput * audioOutput) {
audioOutput->closeDeviceFunc(audioOutput);
}
void finishAudioOutput(AudioOutput * audioOutput) {
audioOutput->finishDriverFunc(audioOutput);
free(audioOutput);
}

View File

@ -28,10 +28,6 @@
typedef struct _AudioOutput AudioOutput;
typedef void (* AudioOutputInitConfigFunc) (AudioOutput * audioOutput);
typedef void (* AudioOutputFinishConfigFunc) (AudioOutput * audioOutput);
typedef void (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput);
typedef void (* AudioOutputFinishDriverFunc) (AudioOutput * audioOutput);
@ -47,32 +43,30 @@ typedef void (* AudioOutputCloseDeviceFunc) (AudioOutput * audioOutput);
struct _AudioOutput {
int error;
AudioOutputInitConfigFunc initConfigFunc;
AudioOutputFinishConfigFunc finishConfigFunc;
AudioOutputInitDriverFunc initDriverFunc;
AudioOutputFinishDriverFunc finishDriverFunc;
AudioOutputOpenDeviceFunc openDeviceFunc;
AudioOutputPlayFunc playFunc;
AudioOutputCloseDevicFunc closeDeviceFunc;
AudioOutputCloseDeviceFunc closeDeviceFunc;
void * data;
};
typedef struct _AudioOutputPlugin {
char * name;
AudioOutputInitConfigFunc initConfigFunc;
AudioOutputFinishConfigFunc finishConfigFunc;
AudioOutputInitDriverFunc initDriverFunc;
AudioOutputFinishDriverFunc finishDriverFunc;
AudioOutputOpenDeviceFunc openDeviceFunc;
AudioOutputPlayFunc playFunc;
AudioOutputCloseDevicFunc closeDeviceFunc;
AudioOutputCloseDeviceFunc closeDeviceFunc;
} AudioOutputPlugin;
void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin);
void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin);
AudioOutput * newAudioOutput(char * name);
int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat);
int audioOutputPlay(AudioOutput * audioOutput, char * playChunk, int size);
void closeAudioOutput(AudioOutput * audioOutput);
void finishAudioOutput(AudioOutput * audioOutput);
#endif

View File

@ -27,14 +27,24 @@
#include <ao/ao.h>
static int audioOutputAo_write_size;
static int driverInitCount = 0;
static int audioOutputAo_driver_id;
static ao_option * audioOutputAo_options;
typedef struct _AoData {
int writeSize;
int driverId;
ao_option * options;
ao_device * device;
} AoData;
static ao_device * audioOutputAo_device = NULL;
static AoData * newAoData() {
AoData * ret = malloc(sizeof(AoData));
ret->device = NULL;
ret->options = NULL;
void audioOutputAo_initDriver() {
return ret;
}
static void audioOutputAo_initDriver(AudioOutput * audioOutput) {
ao_info * ai;
char * dup;
char * stk1;
@ -43,28 +53,33 @@ void audioOutputAo_initDriver() {
char * key;
char * value;
char * test;
AoData * ad = newAoData();
audio_write_size = strtol((getConf())[CONF_AUDIO_WRITE_SIZE],&test,10);
audioOutput->data = ad;
ad->writeSize = strtol((getConf())[CONF_AUDIO_WRITE_SIZE],&test,10);
if (*test!='\0') {
ERROR("\"%s\" is not a valid write size",
(getConf())[CONF_AUDIO_WRITE_SIZE]);
exit(EXIT_FAILURE);
}
audio_ao_options = NULL;
ao_initialize();
if(strcmp(AUDIO_AO_DRIVER_DEFAULT,(getConf())[CONF_AO_DRIVER])==0) {
audio_ao_driver_id = ao_default_driver_id();
if(driverInitCount == 0) {
ao_initialize();
}
else if((audio_ao_driver_id =
driverInitCount++;
if(strcmp(AUDIO_AO_DRIVER_DEFAULT,(getConf())[CONF_AO_DRIVER])==0) {
ad->driverId = ao_default_driver_id();
}
else if((ad->driverId =
ao_driver_id((getConf())[CONF_AO_DRIVER]))<0) {
ERROR("\"%s\" is not a valid ao driver\n",
(getConf())[CONF_AO_DRIVER]);
exit(EXIT_FAILURE);
}
if((ai = ao_driver_info(audio_ao_driver_id))==NULL) {
if((ai = ao_driver_info(ad->driverId))==NULL) {
ERROR("problems getting ao_driver_info\n");
ERROR("you may not have permission to the audio device\n");
exit(EXIT_FAILURE);
@ -101,135 +116,76 @@ void audioOutputAo_initDriver() {
"ao_driver_options \"%s\"\n", n1);
exit(EXIT_FAILURE);
}
ao_append_option(&audio_ao_options,key,value);
ao_append_option(&ad->options,key,value);
n1 = strtok_r(NULL,";",&stk1);
}
}
free(dup);
}
void audioOutputAo_initConfig() {
char * conf = getConf()[CONF_AUDIO_OUTPUT_FORMAT];
char * test;
static void audioOutputAo_finishDriver(AudioOutput * audioOutput) {
AoData * ad = (AoData *)audioOutput->data;
ao_free_options(ad->options);
if(NULL == conf) return;
driverInitCount--;
audio_configFormat = malloc(sizeof(AudioFormat));
memset(audio_configFormat,0,sizeof(AudioFormat));
audio_configFormat->sampleRate = strtol(conf,&test,10);
if(*test!=':') {
ERROR("error parsing audio output format: %s\n",conf);
exit(EXIT_FAILURE);
}
/*switch(audio_configFormat->sampleRate) {
case 48000:
case 44100:
case 32000:
case 16000:
break;
default:
ERROR("sample rate %i can not be used for audio output\n",
(int)audio_configFormat->sampleRate);
exit(EXIT_FAILURE);
}*/
if(audio_configFormat->sampleRate <= 0) {
ERROR("sample rate %i is not >= 0\n",
(int)audio_configFormat->sampleRate);
exit(EXIT_FAILURE);
}
audio_configFormat->bits = strtol(test+1,&test,10);
if(*test!=':') {
ERROR("error parsing audio output format: %s\n",conf);
exit(EXIT_FAILURE);
}
switch(audio_configFormat->bits) {
case 16:
break;
default:
ERROR("bits %i can not be used for audio output\n",
(int)audio_configFormat->bits);
exit(EXIT_FAILURE);
}
audio_configFormat->channels = strtol(test+1,&test,10);
if(*test!='\0') {
ERROR("error parsing audio output format: %s\n",conf);
exit(EXIT_FAILURE);
}
switch(audio_configFormat->channels) {
case 2:
break;
default:
ERROR("channels %i can not be used for audio output\n",
(int)audio_configFormat->channels);
exit(EXIT_FAILURE);
}
if(driverInitCount == 0) ao_shutdown();
}
void audioOutputAo_finishConfig() {
if(audio_configFormat) free(audio_configFormat);
}
void audioOutputAo_finishDriver() {
ao_free_options(audio_ao_options);
ao_shutdown();
}
int audioOutputAo_openDevice(AudioFormat * audioFormat) {
ao_sample_format format;
if(audio_device && !isCurrentAudioFormat(audioFormat)) {
closeAudioDevice();
}
if(!audio_device) {
if(audioFormat) {
copyAudioFormat(&audio_format,audioFormat);
}
format.bits = audio_format.bits;
format.rate = audio_format.sampleRate;
format.byte_format = AO_FMT_NATIVE;
format.channels = audio_format.channels;
static void audioOutputAo_closeDevice(AudioOutput * audioOutput) {
AoData * ad = (AoData *) audioOutput->data;
if(ad->device) {
blockSignals();
audio_device = ao_open_live(audio_ao_driver_id, &format,
audio_ao_options);
ao_close(ad->device);
ad->device = NULL;
unblockSignals();
if(audio_device==NULL) return -1;
}
}
static int audioOutputAo_openDevice(AudioOutput * audioOutput,
AudioFormat * audioFormat)
{
ao_sample_format format;
AoData * ad = (AoData *)audioOutput->data;
if(ad->device) {
audioOutputAo_closeDevice(audioOutput);
}
format.bits = audioFormat->bits;
format.rate = audioFormat->sampleRate;
format.byte_format = AO_FMT_NATIVE;
format.channels = audioFormat->channels;
blockSignals();
ad->device = ao_open_live(ad->driverId, &format, ad->options);
unblockSignals();
if(ad->device==NULL) return -1;
return 0;
}
int audioOutputAo_playAudio(char * playChunk, int size) {
static int audioOutputAo_play(AudioOutput * audioOutput, char * playChunk,
int size)
{
int send;
AoData * ad = (AoData *)audioOutput->data;
if(audio_device==NULL) {
if(ad->device==NULL) {
ERROR("trying to play w/o the audio device being open!\n");
return -1;
}
while(size>0) {
send = audio_write_size>size?size:audio_write_size;
send = ad->writeSize > size ? size : ad->writeSize;
if(ao_play(audio_device,playChunk,send)==0) {
if(ao_play(ad->device, playChunk, send)==0) {
audioError();
ERROR("closing audio device due to write error\n");
closeAudioDevice();
audioOutputAo_closeDevice(audioOutput);
return -1;
}
@ -240,20 +196,9 @@ int audioOutputAo_playAudio(char * playChunk, int size) {
return 0;
}
void audioOutputAo_closeAudioDevice() {
if(audio_device) {
blockSignals();
ao_close(audio_device);
audio_device = NULL;
unblockSignals();
}
}
AudioOutputPlugin aoPlugin =
{
"ao",
audioOutputAo_initConfig,
audioOutputAo_finishConfig,
audioOutputAo_initDriver,
audioOutputAo_finishDriver,
audioOutputAo_openDevice,