Add mpd-indent.sh
Indent the entire tree, hopefully we can keep it indented. git-svn-id: https://svn.musicpd.org/mpd/trunk@4410 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
@@ -39,13 +39,13 @@
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
typedef snd_pcm_sframes_t alsa_writei_t(snd_pcm_t *pcm, const void *buffer,
|
||||
snd_pcm_uframes_t size);
|
||||
typedef snd_pcm_sframes_t alsa_writei_t(snd_pcm_t * pcm, const void *buffer,
|
||||
snd_pcm_uframes_t size);
|
||||
|
||||
typedef struct _AlsaData {
|
||||
char * device;
|
||||
snd_pcm_t * pcmHandle;
|
||||
alsa_writei_t * writei;
|
||||
char *device;
|
||||
snd_pcm_t *pcmHandle;
|
||||
alsa_writei_t *writei;
|
||||
unsigned int buffer_time;
|
||||
unsigned int period_time;
|
||||
int sampleSize;
|
||||
@@ -54,8 +54,9 @@ typedef struct _AlsaData {
|
||||
int canResume;
|
||||
} AlsaData;
|
||||
|
||||
static AlsaData * newAlsaData(void) {
|
||||
AlsaData * ret = malloc(sizeof(AlsaData));
|
||||
static AlsaData *newAlsaData(void)
|
||||
{
|
||||
AlsaData *ret = malloc(sizeof(AlsaData));
|
||||
|
||||
ret->device = NULL;
|
||||
ret->pcmHandle = NULL;
|
||||
@@ -67,22 +68,25 @@ static AlsaData * newAlsaData(void) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void freeAlsaData(AlsaData * ad) {
|
||||
if(ad->device) free(ad->device);
|
||||
static void freeAlsaData(AlsaData * ad)
|
||||
{
|
||||
if (ad->device)
|
||||
free(ad->device);
|
||||
|
||||
free(ad);
|
||||
}
|
||||
|
||||
static int alsa_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
|
||||
AlsaData * ad = newAlsaData();
|
||||
static int alsa_initDriver(AudioOutput * audioOutput, ConfigParam * param)
|
||||
{
|
||||
AlsaData *ad = newAlsaData();
|
||||
|
||||
if (param) {
|
||||
BlockParam * bp = getBlockParam(param, "device");
|
||||
BlockParam *bp = getBlockParam(param, "device");
|
||||
ad->device = bp ? strdup(bp->value) : strdup("default");
|
||||
|
||||
if ((bp = getBlockParam(param, "use_mmap")) &&
|
||||
(!strcasecmp(bp->value, "yes") ||
|
||||
!strcasecmp(bp->value, "true")))
|
||||
(!strcasecmp(bp->value, "yes") ||
|
||||
!strcasecmp(bp->value, "true")))
|
||||
ad->useMmap = 1;
|
||||
if ((bp = getBlockParam(param, "buffer_time")))
|
||||
ad->buffer_time = atoi(bp->value);
|
||||
@@ -94,45 +98,46 @@ static int alsa_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void alsa_finishDriver(AudioOutput * audioOutput) {
|
||||
AlsaData * ad = audioOutput->data;
|
||||
static void alsa_finishDriver(AudioOutput * audioOutput)
|
||||
{
|
||||
AlsaData *ad = audioOutput->data;
|
||||
|
||||
freeAlsaData(ad);
|
||||
}
|
||||
|
||||
static int alsa_testDefault(void)
|
||||
{
|
||||
snd_pcm_t * handle;
|
||||
snd_pcm_t *handle;
|
||||
|
||||
int ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK,
|
||||
SND_PCM_NONBLOCK);
|
||||
int ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK,
|
||||
SND_PCM_NONBLOCK);
|
||||
snd_config_update_free_global();
|
||||
|
||||
if(ret) {
|
||||
|
||||
if (ret) {
|
||||
WARNING("Error opening default alsa device: %s\n",
|
||||
snd_strerror(-ret));
|
||||
snd_strerror(-ret));
|
||||
return -1;
|
||||
}
|
||||
else snd_pcm_close(handle);
|
||||
} else
|
||||
snd_pcm_close(handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alsa_openDevice(AudioOutput * audioOutput)
|
||||
static int alsa_openDevice(AudioOutput * audioOutput)
|
||||
{
|
||||
AlsaData * ad = audioOutput->data;
|
||||
AudioFormat * audioFormat = &audioOutput->outAudioFormat;
|
||||
AlsaData *ad = audioOutput->data;
|
||||
AudioFormat *audioFormat = &audioOutput->outAudioFormat;
|
||||
snd_pcm_format_t bitformat;
|
||||
snd_pcm_hw_params_t * hwparams;
|
||||
snd_pcm_sw_params_t * swparams;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_sw_params_t *swparams;
|
||||
unsigned int sampleRate = audioFormat->sampleRate;
|
||||
unsigned int channels = audioFormat->channels;
|
||||
snd_pcm_uframes_t alsa_buffer_size;
|
||||
snd_pcm_uframes_t alsa_period_size;
|
||||
int err;
|
||||
char * cmd = NULL;
|
||||
char *cmd = NULL;
|
||||
|
||||
switch(audioFormat->bits) {
|
||||
switch (audioFormat->bits) {
|
||||
case 8:
|
||||
bitformat = SND_PCM_FORMAT_S8;
|
||||
break;
|
||||
@@ -147,101 +152,107 @@ static int alsa_openDevice(AudioOutput * audioOutput)
|
||||
break;
|
||||
default:
|
||||
ERROR("Alsa device \"%s\" doesn't support %i bit audio\n",
|
||||
ad->device, audioFormat->bits);
|
||||
ad->device, audioFormat->bits);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_open(&ad->pcmHandle, ad->device,
|
||||
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
||||
err = snd_pcm_open(&ad->pcmHandle, ad->device,
|
||||
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
||||
snd_config_update_free_global();
|
||||
if(err < 0) {
|
||||
if (err < 0) {
|
||||
ad->pcmHandle = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
cmd = "snd_pcm_nonblock";
|
||||
err = snd_pcm_nonblock(ad->pcmHandle, 0);
|
||||
if(err < 0) goto error;
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
/* configure HW params */
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
|
||||
cmd = "snd_pcm_hw_params_any";
|
||||
err = snd_pcm_hw_params_any(ad->pcmHandle, hwparams);
|
||||
if(err < 0) goto error;
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
if(ad->useMmap) {
|
||||
if (ad->useMmap) {
|
||||
err = snd_pcm_hw_params_set_access(ad->pcmHandle, hwparams,
|
||||
SND_PCM_ACCESS_MMAP_INTERLEAVED);
|
||||
if(err < 0) {
|
||||
SND_PCM_ACCESS_MMAP_INTERLEAVED);
|
||||
if (err < 0) {
|
||||
ERROR("Cannot set mmap'ed mode on alsa device \"%s\": "
|
||||
" %s\n", ad->device,
|
||||
snd_strerror(-err));
|
||||
" %s\n", ad->device, snd_strerror(-err));
|
||||
ERROR("Falling back to direct write mode\n");
|
||||
ad->useMmap = 0;
|
||||
}
|
||||
else ad->writei = snd_pcm_mmap_writei;
|
||||
} else
|
||||
ad->writei = snd_pcm_mmap_writei;
|
||||
}
|
||||
|
||||
if(!ad->useMmap) {
|
||||
if (!ad->useMmap) {
|
||||
cmd = "snd_pcm_hw_params_set_access";
|
||||
err = snd_pcm_hw_params_set_access(ad->pcmHandle, hwparams,
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if(err < 0) goto error;
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
ad->writei = snd_pcm_writei;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_format(ad->pcmHandle, hwparams, bitformat);
|
||||
if(err < 0) {
|
||||
if (err < 0) {
|
||||
ERROR("Alsa device \"%s\" does not support %i bit audio: "
|
||||
"%s\n", ad->device, (int)bitformat,
|
||||
snd_strerror(-err));
|
||||
"%s\n", ad->device, (int)bitformat, snd_strerror(-err));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_channels_near(ad->pcmHandle, hwparams,
|
||||
&channels);
|
||||
if(err < 0) {
|
||||
err = snd_pcm_hw_params_set_channels_near(ad->pcmHandle, hwparams,
|
||||
&channels);
|
||||
if (err < 0) {
|
||||
ERROR("Alsa device \"%s\" does not support %i channels: "
|
||||
"%s\n", ad->device, (int)audioFormat->channels,
|
||||
snd_strerror(-err));
|
||||
"%s\n", ad->device, (int)audioFormat->channels,
|
||||
snd_strerror(-err));
|
||||
goto fail;
|
||||
}
|
||||
audioFormat->channels = channels;
|
||||
|
||||
err = snd_pcm_hw_params_set_rate_near(ad->pcmHandle, hwparams,
|
||||
&sampleRate, NULL);
|
||||
if(err < 0 || sampleRate == 0) {
|
||||
err = snd_pcm_hw_params_set_rate_near(ad->pcmHandle, hwparams,
|
||||
&sampleRate, NULL);
|
||||
if (err < 0 || sampleRate == 0) {
|
||||
ERROR("Alsa device \"%s\" does not support %i Hz audio\n",
|
||||
ad->device, (int)audioFormat->sampleRate);
|
||||
ad->device, (int)audioFormat->sampleRate);
|
||||
goto fail;
|
||||
}
|
||||
audioFormat->sampleRate = sampleRate;
|
||||
|
||||
cmd = "snd_pcm_hw_params_set_buffer_time_near";
|
||||
err = snd_pcm_hw_params_set_buffer_time_near(ad->pcmHandle, hwparams,
|
||||
&ad->buffer_time, NULL);
|
||||
if(err < 0) goto error;
|
||||
&ad->buffer_time, NULL);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
if (!ad->period_time && sampleRate > 0)
|
||||
ad->period_time = 1000000 * MPD_ALSA_SAMPLE_XFER / sampleRate;
|
||||
cmd = "snd_pcm_hw_params_set_period_time_near";
|
||||
err = snd_pcm_hw_params_set_period_time_near(ad->pcmHandle, hwparams,
|
||||
&ad->period_time, NULL);
|
||||
if(err < 0) goto error;
|
||||
&ad->period_time, NULL);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
cmd = "snd_pcm_hw_params";
|
||||
err = snd_pcm_hw_params(ad->pcmHandle, hwparams);
|
||||
if(err < 0) goto error;
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
cmd = "snd_pcm_hw_params_get_buffer_size";
|
||||
err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_buffer_size);
|
||||
if(err < 0) goto error;
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
cmd = "snd_pcm_hw_params_get_period_size";
|
||||
err = snd_pcm_hw_params_get_period_size(hwparams, &alsa_period_size,
|
||||
NULL);
|
||||
if(err < 0) goto error;
|
||||
NULL);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
ad->canPause = snd_pcm_hw_params_can_pause(hwparams);
|
||||
ad->canResume = snd_pcm_hw_params_can_resume(hwparams);
|
||||
@@ -251,68 +262,74 @@ static int alsa_openDevice(AudioOutput * audioOutput)
|
||||
|
||||
cmd = "snd_pcm_sw_params_current";
|
||||
err = snd_pcm_sw_params_current(ad->pcmHandle, swparams);
|
||||
if(err < 0) goto error;
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
cmd = "snd_pcm_sw_params_set_start_threshold";
|
||||
err = snd_pcm_sw_params_set_start_threshold(ad->pcmHandle, swparams,
|
||||
alsa_buffer_size - alsa_period_size);
|
||||
if(err < 0) goto error;
|
||||
alsa_buffer_size -
|
||||
alsa_period_size);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
cmd = "snd_pcm_sw_params_set_avail_min";
|
||||
err = snd_pcm_sw_params_set_avail_min(ad->pcmHandle, swparams,
|
||||
alsa_period_size);
|
||||
if(err < 0) goto error;
|
||||
err = snd_pcm_sw_params_set_avail_min(ad->pcmHandle, swparams,
|
||||
alsa_period_size);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
cmd = "snd_pcm_sw_params_set_xfer_align";
|
||||
err = snd_pcm_sw_params_set_xfer_align(ad->pcmHandle, swparams, 1);
|
||||
if(err < 0) goto error;
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
cmd = "snd_pcm_sw_params";
|
||||
err = snd_pcm_sw_params(ad->pcmHandle, swparams);
|
||||
if(err < 0) goto error;
|
||||
|
||||
ad->sampleSize = (audioFormat->bits/8)*audioFormat->channels;
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
ad->sampleSize = (audioFormat->bits / 8) * audioFormat->channels;
|
||||
|
||||
audioOutput->open = 1;
|
||||
|
||||
DEBUG("alsa device \"%s\" will be playing %i bit, %i channel audio at "
|
||||
"%i Hz\n", ad->device, (int)audioFormat->bits,
|
||||
channels, sampleRate);
|
||||
"%i Hz\n", ad->device, (int)audioFormat->bits,
|
||||
channels, sampleRate);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if(cmd) {
|
||||
ERROR("Error opening alsa device \"%s\" (%s): %s\n",
|
||||
ad->device, cmd, snd_strerror(-err));
|
||||
error:
|
||||
if (cmd) {
|
||||
ERROR("Error opening alsa device \"%s\" (%s): %s\n",
|
||||
ad->device, cmd, snd_strerror(-err));
|
||||
} else {
|
||||
ERROR("Error opening alsa device \"%s\": %s\n", ad->device,
|
||||
snd_strerror(-err));
|
||||
}
|
||||
else {
|
||||
ERROR("Error opening alsa device \"%s\": %s\n", ad->device,
|
||||
snd_strerror(-err));
|
||||
}
|
||||
fail:
|
||||
if(ad->pcmHandle) snd_pcm_close(ad->pcmHandle);
|
||||
fail:
|
||||
if (ad->pcmHandle)
|
||||
snd_pcm_close(ad->pcmHandle);
|
||||
ad->pcmHandle = NULL;
|
||||
audioOutput->open = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int alsa_errorRecovery(AlsaData * ad, int err) {
|
||||
if(err == -EPIPE) {
|
||||
static int alsa_errorRecovery(AlsaData * ad, int err)
|
||||
{
|
||||
if (err == -EPIPE) {
|
||||
DEBUG("Underrun on alsa device \"%s\"\n", ad->device);
|
||||
}
|
||||
else if(err == -ESTRPIPE) {
|
||||
} else if (err == -ESTRPIPE) {
|
||||
DEBUG("alsa device \"%s\" was suspended\n", ad->device);
|
||||
}
|
||||
|
||||
switch(snd_pcm_state(ad->pcmHandle)) {
|
||||
switch (snd_pcm_state(ad->pcmHandle)) {
|
||||
case SND_PCM_STATE_PAUSED:
|
||||
err = snd_pcm_pause(ad->pcmHandle, /* disable */ 0);
|
||||
break;
|
||||
case SND_PCM_STATE_SUSPENDED:
|
||||
err = ad->canResume ?
|
||||
snd_pcm_resume(ad->pcmHandle) :
|
||||
snd_pcm_prepare(ad->pcmHandle);
|
||||
snd_pcm_resume(ad->pcmHandle) :
|
||||
snd_pcm_prepare(ad->pcmHandle);
|
||||
break;
|
||||
case SND_PCM_STATE_SETUP:
|
||||
case SND_PCM_STATE_XRUN:
|
||||
@@ -331,16 +348,18 @@ static int alsa_errorRecovery(AlsaData * ad, int err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
static void alsa_dropBufferedAudio(AudioOutput * audioOutput) {
|
||||
AlsaData * ad = audioOutput->data;
|
||||
static void alsa_dropBufferedAudio(AudioOutput * audioOutput)
|
||||
{
|
||||
AlsaData *ad = audioOutput->data;
|
||||
|
||||
alsa_errorRecovery( ad, snd_pcm_drop(ad->pcmHandle) );
|
||||
alsa_errorRecovery(ad, snd_pcm_drop(ad->pcmHandle));
|
||||
}
|
||||
|
||||
static void alsa_closeDevice(AudioOutput * audioOutput) {
|
||||
AlsaData * ad = audioOutput->data;
|
||||
static void alsa_closeDevice(AudioOutput * audioOutput)
|
||||
{
|
||||
AlsaData *ad = audioOutput->data;
|
||||
|
||||
if(ad->pcmHandle) {
|
||||
if (ad->pcmHandle) {
|
||||
snd_pcm_drain(ad->pcmHandle);
|
||||
snd_pcm_close(ad->pcmHandle);
|
||||
ad->pcmHandle = NULL;
|
||||
@@ -349,10 +368,9 @@ static void alsa_closeDevice(AudioOutput * audioOutput) {
|
||||
audioOutput->open = 0;
|
||||
}
|
||||
|
||||
static int alsa_playAudio(AudioOutput * audioOutput, char * playChunk,
|
||||
int size)
|
||||
static int alsa_playAudio(AudioOutput * audioOutput, char *playChunk, int size)
|
||||
{
|
||||
AlsaData * ad = audioOutput->data;
|
||||
AlsaData *ad = audioOutput->data;
|
||||
int ret;
|
||||
|
||||
size /= ad->sampleSize;
|
||||
@@ -360,13 +378,14 @@ static int alsa_playAudio(AudioOutput * audioOutput, char * playChunk,
|
||||
while (size > 0) {
|
||||
ret = ad->writei(ad->pcmHandle, playChunk, size);
|
||||
|
||||
if(ret == -EAGAIN || ret == -EINTR) continue;
|
||||
|
||||
if(ret < 0) {
|
||||
if( alsa_errorRecovery(ad, ret) < 0) {
|
||||
if (ret == -EAGAIN || ret == -EINTR)
|
||||
continue;
|
||||
|
||||
if (ret < 0) {
|
||||
if (alsa_errorRecovery(ad, ret) < 0) {
|
||||
ERROR("closing alsa device \"%s\" due to write "
|
||||
"error: %s\n", ad->device,
|
||||
snd_strerror(-errno));
|
||||
"error: %s\n", ad->device,
|
||||
snd_strerror(-errno));
|
||||
alsa_closeDevice(audioOutput);
|
||||
return -1;
|
||||
}
|
||||
@@ -380,8 +399,7 @@ static int alsa_playAudio(AudioOutput * audioOutput, char * playChunk,
|
||||
return 0;
|
||||
}
|
||||
|
||||
AudioOutputPlugin alsaPlugin =
|
||||
{
|
||||
AudioOutputPlugin alsaPlugin = {
|
||||
"alsa",
|
||||
alsa_testDefault,
|
||||
alsa_initDriver,
|
||||
@@ -390,11 +408,10 @@ AudioOutputPlugin alsaPlugin =
|
||||
alsa_playAudio,
|
||||
alsa_dropBufferedAudio,
|
||||
alsa_closeDevice,
|
||||
NULL, /* sendMetadataFunc */
|
||||
NULL, /* sendMetadataFunc */
|
||||
};
|
||||
|
||||
#else /* HAVE ALSA */
|
||||
#else /* HAVE ALSA */
|
||||
|
||||
DISABLED_AUDIO_OUTPUT_PLUGIN(alsaPlugin)
|
||||
|
||||
#endif /* HAVE_ALSA */
|
||||
#endif /* HAVE_ALSA */
|
||||
|
||||
@@ -34,122 +34,120 @@ static int driverInitCount = 0;
|
||||
typedef struct _AoData {
|
||||
int writeSize;
|
||||
int driverId;
|
||||
ao_option * options;
|
||||
ao_device * device;
|
||||
ao_option *options;
|
||||
ao_device *device;
|
||||
} AoData;
|
||||
|
||||
static AoData * newAoData() {
|
||||
AoData * ret = malloc(sizeof(AoData));
|
||||
static AoData *newAoData()
|
||||
{
|
||||
AoData *ret = malloc(sizeof(AoData));
|
||||
ret->device = NULL;
|
||||
ret->options = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void audioOutputAo_error() {
|
||||
if(errno==AO_ENOTLIVE) {
|
||||
static void audioOutputAo_error()
|
||||
{
|
||||
if (errno == AO_ENOTLIVE) {
|
||||
ERROR("not a live ao device\n");
|
||||
}
|
||||
else if(errno==AO_EOPENDEVICE) {
|
||||
} else if (errno == AO_EOPENDEVICE) {
|
||||
ERROR("not able to open audio device\n");
|
||||
}
|
||||
else if(errno==AO_EBADOPTION) {
|
||||
} else if (errno == AO_EBADOPTION) {
|
||||
ERROR("bad driver option\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int audioOutputAo_initDriver(AudioOutput * audioOutput,
|
||||
ConfigParam * param)
|
||||
ConfigParam * param)
|
||||
{
|
||||
ao_info * ai;
|
||||
char * dup;
|
||||
char * stk1;
|
||||
char * stk2;
|
||||
char * n1;
|
||||
char * key;
|
||||
char * value;
|
||||
char * test;
|
||||
AoData * ad = newAoData();
|
||||
BlockParam * blockParam;
|
||||
ao_info *ai;
|
||||
char *dup;
|
||||
char *stk1;
|
||||
char *stk2;
|
||||
char *n1;
|
||||
char *key;
|
||||
char *value;
|
||||
char *test;
|
||||
AoData *ad = newAoData();
|
||||
BlockParam *blockParam;
|
||||
|
||||
audioOutput->data = ad;
|
||||
|
||||
if((blockParam = getBlockParam(param, "write_size"))) {
|
||||
if ((blockParam = getBlockParam(param, "write_size"))) {
|
||||
ad->writeSize = strtol(blockParam->value, &test, 10);
|
||||
if (*test!='\0') {
|
||||
if (*test != '\0') {
|
||||
ERROR("\"%s\" is not a valid write size at line %i\n",
|
||||
blockParam->value, blockParam->line);
|
||||
blockParam->value, blockParam->line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else ad->writeSize = 1024;
|
||||
} else
|
||||
ad->writeSize = 1024;
|
||||
|
||||
if(driverInitCount == 0) {
|
||||
if (driverInitCount == 0) {
|
||||
ao_initialize();
|
||||
}
|
||||
driverInitCount++;
|
||||
|
||||
blockParam = getBlockParam(param, "driver");
|
||||
|
||||
if(!blockParam || 0 == strcmp(blockParam->value,"default")) {
|
||||
if (!blockParam || 0 == strcmp(blockParam->value, "default")) {
|
||||
ad->driverId = ao_default_driver_id();
|
||||
}
|
||||
else if((ad->driverId =
|
||||
ao_driver_id(blockParam->value))<0) {
|
||||
} else if ((ad->driverId = ao_driver_id(blockParam->value)) < 0) {
|
||||
ERROR("\"%s\" is not a valid ao driver at line %i\n",
|
||||
blockParam->value, blockParam->line);
|
||||
blockParam->value, blockParam->line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if((ai = ao_driver_info(ad->driverId))==NULL) {
|
||||
|
||||
if ((ai = ao_driver_info(ad->driverId)) == NULL) {
|
||||
ERROR("problems getting driver info for device defined at "
|
||||
"line %i\n", param->line);
|
||||
"line %i\n", param->line);
|
||||
ERROR("you may not have permission to the audio device\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
DEBUG("using ao driver \"%s\" for \"%s\"\n", ai->short_name,
|
||||
audioOutput->name);
|
||||
DEBUG("using ao driver \"%s\" for \"%s\"\n", ai->short_name,
|
||||
audioOutput->name);
|
||||
|
||||
blockParam = getBlockParam(param, "options");
|
||||
|
||||
if(blockParam) {
|
||||
if (blockParam) {
|
||||
dup = strdup(blockParam->value);
|
||||
}
|
||||
else dup = strdup("");
|
||||
} else
|
||||
dup = strdup("");
|
||||
|
||||
if(strlen(dup)) {
|
||||
if (strlen(dup)) {
|
||||
stk1 = NULL;
|
||||
n1 = strtok_r(dup,";",&stk1);
|
||||
while(n1) {
|
||||
n1 = strtok_r(dup, ";", &stk1);
|
||||
while (n1) {
|
||||
stk2 = NULL;
|
||||
key = strtok_r(n1,"=",&stk2);
|
||||
if(!key) {
|
||||
key = strtok_r(n1, "=", &stk2);
|
||||
if (!key) {
|
||||
ERROR("problems parsing "
|
||||
"ao_driver_options \"%s\"\n", n1);
|
||||
"ao_driver_options \"%s\"\n", n1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/*found = 0;
|
||||
for(i=0;i<ai->option_count;i++) {
|
||||
if(strcmp(ai->options[i],key)==0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
ERROR("\"%s\" is not an option for "
|
||||
"\"%s\" ao driver\n",key,
|
||||
ai->short_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}*/
|
||||
value = strtok_r(NULL,"",&stk2);
|
||||
if(!value) {
|
||||
for(i=0;i<ai->option_count;i++) {
|
||||
if(strcmp(ai->options[i],key)==0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
ERROR("\"%s\" is not an option for "
|
||||
"\"%s\" ao driver\n",key,
|
||||
ai->short_name);
|
||||
exit(EXIT_FAILURE);
|
||||
} */
|
||||
value = strtok_r(NULL, "", &stk2);
|
||||
if (!value) {
|
||||
ERROR("problems parsing "
|
||||
"ao_driver_options \"%s\"\n", n1);
|
||||
"ao_driver_options \"%s\"\n", n1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
ao_append_option(&ad->options,key,value);
|
||||
n1 = strtok_r(NULL,";",&stk1);
|
||||
ao_append_option(&ad->options, key, value);
|
||||
n1 = strtok_r(NULL, ";", &stk1);
|
||||
}
|
||||
}
|
||||
free(dup);
|
||||
@@ -157,28 +155,33 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void freeAoData(AoData * ad) {
|
||||
static void freeAoData(AoData * ad)
|
||||
{
|
||||
ao_free_options(ad->options);
|
||||
free(ad);
|
||||
}
|
||||
|
||||
static void audioOutputAo_finishDriver(AudioOutput * audioOutput) {
|
||||
AoData * ad = (AoData *)audioOutput->data;
|
||||
static void audioOutputAo_finishDriver(AudioOutput * audioOutput)
|
||||
{
|
||||
AoData *ad = (AoData *) audioOutput->data;
|
||||
freeAoData(ad);
|
||||
|
||||
driverInitCount--;
|
||||
|
||||
if(driverInitCount == 0) ao_shutdown();
|
||||
if (driverInitCount == 0)
|
||||
ao_shutdown();
|
||||
}
|
||||
|
||||
static void audioOutputAo_dropBufferedAudio(AudioOutput * audioOutput) {
|
||||
static void audioOutputAo_dropBufferedAudio(AudioOutput * audioOutput)
|
||||
{
|
||||
/* not supported by libao */
|
||||
}
|
||||
|
||||
static void audioOutputAo_closeDevice(AudioOutput * audioOutput) {
|
||||
AoData * ad = (AoData *) audioOutput->data;
|
||||
static void audioOutputAo_closeDevice(AudioOutput * audioOutput)
|
||||
{
|
||||
AoData *ad = (AoData *) audioOutput->data;
|
||||
|
||||
if(ad->device) {
|
||||
if (ad->device) {
|
||||
ao_close(ad->device);
|
||||
ad->device = NULL;
|
||||
}
|
||||
@@ -186,11 +189,12 @@ static void audioOutputAo_closeDevice(AudioOutput * audioOutput) {
|
||||
audioOutput->open = 0;
|
||||
}
|
||||
|
||||
static int audioOutputAo_openDevice(AudioOutput * audioOutput) {
|
||||
static int audioOutputAo_openDevice(AudioOutput * audioOutput)
|
||||
{
|
||||
ao_sample_format format;
|
||||
AoData * ad = (AoData *)audioOutput->data;
|
||||
AoData *ad = (AoData *) audioOutput->data;
|
||||
|
||||
if(ad->device) {
|
||||
if (ad->device) {
|
||||
audioOutputAo_closeDevice(audioOutput);
|
||||
}
|
||||
|
||||
@@ -201,41 +205,41 @@ static int audioOutputAo_openDevice(AudioOutput * audioOutput) {
|
||||
|
||||
ad->device = ao_open_live(ad->driverId, &format, ad->options);
|
||||
|
||||
if(ad->device==NULL) return -1;
|
||||
if (ad->device == NULL)
|
||||
return -1;
|
||||
|
||||
audioOutput->open = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int audioOutputAo_play(AudioOutput * audioOutput, char * playChunk,
|
||||
int size)
|
||||
static int audioOutputAo_play(AudioOutput * audioOutput, char *playChunk,
|
||||
int size)
|
||||
{
|
||||
int send;
|
||||
AoData * ad = (AoData *)audioOutput->data;
|
||||
AoData *ad = (AoData *) audioOutput->data;
|
||||
|
||||
if(ad->device==NULL) return -1;
|
||||
|
||||
while(size>0) {
|
||||
if (ad->device == NULL)
|
||||
return -1;
|
||||
|
||||
while (size > 0) {
|
||||
send = ad->writeSize > size ? size : ad->writeSize;
|
||||
|
||||
if(ao_play(ad->device, playChunk, send)==0) {
|
||||
|
||||
if (ao_play(ad->device, playChunk, send) == 0) {
|
||||
audioOutputAo_error();
|
||||
ERROR("closing audio device due to write error\n");
|
||||
audioOutputAo_closeDevice(audioOutput);
|
||||
return -1;
|
||||
}
|
||||
|
||||
playChunk+=send;
|
||||
size-=send;
|
||||
playChunk += send;
|
||||
size -= send;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AudioOutputPlugin aoPlugin =
|
||||
{
|
||||
AudioOutputPlugin aoPlugin = {
|
||||
"ao",
|
||||
NULL,
|
||||
audioOutputAo_initDriver,
|
||||
@@ -244,7 +248,7 @@ AudioOutputPlugin aoPlugin =
|
||||
audioOutputAo_play,
|
||||
audioOutputAo_dropBufferedAudio,
|
||||
audioOutputAo_closeDevice,
|
||||
NULL, /* sendMetadataFunc */
|
||||
NULL, /* sendMetadataFunc */
|
||||
};
|
||||
|
||||
#else
|
||||
@@ -252,5 +256,4 @@ AudioOutputPlugin aoPlugin =
|
||||
#include <stdio.h>
|
||||
|
||||
DISABLED_AUDIO_OUTPUT_PLUGIN(aoPlugin)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -42,26 +42,26 @@
|
||||
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
# include <soundcard.h>
|
||||
#else /* !(defined(__OpenBSD__) || defined(__NetBSD__) */
|
||||
#else /* !(defined(__OpenBSD__) || defined(__NetBSD__) */
|
||||
# include <sys/soundcard.h>
|
||||
#endif /* !(defined(__OpenBSD__) || defined(__NetBSD__) */
|
||||
#endif /* !(defined(__OpenBSD__) || defined(__NetBSD__) */
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# define AFMT_S16_MPD AFMT_S16_BE
|
||||
#else
|
||||
# define AFMT_S16_MPD AFMT_S16_LE
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
|
||||
typedef struct _OssData {
|
||||
int fd;
|
||||
char * device;
|
||||
char *device;
|
||||
int channels;
|
||||
int sampleRate;
|
||||
int bitFormat;
|
||||
int bits;
|
||||
int * supported[3];
|
||||
int *supported[3];
|
||||
int numSupported[3];
|
||||
int * unsupported[3];
|
||||
int *unsupported[3];
|
||||
int numUnsupported[3];
|
||||
} OssData;
|
||||
|
||||
@@ -73,10 +73,11 @@ typedef struct _OssData {
|
||||
#define OSS_CHANNELS 1
|
||||
#define OSS_BITS 2
|
||||
|
||||
static int getIndexForParam(int param) {
|
||||
static int getIndexForParam(int param)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
switch(param) {
|
||||
|
||||
switch (param) {
|
||||
case SNDCTL_DSP_SPEED:
|
||||
index = OSS_RATE;
|
||||
break;
|
||||
@@ -91,42 +92,49 @@ static int getIndexForParam(int param) {
|
||||
return index;
|
||||
}
|
||||
|
||||
static int findSupportedParam(OssData * od, int param, int val) {
|
||||
static int findSupportedParam(OssData * od, int param, int val)
|
||||
{
|
||||
int i;
|
||||
int index = getIndexForParam(param);
|
||||
|
||||
for(i = 0; i < od->numSupported[index]; i++) {
|
||||
if(od->supported[index][i] == val) return 1;
|
||||
|
||||
for (i = 0; i < od->numSupported[index]; i++) {
|
||||
if (od->supported[index][i] == val)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int canConvert(int index, int val) {
|
||||
switch(index) {
|
||||
static int canConvert(int index, int val)
|
||||
{
|
||||
switch (index) {
|
||||
case OSS_BITS:
|
||||
if(val!=16) return 0;
|
||||
if (val != 16)
|
||||
return 0;
|
||||
break;
|
||||
case OSS_CHANNELS:
|
||||
if(val!=2) return 0;
|
||||
if (val != 2)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getSupportedParam(OssData * od, int param, int val) {
|
||||
static int getSupportedParam(OssData * od, int param, int val)
|
||||
{
|
||||
int i;
|
||||
int index = getIndexForParam(param);
|
||||
int ret = -1;
|
||||
int least = val;
|
||||
int diff;
|
||||
|
||||
for(i = 0; i < od->numSupported[index]; i++) {
|
||||
diff = od->supported[index][i]-val;
|
||||
if(diff < 0) diff = -diff;
|
||||
if(diff < least) {
|
||||
if(!canConvert(index, od->supported[index][i])) {
|
||||
|
||||
for (i = 0; i < od->numSupported[index]; i++) {
|
||||
diff = od->supported[index][i] - val;
|
||||
if (diff < 0)
|
||||
diff = -diff;
|
||||
if (diff < least) {
|
||||
if (!canConvert(index, od->supported[index][i])) {
|
||||
continue;
|
||||
}
|
||||
least = diff;
|
||||
@@ -137,97 +145,115 @@ static int getSupportedParam(OssData * od, int param, int val) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int findUnsupportedParam(OssData * od, int param, int val) {
|
||||
static int findUnsupportedParam(OssData * od, int param, int val)
|
||||
{
|
||||
int i;
|
||||
int index = getIndexForParam(param);
|
||||
|
||||
for(i = 0; i < od->numUnsupported[index]; i++) {
|
||||
if(od->unsupported[index][i] == val) return 1;
|
||||
|
||||
for (i = 0; i < od->numUnsupported[index]; i++) {
|
||||
if (od->unsupported[index][i] == val)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void addSupportedParam(OssData * od, int param, int val) {
|
||||
static void addSupportedParam(OssData * od, int param, int val)
|
||||
{
|
||||
int index = getIndexForParam(param);
|
||||
|
||||
od->numSupported[index]++;
|
||||
od->supported[index] = realloc(od->supported[index],
|
||||
od->numSupported[index]*sizeof(int));
|
||||
od->supported[index][od->numSupported[index]-1] = val;
|
||||
od->supported[index] = realloc(od->supported[index],
|
||||
od->numSupported[index] * sizeof(int));
|
||||
od->supported[index][od->numSupported[index] - 1] = val;
|
||||
}
|
||||
|
||||
static void addUnsupportedParam(OssData * od, int param, int val) {
|
||||
static void addUnsupportedParam(OssData * od, int param, int val)
|
||||
{
|
||||
int index = getIndexForParam(param);
|
||||
|
||||
od->numUnsupported[index]++;
|
||||
od->unsupported[index] = realloc(od->unsupported[index],
|
||||
od->numUnsupported[index]*sizeof(int));
|
||||
od->unsupported[index][od->numUnsupported[index]-1] = val;
|
||||
od->unsupported[index] = realloc(od->unsupported[index],
|
||||
od->numUnsupported[index] *
|
||||
sizeof(int));
|
||||
od->unsupported[index][od->numUnsupported[index] - 1] = val;
|
||||
}
|
||||
|
||||
static void removeSupportedParam(OssData * od, int param, int val) {
|
||||
static void removeSupportedParam(OssData * od, int param, int val)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int index = getIndexForParam(param);
|
||||
|
||||
for(i = 0; i < od->numSupported[index]-1; i++) {
|
||||
if(od->supported[index][i] == val) j = 1;
|
||||
od->supported[index][i] = od->supported[index][i+j];
|
||||
for (i = 0; i < od->numSupported[index] - 1; i++) {
|
||||
if (od->supported[index][i] == val)
|
||||
j = 1;
|
||||
od->supported[index][i] = od->supported[index][i + j];
|
||||
}
|
||||
|
||||
od->numSupported[index]--;
|
||||
od->supported[index] = realloc(od->supported[index],
|
||||
od->numSupported[index]*sizeof(int));
|
||||
od->supported[index] = realloc(od->supported[index],
|
||||
od->numSupported[index] * sizeof(int));
|
||||
}
|
||||
|
||||
static void removeUnsupportedParam(OssData * od, int param, int val) {
|
||||
static void removeUnsupportedParam(OssData * od, int param, int val)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int index = getIndexForParam(param);
|
||||
|
||||
for(i = 0; i < od->numUnsupported[index]-1; i++) {
|
||||
if(od->unsupported[index][i] == val) j = 1;
|
||||
od->unsupported[index][i] = od->unsupported[index][i+j];
|
||||
for (i = 0; i < od->numUnsupported[index] - 1; i++) {
|
||||
if (od->unsupported[index][i] == val)
|
||||
j = 1;
|
||||
od->unsupported[index][i] = od->unsupported[index][i + j];
|
||||
}
|
||||
|
||||
od->numUnsupported[index]--;
|
||||
od->unsupported[index] = realloc(od->unsupported[index],
|
||||
od->numUnsupported[index]*sizeof(int));
|
||||
od->unsupported[index] = realloc(od->unsupported[index],
|
||||
od->numUnsupported[index] *
|
||||
sizeof(int));
|
||||
}
|
||||
|
||||
static int isSupportedParam(OssData * od, int param, int val) {
|
||||
if(findSupportedParam(od, param, val)) return OSS_SUPPORTED;
|
||||
if(findUnsupportedParam(od, param, val)) return OSS_UNSUPPORTED;
|
||||
static int isSupportedParam(OssData * od, int param, int val)
|
||||
{
|
||||
if (findSupportedParam(od, param, val))
|
||||
return OSS_SUPPORTED;
|
||||
if (findUnsupportedParam(od, param, val))
|
||||
return OSS_UNSUPPORTED;
|
||||
return OSS_UNKNOWN;
|
||||
}
|
||||
|
||||
static void supportParam(OssData * od, int param, int val) {
|
||||
static void supportParam(OssData * od, int param, int val)
|
||||
{
|
||||
int supported = isSupportedParam(od, param, val);
|
||||
|
||||
if(supported == OSS_SUPPORTED) return;
|
||||
if (supported == OSS_SUPPORTED)
|
||||
return;
|
||||
|
||||
if(supported == OSS_UNSUPPORTED) {
|
||||
if (supported == OSS_UNSUPPORTED) {
|
||||
removeUnsupportedParam(od, param, val);
|
||||
}
|
||||
|
||||
addSupportedParam(od, param, val);
|
||||
}
|
||||
|
||||
static void unsupportParam(OssData * od, int param, int val) {
|
||||
static void unsupportParam(OssData * od, int param, int val)
|
||||
{
|
||||
int supported = isSupportedParam(od, param, val);
|
||||
|
||||
if(supported == OSS_UNSUPPORTED) return;
|
||||
if (supported == OSS_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
if(supported == OSS_SUPPORTED) {
|
||||
if (supported == OSS_SUPPORTED) {
|
||||
removeSupportedParam(od, param, val);
|
||||
}
|
||||
|
||||
addUnsupportedParam(od, param, val);
|
||||
}
|
||||
|
||||
static OssData * newOssData(void) {
|
||||
OssData * ret = malloc(sizeof(OssData));
|
||||
static OssData *newOssData(void)
|
||||
{
|
||||
OssData *ret = malloc(sizeof(OssData));
|
||||
|
||||
ret->device = NULL;
|
||||
ret->fd = -1;
|
||||
@@ -246,23 +272,31 @@ static OssData * newOssData(void) {
|
||||
ret->numUnsupported[OSS_CHANNELS] = 0;
|
||||
ret->numUnsupported[OSS_BITS] = 0;
|
||||
|
||||
supportParam(ret, SNDCTL_DSP_SPEED, 48000);
|
||||
supportParam(ret, SNDCTL_DSP_SPEED, 44100);
|
||||
supportParam(ret, SNDCTL_DSP_CHANNELS, 2);
|
||||
supportParam(ret, SNDCTL_DSP_SAMPLESIZE, 16);
|
||||
supportParam(ret, SNDCTL_DSP_SPEED, 48000);
|
||||
supportParam(ret, SNDCTL_DSP_SPEED, 44100);
|
||||
supportParam(ret, SNDCTL_DSP_CHANNELS, 2);
|
||||
supportParam(ret, SNDCTL_DSP_SAMPLESIZE, 16);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void freeOssData(OssData * od) {
|
||||
if(od->device) free(od->device);
|
||||
static void freeOssData(OssData * od)
|
||||
{
|
||||
if (od->device)
|
||||
free(od->device);
|
||||
|
||||
if(od->supported[OSS_RATE]) free(od->supported[OSS_RATE]);
|
||||
if(od->supported[OSS_CHANNELS]) free(od->supported[OSS_CHANNELS]);
|
||||
if(od->supported[OSS_BITS]) free(od->supported[OSS_BITS]);
|
||||
if(od->unsupported[OSS_RATE]) free(od->unsupported[OSS_RATE]);
|
||||
if(od->unsupported[OSS_CHANNELS]) free(od->unsupported[OSS_CHANNELS]);
|
||||
if(od->unsupported[OSS_BITS]) free(od->unsupported[OSS_BITS]);
|
||||
if (od->supported[OSS_RATE])
|
||||
free(od->supported[OSS_RATE]);
|
||||
if (od->supported[OSS_CHANNELS])
|
||||
free(od->supported[OSS_CHANNELS]);
|
||||
if (od->supported[OSS_BITS])
|
||||
free(od->supported[OSS_BITS]);
|
||||
if (od->unsupported[OSS_RATE])
|
||||
free(od->unsupported[OSS_RATE]);
|
||||
if (od->unsupported[OSS_CHANNELS])
|
||||
free(od->unsupported[OSS_CHANNELS]);
|
||||
if (od->unsupported[OSS_BITS])
|
||||
free(od->unsupported[OSS_BITS]);
|
||||
|
||||
free(od);
|
||||
}
|
||||
@@ -273,18 +307,18 @@ static void freeOssData(OssData * od) {
|
||||
#define OSS_STAT_DOESN_T_EXIST -3
|
||||
#define OSS_STAT_OTHER -4
|
||||
|
||||
static int oss_statDevice(char * device, int * stErrno) {
|
||||
static int oss_statDevice(char *device, int *stErrno)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if(0 == stat(device, &st)) {
|
||||
if(!S_ISCHR(st.st_mode)) {
|
||||
|
||||
if (0 == stat(device, &st)) {
|
||||
if (!S_ISCHR(st.st_mode)) {
|
||||
return OSS_STAT_NOT_CHAR_DEV;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
*stErrno = errno;
|
||||
|
||||
switch(errno) {
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
case ENOTDIR:
|
||||
return OSS_STAT_DOESN_T_EXIST;
|
||||
@@ -298,123 +332,122 @@ static int oss_statDevice(char * device, int * stErrno) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oss_testDefault(void) {
|
||||
static int oss_testDefault(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open("/dev/sound/dsp", O_WRONLY);
|
||||
|
||||
if(fd >= 0) {
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
WARNING("Error opening OSS device \"/dev/sound/dsp\": %s\n",
|
||||
strerror(errno));
|
||||
strerror(errno));
|
||||
|
||||
fd = open("/dev/dsp", O_WRONLY);
|
||||
|
||||
if(fd >= 0) {
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
WARNING("Error opening OSS device \"/dev/dsp\": %s\n",
|
||||
strerror(errno));
|
||||
WARNING("Error opening OSS device \"/dev/dsp\": %s\n", strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
|
||||
BlockParam * bp = NULL;
|
||||
OssData * od;
|
||||
static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param)
|
||||
{
|
||||
BlockParam *bp = NULL;
|
||||
OssData *od;
|
||||
|
||||
if(param) bp = getBlockParam(param, "device");
|
||||
if (param)
|
||||
bp = getBlockParam(param, "device");
|
||||
|
||||
od = newOssData();
|
||||
audioOutput->data = od;
|
||||
|
||||
if(!bp) {
|
||||
if (!bp) {
|
||||
int err[2];
|
||||
int ret[2];
|
||||
|
||||
|
||||
ret[0] = oss_statDevice("/dev/sound/dsp", err);
|
||||
ret[1] = oss_statDevice("/dev/dsp", err+1);
|
||||
ret[1] = oss_statDevice("/dev/dsp", err + 1);
|
||||
|
||||
if(ret[0] == 0) od->device = strdup("/dev/sound/dsp");
|
||||
else if(ret[1] == 0) od->device = strdup("/dev/dsp");
|
||||
if (ret[0] == 0)
|
||||
od->device = strdup("/dev/sound/dsp");
|
||||
else if (ret[1] == 0)
|
||||
od->device = strdup("/dev/dsp");
|
||||
else {
|
||||
if(param) {
|
||||
if (param) {
|
||||
ERROR("Error trying to open default OSS device "
|
||||
"specified at line %i\n", param->line);
|
||||
}
|
||||
else {
|
||||
"specified at line %i\n", param->line);
|
||||
} else {
|
||||
ERROR("Error trying to open default OSS "
|
||||
"device\n");
|
||||
"device\n");
|
||||
}
|
||||
|
||||
if((ret[0] == OSS_STAT_DOESN_T_EXIST) &&
|
||||
(ret[1] == OSS_STAT_DOESN_T_EXIST)) {
|
||||
if ((ret[0] == OSS_STAT_DOESN_T_EXIST) &&
|
||||
(ret[1] == OSS_STAT_DOESN_T_EXIST)) {
|
||||
ERROR("Neither /dev/dsp nor /dev/sound/dsp "
|
||||
"were found\n");
|
||||
}
|
||||
else if(ret[0] == OSS_STAT_NOT_CHAR_DEV) {
|
||||
"were found\n");
|
||||
} else if (ret[0] == OSS_STAT_NOT_CHAR_DEV) {
|
||||
ERROR("/dev/sound/dsp is not a char device");
|
||||
}
|
||||
else if(ret[1] == OSS_STAT_NOT_CHAR_DEV) {
|
||||
} else if (ret[1] == OSS_STAT_NOT_CHAR_DEV) {
|
||||
ERROR("/dev/dsp is not a char device");
|
||||
}
|
||||
else if(ret[0] == OSS_STAT_NO_PERMS) {
|
||||
} else if (ret[0] == OSS_STAT_NO_PERMS) {
|
||||
ERROR("no permission to access /dev/sound/dsp");
|
||||
}
|
||||
else if(ret[1] == OSS_STAT_NO_PERMS) {
|
||||
} else if (ret[1] == OSS_STAT_NO_PERMS) {
|
||||
ERROR("no permission to access /dev/dsp");
|
||||
}
|
||||
else if(ret[0] == OSS_STAT_OTHER) {
|
||||
} else if (ret[0] == OSS_STAT_OTHER) {
|
||||
ERROR("Error accessing /dev/sound/dsp: %s",
|
||||
strerror(err[0]));
|
||||
}
|
||||
else if(ret[1] == OSS_STAT_OTHER) {
|
||||
strerror(err[0]));
|
||||
} else if (ret[1] == OSS_STAT_OTHER) {
|
||||
ERROR("Error accessing /dev/dsp: %s",
|
||||
strerror(err[1]));
|
||||
strerror(err[1]));
|
||||
}
|
||||
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else od->device = strdup(bp->value);
|
||||
} else
|
||||
od->device = strdup(bp->value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void oss_finishDriver(AudioOutput * audioOutput) {
|
||||
OssData * od = audioOutput->data;
|
||||
static void oss_finishDriver(AudioOutput * audioOutput)
|
||||
{
|
||||
OssData *od = audioOutput->data;
|
||||
|
||||
freeOssData(od);
|
||||
}
|
||||
|
||||
static int setParam(OssData * od, int param, int * value) {
|
||||
static int setParam(OssData * od, int param, int *value)
|
||||
{
|
||||
int val = *value;
|
||||
int copy;
|
||||
int supported = isSupportedParam(od, param, val);
|
||||
|
||||
do {
|
||||
if(supported == OSS_UNSUPPORTED) {
|
||||
if (supported == OSS_UNSUPPORTED) {
|
||||
val = getSupportedParam(od, param, val);
|
||||
if(copy < 0) return -1;
|
||||
if (copy < 0)
|
||||
return -1;
|
||||
}
|
||||
copy = val;
|
||||
if(ioctl(od->fd, param, ©)) {
|
||||
if (ioctl(od->fd, param, ©)) {
|
||||
unsupportParam(od, param, val);
|
||||
supported = OSS_UNSUPPORTED;
|
||||
}
|
||||
else {
|
||||
if(supported == OSS_UNKNOWN) {
|
||||
} else {
|
||||
if (supported == OSS_UNKNOWN) {
|
||||
supportParam(od, param, val);
|
||||
supported = OSS_SUPPORTED;
|
||||
}
|
||||
val = copy;
|
||||
}
|
||||
} while( supported == OSS_UNSUPPORTED );
|
||||
} while (supported == OSS_UNSUPPORTED);
|
||||
|
||||
*value = val;
|
||||
|
||||
@@ -423,37 +456,35 @@ static int setParam(OssData * od, int param, int * value) {
|
||||
|
||||
static void oss_close(OssData * od)
|
||||
{
|
||||
if(od->fd >= 0) while (close(od->fd) && errno == EINTR);
|
||||
if (od->fd >= 0)
|
||||
while (close(od->fd) && errno == EINTR) ;
|
||||
od->fd = -1;
|
||||
}
|
||||
|
||||
static int oss_open(AudioOutput * audioOutput) {
|
||||
static int oss_open(AudioOutput * audioOutput)
|
||||
{
|
||||
int tmp;
|
||||
OssData * od = audioOutput->data;
|
||||
OssData *od = audioOutput->data;
|
||||
|
||||
if((od->fd = open(od->device, O_WRONLY)) < 0) {
|
||||
ERROR("Error opening OSS device \"%s\": %s\n", od->device,
|
||||
strerror(errno));
|
||||
if ((od->fd = open(od->device, O_WRONLY)) < 0) {
|
||||
ERROR("Error opening OSS device \"%s\": %s\n", od->device,
|
||||
strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(setParam(od, SNDCTL_DSP_CHANNELS, &od->channels)) {
|
||||
ERROR("OSS device \"%s\" does not support %i channels: %s\n",
|
||||
od->device,
|
||||
od->channels,
|
||||
strerror(errno));
|
||||
if (setParam(od, SNDCTL_DSP_CHANNELS, &od->channels)) {
|
||||
ERROR("OSS device \"%s\" does not support %i channels: %s\n",
|
||||
od->device, od->channels, strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(setParam(od, SNDCTL_DSP_SPEED, &od->sampleRate)) {
|
||||
ERROR("OSS device \"%s\" does not support %i Hz audio: %s\n",
|
||||
od->device,
|
||||
od->sampleRate,
|
||||
strerror(errno));
|
||||
if (setParam(od, SNDCTL_DSP_SPEED, &od->sampleRate)) {
|
||||
ERROR("OSS device \"%s\" does not support %i Hz audio: %s\n",
|
||||
od->device, od->sampleRate, strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch(od->bits) {
|
||||
switch (od->bits) {
|
||||
case 8:
|
||||
tmp = AFMT_S8;
|
||||
break;
|
||||
@@ -461,11 +492,9 @@ static int oss_open(AudioOutput * audioOutput) {
|
||||
tmp = AFMT_S16_MPD;
|
||||
}
|
||||
|
||||
if(setParam(od, SNDCTL_DSP_SAMPLESIZE, &tmp)) {
|
||||
ERROR("OSS device \"%s\" does not support %i bit audio: %s\n",
|
||||
od->device,
|
||||
tmp,
|
||||
strerror(errno));
|
||||
if (setParam(od, SNDCTL_DSP_SAMPLESIZE, &tmp)) {
|
||||
ERROR("OSS device \"%s\" does not support %i bit audio: %s\n",
|
||||
od->device, tmp, strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -473,17 +502,17 @@ static int oss_open(AudioOutput * audioOutput) {
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
oss_close(od);
|
||||
audioOutput->open = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int oss_openDevice(AudioOutput * audioOutput)
|
||||
static int oss_openDevice(AudioOutput * audioOutput)
|
||||
{
|
||||
int ret = -1;
|
||||
OssData * od = audioOutput->data;
|
||||
AudioFormat * audioFormat = &audioOutput->outAudioFormat;
|
||||
OssData *od = audioOutput->data;
|
||||
AudioFormat *audioFormat = &audioOutput->outAudioFormat;
|
||||
|
||||
od->channels = audioFormat->channels;
|
||||
od->sampleRate = audioFormat->sampleRate;
|
||||
@@ -497,45 +526,46 @@ static int oss_openDevice(AudioOutput * audioOutput)
|
||||
audioFormat->bits = od->bits;
|
||||
|
||||
DEBUG("oss device \"%s\" will be playing %i bit %i channel audio at "
|
||||
"%i Hz\n", od->device, od->bits,
|
||||
od->channels, od->sampleRate);
|
||||
"%i Hz\n", od->device, od->bits, od->channels, od->sampleRate);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void oss_closeDevice(AudioOutput * audioOutput) {
|
||||
OssData * od = audioOutput->data;
|
||||
static void oss_closeDevice(AudioOutput * audioOutput)
|
||||
{
|
||||
OssData *od = audioOutput->data;
|
||||
|
||||
oss_close(od);
|
||||
|
||||
audioOutput->open = 0;
|
||||
}
|
||||
|
||||
static void oss_dropBufferedAudio(AudioOutput * audioOutput) {
|
||||
OssData * od = audioOutput->data;
|
||||
static void oss_dropBufferedAudio(AudioOutput * audioOutput)
|
||||
{
|
||||
OssData *od = audioOutput->data;
|
||||
|
||||
if(od->fd >= 0) {
|
||||
if (od->fd >= 0) {
|
||||
ioctl(od->fd, SNDCTL_DSP_RESET, 0);
|
||||
oss_close(od);
|
||||
}
|
||||
}
|
||||
|
||||
static int oss_playAudio(AudioOutput * audioOutput, char * playChunk,
|
||||
int size)
|
||||
static int oss_playAudio(AudioOutput * audioOutput, char *playChunk, int size)
|
||||
{
|
||||
OssData * od = audioOutput->data;
|
||||
OssData *od = audioOutput->data;
|
||||
int ret;
|
||||
|
||||
/* reopen the device since it was closed by dropBufferedAudio */
|
||||
if(od->fd < 0 && oss_open(audioOutput) < 0)
|
||||
if (od->fd < 0 && oss_open(audioOutput) < 0)
|
||||
return -1;
|
||||
|
||||
while (size > 0) {
|
||||
ret = write(od->fd, playChunk, size);
|
||||
if(ret<0) {
|
||||
if(errno == EINTR) continue;
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
ERROR("closing oss device \"%s\" due to write error: "
|
||||
"%s\n", od->device, strerror(errno));
|
||||
"%s\n", od->device, strerror(errno));
|
||||
oss_closeDevice(audioOutput);
|
||||
return -1;
|
||||
}
|
||||
@@ -546,8 +576,7 @@ static int oss_playAudio(AudioOutput * audioOutput, char * playChunk,
|
||||
return 0;
|
||||
}
|
||||
|
||||
AudioOutputPlugin ossPlugin =
|
||||
{
|
||||
AudioOutputPlugin ossPlugin = {
|
||||
"oss",
|
||||
oss_testDefault,
|
||||
oss_initDriver,
|
||||
@@ -556,11 +585,10 @@ AudioOutputPlugin ossPlugin =
|
||||
oss_playAudio,
|
||||
oss_dropBufferedAudio,
|
||||
oss_closeDevice,
|
||||
NULL, /* sendMetadataFunc */
|
||||
NULL, /* sendMetadataFunc */
|
||||
};
|
||||
|
||||
#else /* HAVE OSS */
|
||||
#else /* HAVE OSS */
|
||||
|
||||
DISABLED_AUDIO_OUTPUT_PLUGIN(ossPlugin)
|
||||
|
||||
#endif /* HAVE_OSS */
|
||||
#endif /* HAVE_OSS */
|
||||
|
||||
@@ -29,17 +29,18 @@
|
||||
|
||||
typedef struct _OsxData {
|
||||
AudioUnit au;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t condition;
|
||||
char * buffer;
|
||||
char *buffer;
|
||||
int bufferSize;
|
||||
int pos;
|
||||
int len;
|
||||
int started;
|
||||
} OsxData;
|
||||
|
||||
static OsxData * newOsxData() {
|
||||
OsxData * ret = malloc(sizeof(OsxData));
|
||||
static OsxData *newOsxData()
|
||||
{
|
||||
OsxData *ret = malloc(sizeof(OsxData));
|
||||
|
||||
pthread_mutex_init(&ret->mutex, NULL);
|
||||
pthread_cond_init(&ret->condition, NULL);
|
||||
@@ -53,71 +54,78 @@ static OsxData * newOsxData() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int osx_testDefault() {
|
||||
static int osx_testDefault()
|
||||
{
|
||||
/*AudioUnit au;
|
||||
ComponentDescription desc;
|
||||
Component comp;
|
||||
ComponentDescription desc;
|
||||
Component comp;
|
||||
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = kAudioUnitSubType_Output;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = kAudioUnitSubType_Output;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
|
||||
comp = FindNextComponent(NULL, &desc);
|
||||
if(!comp) {
|
||||
ERROR("Unable to open default OS X defice\n");
|
||||
return -1;
|
||||
}
|
||||
comp = FindNextComponent(NULL, &desc);
|
||||
if(!comp) {
|
||||
ERROR("Unable to open default OS X defice\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(OpenAComponent(comp, &au) != noErr) {
|
||||
ERROR("Unable to open default OS X defice\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
CloseComponent(au);*/
|
||||
if(OpenAComponent(comp, &au) != noErr) {
|
||||
ERROR("Unable to open default OS X defice\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
CloseComponent(au); */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osx_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
|
||||
OsxData * od = newOsxData();
|
||||
static int osx_initDriver(AudioOutput * audioOutput, ConfigParam * param)
|
||||
{
|
||||
OsxData *od = newOsxData();
|
||||
|
||||
audioOutput->data = od;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void freeOsxData(OsxData * od) {
|
||||
if(od->buffer) free(od->buffer);
|
||||
static void freeOsxData(OsxData * od)
|
||||
{
|
||||
if (od->buffer)
|
||||
free(od->buffer);
|
||||
pthread_mutex_destroy(&od->mutex);
|
||||
pthread_cond_destroy(&od->condition);
|
||||
free(od);
|
||||
}
|
||||
|
||||
static void osx_finishDriver(AudioOutput * audioOutput) {
|
||||
OsxData * od = (OsxData *)audioOutput->data;
|
||||
static void osx_finishDriver(AudioOutput * audioOutput)
|
||||
{
|
||||
OsxData *od = (OsxData *) audioOutput->data;
|
||||
freeOsxData(od);
|
||||
}
|
||||
|
||||
static void osx_dropBufferedAudio(AudioOutput * audioOutput) {
|
||||
OsxData * od = (OsxData *)audioOutput->data;
|
||||
static void osx_dropBufferedAudio(AudioOutput * audioOutput)
|
||||
{
|
||||
OsxData *od = (OsxData *) audioOutput->data;
|
||||
|
||||
pthread_mutex_lock(&od->mutex);
|
||||
od->len = 0;
|
||||
pthread_mutex_unlock(&od->mutex);
|
||||
}
|
||||
|
||||
static void osx_closeDevice(AudioOutput * audioOutput) {
|
||||
OsxData * od = (OsxData *) audioOutput->data;
|
||||
static void osx_closeDevice(AudioOutput * audioOutput)
|
||||
{
|
||||
OsxData *od = (OsxData *) audioOutput->data;
|
||||
|
||||
pthread_mutex_lock(&od->mutex);
|
||||
while(od->len) {
|
||||
while (od->len) {
|
||||
pthread_cond_wait(&od->condition, &od->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&od->mutex);
|
||||
|
||||
if(od->started) {
|
||||
if (od->started) {
|
||||
AudioOutputUnitStop(od->au);
|
||||
od->started = 0;
|
||||
}
|
||||
@@ -128,79 +136,80 @@ static void osx_closeDevice(AudioOutput * audioOutput) {
|
||||
audioOutput->open = 0;
|
||||
}
|
||||
|
||||
static OSStatus osx_render(void * vdata,
|
||||
AudioUnitRenderActionFlags *ioActionFlags,
|
||||
const AudioTimeStamp * inTimeStamp,
|
||||
UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||
AudioBufferList *bufferList)
|
||||
static OSStatus osx_render(void *vdata,
|
||||
AudioUnitRenderActionFlags * ioActionFlags,
|
||||
const AudioTimeStamp * inTimeStamp,
|
||||
UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||
AudioBufferList * bufferList)
|
||||
{
|
||||
OsxData * od = (OsxData *)vdata;
|
||||
AudioBuffer * buffer = &bufferList->mBuffers[0];
|
||||
OsxData *od = (OsxData *) vdata;
|
||||
AudioBuffer *buffer = &bufferList->mBuffers[0];
|
||||
int bufferSize = buffer->mDataByteSize;
|
||||
int bytesToCopy;
|
||||
int curpos = 0;
|
||||
|
||||
/*DEBUG("osx_render: enter : %i\n", (int)bufferList->mNumberBuffers);
|
||||
DEBUG("osx_render: ioActionFlags: %p\n", ioActionFlags);
|
||||
if(ioActionFlags) {
|
||||
if(*ioActionFlags & kAudioUnitRenderAction_PreRender) {
|
||||
DEBUG("prerender\n");
|
||||
}
|
||||
if(*ioActionFlags & kAudioUnitRenderAction_PostRender) {
|
||||
DEBUG("post render\n");
|
||||
}
|
||||
if(*ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) {
|
||||
DEBUG("post render\n");
|
||||
}
|
||||
if(*ioActionFlags & kAudioOfflineUnitRenderAction_Preflight) {
|
||||
DEBUG("prefilight\n");
|
||||
}
|
||||
if(*ioActionFlags & kAudioOfflineUnitRenderAction_Render) {
|
||||
DEBUG("render\n");
|
||||
}
|
||||
if(*ioActionFlags & kAudioOfflineUnitRenderAction_Complete) {
|
||||
DEBUG("complete\n");
|
||||
}
|
||||
}*/
|
||||
DEBUG("osx_render: ioActionFlags: %p\n", ioActionFlags);
|
||||
if(ioActionFlags) {
|
||||
if(*ioActionFlags & kAudioUnitRenderAction_PreRender) {
|
||||
DEBUG("prerender\n");
|
||||
}
|
||||
if(*ioActionFlags & kAudioUnitRenderAction_PostRender) {
|
||||
DEBUG("post render\n");
|
||||
}
|
||||
if(*ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) {
|
||||
DEBUG("post render\n");
|
||||
}
|
||||
if(*ioActionFlags & kAudioOfflineUnitRenderAction_Preflight) {
|
||||
DEBUG("prefilight\n");
|
||||
}
|
||||
if(*ioActionFlags & kAudioOfflineUnitRenderAction_Render) {
|
||||
DEBUG("render\n");
|
||||
}
|
||||
if(*ioActionFlags & kAudioOfflineUnitRenderAction_Complete) {
|
||||
DEBUG("complete\n");
|
||||
}
|
||||
} */
|
||||
|
||||
/* while(bufferSize) {
|
||||
DEBUG("osx_render: lock\n"); */
|
||||
pthread_mutex_lock(&od->mutex);
|
||||
/*
|
||||
DEBUG("%i:%i\n", bufferSize, od->len);
|
||||
while(od->go && od->len < bufferSize &&
|
||||
od->len < od->bufferSize)
|
||||
{
|
||||
DEBUG("osx_render: wait\n");
|
||||
pthread_cond_wait(&od->condition, &od->mutex);
|
||||
}
|
||||
*/
|
||||
DEBUG("osx_render: lock\n"); */
|
||||
pthread_mutex_lock(&od->mutex);
|
||||
/*
|
||||
DEBUG("%i:%i\n", bufferSize, od->len);
|
||||
while(od->go && od->len < bufferSize &&
|
||||
od->len < od->bufferSize)
|
||||
{
|
||||
DEBUG("osx_render: wait\n");
|
||||
pthread_cond_wait(&od->condition, &od->mutex);
|
||||
}
|
||||
*/
|
||||
|
||||
bytesToCopy = od->len < bufferSize ? od->len : bufferSize;
|
||||
bufferSize = bytesToCopy;
|
||||
od->len -= bytesToCopy;
|
||||
bytesToCopy = od->len < bufferSize ? od->len : bufferSize;
|
||||
bufferSize = bytesToCopy;
|
||||
od->len -= bytesToCopy;
|
||||
|
||||
if(od->pos+bytesToCopy > od->bufferSize) {
|
||||
int bytes = od->bufferSize-od->pos;
|
||||
memcpy(buffer->mData+curpos, od->buffer+od->pos, bytes);
|
||||
od->pos = 0;
|
||||
curpos += bytes;
|
||||
bytesToCopy -= bytes;
|
||||
}
|
||||
if (od->pos + bytesToCopy > od->bufferSize) {
|
||||
int bytes = od->bufferSize - od->pos;
|
||||
memcpy(buffer->mData + curpos, od->buffer + od->pos, bytes);
|
||||
od->pos = 0;
|
||||
curpos += bytes;
|
||||
bytesToCopy -= bytes;
|
||||
}
|
||||
|
||||
memcpy(buffer->mData+curpos, od->buffer+od->pos, bytesToCopy);
|
||||
od->pos += bytesToCopy;
|
||||
curpos += bytesToCopy;
|
||||
memcpy(buffer->mData + curpos, od->buffer + od->pos, bytesToCopy);
|
||||
od->pos += bytesToCopy;
|
||||
curpos += bytesToCopy;
|
||||
|
||||
if(od->pos >= od->bufferSize) od->pos = 0;
|
||||
/* DEBUG("osx_render: unlock\n"); */
|
||||
pthread_mutex_unlock(&od->mutex);
|
||||
pthread_cond_signal(&od->condition);
|
||||
if (od->pos >= od->bufferSize)
|
||||
od->pos = 0;
|
||||
/* DEBUG("osx_render: unlock\n"); */
|
||||
pthread_mutex_unlock(&od->mutex);
|
||||
pthread_cond_signal(&od->condition);
|
||||
/* } */
|
||||
|
||||
buffer->mDataByteSize = bufferSize;
|
||||
|
||||
if(!bufferSize) {
|
||||
if (!bufferSize) {
|
||||
my_usleep(1000);
|
||||
}
|
||||
|
||||
@@ -208,12 +217,13 @@ static OSStatus osx_render(void * vdata,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osx_openDevice(AudioOutput * audioOutput) {
|
||||
OsxData * od = (OsxData *)audioOutput->data;
|
||||
static int osx_openDevice(AudioOutput * audioOutput)
|
||||
{
|
||||
OsxData *od = (OsxData *) audioOutput->data;
|
||||
ComponentDescription desc;
|
||||
Component comp;
|
||||
AURenderCallbackStruct callback;
|
||||
AudioFormat * audioFormat = &audioOutput->outAudioFormat;
|
||||
AudioFormat *audioFormat = &audioOutput->outAudioFormat;
|
||||
AudioStreamBasicDescription streamDesc;
|
||||
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
@@ -223,17 +233,17 @@ static int osx_openDevice(AudioOutput * audioOutput) {
|
||||
desc.componentFlagsMask = 0;
|
||||
|
||||
comp = FindNextComponent(NULL, &desc);
|
||||
if(comp == 0) {
|
||||
if (comp == 0) {
|
||||
ERROR("Error finding OS X component\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(OpenAComponent(comp, &od->au) != noErr) {
|
||||
if (OpenAComponent(comp, &od->au) != noErr) {
|
||||
ERROR("Unable to open OS X component\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(AudioUnitInitialize(od->au) != 0) {
|
||||
if (AudioUnitInitialize(od->au) != 0) {
|
||||
CloseComponent(od->au);
|
||||
ERROR("Unable to initialuze OS X audio unit\n");
|
||||
return -1;
|
||||
@@ -242,10 +252,9 @@ static int osx_openDevice(AudioOutput * audioOutput) {
|
||||
callback.inputProc = osx_render;
|
||||
callback.inputProcRefCon = od;
|
||||
|
||||
if(AudioUnitSetProperty(od->au, kAudioUnitProperty_SetRenderCallback,
|
||||
kAudioUnitScope_Input, 0,
|
||||
&callback, sizeof(callback)) != 0)
|
||||
{
|
||||
if (AudioUnitSetProperty(od->au, kAudioUnitProperty_SetRenderCallback,
|
||||
kAudioUnitScope_Input, 0,
|
||||
&callback, sizeof(callback)) != 0) {
|
||||
AudioUnitUninitialize(od->au);
|
||||
CloseComponent(od->au);
|
||||
ERROR("unable to set callbak for OS X audio unit\n");
|
||||
@@ -255,17 +264,17 @@ static int osx_openDevice(AudioOutput * audioOutput) {
|
||||
streamDesc.mSampleRate = audioFormat->sampleRate;
|
||||
streamDesc.mFormatID = kAudioFormatLinearPCM;
|
||||
streamDesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |
|
||||
kLinearPCMFormatFlagIsBigEndian;
|
||||
streamDesc.mBytesPerPacket = audioFormat->channels*audioFormat->bits/8;
|
||||
kLinearPCMFormatFlagIsBigEndian;
|
||||
streamDesc.mBytesPerPacket =
|
||||
audioFormat->channels * audioFormat->bits / 8;
|
||||
streamDesc.mFramesPerPacket = 1;
|
||||
streamDesc.mBytesPerFrame = streamDesc.mBytesPerPacket;
|
||||
streamDesc.mChannelsPerFrame = audioFormat->channels;
|
||||
streamDesc.mBitsPerChannel = audioFormat->bits;
|
||||
|
||||
if(AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat,
|
||||
kAudioUnitScope_Input, 0,
|
||||
&streamDesc, sizeof(streamDesc)) != 0)
|
||||
{
|
||||
if (AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat,
|
||||
kAudioUnitScope_Input, 0,
|
||||
&streamDesc, sizeof(streamDesc)) != 0) {
|
||||
AudioUnitUninitialize(od->au);
|
||||
CloseComponent(od->au);
|
||||
ERROR("Unable to set format on OS X device\n");
|
||||
@@ -274,7 +283,7 @@ static int osx_openDevice(AudioOutput * audioOutput) {
|
||||
|
||||
/* create a buffer of 1s */
|
||||
od->bufferSize = (audioFormat->sampleRate) *
|
||||
(audioFormat->bits >> 3) * (audioFormat->channels);
|
||||
(audioFormat->bits >> 3) * (audioFormat->channels);
|
||||
od->buffer = realloc(od->buffer, od->bufferSize);
|
||||
|
||||
od->pos = 0;
|
||||
@@ -285,18 +294,19 @@ static int osx_openDevice(AudioOutput * audioOutput) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osx_play(AudioOutput * audioOutput, char * playChunk, int size) {
|
||||
OsxData * od = (OsxData *)audioOutput->data;
|
||||
static int osx_play(AudioOutput * audioOutput, char *playChunk, int size)
|
||||
{
|
||||
OsxData *od = (OsxData *) audioOutput->data;
|
||||
int bytesToCopy;
|
||||
int curpos;
|
||||
|
||||
/* DEBUG("osx_play: enter\n"); */
|
||||
|
||||
if(!od->started) {
|
||||
if (!od->started) {
|
||||
int err;
|
||||
od->started = 1;
|
||||
err = AudioOutputUnitStart(od->au);
|
||||
if(err) {
|
||||
if (err) {
|
||||
ERROR("unable to start audio output: %i\n", err);
|
||||
return -1;
|
||||
}
|
||||
@@ -304,14 +314,15 @@ static int osx_play(AudioOutput * audioOutput, char * playChunk, int size) {
|
||||
|
||||
pthread_mutex_lock(&od->mutex);
|
||||
|
||||
while(size) {
|
||||
while (size) {
|
||||
/* DEBUG("osx_play: lock\n"); */
|
||||
curpos = od->pos+od->len;
|
||||
if(curpos >= od->bufferSize) curpos -= od->bufferSize;
|
||||
curpos = od->pos + od->len;
|
||||
if (curpos >= od->bufferSize)
|
||||
curpos -= od->bufferSize;
|
||||
|
||||
bytesToCopy = od->bufferSize < size ? od->bufferSize : size;
|
||||
|
||||
while(od->len > od->bufferSize-bytesToCopy) {
|
||||
while (od->len > od->bufferSize - bytesToCopy) {
|
||||
/* DEBUG("osx_play: wait\n"); */
|
||||
pthread_cond_wait(&od->condition, &od->mutex);
|
||||
}
|
||||
@@ -321,15 +332,15 @@ static int osx_play(AudioOutput * audioOutput, char * playChunk, int size) {
|
||||
size -= bytesToCopy;
|
||||
od->len += bytesToCopy;
|
||||
|
||||
if(curpos+bytesToCopy > od->bufferSize) {
|
||||
int bytes = od->bufferSize-curpos;
|
||||
memcpy(od->buffer+curpos, playChunk, bytes);
|
||||
if (curpos + bytesToCopy > od->bufferSize) {
|
||||
int bytes = od->bufferSize - curpos;
|
||||
memcpy(od->buffer + curpos, playChunk, bytes);
|
||||
curpos = 0;
|
||||
playChunk += bytes;
|
||||
bytesToCopy -= bytes;
|
||||
}
|
||||
|
||||
memcpy(od->buffer+curpos, playChunk, bytesToCopy);
|
||||
memcpy(od->buffer + curpos, playChunk, bytesToCopy);
|
||||
curpos += bytesToCopy;
|
||||
playChunk += bytesToCopy;
|
||||
|
||||
@@ -341,8 +352,7 @@ static int osx_play(AudioOutput * audioOutput, char * playChunk, int size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
AudioOutputPlugin osxPlugin =
|
||||
{
|
||||
AudioOutputPlugin osxPlugin = {
|
||||
"osx",
|
||||
osx_testDefault,
|
||||
osx_initDriver,
|
||||
@@ -351,7 +361,7 @@ AudioOutputPlugin osxPlugin =
|
||||
osx_play,
|
||||
osx_dropBufferedAudio,
|
||||
osx_closeDevice,
|
||||
NULL, /* sendMetadataFunc */
|
||||
NULL, /* sendMetadataFunc */
|
||||
};
|
||||
|
||||
#else
|
||||
@@ -359,5 +369,4 @@ AudioOutputPlugin osxPlugin =
|
||||
#include <stdio.h>
|
||||
|
||||
DISABLED_AUDIO_OUTPUT_PLUGIN(osxPlugin)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,17 +34,17 @@
|
||||
#define CONN_ATTEMPT_INTERVAL 60
|
||||
|
||||
typedef struct _PulseData {
|
||||
pa_simple * s;
|
||||
char * server;
|
||||
char * sink;
|
||||
pa_simple *s;
|
||||
char *server;
|
||||
char *sink;
|
||||
int connAttempts;
|
||||
time_t lastAttempt;
|
||||
} PulseData;
|
||||
|
||||
static PulseData * newPulseData()
|
||||
static PulseData *newPulseData()
|
||||
{
|
||||
PulseData * ret;
|
||||
|
||||
PulseData *ret;
|
||||
|
||||
ret = malloc(sizeof(PulseData));
|
||||
|
||||
ret->s = NULL;
|
||||
@@ -58,16 +58,18 @@ static PulseData * newPulseData()
|
||||
|
||||
static void freePulseData(PulseData * pd)
|
||||
{
|
||||
if (pd->server) free(pd->server);
|
||||
if (pd->sink) free(pd->sink);
|
||||
if (pd->server)
|
||||
free(pd->server);
|
||||
if (pd->sink)
|
||||
free(pd->sink);
|
||||
free(pd);
|
||||
}
|
||||
|
||||
static int pulse_initDriver(AudioOutput * audioOutput, ConfigParam * param)
|
||||
{
|
||||
BlockParam * server = NULL;
|
||||
BlockParam * sink = NULL;
|
||||
PulseData * pd;
|
||||
BlockParam *server = NULL;
|
||||
BlockParam *sink = NULL;
|
||||
PulseData *pd;
|
||||
|
||||
if (param) {
|
||||
server = getBlockParam(param, "server");
|
||||
@@ -89,7 +91,7 @@ static void pulse_finishDriver(AudioOutput * audioOutput)
|
||||
|
||||
static int pulse_testDefault()
|
||||
{
|
||||
pa_simple * s;
|
||||
pa_simple *s;
|
||||
pa_sample_spec ss;
|
||||
int error;
|
||||
|
||||
@@ -98,10 +100,10 @@ static int pulse_testDefault()
|
||||
ss.channels = 2;
|
||||
|
||||
s = pa_simple_new(NULL, MPD_PULSE_NAME, PA_STREAM_PLAYBACK, NULL,
|
||||
MPD_PULSE_NAME, &ss, NULL, NULL, &error);
|
||||
MPD_PULSE_NAME, &ss, NULL, NULL, &error);
|
||||
if (!s) {
|
||||
WARNING("Cannot connect to default PulseAudio server: %s\n",
|
||||
pa_strerror(error));
|
||||
pa_strerror(error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -112,8 +114,8 @@ static int pulse_testDefault()
|
||||
|
||||
static int pulse_openDevice(AudioOutput * audioOutput)
|
||||
{
|
||||
PulseData * pd;
|
||||
AudioFormat * audioFormat;
|
||||
PulseData *pd;
|
||||
AudioFormat *audioFormat;
|
||||
pa_sample_spec ss;
|
||||
time_t t;
|
||||
int error;
|
||||
@@ -123,7 +125,8 @@ static int pulse_openDevice(AudioOutput * audioOutput)
|
||||
audioFormat = &audioOutput->outAudioFormat;
|
||||
|
||||
if (pd->connAttempts != 0 &&
|
||||
(t - pd->lastAttempt) < CONN_ATTEMPT_INTERVAL) return -1;
|
||||
(t - pd->lastAttempt) < CONN_ATTEMPT_INTERVAL)
|
||||
return -1;
|
||||
|
||||
pd->connAttempts++;
|
||||
pd->lastAttempt = t;
|
||||
@@ -139,10 +142,10 @@ static int pulse_openDevice(AudioOutput * audioOutput)
|
||||
ss.channels = audioFormat->channels;
|
||||
|
||||
pd->s = pa_simple_new(pd->server, MPD_PULSE_NAME, PA_STREAM_PLAYBACK,
|
||||
pd->sink, audioOutput->name, &ss, NULL, NULL,
|
||||
&error);
|
||||
pd->sink, audioOutput->name, &ss, NULL, NULL,
|
||||
&error);
|
||||
if (!pd->s) {
|
||||
ERROR("Cannot connect to server in PulseAudio output " \
|
||||
ERROR("Cannot connect to server in PulseAudio output "
|
||||
"\"%s\" (attempt %i): %s\n", audioOutput->name,
|
||||
pd->connAttempts, pa_strerror(error));
|
||||
return -1;
|
||||
@@ -151,7 +154,7 @@ static int pulse_openDevice(AudioOutput * audioOutput)
|
||||
pd->connAttempts = 0;
|
||||
audioOutput->open = 1;
|
||||
|
||||
DEBUG("PulseAudio output \"%s\" connected and playing %i bit, %i " \
|
||||
DEBUG("PulseAudio output \"%s\" connected and playing %i bit, %i "
|
||||
"channel audio at %i Hz\n", audioOutput->name, audioFormat->bits,
|
||||
audioFormat->channels, audioFormat->sampleRate);
|
||||
|
||||
@@ -160,18 +163,18 @@ static int pulse_openDevice(AudioOutput * audioOutput)
|
||||
|
||||
static void pulse_dropBufferedAudio(AudioOutput * audioOutput)
|
||||
{
|
||||
PulseData * pd;
|
||||
PulseData *pd;
|
||||
int error;
|
||||
|
||||
pd = audioOutput->data;
|
||||
if (pa_simple_flush(pd->s, &error) < 0)
|
||||
if (pa_simple_flush(pd->s, &error) < 0)
|
||||
WARNING("Flush failed in PulseAudio output \"%s\": %s\n",
|
||||
audioOutput->name, pa_strerror(error));
|
||||
audioOutput->name, pa_strerror(error));
|
||||
}
|
||||
|
||||
static void pulse_closeDevice(AudioOutput * audioOutput)
|
||||
{
|
||||
PulseData * pd;
|
||||
PulseData *pd;
|
||||
|
||||
pd = audioOutput->data;
|
||||
if (pd->s) {
|
||||
@@ -182,16 +185,15 @@ static void pulse_closeDevice(AudioOutput * audioOutput)
|
||||
audioOutput->open = 0;
|
||||
}
|
||||
|
||||
static int pulse_playAudio(AudioOutput * audioOutput, char * playChunk,
|
||||
int size)
|
||||
static int pulse_playAudio(AudioOutput * audioOutput, char *playChunk, int size)
|
||||
{
|
||||
PulseData * pd;
|
||||
PulseData *pd;
|
||||
int error;
|
||||
|
||||
pd = audioOutput->data;
|
||||
|
||||
if (pa_simple_write(pd->s, playChunk, size, &error) < 0) {
|
||||
ERROR("PulseAudio output \"%s\" disconnecting due to write " \
|
||||
ERROR("PulseAudio output \"%s\" disconnecting due to write "
|
||||
"error: %s\n", audioOutput->name, pa_strerror(error));
|
||||
pulse_closeDevice(audioOutput);
|
||||
return -1;
|
||||
@@ -209,11 +211,10 @@ AudioOutputPlugin pulsePlugin = {
|
||||
pulse_playAudio,
|
||||
pulse_dropBufferedAudio,
|
||||
pulse_closeDevice,
|
||||
NULL, /* sendMetadataFunc */
|
||||
NULL, /* sendMetadataFunc */
|
||||
};
|
||||
|
||||
#else /* HAVE_PULSE */
|
||||
#else /* HAVE_PULSE */
|
||||
|
||||
DISABLED_AUDIO_OUTPUT_PLUGIN(pulsePlugin)
|
||||
|
||||
#endif /* HAVE_PULSE */
|
||||
#endif /* HAVE_PULSE */
|
||||
|
||||
@@ -42,7 +42,7 @@ static int shoutInitCount = 0;
|
||||
/* lots of this code blatantly stolent from bossogg/bossao2 */
|
||||
|
||||
typedef struct _ShoutData {
|
||||
shout_t * shoutConn;
|
||||
shout_t *shoutConn;
|
||||
int shoutError;
|
||||
|
||||
ogg_stream_state os;
|
||||
@@ -51,7 +51,7 @@ typedef struct _ShoutData {
|
||||
ogg_packet header_main;
|
||||
ogg_packet header_comments;
|
||||
ogg_packet header_codebooks;
|
||||
|
||||
|
||||
vorbis_dsp_state vd;
|
||||
vorbis_block vb;
|
||||
vorbis_info vi;
|
||||
@@ -62,18 +62,19 @@ typedef struct _ShoutData {
|
||||
|
||||
int opened;
|
||||
|
||||
MpdTag * tag;
|
||||
MpdTag *tag;
|
||||
int tagToSend;
|
||||
|
||||
int connAttempts;
|
||||
time_t lastAttempt;
|
||||
|
||||
/* just a pointer to audioOutput->outAudioFormat */
|
||||
AudioFormat * audioFormat;
|
||||
AudioFormat *audioFormat;
|
||||
} ShoutData;
|
||||
|
||||
static ShoutData * newShoutData(void) {
|
||||
ShoutData * ret = malloc(sizeof(ShoutData));
|
||||
static ShoutData *newShoutData(void)
|
||||
{
|
||||
ShoutData *ret = malloc(sizeof(ShoutData));
|
||||
|
||||
ret->shoutConn = shout_new();
|
||||
ret->opened = 0;
|
||||
@@ -88,9 +89,12 @@ static ShoutData * newShoutData(void) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void freeShoutData(ShoutData * sd) {
|
||||
if(sd->shoutConn) shout_free(sd->shoutConn);
|
||||
if(sd->tag) freeMpdTag(sd->tag);
|
||||
static void freeShoutData(ShoutData * sd)
|
||||
{
|
||||
if (sd->shoutConn)
|
||||
shout_free(sd->shoutConn);
|
||||
if (sd->tag)
|
||||
freeMpdTag(sd->tag);
|
||||
|
||||
free(sd);
|
||||
}
|
||||
@@ -104,21 +108,23 @@ static void freeShoutData(ShoutData * sd) {
|
||||
} \
|
||||
}
|
||||
|
||||
static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
|
||||
ShoutData * sd;
|
||||
char * test;
|
||||
static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param)
|
||||
{
|
||||
ShoutData *sd;
|
||||
char *test;
|
||||
int port;
|
||||
char * host;
|
||||
char * mount;
|
||||
char * passwd;
|
||||
char * user;
|
||||
char * name;
|
||||
BlockParam * blockParam;
|
||||
char *host;
|
||||
char *mount;
|
||||
char *passwd;
|
||||
char *user;
|
||||
char *name;
|
||||
BlockParam *blockParam;
|
||||
unsigned int public;
|
||||
|
||||
sd = newShoutData();
|
||||
|
||||
if(shoutInitCount == 0) shout_init();
|
||||
if (shoutInitCount == 0)
|
||||
shout_init();
|
||||
|
||||
shoutInitCount++;
|
||||
|
||||
@@ -132,9 +138,9 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
|
||||
|
||||
port = strtol(blockParam->value, &test, 10);
|
||||
|
||||
if(*test != '\0' || port <= 0) {
|
||||
ERROR("shout port \"%s\" is not a positive integer, line %i\n",
|
||||
blockParam->value, blockParam->line);
|
||||
if (*test != '\0' || port <= 0) {
|
||||
ERROR("shout port \"%s\" is not a positive integer, line %i\n",
|
||||
blockParam->value, blockParam->line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@@ -145,58 +151,61 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
|
||||
name = blockParam->value;
|
||||
|
||||
blockParam = getBlockParam(param, "public");
|
||||
if(blockParam) {
|
||||
if(0 == strcmp(blockParam->value, "yes")) public = 1;
|
||||
else if(0 == strcmp(blockParam->value, "no")) public = 0;
|
||||
if (blockParam) {
|
||||
if (0 == strcmp(blockParam->value, "yes"))
|
||||
public = 1;
|
||||
else if (0 == strcmp(blockParam->value, "no"))
|
||||
public = 0;
|
||||
else {
|
||||
ERROR("public \"%s\" is not \"yes\" or \"no\" at line "
|
||||
"%i\n", param->value, param->line);
|
||||
"%i\n", param->value, param->line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else public = 0;
|
||||
} else
|
||||
public = 0;
|
||||
|
||||
blockParam = getBlockParam(param, "user");
|
||||
if(blockParam) user = blockParam->value;
|
||||
else user = "source";
|
||||
if (blockParam)
|
||||
user = blockParam->value;
|
||||
else
|
||||
user = "source";
|
||||
|
||||
blockParam = getBlockParam(param, "quality");
|
||||
|
||||
if(blockParam) {
|
||||
if (blockParam) {
|
||||
int line = blockParam->line;
|
||||
|
||||
sd->quality = strtod(blockParam->value, &test);
|
||||
|
||||
if(*test != '\0' || sd->quality < 0.0 || sd->quality > 10.0) {
|
||||
if (*test != '\0' || sd->quality < 0.0 || sd->quality > 10.0) {
|
||||
ERROR("shout quality \"%s\" is not a number in the "
|
||||
"range 0-10, line %i\n", blockParam->value,
|
||||
blockParam->line);
|
||||
"range 0-10, line %i\n", blockParam->value,
|
||||
blockParam->line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
blockParam = getBlockParam(param, "bitrate");
|
||||
|
||||
if(blockParam) {
|
||||
if (blockParam) {
|
||||
ERROR("quality (line %i) and bitrate (line %i) are "
|
||||
"both defined for shout output\n", line,
|
||||
blockParam->line);
|
||||
"both defined for shout output\n", line,
|
||||
blockParam->line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
blockParam = getBlockParam(param, "bitrate");
|
||||
|
||||
if(!blockParam) {
|
||||
if (!blockParam) {
|
||||
ERROR("neither bitrate nor quality defined for shout "
|
||||
"output at line %i\n", param->line);
|
||||
"output at line %i\n", param->line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sd->bitrate = strtol(blockParam->value, &test, 10);
|
||||
|
||||
if(*test != '\0' || sd->bitrate <= 0) {
|
||||
if (*test != '\0' || sd->bitrate <= 0) {
|
||||
ERROR("bitrate at line %i should be a positive integer "
|
||||
"\n", blockParam->line);
|
||||
"\n", blockParam->line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -204,64 +213,58 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
|
||||
checkBlockParam("format");
|
||||
sd->audioFormat = &audioOutput->outAudioFormat;
|
||||
|
||||
if(shout_set_host(sd->shoutConn, host) != SHOUTERR_SUCCESS ||
|
||||
shout_set_port(sd->shoutConn, port) != SHOUTERR_SUCCESS ||
|
||||
shout_set_password(sd->shoutConn, passwd) != SHOUTERR_SUCCESS ||
|
||||
shout_set_mount(sd->shoutConn, mount) != SHOUTERR_SUCCESS ||
|
||||
shout_set_name(sd->shoutConn, name) != SHOUTERR_SUCCESS ||
|
||||
shout_set_user(sd->shoutConn, user) != SHOUTERR_SUCCESS ||
|
||||
shout_set_public(sd->shoutConn, public) != SHOUTERR_SUCCESS ||
|
||||
shout_set_format(sd->shoutConn, SHOUT_FORMAT_VORBIS)
|
||||
!= SHOUTERR_SUCCESS ||
|
||||
shout_set_protocol(sd->shoutConn, SHOUT_PROTOCOL_HTTP)
|
||||
!= SHOUTERR_SUCCESS ||
|
||||
shout_set_agent(sd->shoutConn, "MPD") != SHOUTERR_SUCCESS)
|
||||
{
|
||||
if (shout_set_host(sd->shoutConn, host) != SHOUTERR_SUCCESS ||
|
||||
shout_set_port(sd->shoutConn, port) != SHOUTERR_SUCCESS ||
|
||||
shout_set_password(sd->shoutConn, passwd) != SHOUTERR_SUCCESS ||
|
||||
shout_set_mount(sd->shoutConn, mount) != SHOUTERR_SUCCESS ||
|
||||
shout_set_name(sd->shoutConn, name) != SHOUTERR_SUCCESS ||
|
||||
shout_set_user(sd->shoutConn, user) != SHOUTERR_SUCCESS ||
|
||||
shout_set_public(sd->shoutConn, public) != SHOUTERR_SUCCESS ||
|
||||
shout_set_format(sd->shoutConn, SHOUT_FORMAT_VORBIS)
|
||||
!= SHOUTERR_SUCCESS ||
|
||||
shout_set_protocol(sd->shoutConn, SHOUT_PROTOCOL_HTTP)
|
||||
!= SHOUTERR_SUCCESS ||
|
||||
shout_set_agent(sd->shoutConn, "MPD") != SHOUTERR_SUCCESS) {
|
||||
ERROR("error configuring shout defined at line %i: %s\n",
|
||||
param->line,
|
||||
shout_get_error(sd->shoutConn));
|
||||
param->line, shout_get_error(sd->shoutConn));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* optional paramters */
|
||||
blockParam = getBlockParam(param, "genre");
|
||||
if(blockParam && shout_set_genre(sd->shoutConn, blockParam->value)) {
|
||||
if (blockParam && shout_set_genre(sd->shoutConn, blockParam->value)) {
|
||||
ERROR("error configuring shout defined at line %i: %s\n",
|
||||
param->line,
|
||||
shout_get_error(sd->shoutConn));
|
||||
param->line, shout_get_error(sd->shoutConn));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
blockParam = getBlockParam(param, "description");
|
||||
if(blockParam && shout_set_description(sd->shoutConn,
|
||||
blockParam->value))
|
||||
{
|
||||
if (blockParam && shout_set_description(sd->shoutConn,
|
||||
blockParam->value)) {
|
||||
ERROR("error configuring shout defined at line %i: %s\n",
|
||||
param->line,
|
||||
shout_get_error(sd->shoutConn));
|
||||
param->line, shout_get_error(sd->shoutConn));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
{
|
||||
char temp[11];
|
||||
memset(temp, 0, sizeof(temp));
|
||||
|
||||
|
||||
snprintf(temp, sizeof(temp), "%d", sd->audioFormat->channels);
|
||||
shout_set_audio_info(sd->shoutConn, SHOUT_AI_CHANNELS, temp);
|
||||
|
||||
snprintf(temp, sizeof(temp), "%d", sd->audioFormat->sampleRate);
|
||||
|
||||
|
||||
shout_set_audio_info(sd->shoutConn, SHOUT_AI_SAMPLERATE, temp);
|
||||
|
||||
if(sd->quality >= 0) {
|
||||
if (sd->quality >= 0) {
|
||||
snprintf(temp, sizeof(temp), "%2.2f", sd->quality);
|
||||
shout_set_audio_info(sd->shoutConn, SHOUT_AI_QUALITY,
|
||||
temp);
|
||||
}
|
||||
else {
|
||||
temp);
|
||||
} else {
|
||||
snprintf(temp, sizeof(temp), "%d", sd->bitrate);
|
||||
shout_set_audio_info(sd->shoutConn, SHOUT_AI_BITRATE,
|
||||
temp);
|
||||
temp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,23 +273,24 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int myShout_handleError(ShoutData * sd, int err) {
|
||||
switch(err) {
|
||||
static int myShout_handleError(ShoutData * sd, int err)
|
||||
{
|
||||
switch (err) {
|
||||
case SHOUTERR_SUCCESS:
|
||||
break;
|
||||
case SHOUTERR_UNCONNECTED:
|
||||
case SHOUTERR_SOCKET:
|
||||
ERROR("Lost shout connection to %s:%i : %s\n",
|
||||
shout_get_host(sd->shoutConn),
|
||||
shout_get_port(sd->shoutConn),
|
||||
shout_get_error(sd->shoutConn));
|
||||
ERROR("Lost shout connection to %s:%i : %s\n",
|
||||
shout_get_host(sd->shoutConn),
|
||||
shout_get_port(sd->shoutConn),
|
||||
shout_get_error(sd->shoutConn));
|
||||
sd->shoutError = 1;
|
||||
return -1;
|
||||
default:
|
||||
ERROR("shout: connection to %s:%i error : %s\n",
|
||||
shout_get_host(sd->shoutConn),
|
||||
shout_get_port(sd->shoutConn),
|
||||
shout_get_error(sd->shoutConn));
|
||||
ERROR("shout: connection to %s:%i error : %s\n",
|
||||
shout_get_host(sd->shoutConn),
|
||||
shout_get_port(sd->shoutConn),
|
||||
shout_get_error(sd->shoutConn));
|
||||
sd->shoutError = 1;
|
||||
return -1;
|
||||
}
|
||||
@@ -294,39 +298,46 @@ static int myShout_handleError(ShoutData * sd, int err) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_page(ShoutData * sd) {
|
||||
static int write_page(ShoutData * sd)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
/*DEBUG("shout_delay: %i\n", shout_delay(sd->shoutConn));*/
|
||||
/*DEBUG("shout_delay: %i\n", shout_delay(sd->shoutConn)); */
|
||||
shout_sync(sd->shoutConn);
|
||||
err = shout_send(sd->shoutConn, sd->og.header, sd->og.header_len);
|
||||
if(myShout_handleError(sd, err) < 0) return -1;
|
||||
if (myShout_handleError(sd, err) < 0)
|
||||
return -1;
|
||||
err = shout_send(sd->shoutConn, sd->og.body, sd->og.body_len);
|
||||
if(myShout_handleError(sd, err) < 0) return -1;
|
||||
if (myShout_handleError(sd, err) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void finishEncoder(ShoutData * sd) {
|
||||
static void finishEncoder(ShoutData * sd)
|
||||
{
|
||||
vorbis_analysis_wrote(&sd->vd, 0);
|
||||
|
||||
while(vorbis_analysis_blockout(&sd->vd, &sd->vb) == 1) {
|
||||
while (vorbis_analysis_blockout(&sd->vd, &sd->vb) == 1) {
|
||||
vorbis_analysis(&sd->vb, NULL);
|
||||
vorbis_bitrate_addblock(&sd->vb);
|
||||
while(vorbis_bitrate_flushpacket(&sd->vd, &sd->op)) {
|
||||
while (vorbis_bitrate_flushpacket(&sd->vd, &sd->op)) {
|
||||
ogg_stream_packetin(&sd->os, &sd->op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int flushEncoder(ShoutData * sd) {
|
||||
static int flushEncoder(ShoutData * sd)
|
||||
{
|
||||
return (ogg_stream_pageout(&sd->os, &sd->og) > 0);
|
||||
}
|
||||
|
||||
static void clearEncoder(ShoutData * sd) {
|
||||
static void clearEncoder(ShoutData * sd)
|
||||
{
|
||||
finishEncoder(sd);
|
||||
while(1 == flushEncoder(sd)) {
|
||||
if(!sd->shoutError) write_page(sd);
|
||||
while (1 == flushEncoder(sd)) {
|
||||
if (!sd->shoutError)
|
||||
write_page(sd);
|
||||
}
|
||||
|
||||
vorbis_comment_clear(&sd->vc);
|
||||
@@ -336,21 +347,23 @@ static void clearEncoder(ShoutData * sd) {
|
||||
vorbis_info_clear(&sd->vi);
|
||||
}
|
||||
|
||||
static void myShout_closeShoutConn(ShoutData * sd) {
|
||||
if(sd->opened) {
|
||||
static void myShout_closeShoutConn(ShoutData * sd)
|
||||
{
|
||||
if (sd->opened) {
|
||||
clearEncoder(sd);
|
||||
|
||||
if(shout_close(sd->shoutConn) != SHOUTERR_SUCCESS) {
|
||||
if (shout_close(sd->shoutConn) != SHOUTERR_SUCCESS) {
|
||||
ERROR("problem closing connection to shout server: "
|
||||
"%s\n", shout_get_error(sd->shoutConn));
|
||||
"%s\n", shout_get_error(sd->shoutConn));
|
||||
}
|
||||
}
|
||||
|
||||
sd->opened = 0;
|
||||
}
|
||||
|
||||
static void myShout_finishDriver(AudioOutput * audioOutput) {
|
||||
ShoutData * sd = (ShoutData *)audioOutput->data;
|
||||
static void myShout_finishDriver(AudioOutput * audioOutput)
|
||||
{
|
||||
ShoutData *sd = (ShoutData *) audioOutput->data;
|
||||
|
||||
myShout_closeShoutConn(sd);
|
||||
|
||||
@@ -358,15 +371,18 @@ static void myShout_finishDriver(AudioOutput * audioOutput) {
|
||||
|
||||
shoutInitCount--;
|
||||
|
||||
if(shoutInitCount == 0) shout_shutdown();
|
||||
if (shoutInitCount == 0)
|
||||
shout_shutdown();
|
||||
}
|
||||
|
||||
static void myShout_dropBufferedAudio(AudioOutput * audioOutput) {
|
||||
static void myShout_dropBufferedAudio(AudioOutput * audioOutput)
|
||||
{
|
||||
/* needs to be implemented */
|
||||
}
|
||||
|
||||
static void myShout_closeDevice(AudioOutput * audioOutput) {
|
||||
ShoutData * sd = (ShoutData *)audioOutput->data;
|
||||
static void myShout_closeDevice(AudioOutput * audioOutput)
|
||||
{
|
||||
ShoutData *sd = (ShoutData *) audioOutput->data;
|
||||
|
||||
myShout_closeShoutConn(sd);
|
||||
|
||||
@@ -377,12 +393,13 @@ static void myShout_closeDevice(AudioOutput * audioOutput) {
|
||||
if(value) vorbis_comment_add_tag(&(sd->vc), name, value); \
|
||||
}
|
||||
|
||||
static void copyTagToVorbisComment(ShoutData * sd) {
|
||||
if(sd->tag) {
|
||||
static void copyTagToVorbisComment(ShoutData * sd)
|
||||
{
|
||||
if (sd->tag) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < sd->tag->numOfItems; i++) {
|
||||
switch(sd->tag->items[i].type) {
|
||||
for (i = 0; i < sd->tag->numOfItems; i++) {
|
||||
switch (sd->tag->items[i].type) {
|
||||
case TAG_ITEM_ARTIST:
|
||||
addTag("ARTIST", sd->tag->items[i].value);
|
||||
break;
|
||||
@@ -397,25 +414,24 @@ static void copyTagToVorbisComment(ShoutData * sd) {
|
||||
}
|
||||
}
|
||||
|
||||
static int initEncoder(ShoutData * sd) {
|
||||
static int initEncoder(ShoutData * sd)
|
||||
{
|
||||
vorbis_info_init(&(sd->vi));
|
||||
|
||||
if(sd->quality >= 0) {
|
||||
if( 0 != vorbis_encode_init_vbr(&(sd->vi),
|
||||
sd->audioFormat->channels,
|
||||
sd->audioFormat->sampleRate, sd->quality*0.1) )
|
||||
{
|
||||
if (sd->quality >= 0) {
|
||||
if (0 != vorbis_encode_init_vbr(&(sd->vi),
|
||||
sd->audioFormat->channels,
|
||||
sd->audioFormat->sampleRate,
|
||||
sd->quality * 0.1)) {
|
||||
ERROR("problem seting up vorbis encoder for shout\n");
|
||||
vorbis_info_clear(&(sd->vi));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( 0 != vorbis_encode_init(&(sd->vi),
|
||||
sd->audioFormat->channels,
|
||||
sd->audioFormat->sampleRate, -1.0,
|
||||
sd->bitrate*1000, -1.0) )
|
||||
{
|
||||
} else {
|
||||
if (0 != vorbis_encode_init(&(sd->vi),
|
||||
sd->audioFormat->channels,
|
||||
sd->audioFormat->sampleRate, -1.0,
|
||||
sd->bitrate * 1000, -1.0)) {
|
||||
ERROR("problem seting up vorbis encoder for shout\n");
|
||||
vorbis_info_clear(&(sd->vi));
|
||||
return -1;
|
||||
@@ -423,7 +439,7 @@ static int initEncoder(ShoutData * sd) {
|
||||
}
|
||||
|
||||
vorbis_analysis_init(&(sd->vd), &(sd->vi));
|
||||
vorbis_block_init (&(sd->vd), &(sd->vb));
|
||||
vorbis_block_init(&(sd->vd), &(sd->vb));
|
||||
|
||||
ogg_stream_init(&(sd->os), rand());
|
||||
|
||||
@@ -432,13 +448,13 @@ static int initEncoder(ShoutData * sd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int myShout_openShoutConn(AudioOutput * audioOutput) {
|
||||
ShoutData * sd = (ShoutData *)audioOutput->data;
|
||||
static int myShout_openShoutConn(AudioOutput * audioOutput)
|
||||
{
|
||||
ShoutData *sd = (ShoutData *) audioOutput->data;
|
||||
time_t t = time(NULL);
|
||||
|
||||
if(sd->connAttempts!= 0 &&
|
||||
(t - sd->lastAttempt) < CONN_ATTEMPT_INTERVAL)
|
||||
{
|
||||
if (sd->connAttempts != 0 &&
|
||||
(t - sd->lastAttempt) < CONN_ATTEMPT_INTERVAL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -446,17 +462,16 @@ static int myShout_openShoutConn(AudioOutput * audioOutput) {
|
||||
|
||||
sd->lastAttempt = t;
|
||||
|
||||
if(shout_open(sd->shoutConn) != SHOUTERR_SUCCESS) {
|
||||
if (shout_open(sd->shoutConn) != SHOUTERR_SUCCESS) {
|
||||
ERROR("problem opening connection to shout server %s:%i "
|
||||
"(attempt %i): %s\n",
|
||||
shout_get_host(sd->shoutConn),
|
||||
shout_get_port(sd->shoutConn),
|
||||
sd->connAttempts,
|
||||
shout_get_error(sd->shoutConn));
|
||||
"(attempt %i): %s\n",
|
||||
shout_get_host(sd->shoutConn),
|
||||
shout_get_port(sd->shoutConn),
|
||||
sd->connAttempts, shout_get_error(sd->shoutConn));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(initEncoder(sd) < 0) {
|
||||
if (initEncoder(sd) < 0) {
|
||||
shout_close(sd->shoutConn);
|
||||
return -1;
|
||||
}
|
||||
@@ -466,7 +481,8 @@ static int myShout_openShoutConn(AudioOutput * audioOutput) {
|
||||
copyTagToVorbisComment(sd);
|
||||
|
||||
vorbis_analysis_headerout(&(sd->vd), &(sd->vc), &(sd->header_main),
|
||||
&(sd->header_comments), &(sd->header_codebooks));
|
||||
&(sd->header_comments),
|
||||
&(sd->header_codebooks));
|
||||
|
||||
ogg_stream_packetin(&(sd->os), &(sd->header_main));
|
||||
ogg_stream_packetin(&(sd->os), &(sd->header_comments));
|
||||
@@ -475,9 +491,8 @@ static int myShout_openShoutConn(AudioOutput * audioOutput) {
|
||||
sd->opened = 1;
|
||||
sd->tagToSend = 0;
|
||||
|
||||
while(ogg_stream_flush(&(sd->os), &(sd->og)))
|
||||
{
|
||||
if(write_page(sd) < 0) {
|
||||
while (ogg_stream_flush(&(sd->os), &(sd->og))) {
|
||||
if (write_page(sd) < 0) {
|
||||
myShout_closeShoutConn(sd);
|
||||
return -1;
|
||||
}
|
||||
@@ -488,14 +503,16 @@ static int myShout_openShoutConn(AudioOutput * audioOutput) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int myShout_openDevice(AudioOutput * audioOutput) {
|
||||
ShoutData * sd = (ShoutData *)audioOutput->data;
|
||||
static int myShout_openDevice(AudioOutput * audioOutput)
|
||||
{
|
||||
ShoutData *sd = (ShoutData *) audioOutput->data;
|
||||
|
||||
audioOutput->open = 1;
|
||||
|
||||
if(sd->opened) return 0;
|
||||
if (sd->opened)
|
||||
return 0;
|
||||
|
||||
if(myShout_openShoutConn(audioOutput) < 0) {
|
||||
if (myShout_openShoutConn(audioOutput) < 0) {
|
||||
audioOutput->open = 0;
|
||||
return -1;
|
||||
}
|
||||
@@ -503,76 +520,80 @@ static int myShout_openDevice(AudioOutput * audioOutput) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void myShout_sendMetadata(ShoutData * sd) {
|
||||
if(!sd->opened || !sd->tag) return;
|
||||
static void myShout_sendMetadata(ShoutData * sd)
|
||||
{
|
||||
if (!sd->opened || !sd->tag)
|
||||
return;
|
||||
|
||||
clearEncoder(sd);
|
||||
if(initEncoder(sd) < 0) return;
|
||||
if (initEncoder(sd) < 0)
|
||||
return;
|
||||
|
||||
copyTagToVorbisComment(sd);
|
||||
|
||||
vorbis_analysis_headerout(&(sd->vd), &(sd->vc), &(sd->header_main),
|
||||
&(sd->header_comments), &(sd->header_codebooks));
|
||||
&(sd->header_comments),
|
||||
&(sd->header_codebooks));
|
||||
|
||||
ogg_stream_packetin(&(sd->os), &(sd->header_main));
|
||||
ogg_stream_packetin(&(sd->os), &(sd->header_comments));
|
||||
ogg_stream_packetin(&(sd->os), &(sd->header_codebooks));
|
||||
|
||||
while(ogg_stream_flush(&(sd->os), &(sd->og)))
|
||||
{
|
||||
if(write_page(sd) < 0) {
|
||||
while (ogg_stream_flush(&(sd->os), &(sd->og))) {
|
||||
if (write_page(sd) < 0) {
|
||||
myShout_closeShoutConn(sd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*if(sd->tag) freeMpdTag(sd->tag);
|
||||
sd->tag = NULL;*/
|
||||
sd->tag = NULL; */
|
||||
sd->tagToSend = 0;
|
||||
}
|
||||
|
||||
static int myShout_play(AudioOutput * audioOutput, char * playChunk, int size) {
|
||||
int i,j;
|
||||
ShoutData * sd = (ShoutData *)audioOutput->data;
|
||||
float ** vorbbuf;
|
||||
static int myShout_play(AudioOutput * audioOutput, char *playChunk, int size)
|
||||
{
|
||||
int i, j;
|
||||
ShoutData *sd = (ShoutData *) audioOutput->data;
|
||||
float **vorbbuf;
|
||||
int samples;
|
||||
int bytes = sd->audioFormat->bits/8;
|
||||
int bytes = sd->audioFormat->bits / 8;
|
||||
|
||||
if(sd->opened && sd->tagToSend) myShout_sendMetadata(sd);
|
||||
if (sd->opened && sd->tagToSend)
|
||||
myShout_sendMetadata(sd);
|
||||
|
||||
if(!sd->opened) {
|
||||
if(myShout_openShoutConn(audioOutput) < 0) {
|
||||
if (!sd->opened) {
|
||||
if (myShout_openShoutConn(audioOutput) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
samples = size/(bytes*sd->audioFormat->channels);
|
||||
samples = size / (bytes * sd->audioFormat->channels);
|
||||
|
||||
/* this is for only 16-bit audio */
|
||||
|
||||
vorbbuf = vorbis_analysis_buffer(&(sd->vd), samples);
|
||||
|
||||
for(i=0; i<samples; i++) {
|
||||
for(j=0; j<sd->audioFormat->channels; j++) {
|
||||
vorbbuf[j][i] = (*((mpd_sint16 *)playChunk)) / 32768.0;
|
||||
for (i = 0; i < samples; i++) {
|
||||
for (j = 0; j < sd->audioFormat->channels; j++) {
|
||||
vorbbuf[j][i] = (*((mpd_sint16 *) playChunk)) / 32768.0;
|
||||
playChunk += bytes;
|
||||
}
|
||||
}
|
||||
|
||||
vorbis_analysis_wrote(&(sd->vd), samples);
|
||||
|
||||
while(1 == vorbis_analysis_blockout(&(sd->vd), &(sd->vb))) {
|
||||
while (1 == vorbis_analysis_blockout(&(sd->vd), &(sd->vb))) {
|
||||
vorbis_analysis(&(sd->vb), NULL);
|
||||
vorbis_bitrate_addblock(&(sd->vb));
|
||||
|
||||
while(vorbis_bitrate_flushpacket(&(sd->vd), &(sd->op))) {
|
||||
while (vorbis_bitrate_flushpacket(&(sd->vd), &(sd->op))) {
|
||||
ogg_stream_packetin(&(sd->os), &(sd->op));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while(ogg_stream_pageout(&(sd->os), &(sd->og)) != 0) {
|
||||
if(write_page(sd) < 0) {
|
||||
while (ogg_stream_pageout(&(sd->os), &(sd->og)) != 0) {
|
||||
if (write_page(sd) < 0) {
|
||||
myShout_closeShoutConn(sd);
|
||||
return -1;
|
||||
}
|
||||
@@ -581,21 +602,23 @@ static int myShout_play(AudioOutput * audioOutput, char * playChunk, int size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void myShout_setTag(AudioOutput * audioOutput, MpdTag * tag) {
|
||||
ShoutData * sd = (ShoutData *)audioOutput->data;
|
||||
static void myShout_setTag(AudioOutput * audioOutput, MpdTag * tag)
|
||||
{
|
||||
ShoutData *sd = (ShoutData *) audioOutput->data;
|
||||
|
||||
if(sd->tag) freeMpdTag(sd->tag);
|
||||
if (sd->tag)
|
||||
freeMpdTag(sd->tag);
|
||||
sd->tag = NULL;
|
||||
sd->tagToSend = 0;
|
||||
|
||||
if(!tag) return;
|
||||
if (!tag)
|
||||
return;
|
||||
|
||||
sd->tag = mpdTagDup(tag);
|
||||
sd->tagToSend = 1;
|
||||
}
|
||||
|
||||
AudioOutputPlugin shoutPlugin =
|
||||
{
|
||||
AudioOutputPlugin shoutPlugin = {
|
||||
"shout",
|
||||
NULL,
|
||||
myShout_initDriver,
|
||||
@@ -610,5 +633,4 @@ AudioOutputPlugin shoutPlugin =
|
||||
#else
|
||||
|
||||
DISABLED_AUDIO_OUTPUT_PLUGIN(shoutPlugin)
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user