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:
Avuton Olrich 2006-07-20 16:02:40 +00:00
parent 099f0e103f
commit 29a25b9933
92 changed files with 8976 additions and 7978 deletions

View File

@ -56,8 +56,10 @@ static mpd_sint32 audioBufferSize = 0;
static char *audioBuffer = NULL; static char *audioBuffer = NULL;
static mpd_sint32 audioBufferPos = 0; static mpd_sint32 audioBufferPos = 0;
void copyAudioFormat(AudioFormat * dest, AudioFormat * src) { void copyAudioFormat(AudioFormat * dest, AudioFormat * src)
if(!src) return; {
if (!src)
return;
memcpy(dest, src, sizeof(AudioFormat)); memcpy(dest, src, sizeof(AudioFormat));
} }
@ -65,8 +67,7 @@ void copyAudioFormat(AudioFormat * dest, AudioFormat * src) {
int cmpAudioFormat(AudioFormat * f1, AudioFormat * f2) int cmpAudioFormat(AudioFormat * f1, AudioFormat * f2)
{ {
if (f1 && f2 && (f1->sampleRate == f2->sampleRate) && if (f1 && f2 && (f1->sampleRate == f2->sampleRate) &&
(f1->bits == f2->bits) && (f1->bits == f2->bits) && (f1->channels == f2->channels))
(f1->channels == f2->channels))
return 0; return 0;
return 1; return 1;
} }
@ -79,8 +80,8 @@ extern AudioOutputPlugin pulsePlugin;
extern AudioOutputPlugin mvpPlugin; extern AudioOutputPlugin mvpPlugin;
extern AudioOutputPlugin shoutPlugin; extern AudioOutputPlugin shoutPlugin;
void loadAudioDrivers(void)
void loadAudioDrivers(void) { {
initAudioOutputPlugins(); initAudioOutputPlugins();
loadAudioOutputPlugin(&alsaPlugin); loadAudioOutputPlugin(&alsaPlugin);
loadAudioOutputPlugin(&aoPlugin); loadAudioOutputPlugin(&aoPlugin);
@ -92,7 +93,8 @@ void loadAudioDrivers(void) {
} }
/* make sure initPlayerData is called before this function!! */ /* make sure initPlayerData is called before this function!! */
void initAudioDriver(void) { void initAudioDriver(void)
{
ConfigParam *param = NULL; ConfigParam *param = NULL;
int i; int i;
@ -120,7 +122,8 @@ void initAudioDriver(void) {
i = audioOutputArraySize++; i = audioOutputArraySize++;
audioOutputArray = realloc(audioOutputArray, audioOutputArray = realloc(audioOutputArray,
audioOutputArraySize*sizeof(AudioOutput *)); audioOutputArraySize *
sizeof(AudioOutput *));
output = newAudioOutput(param); output = newAudioOutput(param);
if (!output && param) { if (!output && param) {
@ -131,11 +134,9 @@ void initAudioDriver(void) {
/* require output names to be unique: */ /* require output names to be unique: */
for (j = i - 1; j >= 0; --j) { for (j = i - 1; j >= 0; --j) {
if ( !strcmp( output->name, if (!strcmp(output->name, audioOutputArray[j]->name)) {
audioOutputArray[j]->name) ) {
ERROR("output devices with identical " ERROR("output devices with identical "
"names: %s\n", "names: %s\n", output->name);
output->name);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
@ -148,14 +149,16 @@ void getOutputAudioFormat(AudioFormat * inAudioFormat,
{ {
if (audio_configFormat) { if (audio_configFormat) {
copyAudioFormat(outAudioFormat, audio_configFormat); copyAudioFormat(outAudioFormat, audio_configFormat);
} } else
else copyAudioFormat(outAudioFormat,inAudioFormat); copyAudioFormat(outAudioFormat, inAudioFormat);
} }
void initAudioConfig(void) { void initAudioConfig(void)
{
ConfigParam *param = getConfigParam(CONF_AUDIO_OUTPUT_FORMAT); ConfigParam *param = getConfigParam(CONF_AUDIO_OUTPUT_FORMAT);
if(NULL == param || NULL == param->value) return; if (NULL == param || NULL == param->value)
return;
audio_configFormat = malloc(sizeof(AudioFormat)); audio_configFormat = malloc(sizeof(AudioFormat));
@ -166,7 +169,8 @@ void initAudioConfig(void) {
} }
} }
int parseAudioConfig(AudioFormat * audioFormat, char * conf) { int parseAudioConfig(AudioFormat * audioFormat, char *conf)
{
char *test; char *test;
memset(audioFormat, 0, sizeof(AudioFormat)); memset(audioFormat, 0, sizeof(AudioFormat));
@ -232,11 +236,14 @@ int parseAudioConfig(AudioFormat * audioFormat, char * conf) {
return 0; return 0;
} }
void finishAudioConfig(void) { void finishAudioConfig(void)
if(audio_configFormat) free(audio_configFormat); {
if (audio_configFormat)
free(audio_configFormat);
} }
void finishAudioDriver(void) { void finishAudioDriver(void)
{
int i; int i;
for (i = 0; i < audioOutputArraySize; i++) { for (i = 0; i < audioOutputArraySize; i++) {
@ -248,15 +255,19 @@ void finishAudioDriver(void) {
audioOutputArraySize = 0; audioOutputArraySize = 0;
} }
int isCurrentAudioFormat(AudioFormat * audioFormat) { int isCurrentAudioFormat(AudioFormat * audioFormat)
if(!audioFormat) return 1; {
if (!audioFormat)
return 1;
if(cmpAudioFormat(audioFormat, &audio_format) != 0) return 0; if (cmpAudioFormat(audioFormat, &audio_format) != 0)
return 0;
return 1; return 1;
} }
static void syncAudioDevicesEnabledArrays(void) { static void syncAudioDevicesEnabledArrays(void)
{
int i; int i;
memcpy(myAudioDevicesEnabled, pdAudioDevicesEnabled, AUDIO_MAX_DEVICES); memcpy(myAudioDevicesEnabled, pdAudioDevicesEnabled, AUDIO_MAX_DEVICES);
@ -264,28 +275,29 @@ static void syncAudioDevicesEnabledArrays(void) {
for (i = 0; i < audioOutputArraySize; i++) { for (i = 0; i < audioOutputArraySize; i++) {
if (myAudioDevicesEnabled[i]) { if (myAudioDevicesEnabled[i]) {
openAudioOutput(audioOutputArray[i], &audio_format); openAudioOutput(audioOutputArray[i], &audio_format);
} } else {
else {
dropBufferedAudioOutput(audioOutputArray[i]); dropBufferedAudioOutput(audioOutputArray[i]);
closeAudioOutput(audioOutputArray[i]); closeAudioOutput(audioOutputArray[i]);
} }
} }
} }
static int flushAudioBuffer(void) { static int flushAudioBuffer(void)
{
int ret = -1; int ret = -1;
int i, err; int i, err;
if(audioBufferPos == 0) return 0; if (audioBufferPos == 0)
return 0;
if (0 != memcmp(pdAudioDevicesEnabled, myAudioDevicesEnabled, if (0 != memcmp(pdAudioDevicesEnabled, myAudioDevicesEnabled,
AUDIO_MAX_DEVICES)) AUDIO_MAX_DEVICES)) {
{
syncAudioDevicesEnabledArrays(); syncAudioDevicesEnabledArrays();
} }
for (i = 0; i < audioOutputArraySize; i++) { for (i = 0; i < audioOutputArraySize; i++) {
if(!myAudioDevicesEnabled[i]) continue; if (!myAudioDevicesEnabled[i])
continue;
err = playAudioOutput(audioOutputArray[i], audioBuffer, err = playAudioOutput(audioOutputArray[i], audioBuffer,
audioBufferPos); audioBufferPos);
if (!err) if (!err)
@ -301,12 +313,14 @@ static int flushAudioBuffer(void) {
return ret; return ret;
} }
int openAudioDevice(AudioFormat * audioFormat) { int openAudioDevice(AudioFormat * audioFormat)
{
int isCurrentFormat = isCurrentAudioFormat(audioFormat); int isCurrentFormat = isCurrentAudioFormat(audioFormat);
int ret = -1; int ret = -1;
int i; int i;
if(!audioOutputArray) return -1; if (!audioOutputArray)
return -1;
if (!audioOpened || !isCurrentFormat) { if (!audioOpened || !isCurrentFormat) {
flushAudioBuffer(); flushAudioBuffer();
@ -320,10 +334,12 @@ int openAudioDevice(AudioFormat * audioFormat) {
syncAudioDevicesEnabledArrays(); syncAudioDevicesEnabledArrays();
for (i = 0; i < audioOutputArraySize; i++) { for (i = 0; i < audioOutputArraySize; i++) {
if(audioOutputArray[i]->open) ret = 0; if (audioOutputArray[i]->open)
ret = 0;
} }
if(ret == 0) audioOpened = 1; if (ret == 0)
audioOpened = 1;
else { else {
/* close all devices if there was an error */ /* close all devices if there was an error */
for (i = 0; i < audioOutputArraySize; i++) { for (i = 0; i < audioOutputArraySize; i++) {
@ -336,7 +352,8 @@ int openAudioDevice(AudioFormat * audioFormat) {
return ret; return ret;
} }
int playAudio(char * playChunk, int size) { int playAudio(char *playChunk, int size)
{
int send; int send;
while (size > 0) { while (size > 0) {
@ -349,35 +366,39 @@ int playAudio(char * playChunk, int size) {
playChunk += send; playChunk += send;
if (audioBufferPos == audioBufferSize) { if (audioBufferPos == audioBufferSize) {
if( flushAudioBuffer() < 0 ) return -1; if (flushAudioBuffer() < 0)
return -1;
} }
} }
return 0; return 0;
} }
int isAudioDeviceOpen(void) { int isAudioDeviceOpen(void)
{
return audioOpened; return audioOpened;
} }
void dropBufferedAudio(void) { void dropBufferedAudio(void)
{
int i; int i;
if (0 != memcmp(pdAudioDevicesEnabled, myAudioDevicesEnabled, if (0 != memcmp(pdAudioDevicesEnabled, myAudioDevicesEnabled,
AUDIO_MAX_DEVICES)) AUDIO_MAX_DEVICES)) {
{
syncAudioDevicesEnabledArrays(); syncAudioDevicesEnabledArrays();
} }
audioBufferPos = 0; audioBufferPos = 0;
for (i = 0; i < audioOutputArraySize; i++) { for (i = 0; i < audioOutputArraySize; i++) {
if(!myAudioDevicesEnabled[i]) continue; if (!myAudioDevicesEnabled[i])
continue;
dropBufferedAudioOutput(audioOutputArray[i]); dropBufferedAudioOutput(audioOutputArray[i]);
} }
} }
void closeAudioDevice(void) { void closeAudioDevice(void)
{
int i; int i;
flushAudioBuffer(); flushAudioBuffer();
@ -393,7 +414,8 @@ void closeAudioDevice(void) {
audioOpened = 0; audioOpened = 0;
} }
void sendMetadataToAudioDevice(MpdTag * tag) { void sendMetadataToAudioDevice(MpdTag * tag)
{
int i; int i;
for (i = 0; i < audioOutputArraySize; i++) { for (i = 0; i < audioOutputArraySize; i++) {
@ -401,7 +423,8 @@ void sendMetadataToAudioDevice(MpdTag * tag) {
} }
} }
int enableAudioDevice(FILE * fp, int device) { int enableAudioDevice(FILE * fp, int device)
{
if (device < 0 || device >= audioOutputArraySize) { if (device < 0 || device >= audioOutputArraySize) {
commandError(fp, ACK_ERROR_ARG, "audio output device id %i " commandError(fp, ACK_ERROR_ARG, "audio output device id %i "
"doesn't exist\n", device); "doesn't exist\n", device);
@ -413,7 +436,8 @@ int enableAudioDevice(FILE * fp, int device) {
return 0; return 0;
} }
int disableAudioDevice(FILE * fp, int device) { int disableAudioDevice(FILE * fp, int device)
{
if (device < 0 || device >= audioOutputArraySize) { if (device < 0 || device >= audioOutputArraySize) {
commandError(fp, ACK_ERROR_ARG, "audio output device id %i " commandError(fp, ACK_ERROR_ARG, "audio output device id %i "
"doesn't exist\n", device); "doesn't exist\n", device);
@ -425,7 +449,8 @@ int disableAudioDevice(FILE * fp, int device) {
return 0; return 0;
} }
void printAudioDevices(FILE * fp) { void printAudioDevices(FILE * fp)
{
int i; int i;
for (i = 0; i < audioOutputArraySize; i++) { for (i = 0; i < audioOutputArraySize; i++) {
@ -436,7 +461,8 @@ void printAudioDevices(FILE * fp) {
} }
} }
void saveAudioDevicesState(void) { void saveAudioDevicesState(void)
{
char *stateFile; char *stateFile;
FILE *fp; FILE *fp;
int i; int i;
@ -494,7 +520,8 @@ errline:
} }
} }
void readAudioDevicesState(void) { void readAudioDevicesState(void)
{
char *stateFile; char *stateFile;
FILE *fp; FILE *fp;
struct stat st; struct stat st;
@ -506,19 +533,16 @@ void readAudioDevicesState(void) {
return; return;
} }
if (!S_ISREG(st.st_mode)) { if (!S_ISREG(st.st_mode)) {
ERROR("state file \"%s\" is not a regular file\n", ERROR("state file \"%s\" is not a regular file\n", stateFile);
stateFile);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
fp = fopen(stateFile, "r"); fp = fopen(stateFile, "r");
if (!fp) { if (!fp) {
ERROR("problems opening state file \"%s\" for " ERROR("problems opening state file \"%s\" for "
"reading: %s\n", stateFile, "reading: %s\n", stateFile, strerror(errno));
strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
parse_audio_device_state(fp); parse_audio_device_state(fp);
fclose(fp); fclose(fp);
} }

View File

@ -30,22 +30,28 @@
static List *audioOutputPluginList; static List *audioOutputPluginList;
void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin) { void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin)
if(!audioOutputPlugin->name) return; {
if (!audioOutputPlugin->name)
return;
insertInList(audioOutputPluginList, audioOutputPlugin->name, insertInList(audioOutputPluginList, audioOutputPlugin->name,
audioOutputPlugin); audioOutputPlugin);
} }
void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin) { void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin)
if(!audioOutputPlugin->name) return; {
if (!audioOutputPlugin->name)
return;
deleteFromList(audioOutputPluginList, audioOutputPlugin->name); deleteFromList(audioOutputPluginList, audioOutputPlugin->name);
} }
void initAudioOutputPlugins(void) { void initAudioOutputPlugins(void)
{
audioOutputPluginList = makeList(NULL, 0); audioOutputPluginList = makeList(NULL, 0);
} }
void finishAudioOutputPlugins(void) { void finishAudioOutputPlugins(void)
{
freeList(audioOutputPluginList); freeList(audioOutputPluginList);
} }
@ -60,7 +66,8 @@ void finishAudioOutputPlugins(void) {
if(bp) str = bp->value; \ if(bp) str = bp->value; \
} }
AudioOutput * newAudioOutput(ConfigParam * param) { AudioOutput *newAudioOutput(ConfigParam * param)
{
AudioOutput *ret = NULL; AudioOutput *ret = NULL;
void *data = NULL; void *data = NULL;
char *name = NULL; char *name = NULL;
@ -76,14 +83,12 @@ AudioOutput * newAudioOutput(ConfigParam * param) {
if (!findInList(audioOutputPluginList, type, &data)) { if (!findInList(audioOutputPluginList, type, &data)) {
ERROR("couldn't find audio output plugin for type " ERROR("couldn't find audio output plugin for type "
"\"%s\" at line %i\n", type, "\"%s\" at line %i\n", type, param->line);
param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
plugin = (AudioOutputPlugin *) data; plugin = (AudioOutputPlugin *) data;
} } else {
else {
ListNode *node = audioOutputPluginList->firstNode; ListNode *node = audioOutputPluginList->firstNode;
WARNING("No \"%s\" defined in config file\n", WARNING("No \"%s\" defined in config file\n",
@ -97,8 +102,7 @@ AudioOutput * newAudioOutput(ConfigParam * param) {
"device\n", plugin->name); "device\n", plugin->name);
if (plugin->testDefaultDeviceFunc() == 0) { if (plugin->testDefaultDeviceFunc() == 0) {
WARNING("Successfully detected a %s " WARNING("Successfully detected a %s "
"audio device\n", "audio device\n", plugin->name);
plugin->name);
break; break;
} }
} }
@ -137,10 +141,8 @@ AudioOutput * newAudioOutput(ConfigParam * param) {
if (format) { if (format) {
ret->convertAudioFormat = 1; ret->convertAudioFormat = 1;
if(0 != parseAudioConfig(&ret->reqAudioFormat, format)) if (0 != parseAudioConfig(&ret->reqAudioFormat, format)) {
{ ERROR("error parsing format at line %i\n", bp->line);
ERROR("error parsing format at line %i\n",
bp->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -155,13 +157,13 @@ AudioOutput * newAudioOutput(ConfigParam * param) {
return ret; return ret;
} }
int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat) { int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat)
{
int ret; int ret;
if (audioOutput->open) { if (audioOutput->open) {
if (cmpAudioFormat(audioFormat, &audioOutput->inAudioFormat) if (cmpAudioFormat(audioFormat, &audioOutput->inAudioFormat)
== 0) == 0) {
{
return 0; return 0;
} }
closeAudioOutput(audioOutput); closeAudioOutput(audioOutput);
@ -172,8 +174,7 @@ int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat) {
if (audioOutput->convertAudioFormat) { if (audioOutput->convertAudioFormat) {
copyAudioFormat(&audioOutput->outAudioFormat, copyAudioFormat(&audioOutput->outAudioFormat,
&audioOutput->reqAudioFormat); &audioOutput->reqAudioFormat);
} } else {
else {
copyAudioFormat(&audioOutput->outAudioFormat, copyAudioFormat(&audioOutput->outAudioFormat,
&audioOutput->inAudioFormat); &audioOutput->inAudioFormat);
} }
@ -181,11 +182,10 @@ int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat) {
ret = audioOutput->openDeviceFunc(audioOutput); ret = audioOutput->openDeviceFunc(audioOutput);
if (cmpAudioFormat(&audioOutput->inAudioFormat, if (cmpAudioFormat(&audioOutput->inAudioFormat,
&audioOutput->outAudioFormat) == 0) &audioOutput->outAudioFormat) == 0) {
{
audioOutput->sameInAndOutFormats = 1; audioOutput->sameInAndOutFormats = 1;
} } else
else audioOutput->sameInAndOutFormats = 0; audioOutput->sameInAndOutFormats = 0;
return ret; return ret;
} }
@ -193,8 +193,11 @@ int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat) {
static void convertAudioFormat(AudioOutput * audioOutput, char **chunkArgPtr, static void convertAudioFormat(AudioOutput * audioOutput, char **chunkArgPtr,
int *sizeArgPtr) int *sizeArgPtr)
{ {
int size = pcm_sizeOfOutputBufferForAudioFormatConversion( int size =
&(audioOutput->inAudioFormat), *sizeArgPtr, pcm_sizeOfOutputBufferForAudioFormatConversion(&
(audioOutput->
inAudioFormat),
*sizeArgPtr,
&(audioOutput->outAudioFormat)); &(audioOutput->outAudioFormat));
if (size > audioOutput->convBufferLen) { if (size > audioOutput->convBufferLen) {
@ -211,44 +214,54 @@ static void convertAudioFormat(AudioOutput * audioOutput, char ** chunkArgPtr,
*chunkArgPtr = audioOutput->convBuffer; *chunkArgPtr = audioOutput->convBuffer;
} }
int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size) { int playAudioOutput(AudioOutput * audioOutput, char *playChunk, int size)
{
int ret; int ret;
if(!audioOutput->open) return -1; if (!audioOutput->open)
return -1;
if (!audioOutput->sameInAndOutFormats) { if (!audioOutput->sameInAndOutFormats) {
convertAudioFormat(audioOutput, &playChunk, &size); convertAudioFormat(audioOutput, &playChunk, &size);
} }
ret = audioOutput->playFunc(audioOutput, playChunk, size); ret = audioOutput->playFunc(audioOutput, playChunk, size);
return ret; return ret;
} }
void dropBufferedAudioOutput(AudioOutput * audioOutput) { void dropBufferedAudioOutput(AudioOutput * audioOutput)
if(audioOutput->open) audioOutput->dropBufferedAudioFunc(audioOutput); {
if (audioOutput->open)
audioOutput->dropBufferedAudioFunc(audioOutput);
} }
void closeAudioOutput(AudioOutput * audioOutput) { void closeAudioOutput(AudioOutput * audioOutput)
if(audioOutput->open) audioOutput->closeDeviceFunc(audioOutput); {
if (audioOutput->open)
audioOutput->closeDeviceFunc(audioOutput);
} }
void finishAudioOutput(AudioOutput * audioOutput) { void finishAudioOutput(AudioOutput * audioOutput)
{
closeAudioOutput(audioOutput); closeAudioOutput(audioOutput);
audioOutput->finishDriverFunc(audioOutput); audioOutput->finishDriverFunc(audioOutput);
if(audioOutput->convBuffer) free(audioOutput->convBuffer); if (audioOutput->convBuffer)
free(audioOutput->convBuffer);
free(audioOutput->type); free(audioOutput->type);
free(audioOutput->name); free(audioOutput->name);
free(audioOutput); free(audioOutput);
} }
void sendMetadataToAudioOutput(AudioOutput * audioOutput, MpdTag * tag) { void sendMetadataToAudioOutput(AudioOutput * audioOutput, MpdTag * tag)
if(!audioOutput->sendMetdataFunc) return; {
if (!audioOutput->sendMetdataFunc)
return;
audioOutput->sendMetdataFunc(audioOutput, tag); audioOutput->sendMetdataFunc(audioOutput, tag);
} }
void printAllOutputPluginTypes(FILE *fp) { void printAllOutputPluginTypes(FILE * fp)
{
ListNode *node = audioOutputPluginList->firstNode; ListNode *node = audioOutputPluginList->firstNode;
AudioOutputPlugin *plugin; AudioOutputPlugin *plugin;

View File

@ -54,7 +54,8 @@ typedef struct _AlsaData {
int canResume; int canResume;
} AlsaData; } AlsaData;
static AlsaData * newAlsaData(void) { static AlsaData *newAlsaData(void)
{
AlsaData *ret = malloc(sizeof(AlsaData)); AlsaData *ret = malloc(sizeof(AlsaData));
ret->device = NULL; ret->device = NULL;
@ -67,13 +68,16 @@ static AlsaData * newAlsaData(void) {
return ret; return ret;
} }
static void freeAlsaData(AlsaData * ad) { static void freeAlsaData(AlsaData * ad)
if(ad->device) free(ad->device); {
if (ad->device)
free(ad->device);
free(ad); free(ad);
} }
static int alsa_initDriver(AudioOutput * audioOutput, ConfigParam * param) { static int alsa_initDriver(AudioOutput * audioOutput, ConfigParam * param)
{
AlsaData *ad = newAlsaData(); AlsaData *ad = newAlsaData();
if (param) { if (param) {
@ -94,7 +98,8 @@ static int alsa_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
return 0; return 0;
} }
static void alsa_finishDriver(AudioOutput * audioOutput) { static void alsa_finishDriver(AudioOutput * audioOutput)
{
AlsaData *ad = audioOutput->data; AlsaData *ad = audioOutput->data;
freeAlsaData(ad); freeAlsaData(ad);
@ -112,8 +117,8 @@ static int alsa_testDefault(void)
WARNING("Error opening default alsa device: %s\n", WARNING("Error opening default alsa device: %s\n",
snd_strerror(-ret)); snd_strerror(-ret));
return -1; return -1;
} } else
else snd_pcm_close(handle); snd_pcm_close(handle);
return 0; return 0;
} }
@ -161,41 +166,42 @@ static int alsa_openDevice(AudioOutput * audioOutput)
cmd = "snd_pcm_nonblock"; cmd = "snd_pcm_nonblock";
err = snd_pcm_nonblock(ad->pcmHandle, 0); err = snd_pcm_nonblock(ad->pcmHandle, 0);
if(err < 0) goto error; if (err < 0)
goto error;
/* configure HW params */ /* configure HW params */
snd_pcm_hw_params_alloca(&hwparams); snd_pcm_hw_params_alloca(&hwparams);
cmd = "snd_pcm_hw_params_any"; cmd = "snd_pcm_hw_params_any";
err = snd_pcm_hw_params_any(ad->pcmHandle, hwparams); 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, err = snd_pcm_hw_params_set_access(ad->pcmHandle, hwparams,
SND_PCM_ACCESS_MMAP_INTERLEAVED); SND_PCM_ACCESS_MMAP_INTERLEAVED);
if (err < 0) { if (err < 0) {
ERROR("Cannot set mmap'ed mode on alsa device \"%s\": " ERROR("Cannot set mmap'ed mode on alsa device \"%s\": "
" %s\n", ad->device, " %s\n", ad->device, snd_strerror(-err));
snd_strerror(-err));
ERROR("Falling back to direct write mode\n"); ERROR("Falling back to direct write mode\n");
ad->useMmap = 0; ad->useMmap = 0;
} } else
else ad->writei = snd_pcm_mmap_writei; ad->writei = snd_pcm_mmap_writei;
} }
if (!ad->useMmap) { if (!ad->useMmap) {
cmd = "snd_pcm_hw_params_set_access"; cmd = "snd_pcm_hw_params_set_access";
err = snd_pcm_hw_params_set_access(ad->pcmHandle, hwparams, err = snd_pcm_hw_params_set_access(ad->pcmHandle, hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED); SND_PCM_ACCESS_RW_INTERLEAVED);
if(err < 0) goto error; if (err < 0)
goto error;
ad->writei = snd_pcm_writei; ad->writei = snd_pcm_writei;
} }
err = snd_pcm_hw_params_set_format(ad->pcmHandle, hwparams, bitformat); 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: " ERROR("Alsa device \"%s\" does not support %i bit audio: "
"%s\n", ad->device, (int)bitformat, "%s\n", ad->device, (int)bitformat, snd_strerror(-err));
snd_strerror(-err));
goto fail; goto fail;
} }
@ -221,27 +227,32 @@ static int alsa_openDevice(AudioOutput * audioOutput)
cmd = "snd_pcm_hw_params_set_buffer_time_near"; cmd = "snd_pcm_hw_params_set_buffer_time_near";
err = snd_pcm_hw_params_set_buffer_time_near(ad->pcmHandle, hwparams, err = snd_pcm_hw_params_set_buffer_time_near(ad->pcmHandle, hwparams,
&ad->buffer_time, NULL); &ad->buffer_time, NULL);
if(err < 0) goto error; if (err < 0)
goto error;
if (!ad->period_time && sampleRate > 0) if (!ad->period_time && sampleRate > 0)
ad->period_time = 1000000 * MPD_ALSA_SAMPLE_XFER / sampleRate; ad->period_time = 1000000 * MPD_ALSA_SAMPLE_XFER / sampleRate;
cmd = "snd_pcm_hw_params_set_period_time_near"; cmd = "snd_pcm_hw_params_set_period_time_near";
err = snd_pcm_hw_params_set_period_time_near(ad->pcmHandle, hwparams, err = snd_pcm_hw_params_set_period_time_near(ad->pcmHandle, hwparams,
&ad->period_time, NULL); &ad->period_time, NULL);
if(err < 0) goto error; if (err < 0)
goto error;
cmd = "snd_pcm_hw_params"; cmd = "snd_pcm_hw_params";
err = snd_pcm_hw_params(ad->pcmHandle, hwparams); 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"; cmd = "snd_pcm_hw_params_get_buffer_size";
err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_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"; cmd = "snd_pcm_hw_params_get_period_size";
err = snd_pcm_hw_params_get_period_size(hwparams, &alsa_period_size, err = snd_pcm_hw_params_get_period_size(hwparams, &alsa_period_size,
NULL); NULL);
if(err < 0) goto error; if (err < 0)
goto error;
ad->canPause = snd_pcm_hw_params_can_pause(hwparams); ad->canPause = snd_pcm_hw_params_can_pause(hwparams);
ad->canResume = snd_pcm_hw_params_can_resume(hwparams); ad->canResume = snd_pcm_hw_params_can_resume(hwparams);
@ -251,25 +262,31 @@ static int alsa_openDevice(AudioOutput * audioOutput)
cmd = "snd_pcm_sw_params_current"; cmd = "snd_pcm_sw_params_current";
err = snd_pcm_sw_params_current(ad->pcmHandle, swparams); 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"; cmd = "snd_pcm_sw_params_set_start_threshold";
err = snd_pcm_sw_params_set_start_threshold(ad->pcmHandle, swparams, err = snd_pcm_sw_params_set_start_threshold(ad->pcmHandle, swparams,
alsa_buffer_size - alsa_period_size); alsa_buffer_size -
if(err < 0) goto error; alsa_period_size);
if (err < 0)
goto error;
cmd = "snd_pcm_sw_params_set_avail_min"; cmd = "snd_pcm_sw_params_set_avail_min";
err = snd_pcm_sw_params_set_avail_min(ad->pcmHandle, swparams, err = snd_pcm_sw_params_set_avail_min(ad->pcmHandle, swparams,
alsa_period_size); alsa_period_size);
if(err < 0) goto error; if (err < 0)
goto error;
cmd = "snd_pcm_sw_params_set_xfer_align"; cmd = "snd_pcm_sw_params_set_xfer_align";
err = snd_pcm_sw_params_set_xfer_align(ad->pcmHandle, swparams, 1); 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"; cmd = "snd_pcm_sw_params";
err = snd_pcm_sw_params(ad->pcmHandle, swparams); err = snd_pcm_sw_params(ad->pcmHandle, swparams);
if(err < 0) goto error; if (err < 0)
goto error;
ad->sampleSize = (audioFormat->bits / 8) * audioFormat->channels; ad->sampleSize = (audioFormat->bits / 8) * audioFormat->channels;
@ -285,23 +302,23 @@ error:
if (cmd) { if (cmd) {
ERROR("Error opening alsa device \"%s\" (%s): %s\n", ERROR("Error opening alsa device \"%s\" (%s): %s\n",
ad->device, cmd, snd_strerror(-err)); ad->device, cmd, snd_strerror(-err));
} } else {
else {
ERROR("Error opening alsa device \"%s\": %s\n", ad->device, ERROR("Error opening alsa device \"%s\": %s\n", ad->device,
snd_strerror(-err)); snd_strerror(-err));
} }
fail: fail:
if(ad->pcmHandle) snd_pcm_close(ad->pcmHandle); if (ad->pcmHandle)
snd_pcm_close(ad->pcmHandle);
ad->pcmHandle = NULL; ad->pcmHandle = NULL;
audioOutput->open = 0; audioOutput->open = 0;
return -1; return -1;
} }
static int alsa_errorRecovery(AlsaData * ad, int err) { static int alsa_errorRecovery(AlsaData * ad, int err)
{
if (err == -EPIPE) { if (err == -EPIPE) {
DEBUG("Underrun on alsa device \"%s\"\n", ad->device); 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); DEBUG("alsa device \"%s\" was suspended\n", ad->device);
} }
@ -331,13 +348,15 @@ static int alsa_errorRecovery(AlsaData * ad, int err) {
return err; return err;
} }
static void alsa_dropBufferedAudio(AudioOutput * audioOutput) { static void alsa_dropBufferedAudio(AudioOutput * audioOutput)
{
AlsaData *ad = audioOutput->data; 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) { static void alsa_closeDevice(AudioOutput * audioOutput)
{
AlsaData *ad = audioOutput->data; AlsaData *ad = audioOutput->data;
if (ad->pcmHandle) { if (ad->pcmHandle) {
@ -349,8 +368,7 @@ static void alsa_closeDevice(AudioOutput * audioOutput) {
audioOutput->open = 0; audioOutput->open = 0;
} }
static int alsa_playAudio(AudioOutput * audioOutput, char * playChunk, static int alsa_playAudio(AudioOutput * audioOutput, char *playChunk, int size)
int size)
{ {
AlsaData *ad = audioOutput->data; AlsaData *ad = audioOutput->data;
int ret; int ret;
@ -360,7 +378,8 @@ static int alsa_playAudio(AudioOutput * audioOutput, char * playChunk,
while (size > 0) { while (size > 0) {
ret = ad->writei(ad->pcmHandle, playChunk, size); ret = ad->writei(ad->pcmHandle, playChunk, size);
if(ret == -EAGAIN || ret == -EINTR) continue; if (ret == -EAGAIN || ret == -EINTR)
continue;
if (ret < 0) { if (ret < 0) {
if (alsa_errorRecovery(ad, ret) < 0) { if (alsa_errorRecovery(ad, ret) < 0) {
@ -380,8 +399,7 @@ static int alsa_playAudio(AudioOutput * audioOutput, char * playChunk,
return 0; return 0;
} }
AudioOutputPlugin alsaPlugin = AudioOutputPlugin alsaPlugin = {
{
"alsa", "alsa",
alsa_testDefault, alsa_testDefault,
alsa_initDriver, alsa_initDriver,
@ -396,5 +414,4 @@ AudioOutputPlugin alsaPlugin =
#else /* HAVE ALSA */ #else /* HAVE ALSA */
DISABLED_AUDIO_OUTPUT_PLUGIN(alsaPlugin) DISABLED_AUDIO_OUTPUT_PLUGIN(alsaPlugin)
#endif /* HAVE_ALSA */ #endif /* HAVE_ALSA */

View File

@ -38,7 +38,8 @@ typedef struct _AoData {
ao_device *device; ao_device *device;
} AoData; } AoData;
static AoData * newAoData() { static AoData *newAoData()
{
AoData *ret = malloc(sizeof(AoData)); AoData *ret = malloc(sizeof(AoData));
ret->device = NULL; ret->device = NULL;
ret->options = NULL; ret->options = NULL;
@ -46,14 +47,13 @@ static AoData * newAoData() {
return ret; return ret;
} }
static void audioOutputAo_error() { static void audioOutputAo_error()
{
if (errno == AO_ENOTLIVE) { if (errno == AO_ENOTLIVE) {
ERROR("not a live ao device\n"); 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"); ERROR("not able to open audio device\n");
} } else if (errno == AO_EBADOPTION) {
else if(errno==AO_EBADOPTION) {
ERROR("bad driver option\n"); ERROR("bad driver option\n");
} }
} }
@ -81,8 +81,8 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput,
blockParam->value, blockParam->line); blockParam->value, blockParam->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} } else
else ad->writeSize = 1024; ad->writeSize = 1024;
if (driverInitCount == 0) { if (driverInitCount == 0) {
ao_initialize(); ao_initialize();
@ -93,9 +93,7 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput,
if (!blockParam || 0 == strcmp(blockParam->value, "default")) { if (!blockParam || 0 == strcmp(blockParam->value, "default")) {
ad->driverId = ao_default_driver_id(); 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", ERROR("\"%s\" is not a valid ao driver at line %i\n",
blockParam->value, blockParam->line); blockParam->value, blockParam->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -115,8 +113,8 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput,
if (blockParam) { if (blockParam) {
dup = strdup(blockParam->value); dup = strdup(blockParam->value);
} } else
else dup = strdup(""); dup = strdup("");
if (strlen(dup)) { if (strlen(dup)) {
stk1 = NULL; stk1 = NULL;
@ -157,25 +155,30 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput,
return 0; return 0;
} }
static void freeAoData(AoData * ad) { static void freeAoData(AoData * ad)
{
ao_free_options(ad->options); ao_free_options(ad->options);
free(ad); free(ad);
} }
static void audioOutputAo_finishDriver(AudioOutput * audioOutput) { static void audioOutputAo_finishDriver(AudioOutput * audioOutput)
{
AoData *ad = (AoData *) audioOutput->data; AoData *ad = (AoData *) audioOutput->data;
freeAoData(ad); freeAoData(ad);
driverInitCount--; 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 */ /* not supported by libao */
} }
static void audioOutputAo_closeDevice(AudioOutput * audioOutput) { static void audioOutputAo_closeDevice(AudioOutput * audioOutput)
{
AoData *ad = (AoData *) audioOutput->data; AoData *ad = (AoData *) audioOutput->data;
if (ad->device) { if (ad->device) {
@ -186,7 +189,8 @@ static void audioOutputAo_closeDevice(AudioOutput * audioOutput) {
audioOutput->open = 0; audioOutput->open = 0;
} }
static int audioOutputAo_openDevice(AudioOutput * audioOutput) { static int audioOutputAo_openDevice(AudioOutput * audioOutput)
{
ao_sample_format format; ao_sample_format format;
AoData *ad = (AoData *) audioOutput->data; AoData *ad = (AoData *) audioOutput->data;
@ -201,21 +205,22 @@ static int audioOutputAo_openDevice(AudioOutput * audioOutput) {
ad->device = ao_open_live(ad->driverId, &format, ad->options); 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; audioOutput->open = 1;
return 0; return 0;
} }
static int audioOutputAo_play(AudioOutput * audioOutput, char *playChunk, static int audioOutputAo_play(AudioOutput * audioOutput, char *playChunk,
int size) int size)
{ {
int send; int send;
AoData *ad = (AoData *) audioOutput->data; AoData *ad = (AoData *) audioOutput->data;
if(ad->device==NULL) return -1; if (ad->device == NULL)
return -1;
while (size > 0) { while (size > 0) {
send = ad->writeSize > size ? size : ad->writeSize; send = ad->writeSize > size ? size : ad->writeSize;
@ -234,8 +239,7 @@ static int audioOutputAo_play(AudioOutput * audioOutput, char * playChunk,
return 0; return 0;
} }
AudioOutputPlugin aoPlugin = AudioOutputPlugin aoPlugin = {
{
"ao", "ao",
NULL, NULL,
audioOutputAo_initDriver, audioOutputAo_initDriver,
@ -252,5 +256,4 @@ AudioOutputPlugin aoPlugin =
#include <stdio.h> #include <stdio.h>
DISABLED_AUDIO_OUTPUT_PLUGIN(aoPlugin) DISABLED_AUDIO_OUTPUT_PLUGIN(aoPlugin)
#endif #endif

View File

@ -73,7 +73,8 @@ typedef struct _OssData {
#define OSS_CHANNELS 1 #define OSS_CHANNELS 1
#define OSS_BITS 2 #define OSS_BITS 2
static int getIndexForParam(int param) { static int getIndexForParam(int param)
{
int index = 0; int index = 0;
switch (param) { switch (param) {
@ -91,31 +92,37 @@ static int getIndexForParam(int param) {
return index; return index;
} }
static int findSupportedParam(OssData * od, int param, int val) { static int findSupportedParam(OssData * od, int param, int val)
{
int i; int i;
int index = getIndexForParam(param); int index = getIndexForParam(param);
for (i = 0; i < od->numSupported[index]; i++) { for (i = 0; i < od->numSupported[index]; i++) {
if(od->supported[index][i] == val) return 1; if (od->supported[index][i] == val)
return 1;
} }
return 0; return 0;
} }
static int canConvert(int index, int val) { static int canConvert(int index, int val)
{
switch (index) { switch (index) {
case OSS_BITS: case OSS_BITS:
if(val!=16) return 0; if (val != 16)
return 0;
break; break;
case OSS_CHANNELS: case OSS_CHANNELS:
if(val!=2) return 0; if (val != 2)
return 0;
break; break;
} }
return 1; return 1;
} }
static int getSupportedParam(OssData * od, int param, int val) { static int getSupportedParam(OssData * od, int param, int val)
{
int i; int i;
int index = getIndexForParam(param); int index = getIndexForParam(param);
int ret = -1; int ret = -1;
@ -124,7 +131,8 @@ static int getSupportedParam(OssData * od, int param, int val) {
for (i = 0; i < od->numSupported[index]; i++) { for (i = 0; i < od->numSupported[index]; i++) {
diff = od->supported[index][i] - val; diff = od->supported[index][i] - val;
if(diff < 0) diff = -diff; if (diff < 0)
diff = -diff;
if (diff < least) { if (diff < least) {
if (!canConvert(index, od->supported[index][i])) { if (!canConvert(index, od->supported[index][i])) {
continue; continue;
@ -137,18 +145,21 @@ static int getSupportedParam(OssData * od, int param, int val) {
return ret; return ret;
} }
static int findUnsupportedParam(OssData * od, int param, int val) { static int findUnsupportedParam(OssData * od, int param, int val)
{
int i; int i;
int index = getIndexForParam(param); int index = getIndexForParam(param);
for (i = 0; i < od->numUnsupported[index]; i++) { for (i = 0; i < od->numUnsupported[index]; i++) {
if(od->unsupported[index][i] == val) return 1; if (od->unsupported[index][i] == val)
return 1;
} }
return 0; return 0;
} }
static void addSupportedParam(OssData * od, int param, int val) { static void addSupportedParam(OssData * od, int param, int val)
{
int index = getIndexForParam(param); int index = getIndexForParam(param);
od->numSupported[index]++; od->numSupported[index]++;
@ -157,22 +168,26 @@ static void addSupportedParam(OssData * od, int param, int val) {
od->supported[index][od->numSupported[index] - 1] = val; 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); int index = getIndexForParam(param);
od->numUnsupported[index]++; od->numUnsupported[index]++;
od->unsupported[index] = realloc(od->unsupported[index], od->unsupported[index] = realloc(od->unsupported[index],
od->numUnsupported[index]*sizeof(int)); od->numUnsupported[index] *
sizeof(int));
od->unsupported[index][od->numUnsupported[index] - 1] = val; 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 i = 0;
int j = 0; int j = 0;
int index = getIndexForParam(param); int index = getIndexForParam(param);
for (i = 0; i < od->numSupported[index] - 1; i++) { for (i = 0; i < od->numSupported[index] - 1; i++) {
if(od->supported[index][i] == val) j = 1; if (od->supported[index][i] == val)
j = 1;
od->supported[index][i] = od->supported[index][i + j]; od->supported[index][i] = od->supported[index][i + j];
} }
@ -181,31 +196,39 @@ static void removeSupportedParam(OssData * od, int param, int val) {
od->numSupported[index] * sizeof(int)); 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 i = 0;
int j = 0; int j = 0;
int index = getIndexForParam(param); int index = getIndexForParam(param);
for (i = 0; i < od->numUnsupported[index] - 1; i++) { for (i = 0; i < od->numUnsupported[index] - 1; i++) {
if(od->unsupported[index][i] == val) j = 1; if (od->unsupported[index][i] == val)
j = 1;
od->unsupported[index][i] = od->unsupported[index][i + j]; od->unsupported[index][i] = od->unsupported[index][i + j];
} }
od->numUnsupported[index]--; od->numUnsupported[index]--;
od->unsupported[index] = realloc(od->unsupported[index], od->unsupported[index] = realloc(od->unsupported[index],
od->numUnsupported[index]*sizeof(int)); od->numUnsupported[index] *
sizeof(int));
} }
static int isSupportedParam(OssData * od, int param, int val) { 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; if (findSupportedParam(od, param, val))
return OSS_SUPPORTED;
if (findUnsupportedParam(od, param, val))
return OSS_UNSUPPORTED;
return OSS_UNKNOWN; 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); 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); removeUnsupportedParam(od, param, val);
@ -214,10 +237,12 @@ static void supportParam(OssData * od, int param, int val) {
addSupportedParam(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); 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); removeSupportedParam(od, param, val);
@ -226,7 +251,8 @@ static void unsupportParam(OssData * od, int param, int val) {
addUnsupportedParam(od, param, val); addUnsupportedParam(od, param, val);
} }
static OssData * newOssData(void) { static OssData *newOssData(void)
{
OssData *ret = malloc(sizeof(OssData)); OssData *ret = malloc(sizeof(OssData));
ret->device = NULL; ret->device = NULL;
@ -254,15 +280,23 @@ static OssData * newOssData(void) {
return ret; return ret;
} }
static void freeOssData(OssData * od) { static void freeOssData(OssData * od)
if(od->device) free(od->device); {
if (od->device)
free(od->device);
if(od->supported[OSS_RATE]) free(od->supported[OSS_RATE]); if (od->supported[OSS_RATE])
if(od->supported[OSS_CHANNELS]) free(od->supported[OSS_CHANNELS]); free(od->supported[OSS_RATE]);
if(od->supported[OSS_BITS]) free(od->supported[OSS_BITS]); if (od->supported[OSS_CHANNELS])
if(od->unsupported[OSS_RATE]) free(od->unsupported[OSS_RATE]); free(od->supported[OSS_CHANNELS]);
if(od->unsupported[OSS_CHANNELS]) free(od->unsupported[OSS_CHANNELS]); if (od->supported[OSS_BITS])
if(od->unsupported[OSS_BITS]) free(od->unsupported[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); free(od);
} }
@ -273,15 +307,15 @@ static void freeOssData(OssData * od) {
#define OSS_STAT_DOESN_T_EXIST -3 #define OSS_STAT_DOESN_T_EXIST -3
#define OSS_STAT_OTHER -4 #define OSS_STAT_OTHER -4
static int oss_statDevice(char * device, int * stErrno) { static int oss_statDevice(char *device, int *stErrno)
{
struct stat st; struct stat st;
if (0 == stat(device, &st)) { if (0 == stat(device, &st)) {
if (!S_ISCHR(st.st_mode)) { if (!S_ISCHR(st.st_mode)) {
return OSS_STAT_NOT_CHAR_DEV; return OSS_STAT_NOT_CHAR_DEV;
} }
} } else {
else {
*stErrno = errno; *stErrno = errno;
switch (errno) { switch (errno) {
@ -298,7 +332,8 @@ static int oss_statDevice(char * device, int * stErrno) {
return 0; return 0;
} }
static int oss_testDefault(void) { static int oss_testDefault(void)
{
int fd; int fd;
fd = open("/dev/sound/dsp", O_WRONLY); fd = open("/dev/sound/dsp", O_WRONLY);
@ -318,17 +353,18 @@ static int oss_testDefault(void) {
return 0; return 0;
} }
WARNING("Error opening OSS device \"/dev/dsp\": %s\n", WARNING("Error opening OSS device \"/dev/dsp\": %s\n", strerror(errno));
strerror(errno));
return -1; return -1;
} }
static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) { static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param)
{
BlockParam *bp = NULL; BlockParam *bp = NULL;
OssData *od; OssData *od;
if(param) bp = getBlockParam(param, "device"); if (param)
bp = getBlockParam(param, "device");
od = newOssData(); od = newOssData();
audioOutput->data = od; audioOutput->data = od;
@ -340,14 +376,15 @@ static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
ret[0] = oss_statDevice("/dev/sound/dsp", err); 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"); if (ret[0] == 0)
else if(ret[1] == 0) od->device = strdup("/dev/dsp"); od->device = strdup("/dev/sound/dsp");
else if (ret[1] == 0)
od->device = strdup("/dev/dsp");
else { else {
if (param) { if (param) {
ERROR("Error trying to open default OSS device " ERROR("Error trying to open default OSS device "
"specified at line %i\n", param->line); "specified at line %i\n", param->line);
} } else {
else {
ERROR("Error trying to open default OSS " ERROR("Error trying to open default OSS "
"device\n"); "device\n");
} }
@ -356,43 +393,39 @@ static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
(ret[1] == OSS_STAT_DOESN_T_EXIST)) { (ret[1] == OSS_STAT_DOESN_T_EXIST)) {
ERROR("Neither /dev/dsp nor /dev/sound/dsp " ERROR("Neither /dev/dsp nor /dev/sound/dsp "
"were found\n"); "were found\n");
} } else if (ret[0] == OSS_STAT_NOT_CHAR_DEV) {
else if(ret[0] == OSS_STAT_NOT_CHAR_DEV) {
ERROR("/dev/sound/dsp is not a char device"); 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"); 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"); 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"); 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", ERROR("Error accessing /dev/sound/dsp: %s",
strerror(err[0])); strerror(err[0]));
} } else if (ret[1] == OSS_STAT_OTHER) {
else if(ret[1] == OSS_STAT_OTHER) {
ERROR("Error accessing /dev/dsp: %s", ERROR("Error accessing /dev/dsp: %s",
strerror(err[1])); strerror(err[1]));
} }
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} } else
else od->device = strdup(bp->value); od->device = strdup(bp->value);
return 0; return 0;
} }
static void oss_finishDriver(AudioOutput * audioOutput) { static void oss_finishDriver(AudioOutput * audioOutput)
{
OssData *od = audioOutput->data; OssData *od = audioOutput->data;
freeOssData(od); freeOssData(od);
} }
static int setParam(OssData * od, int param, int * value) { static int setParam(OssData * od, int param, int *value)
{
int val = *value; int val = *value;
int copy; int copy;
int supported = isSupportedParam(od, param, val); int supported = isSupportedParam(od, param, val);
@ -400,14 +433,14 @@ static int setParam(OssData * od, int param, int * value) {
do { do {
if (supported == OSS_UNSUPPORTED) { if (supported == OSS_UNSUPPORTED) {
val = getSupportedParam(od, param, val); val = getSupportedParam(od, param, val);
if(copy < 0) return -1; if (copy < 0)
return -1;
} }
copy = val; copy = val;
if (ioctl(od->fd, param, &copy)) { if (ioctl(od->fd, param, &copy)) {
unsupportParam(od, param, val); unsupportParam(od, param, val);
supported = OSS_UNSUPPORTED; supported = OSS_UNSUPPORTED;
} } else {
else {
if (supported == OSS_UNKNOWN) { if (supported == OSS_UNKNOWN) {
supportParam(od, param, val); supportParam(od, param, val);
supported = OSS_SUPPORTED; supported = OSS_SUPPORTED;
@ -423,11 +456,13 @@ static int setParam(OssData * od, int param, int * value) {
static void oss_close(OssData * od) 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; od->fd = -1;
} }
static int oss_open(AudioOutput * audioOutput) { static int oss_open(AudioOutput * audioOutput)
{
int tmp; int tmp;
OssData *od = audioOutput->data; OssData *od = audioOutput->data;
@ -439,17 +474,13 @@ static int oss_open(AudioOutput * audioOutput) {
if (setParam(od, SNDCTL_DSP_CHANNELS, &od->channels)) { if (setParam(od, SNDCTL_DSP_CHANNELS, &od->channels)) {
ERROR("OSS device \"%s\" does not support %i channels: %s\n", ERROR("OSS device \"%s\" does not support %i channels: %s\n",
od->device, od->device, od->channels, strerror(errno));
od->channels,
strerror(errno));
goto fail; goto fail;
} }
if (setParam(od, SNDCTL_DSP_SPEED, &od->sampleRate)) { if (setParam(od, SNDCTL_DSP_SPEED, &od->sampleRate)) {
ERROR("OSS device \"%s\" does not support %i Hz audio: %s\n", ERROR("OSS device \"%s\" does not support %i Hz audio: %s\n",
od->device, od->device, od->sampleRate, strerror(errno));
od->sampleRate,
strerror(errno));
goto fail; goto fail;
} }
@ -463,9 +494,7 @@ static int oss_open(AudioOutput * audioOutput) {
if (setParam(od, SNDCTL_DSP_SAMPLESIZE, &tmp)) { if (setParam(od, SNDCTL_DSP_SAMPLESIZE, &tmp)) {
ERROR("OSS device \"%s\" does not support %i bit audio: %s\n", ERROR("OSS device \"%s\" does not support %i bit audio: %s\n",
od->device, od->device, tmp, strerror(errno));
tmp,
strerror(errno));
goto fail; goto fail;
} }
@ -497,13 +526,13 @@ static int oss_openDevice(AudioOutput * audioOutput)
audioFormat->bits = od->bits; audioFormat->bits = od->bits;
DEBUG("oss device \"%s\" will be playing %i bit %i channel audio at " DEBUG("oss device \"%s\" will be playing %i bit %i channel audio at "
"%i Hz\n", od->device, od->bits, "%i Hz\n", od->device, od->bits, od->channels, od->sampleRate);
od->channels, od->sampleRate);
return ret; return ret;
} }
static void oss_closeDevice(AudioOutput * audioOutput) { static void oss_closeDevice(AudioOutput * audioOutput)
{
OssData *od = audioOutput->data; OssData *od = audioOutput->data;
oss_close(od); oss_close(od);
@ -511,7 +540,8 @@ static void oss_closeDevice(AudioOutput * audioOutput) {
audioOutput->open = 0; audioOutput->open = 0;
} }
static void oss_dropBufferedAudio(AudioOutput * audioOutput) { static void oss_dropBufferedAudio(AudioOutput * audioOutput)
{
OssData *od = audioOutput->data; OssData *od = audioOutput->data;
if (od->fd >= 0) { if (od->fd >= 0) {
@ -520,8 +550,7 @@ static void oss_dropBufferedAudio(AudioOutput * audioOutput) {
} }
} }
static int oss_playAudio(AudioOutput * audioOutput, char * playChunk, static int oss_playAudio(AudioOutput * audioOutput, char *playChunk, int size)
int size)
{ {
OssData *od = audioOutput->data; OssData *od = audioOutput->data;
int ret; int ret;
@ -533,7 +562,8 @@ static int oss_playAudio(AudioOutput * audioOutput, char * playChunk,
while (size > 0) { while (size > 0) {
ret = write(od->fd, playChunk, size); ret = write(od->fd, playChunk, size);
if (ret < 0) { if (ret < 0) {
if(errno == EINTR) continue; if (errno == EINTR)
continue;
ERROR("closing oss device \"%s\" due to write error: " ERROR("closing oss device \"%s\" due to write error: "
"%s\n", od->device, strerror(errno)); "%s\n", od->device, strerror(errno));
oss_closeDevice(audioOutput); oss_closeDevice(audioOutput);
@ -546,8 +576,7 @@ static int oss_playAudio(AudioOutput * audioOutput, char * playChunk,
return 0; return 0;
} }
AudioOutputPlugin ossPlugin = AudioOutputPlugin ossPlugin = {
{
"oss", "oss",
oss_testDefault, oss_testDefault,
oss_initDriver, oss_initDriver,
@ -562,5 +591,4 @@ AudioOutputPlugin ossPlugin =
#else /* HAVE OSS */ #else /* HAVE OSS */
DISABLED_AUDIO_OUTPUT_PLUGIN(ossPlugin) DISABLED_AUDIO_OUTPUT_PLUGIN(ossPlugin)
#endif /* HAVE_OSS */ #endif /* HAVE_OSS */

View File

@ -38,7 +38,8 @@ typedef struct _OsxData {
int started; int started;
} OsxData; } OsxData;
static OsxData * newOsxData() { static OsxData *newOsxData()
{
OsxData *ret = malloc(sizeof(OsxData)); OsxData *ret = malloc(sizeof(OsxData));
pthread_mutex_init(&ret->mutex, NULL); pthread_mutex_init(&ret->mutex, NULL);
@ -53,7 +54,8 @@ static OsxData * newOsxData() {
return ret; return ret;
} }
static int osx_testDefault() { static int osx_testDefault()
{
/*AudioUnit au; /*AudioUnit au;
ComponentDescription desc; ComponentDescription desc;
Component comp; Component comp;
@ -80,7 +82,8 @@ static int osx_testDefault() {
return 0; return 0;
} }
static int osx_initDriver(AudioOutput * audioOutput, ConfigParam * param) { static int osx_initDriver(AudioOutput * audioOutput, ConfigParam * param)
{
OsxData *od = newOsxData(); OsxData *od = newOsxData();
audioOutput->data = od; audioOutput->data = od;
@ -88,19 +91,23 @@ static int osx_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
return 0; return 0;
} }
static void freeOsxData(OsxData * od) { static void freeOsxData(OsxData * od)
if(od->buffer) free(od->buffer); {
if (od->buffer)
free(od->buffer);
pthread_mutex_destroy(&od->mutex); pthread_mutex_destroy(&od->mutex);
pthread_cond_destroy(&od->condition); pthread_cond_destroy(&od->condition);
free(od); free(od);
} }
static void osx_finishDriver(AudioOutput * audioOutput) { static void osx_finishDriver(AudioOutput * audioOutput)
{
OsxData *od = (OsxData *) audioOutput->data; OsxData *od = (OsxData *) audioOutput->data;
freeOsxData(od); freeOsxData(od);
} }
static void osx_dropBufferedAudio(AudioOutput * audioOutput) { static void osx_dropBufferedAudio(AudioOutput * audioOutput)
{
OsxData *od = (OsxData *) audioOutput->data; OsxData *od = (OsxData *) audioOutput->data;
pthread_mutex_lock(&od->mutex); pthread_mutex_lock(&od->mutex);
@ -108,7 +115,8 @@ static void osx_dropBufferedAudio(AudioOutput * audioOutput) {
pthread_mutex_unlock(&od->mutex); pthread_mutex_unlock(&od->mutex);
} }
static void osx_closeDevice(AudioOutput * audioOutput) { static void osx_closeDevice(AudioOutput * audioOutput)
{
OsxData *od = (OsxData *) audioOutput->data; OsxData *od = (OsxData *) audioOutput->data;
pthread_mutex_lock(&od->mutex); pthread_mutex_lock(&od->mutex);
@ -192,7 +200,8 @@ static OSStatus osx_render(void * vdata,
od->pos += bytesToCopy; od->pos += bytesToCopy;
curpos += bytesToCopy; curpos += bytesToCopy;
if(od->pos >= od->bufferSize) od->pos = 0; if (od->pos >= od->bufferSize)
od->pos = 0;
/* DEBUG("osx_render: unlock\n"); */ /* DEBUG("osx_render: unlock\n"); */
pthread_mutex_unlock(&od->mutex); pthread_mutex_unlock(&od->mutex);
pthread_cond_signal(&od->condition); pthread_cond_signal(&od->condition);
@ -208,7 +217,8 @@ static OSStatus osx_render(void * vdata,
return 0; return 0;
} }
static int osx_openDevice(AudioOutput * audioOutput) { static int osx_openDevice(AudioOutput * audioOutput)
{
OsxData *od = (OsxData *) audioOutput->data; OsxData *od = (OsxData *) audioOutput->data;
ComponentDescription desc; ComponentDescription desc;
Component comp; Component comp;
@ -244,8 +254,7 @@ static int osx_openDevice(AudioOutput * audioOutput) {
if (AudioUnitSetProperty(od->au, kAudioUnitProperty_SetRenderCallback, if (AudioUnitSetProperty(od->au, kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input, 0, kAudioUnitScope_Input, 0,
&callback, sizeof(callback)) != 0) &callback, sizeof(callback)) != 0) {
{
AudioUnitUninitialize(od->au); AudioUnitUninitialize(od->au);
CloseComponent(od->au); CloseComponent(od->au);
ERROR("unable to set callbak for OS X audio unit\n"); ERROR("unable to set callbak for OS X audio unit\n");
@ -256,7 +265,8 @@ static int osx_openDevice(AudioOutput * audioOutput) {
streamDesc.mFormatID = kAudioFormatLinearPCM; streamDesc.mFormatID = kAudioFormatLinearPCM;
streamDesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | streamDesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |
kLinearPCMFormatFlagIsBigEndian; kLinearPCMFormatFlagIsBigEndian;
streamDesc.mBytesPerPacket = audioFormat->channels*audioFormat->bits/8; streamDesc.mBytesPerPacket =
audioFormat->channels * audioFormat->bits / 8;
streamDesc.mFramesPerPacket = 1; streamDesc.mFramesPerPacket = 1;
streamDesc.mBytesPerFrame = streamDesc.mBytesPerPacket; streamDesc.mBytesPerFrame = streamDesc.mBytesPerPacket;
streamDesc.mChannelsPerFrame = audioFormat->channels; streamDesc.mChannelsPerFrame = audioFormat->channels;
@ -264,8 +274,7 @@ static int osx_openDevice(AudioOutput * audioOutput) {
if (AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat, if (AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0, kAudioUnitScope_Input, 0,
&streamDesc, sizeof(streamDesc)) != 0) &streamDesc, sizeof(streamDesc)) != 0) {
{
AudioUnitUninitialize(od->au); AudioUnitUninitialize(od->au);
CloseComponent(od->au); CloseComponent(od->au);
ERROR("Unable to set format on OS X device\n"); ERROR("Unable to set format on OS X device\n");
@ -285,7 +294,8 @@ static int osx_openDevice(AudioOutput * audioOutput) {
return 0; return 0;
} }
static int osx_play(AudioOutput * audioOutput, char * playChunk, int size) { static int osx_play(AudioOutput * audioOutput, char *playChunk, int size)
{
OsxData *od = (OsxData *) audioOutput->data; OsxData *od = (OsxData *) audioOutput->data;
int bytesToCopy; int bytesToCopy;
int curpos; int curpos;
@ -307,7 +317,8 @@ static int osx_play(AudioOutput * audioOutput, char * playChunk, int size) {
while (size) { while (size) {
/* DEBUG("osx_play: lock\n"); */ /* DEBUG("osx_play: lock\n"); */
curpos = od->pos + od->len; curpos = od->pos + od->len;
if(curpos >= od->bufferSize) curpos -= od->bufferSize; if (curpos >= od->bufferSize)
curpos -= od->bufferSize;
bytesToCopy = od->bufferSize < size ? od->bufferSize : size; bytesToCopy = od->bufferSize < size ? od->bufferSize : size;
@ -341,8 +352,7 @@ static int osx_play(AudioOutput * audioOutput, char * playChunk, int size) {
return 0; return 0;
} }
AudioOutputPlugin osxPlugin = AudioOutputPlugin osxPlugin = {
{
"osx", "osx",
osx_testDefault, osx_testDefault,
osx_initDriver, osx_initDriver,
@ -359,5 +369,4 @@ AudioOutputPlugin osxPlugin =
#include <stdio.h> #include <stdio.h>
DISABLED_AUDIO_OUTPUT_PLUGIN(osxPlugin) DISABLED_AUDIO_OUTPUT_PLUGIN(osxPlugin)
#endif #endif

View File

@ -58,8 +58,10 @@ static PulseData * newPulseData()
static void freePulseData(PulseData * pd) static void freePulseData(PulseData * pd)
{ {
if (pd->server) free(pd->server); if (pd->server)
if (pd->sink) free(pd->sink); free(pd->server);
if (pd->sink)
free(pd->sink);
free(pd); free(pd);
} }
@ -123,7 +125,8 @@ static int pulse_openDevice(AudioOutput * audioOutput)
audioFormat = &audioOutput->outAudioFormat; audioFormat = &audioOutput->outAudioFormat;
if (pd->connAttempts != 0 && if (pd->connAttempts != 0 &&
(t - pd->lastAttempt) < CONN_ATTEMPT_INTERVAL) return -1; (t - pd->lastAttempt) < CONN_ATTEMPT_INTERVAL)
return -1;
pd->connAttempts++; pd->connAttempts++;
pd->lastAttempt = t; pd->lastAttempt = t;
@ -142,7 +145,7 @@ static int pulse_openDevice(AudioOutput * audioOutput)
pd->sink, audioOutput->name, &ss, NULL, NULL, pd->sink, audioOutput->name, &ss, NULL, NULL,
&error); &error);
if (!pd->s) { 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, "\"%s\" (attempt %i): %s\n", audioOutput->name,
pd->connAttempts, pa_strerror(error)); pd->connAttempts, pa_strerror(error));
return -1; return -1;
@ -151,7 +154,7 @@ static int pulse_openDevice(AudioOutput * audioOutput)
pd->connAttempts = 0; pd->connAttempts = 0;
audioOutput->open = 1; 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, "channel audio at %i Hz\n", audioOutput->name, audioFormat->bits,
audioFormat->channels, audioFormat->sampleRate); audioFormat->channels, audioFormat->sampleRate);
@ -182,8 +185,7 @@ static void pulse_closeDevice(AudioOutput * audioOutput)
audioOutput->open = 0; audioOutput->open = 0;
} }
static int pulse_playAudio(AudioOutput * audioOutput, char * playChunk, static int pulse_playAudio(AudioOutput * audioOutput, char *playChunk, int size)
int size)
{ {
PulseData *pd; PulseData *pd;
int error; int error;
@ -191,7 +193,7 @@ static int pulse_playAudio(AudioOutput * audioOutput, char * playChunk,
pd = audioOutput->data; pd = audioOutput->data;
if (pa_simple_write(pd->s, playChunk, size, &error) < 0) { 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)); "error: %s\n", audioOutput->name, pa_strerror(error));
pulse_closeDevice(audioOutput); pulse_closeDevice(audioOutput);
return -1; return -1;
@ -215,5 +217,4 @@ AudioOutputPlugin pulsePlugin = {
#else /* HAVE_PULSE */ #else /* HAVE_PULSE */
DISABLED_AUDIO_OUTPUT_PLUGIN(pulsePlugin) DISABLED_AUDIO_OUTPUT_PLUGIN(pulsePlugin)
#endif /* HAVE_PULSE */ #endif /* HAVE_PULSE */

View File

@ -72,7 +72,8 @@ typedef struct _ShoutData {
AudioFormat *audioFormat; AudioFormat *audioFormat;
} ShoutData; } ShoutData;
static ShoutData * newShoutData(void) { static ShoutData *newShoutData(void)
{
ShoutData *ret = malloc(sizeof(ShoutData)); ShoutData *ret = malloc(sizeof(ShoutData));
ret->shoutConn = shout_new(); ret->shoutConn = shout_new();
@ -88,9 +89,12 @@ static ShoutData * newShoutData(void) {
return ret; return ret;
} }
static void freeShoutData(ShoutData * sd) { static void freeShoutData(ShoutData * sd)
if(sd->shoutConn) shout_free(sd->shoutConn); {
if(sd->tag) freeMpdTag(sd->tag); if (sd->shoutConn)
shout_free(sd->shoutConn);
if (sd->tag)
freeMpdTag(sd->tag);
free(sd); free(sd);
} }
@ -104,7 +108,8 @@ static void freeShoutData(ShoutData * sd) {
} \ } \
} }
static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) { static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param)
{
ShoutData *sd; ShoutData *sd;
char *test; char *test;
int port; int port;
@ -118,7 +123,8 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
sd = newShoutData(); sd = newShoutData();
if(shoutInitCount == 0) shout_init(); if (shoutInitCount == 0)
shout_init();
shoutInitCount++; shoutInitCount++;
@ -146,19 +152,23 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
blockParam = getBlockParam(param, "public"); blockParam = getBlockParam(param, "public");
if (blockParam) { if (blockParam) {
if(0 == strcmp(blockParam->value, "yes")) public = 1; if (0 == strcmp(blockParam->value, "yes"))
else if(0 == strcmp(blockParam->value, "no")) public = 0; public = 1;
else if (0 == strcmp(blockParam->value, "no"))
public = 0;
else { else {
ERROR("public \"%s\" is not \"yes\" or \"no\" at line " 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); exit(EXIT_FAILURE);
} }
} } else
else public = 0; public = 0;
blockParam = getBlockParam(param, "user"); blockParam = getBlockParam(param, "user");
if(blockParam) user = blockParam->value; if (blockParam)
else user = "source"; user = blockParam->value;
else
user = "source";
blockParam = getBlockParam(param, "quality"); blockParam = getBlockParam(param, "quality");
@ -182,8 +192,7 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
blockParam->line); blockParam->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} } else {
else {
blockParam = getBlockParam(param, "bitrate"); blockParam = getBlockParam(param, "bitrate");
if (!blockParam) { if (!blockParam) {
@ -215,11 +224,9 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
!= SHOUTERR_SUCCESS || != SHOUTERR_SUCCESS ||
shout_set_protocol(sd->shoutConn, SHOUT_PROTOCOL_HTTP) shout_set_protocol(sd->shoutConn, SHOUT_PROTOCOL_HTTP)
!= SHOUTERR_SUCCESS || != SHOUTERR_SUCCESS ||
shout_set_agent(sd->shoutConn, "MPD") != SHOUTERR_SUCCESS) shout_set_agent(sd->shoutConn, "MPD") != SHOUTERR_SUCCESS) {
{
ERROR("error configuring shout defined at line %i: %s\n", ERROR("error configuring shout defined at line %i: %s\n",
param->line, param->line, shout_get_error(sd->shoutConn));
shout_get_error(sd->shoutConn));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -227,18 +234,15 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
blockParam = getBlockParam(param, "genre"); 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", ERROR("error configuring shout defined at line %i: %s\n",
param->line, param->line, shout_get_error(sd->shoutConn));
shout_get_error(sd->shoutConn));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
blockParam = getBlockParam(param, "description"); blockParam = getBlockParam(param, "description");
if (blockParam && shout_set_description(sd->shoutConn, if (blockParam && shout_set_description(sd->shoutConn,
blockParam->value)) blockParam->value)) {
{
ERROR("error configuring shout defined at line %i: %s\n", ERROR("error configuring shout defined at line %i: %s\n",
param->line, param->line, shout_get_error(sd->shoutConn));
shout_get_error(sd->shoutConn));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -257,8 +261,7 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
snprintf(temp, sizeof(temp), "%2.2f", sd->quality); snprintf(temp, sizeof(temp), "%2.2f", sd->quality);
shout_set_audio_info(sd->shoutConn, SHOUT_AI_QUALITY, shout_set_audio_info(sd->shoutConn, SHOUT_AI_QUALITY,
temp); temp);
} } else {
else {
snprintf(temp, sizeof(temp), "%d", sd->bitrate); snprintf(temp, sizeof(temp), "%d", sd->bitrate);
shout_set_audio_info(sd->shoutConn, SHOUT_AI_BITRATE, shout_set_audio_info(sd->shoutConn, SHOUT_AI_BITRATE,
temp); temp);
@ -270,7 +273,8 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
return 0; return 0;
} }
static int myShout_handleError(ShoutData * sd, int err) { static int myShout_handleError(ShoutData * sd, int err)
{
switch (err) { switch (err) {
case SHOUTERR_SUCCESS: case SHOUTERR_SUCCESS:
break; break;
@ -294,20 +298,24 @@ static int myShout_handleError(ShoutData * sd, int err) {
return 0; return 0;
} }
static int write_page(ShoutData * sd) { static int write_page(ShoutData * sd)
{
int err = 0; 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); shout_sync(sd->shoutConn);
err = shout_send(sd->shoutConn, sd->og.header, sd->og.header_len); 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); 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; return 0;
} }
static void finishEncoder(ShoutData * sd) { static void finishEncoder(ShoutData * sd)
{
vorbis_analysis_wrote(&sd->vd, 0); vorbis_analysis_wrote(&sd->vd, 0);
while (vorbis_analysis_blockout(&sd->vd, &sd->vb) == 1) { while (vorbis_analysis_blockout(&sd->vd, &sd->vb) == 1) {
@ -319,14 +327,17 @@ static void finishEncoder(ShoutData * sd) {
} }
} }
static int flushEncoder(ShoutData * sd) { static int flushEncoder(ShoutData * sd)
{
return (ogg_stream_pageout(&sd->os, &sd->og) > 0); return (ogg_stream_pageout(&sd->os, &sd->og) > 0);
} }
static void clearEncoder(ShoutData * sd) { static void clearEncoder(ShoutData * sd)
{
finishEncoder(sd); finishEncoder(sd);
while (1 == flushEncoder(sd)) { while (1 == flushEncoder(sd)) {
if(!sd->shoutError) write_page(sd); if (!sd->shoutError)
write_page(sd);
} }
vorbis_comment_clear(&sd->vc); vorbis_comment_clear(&sd->vc);
@ -336,7 +347,8 @@ static void clearEncoder(ShoutData * sd) {
vorbis_info_clear(&sd->vi); vorbis_info_clear(&sd->vi);
} }
static void myShout_closeShoutConn(ShoutData * sd) { static void myShout_closeShoutConn(ShoutData * sd)
{
if (sd->opened) { if (sd->opened) {
clearEncoder(sd); clearEncoder(sd);
@ -349,7 +361,8 @@ static void myShout_closeShoutConn(ShoutData * sd) {
sd->opened = 0; sd->opened = 0;
} }
static void myShout_finishDriver(AudioOutput * audioOutput) { static void myShout_finishDriver(AudioOutput * audioOutput)
{
ShoutData *sd = (ShoutData *) audioOutput->data; ShoutData *sd = (ShoutData *) audioOutput->data;
myShout_closeShoutConn(sd); myShout_closeShoutConn(sd);
@ -358,14 +371,17 @@ static void myShout_finishDriver(AudioOutput * audioOutput) {
shoutInitCount--; 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 */ /* needs to be implemented */
} }
static void myShout_closeDevice(AudioOutput * audioOutput) { static void myShout_closeDevice(AudioOutput * audioOutput)
{
ShoutData *sd = (ShoutData *) audioOutput->data; ShoutData *sd = (ShoutData *) audioOutput->data;
myShout_closeShoutConn(sd); myShout_closeShoutConn(sd);
@ -377,7 +393,8 @@ static void myShout_closeDevice(AudioOutput * audioOutput) {
if(value) vorbis_comment_add_tag(&(sd->vc), name, value); \ if(value) vorbis_comment_add_tag(&(sd->vc), name, value); \
} }
static void copyTagToVorbisComment(ShoutData * sd) { static void copyTagToVorbisComment(ShoutData * sd)
{
if (sd->tag) { if (sd->tag) {
int i; int i;
@ -397,25 +414,24 @@ static void copyTagToVorbisComment(ShoutData * sd) {
} }
} }
static int initEncoder(ShoutData * sd) { static int initEncoder(ShoutData * sd)
{
vorbis_info_init(&(sd->vi)); vorbis_info_init(&(sd->vi));
if (sd->quality >= 0) { if (sd->quality >= 0) {
if (0 != vorbis_encode_init_vbr(&(sd->vi), if (0 != vorbis_encode_init_vbr(&(sd->vi),
sd->audioFormat->channels, sd->audioFormat->channels,
sd->audioFormat->sampleRate, sd->quality*0.1) ) sd->audioFormat->sampleRate,
{ sd->quality * 0.1)) {
ERROR("problem seting up vorbis encoder for shout\n"); ERROR("problem seting up vorbis encoder for shout\n");
vorbis_info_clear(&(sd->vi)); vorbis_info_clear(&(sd->vi));
return -1; return -1;
} }
} } else {
else {
if (0 != vorbis_encode_init(&(sd->vi), if (0 != vorbis_encode_init(&(sd->vi),
sd->audioFormat->channels, sd->audioFormat->channels,
sd->audioFormat->sampleRate, -1.0, sd->audioFormat->sampleRate, -1.0,
sd->bitrate*1000, -1.0) ) sd->bitrate * 1000, -1.0)) {
{
ERROR("problem seting up vorbis encoder for shout\n"); ERROR("problem seting up vorbis encoder for shout\n");
vorbis_info_clear(&(sd->vi)); vorbis_info_clear(&(sd->vi));
return -1; return -1;
@ -432,13 +448,13 @@ static int initEncoder(ShoutData * sd) {
return 0; return 0;
} }
static int myShout_openShoutConn(AudioOutput * audioOutput) { static int myShout_openShoutConn(AudioOutput * audioOutput)
{
ShoutData *sd = (ShoutData *) audioOutput->data; ShoutData *sd = (ShoutData *) audioOutput->data;
time_t t = time(NULL); time_t t = time(NULL);
if (sd->connAttempts != 0 && if (sd->connAttempts != 0 &&
(t - sd->lastAttempt) < CONN_ATTEMPT_INTERVAL) (t - sd->lastAttempt) < CONN_ATTEMPT_INTERVAL) {
{
return -1; return -1;
} }
@ -451,8 +467,7 @@ static int myShout_openShoutConn(AudioOutput * audioOutput) {
"(attempt %i): %s\n", "(attempt %i): %s\n",
shout_get_host(sd->shoutConn), shout_get_host(sd->shoutConn),
shout_get_port(sd->shoutConn), shout_get_port(sd->shoutConn),
sd->connAttempts, sd->connAttempts, shout_get_error(sd->shoutConn));
shout_get_error(sd->shoutConn));
return -1; return -1;
} }
@ -466,7 +481,8 @@ static int myShout_openShoutConn(AudioOutput * audioOutput) {
copyTagToVorbisComment(sd); copyTagToVorbisComment(sd);
vorbis_analysis_headerout(&(sd->vd), &(sd->vc), &(sd->header_main), 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_main));
ogg_stream_packetin(&(sd->os), &(sd->header_comments)); ogg_stream_packetin(&(sd->os), &(sd->header_comments));
@ -475,8 +491,7 @@ static int myShout_openShoutConn(AudioOutput * audioOutput) {
sd->opened = 1; sd->opened = 1;
sd->tagToSend = 0; sd->tagToSend = 0;
while(ogg_stream_flush(&(sd->os), &(sd->og))) while (ogg_stream_flush(&(sd->os), &(sd->og))) {
{
if (write_page(sd) < 0) { if (write_page(sd) < 0) {
myShout_closeShoutConn(sd); myShout_closeShoutConn(sd);
return -1; return -1;
@ -488,12 +503,14 @@ static int myShout_openShoutConn(AudioOutput * audioOutput) {
return 0; return 0;
} }
static int myShout_openDevice(AudioOutput * audioOutput) { static int myShout_openDevice(AudioOutput * audioOutput)
{
ShoutData *sd = (ShoutData *) audioOutput->data; ShoutData *sd = (ShoutData *) audioOutput->data;
audioOutput->open = 1; 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; audioOutput->open = 0;
@ -503,23 +520,26 @@ static int myShout_openDevice(AudioOutput * audioOutput) {
return 0; return 0;
} }
static void myShout_sendMetadata(ShoutData * sd) { static void myShout_sendMetadata(ShoutData * sd)
if(!sd->opened || !sd->tag) return; {
if (!sd->opened || !sd->tag)
return;
clearEncoder(sd); clearEncoder(sd);
if(initEncoder(sd) < 0) return; if (initEncoder(sd) < 0)
return;
copyTagToVorbisComment(sd); copyTagToVorbisComment(sd);
vorbis_analysis_headerout(&(sd->vd), &(sd->vc), &(sd->header_main), 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_main));
ogg_stream_packetin(&(sd->os), &(sd->header_comments)); ogg_stream_packetin(&(sd->os), &(sd->header_comments));
ogg_stream_packetin(&(sd->os), &(sd->header_codebooks)); ogg_stream_packetin(&(sd->os), &(sd->header_codebooks));
while(ogg_stream_flush(&(sd->os), &(sd->og))) while (ogg_stream_flush(&(sd->os), &(sd->og))) {
{
if (write_page(sd) < 0) { if (write_page(sd) < 0) {
myShout_closeShoutConn(sd); myShout_closeShoutConn(sd);
return; return;
@ -531,14 +551,16 @@ static void myShout_sendMetadata(ShoutData * sd) {
sd->tagToSend = 0; sd->tagToSend = 0;
} }
static int myShout_play(AudioOutput * audioOutput, char * playChunk, int size) { static int myShout_play(AudioOutput * audioOutput, char *playChunk, int size)
{
int i, j; int i, j;
ShoutData *sd = (ShoutData *) audioOutput->data; ShoutData *sd = (ShoutData *) audioOutput->data;
float **vorbbuf; float **vorbbuf;
int samples; 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 (!sd->opened) {
if (myShout_openShoutConn(audioOutput) < 0) { if (myShout_openShoutConn(audioOutput) < 0) {
@ -570,7 +592,6 @@ static int myShout_play(AudioOutput * audioOutput, char * playChunk, int size) {
} }
} }
while (ogg_stream_pageout(&(sd->os), &(sd->og)) != 0) { while (ogg_stream_pageout(&(sd->os), &(sd->og)) != 0) {
if (write_page(sd) < 0) { if (write_page(sd) < 0) {
myShout_closeShoutConn(sd); myShout_closeShoutConn(sd);
@ -581,21 +602,23 @@ static int myShout_play(AudioOutput * audioOutput, char * playChunk, int size) {
return 0; return 0;
} }
static void myShout_setTag(AudioOutput * audioOutput, MpdTag * tag) { static void myShout_setTag(AudioOutput * audioOutput, MpdTag * tag)
{
ShoutData *sd = (ShoutData *) audioOutput->data; ShoutData *sd = (ShoutData *) audioOutput->data;
if(sd->tag) freeMpdTag(sd->tag); if (sd->tag)
freeMpdTag(sd->tag);
sd->tag = NULL; sd->tag = NULL;
sd->tagToSend = 0; sd->tagToSend = 0;
if(!tag) return; if (!tag)
return;
sd->tag = mpdTagDup(tag); sd->tag = mpdTagDup(tag);
sd->tagToSend = 1; sd->tagToSend = 1;
} }
AudioOutputPlugin shoutPlugin = AudioOutputPlugin shoutPlugin = {
{
"shout", "shout",
NULL, NULL,
myShout_initDriver, myShout_initDriver,
@ -610,5 +633,4 @@ AudioOutputPlugin shoutPlugin =
#else #else
DISABLED_AUDIO_OUTPUT_PLUGIN(shoutPlugin) DISABLED_AUDIO_OUTPUT_PLUGIN(shoutPlugin)
#endif #endif

View File

@ -22,7 +22,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
int buffer2array(char * origBuffer, char *** array) { int buffer2array(char *origBuffer, char ***array)
{
int quotes = 0; int quotes = 0;
int count = 0; int count = 0;
int i; int i;
@ -35,17 +36,14 @@ int buffer2array(char * origBuffer, char *** array) {
for (curr = 0; curr < bufferLength; curr++) { for (curr = 0; curr < bufferLength; curr++) {
if (!quotes && (buffer[curr] == ' ' || buffer[curr] == '\t')) { if (!quotes && (buffer[curr] == ' ' || buffer[curr] == '\t')) {
markArray[curr] = '0'; markArray[curr] = '0';
} } else if (buffer[curr] == '\"') {
else if(buffer[curr] == '\"') {
if (curr > 0 && buffer[curr - 1] != '\\') { if (curr > 0 && buffer[curr - 1] != '\\') {
quotes = quotes ? 0 : 1; quotes = quotes ? 0 : 1;
markArray[curr] = '0'; markArray[curr] = '0';
} } else {
else {
markArray[curr] = '1'; markArray[curr] = '1';
} }
} } else {
else {
markArray[curr] = '1'; markArray[curr] = '1';
} }
if (markArray[curr] == '1') { if (markArray[curr] == '1') {
@ -53,8 +51,7 @@ int buffer2array(char * origBuffer, char *** array) {
if (markArray[curr - 1] == '0') { if (markArray[curr - 1] == '0') {
count++; count++;
} }
} } else {
else {
count++; count++;
} }
} }
@ -78,12 +75,10 @@ int buffer2array(char * origBuffer, char *** array) {
if (markArray[curr - 1] == '0') { if (markArray[curr - 1] == '0') {
beginArray[count++] = curr; beginArray[count++] = curr;
} }
} } else {
else {
beginArray[count++] = curr; beginArray[count++] = curr;
} }
} } else {
else {
buffer[curr] = '\0'; buffer[curr] = '\0';
} }
} }
@ -110,10 +105,12 @@ int buffer2array(char * origBuffer, char *** array) {
return count; return count;
} }
void freeArgArray(char ** array, int argArrayLength) { void freeArgArray(char **array, int argArrayLength)
{
int i; int i;
if(argArrayLength==0) return; if (argArrayLength == 0)
return;
for (i = 0; i < argArrayLength; i++) { for (i = 0; i < argArrayLength; i++) {
free(array[i]); free(array[i]);

View File

@ -43,7 +43,8 @@ mpd_sint8 char_conv_latin1ToUtf8 = 0;
static void closeCharSetConversion(); static void closeCharSetConversion();
int setCharSetConversion(char * to, char * from) { int setCharSetConversion(char *to, char *from)
{
if (char_conv_to && char_conv_from && if (char_conv_to && char_conv_from &&
strcmp(to, char_conv_to) == 0 && strcmp(from, char_conv_from) == 0) strcmp(to, char_conv_to) == 0 && strcmp(from, char_conv_from) == 0)
{ {
@ -61,8 +62,7 @@ int setCharSetConversion(char * to, char * from) {
if (strcmp(to, "UTF-8") == 0 && strcmp(from, "ISO-8859-1") == 0) { if (strcmp(to, "UTF-8") == 0 && strcmp(from, "ISO-8859-1") == 0) {
char_conv_latin1ToUtf8 = 1; char_conv_latin1ToUtf8 = 1;
} } else if (strcmp(to, "ISO-8859-1") == 0 && strcmp(from, "UTF-8") == 0) {
else if(strcmp(to,"ISO-8859-1")==0 && strcmp(from,"UTF-8")==0) {
char_conv_latin1ToUtf8 = -1; char_conv_latin1ToUtf8 = -1;
} }
@ -71,9 +71,9 @@ int setCharSetConversion(char * to, char * from) {
char_conv_from = strdup(from); char_conv_from = strdup(from);
return 0; return 0;
} }
#ifdef HAVE_ICONV #ifdef HAVE_ICONV
if((char_conv_iconv = iconv_open(to,from))==(iconv_t)(-1)) return -1; if ((char_conv_iconv = iconv_open(to, from)) == (iconv_t) (-1))
return -1;
char_conv_to = strdup(to); char_conv_to = strdup(to);
char_conv_from = strdup(from); char_conv_from = strdup(from);
@ -85,10 +85,13 @@ int setCharSetConversion(char * to, char * from) {
return -1; return -1;
} }
char * convStrDup(char * string) { char *convStrDup(char *string)
if(!char_conv_to) return NULL; {
if (!char_conv_to)
return NULL;
if(char_conv_same) return strdup(string); if (char_conv_same)
return strdup(string);
#ifdef HAVE_ICONV #ifdef HAVE_ICONV
if (char_conv_use_iconv) { if (char_conv_use_iconv) {
@ -106,9 +109,11 @@ char * convStrDup(char * string) {
while (inleft) { while (inleft) {
bufferPtr = buffer; bufferPtr = buffer;
outleft = BUFFER_SIZE; outleft = BUFFER_SIZE;
err = iconv(char_conv_iconv,&string,&inleft,&bufferPtr, err =
iconv(char_conv_iconv, &string, &inleft, &bufferPtr,
&outleft); &outleft);
if(outleft==BUFFER_SIZE || (err<0 && errno!=E2BIG)) { if (outleft == BUFFER_SIZE
|| (err < 0 && errno != E2BIG)) {
free(ret); free(ret);
return NULL; return NULL;
} }
@ -135,10 +140,12 @@ char * convStrDup(char * string) {
return NULL; return NULL;
} }
static void closeCharSetConversion(void) { static void closeCharSetConversion(void)
{
if (char_conv_to) { if (char_conv_to) {
#ifdef HAVE_ICONV #ifdef HAVE_ICONV
if(char_conv_use_iconv) iconv_close(char_conv_iconv); if (char_conv_use_iconv)
iconv_close(char_conv_iconv);
#endif #endif
free(char_conv_to); free(char_conv_to);
free(char_conv_from); free(char_conv_from);

View File

@ -110,7 +110,6 @@ typedef int (* CommandHandlerFunction)(FILE *, int *, int, char **);
typedef int (*CommandListHandlerFunction) typedef int (*CommandListHandlerFunction)
(FILE *, int *, int, char **, ListNode *, CommandEntry *); (FILE *, int *, int, char **, ListNode *, CommandEntry *);
/* if min: -1 don't check args * /* if min: -1 don't check args *
* if max: -1 no max args */ * if max: -1 no max args */
struct _CommandEntry { struct _CommandEntry {
@ -129,7 +128,8 @@ static CommandEntry * getCommandEntryFromString(char * string, int * permission)
List *commandList; List *commandList;
CommandEntry * newCommandEntry(void) { CommandEntry *newCommandEntry(void)
{
CommandEntry *cmd = malloc(sizeof(CommandEntry)); CommandEntry *cmd = malloc(sizeof(CommandEntry));
cmd->cmd = NULL; cmd->cmd = NULL;
cmd->min = 0; cmd->min = 0;
@ -211,8 +211,8 @@ static int handleCurrentSong(FILE * fp, int * permission, int argArrayLength,
if (song >= 0) { if (song >= 0) {
return playlistInfo(fp, song); return playlistInfo(fp, song);
} } else
else return 0; return 0;
} }
static int handlePause(FILE * fp, int *permission, static int handlePause(FILE * fp, int *permission,
@ -222,7 +222,8 @@ static int handlePause(FILE * fp, int * permission,
char *test; char *test;
int pause = strtol(argArray[1], &test, 10); int pause = strtol(argArray[1], &test, 10);
if (*test != '\0' || (pause != 0 && pause != 1)) { if (*test != '\0' || (pause != 0 && pause != 1)) {
commandError(fp, ACK_ERROR_ARG, "\"%s\" is not 0 or 1", argArray[1]); commandError(fp, ACK_ERROR_ARG, "\"%s\" is not 0 or 1",
argArray[1]);
return -1; return -1;
} }
return playerSetPause(fp, pause); return playerSetPause(fp, pause);
@ -252,10 +253,14 @@ static int commandStatus(FILE * fp, int * permission, int argArrayLength,
} }
myfprintf(fp, "%s: %i\n", COMMAND_STATUS_VOLUME, getVolumeLevel()); myfprintf(fp, "%s: %i\n", COMMAND_STATUS_VOLUME, getVolumeLevel());
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_REPEAT,getPlaylistRepeatStatus()); myfprintf(fp, "%s: %i\n", COMMAND_STATUS_REPEAT,
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_RANDOM,getPlaylistRandomStatus()); getPlaylistRepeatStatus());
myfprintf(fp,"%s: %li\n",COMMAND_STATUS_PLAYLIST,getPlaylistVersion()); myfprintf(fp, "%s: %i\n", COMMAND_STATUS_RANDOM,
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_PLAYLIST_LENGTH,getPlaylistLength()); getPlaylistRandomStatus());
myfprintf(fp, "%s: %li\n", COMMAND_STATUS_PLAYLIST,
getPlaylistVersion());
myfprintf(fp, "%s: %i\n", COMMAND_STATUS_PLAYLIST_LENGTH,
getPlaylistLength());
myfprintf(fp, "%s: %i\n", COMMAND_STATUS_CROSSFADE, myfprintf(fp, "%s: %i\n", COMMAND_STATUS_CROSSFADE,
(int)(getPlayerCrossFade() + 0.5)); (int)(getPlayerCrossFade() + 0.5));
@ -268,17 +273,23 @@ static int commandStatus(FILE * fp, int * permission, int argArrayLength,
getPlaylistSongId(song)); getPlaylistSongId(song));
} }
if (getPlayerState() != PLAYER_STATE_STOP) { if (getPlayerState() != PLAYER_STATE_STOP) {
myfprintf(fp,"%s: %i:%i\n",COMMAND_STATUS_TIME,getPlayerElapsedTime(),getPlayerTotalTime()); myfprintf(fp, "%s: %i:%i\n", COMMAND_STATUS_TIME,
myfprintf(fp,"%s: %li\n",COMMAND_STATUS_BITRATE,getPlayerBitRate(),getPlayerTotalTime()); getPlayerElapsedTime(), getPlayerTotalTime());
myfprintf(fp,"%s: %u:%i:%i\n",COMMAND_STATUS_AUDIO,getPlayerSampleRate(),getPlayerBits(),getPlayerChannels()); myfprintf(fp, "%s: %li\n", COMMAND_STATUS_BITRATE,
getPlayerBitRate(), getPlayerTotalTime());
myfprintf(fp, "%s: %u:%i:%i\n", COMMAND_STATUS_AUDIO,
getPlayerSampleRate(), getPlayerBits(),
getPlayerChannels());
} }
if ((updateJobId = isUpdatingDB())) { if ((updateJobId = isUpdatingDB())) {
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_UPDATING_DB,updateJobId); myfprintf(fp, "%s: %i\n", COMMAND_STATUS_UPDATING_DB,
updateJobId);
} }
if (getPlayerError() != PLAYER_ERROR_NOERROR) { if (getPlayerError() != PLAYER_ERROR_NOERROR) {
myfprintf(fp,"%s: %s\n",COMMAND_STATUS_ERROR,getPlayerErrorStr()); myfprintf(fp, "%s: %s\n", COMMAND_STATUS_ERROR,
getPlayerErrorStr());
} }
return 0; return 0;
@ -301,7 +312,8 @@ static int handleAdd(FILE * fp, int * permission, int argArrayLength,
{ {
char *path = argArray[1]; char *path = argArray[1];
if(isRemoteUrl(path)) return addToPlaylist(fp, path, 0); if (isRemoteUrl(path))
return addToPlaylist(fp, path, 0);
return addAllIn(fp, path); return addAllIn(fp, path);
} }
@ -378,8 +390,8 @@ static int handleListPlaylist(FILE * fp, int * permission, int argArrayLength,
return PlaylistInfo(fp, argArray[1], 0); return PlaylistInfo(fp, argArray[1], 0);
} }
static int handleListPlaylistInfo(FILE * fp, int * permission, int argArrayLength, static int handleListPlaylistInfo(FILE * fp, int *permission,
char ** argArray) int argArrayLength, char **argArray)
{ {
return PlaylistInfo(fp, argArray[1], 1); return PlaylistInfo(fp, argArray[1], 1);
} }
@ -388,12 +400,15 @@ static int handleLsInfo(FILE * fp, int * permission, int argArrayLength,
char **argArray) char **argArray)
{ {
if (argArrayLength == 1) { if (argArrayLength == 1) {
if(printDirectoryInfo(fp,NULL)<0) return -1; if (printDirectoryInfo(fp, NULL) < 0)
else return lsPlaylists(fp,""); return -1;
} else
else { return lsPlaylists(fp, "");
if(printDirectoryInfo(fp,argArray[1])<0) return -1; } else {
else return lsPlaylists(fp,argArray[1]); if (printDirectoryInfo(fp, argArray[1]) < 0)
return -1;
else
return lsPlaylists(fp, argArray[1]);
} }
} }
@ -474,7 +489,8 @@ static int handleFind(FILE * fp, int * permission, int argArrayLength,
LocateTagItem *items; LocateTagItem *items;
int numItems = newLocateTagItemArrayFromArgArray(argArray + 1, int numItems = newLocateTagItemArrayFromArgArray(argArray + 1,
argArrayLength-1, &items); argArrayLength - 1,
&items);
if (numItems <= 0) { if (numItems <= 0) {
commandError(fp, ACK_ERROR_ARG, "incorrect arguments", NULL); commandError(fp, ACK_ERROR_ARG, "incorrect arguments", NULL);
@ -495,7 +511,8 @@ static int handleSearch(FILE * fp, int * permission, int argArrayLength,
LocateTagItem *items; LocateTagItem *items;
int numItems = newLocateTagItemArrayFromArgArray(argArray + 1, int numItems = newLocateTagItemArrayFromArgArray(argArray + 1,
argArrayLength-1, &items); argArrayLength - 1,
&items);
if (numItems <= 0) { if (numItems <= 0) {
commandError(fp, ACK_ERROR_ARG, "incorrect arguments", NULL); commandError(fp, ACK_ERROR_ARG, "incorrect arguments", NULL);
@ -513,17 +530,19 @@ static int listHandleUpdate(FILE * fp,
int *permission, int *permission,
int argArrayLength, int argArrayLength,
char **argArray, char **argArray,
ListNode * commandNode, ListNode * commandNode, CommandEntry * cmd)
CommandEntry * cmd)
{ {
static List *pathList = NULL; static List *pathList = NULL;
CommandEntry *nextCmd = NULL; CommandEntry *nextCmd = NULL;
ListNode *nextNode = commandNode->nextNode;; ListNode *nextNode = commandNode->nextNode;;
if(!pathList) pathList = makeList(NULL, 1); if (!pathList)
pathList = makeList(NULL, 1);
if(argArrayLength==2) insertInList(pathList,argArray[1],NULL); if (argArrayLength == 2)
else insertInList(pathList,"",NULL); insertInList(pathList, argArray[1], NULL);
else
insertInList(pathList, "", NULL);
if (nextNode) { if (nextNode) {
nextCmd = getCommandEntryFromString((void *)nextNode->data, nextCmd = getCommandEntryFromString((void *)nextNode->data,
@ -571,7 +590,8 @@ static int handleListAll(FILE * fp, int * permission, int argArrayLength,
{ {
char *directory = NULL; char *directory = NULL;
if(argArrayLength==2) directory = argArray[1]; if (argArrayLength == 2)
directory = argArray[1];
return printAllIn(fp, directory); return printAllIn(fp, directory);
} }
@ -669,10 +689,11 @@ static int handleList(FILE * fp, int * permission, int argArrayLength,
conditionals = newLocateTagItem(mpdTagItemKeys[TAG_ITEM_ARTIST], conditionals = newLocateTagItem(mpdTagItemKeys[TAG_ITEM_ARTIST],
argArray[2]); argArray[2]);
numConditionals = 1; numConditionals = 1;
} } else {
else { numConditionals =
numConditionals = newLocateTagItemArrayFromArgArray(argArray+2, newLocateTagItemArrayFromArgArray(argArray + 2,
argArrayLength-2, &conditionals); argArrayLength - 2,
&conditionals);
if (numConditionals < 0) { if (numConditionals < 0) {
commandError(fp, ACK_ERROR_ARG, commandError(fp, ACK_ERROR_ARG,
@ -683,7 +704,8 @@ static int handleList(FILE * fp, int * permission, int argArrayLength,
ret = listAllUniqueTags(fp, tagType, numConditionals, conditionals); ret = listAllUniqueTags(fp, tagType, numConditionals, conditionals);
if(conditionals) freeLocateTagItemArray(numConditionals, conditionals); if (conditionals)
freeLocateTagItemArray(numConditionals, conditionals);
return ret; return ret;
} }
@ -825,7 +847,8 @@ static int handleListAllInfo(FILE * fp, int * permission, int argArrayLength,
{ {
char *directory = NULL; char *directory = NULL;
if(argArrayLength==2) directory = argArray[1]; if (argArrayLength == 2)
directory = argArray[1];
return printInfoForAllIn(fp, directory); return printInfoForAllIn(fp, directory);
} }
@ -839,7 +862,8 @@ static int handlePassword(FILE * fp, int * permission, int argArrayLength,
char **argArray) char **argArray)
{ {
if (getPermissionFromPassword(argArray[1], permission) < 0) { if (getPermissionFromPassword(argArray[1], permission) < 0) {
commandError(fp, ACK_ERROR_PASSWORD, "incorrect password", NULL); commandError(fp, ACK_ERROR_PASSWORD, "incorrect password",
NULL);
return -1; return -1;
} }
@ -942,60 +966,88 @@ static int handleNotcommands(FILE * fp, int * permission, int argArrayLength,
return 0; return 0;
} }
void initCommands(void) { void initCommands(void)
{
commandList = makeList(free, 1); commandList = makeList(free, 1);
addCommand(COMMAND_PLAY, PERMISSION_CONTROL, 0, 1, handlePlay, NULL); addCommand(COMMAND_PLAY, PERMISSION_CONTROL, 0, 1, handlePlay, NULL);
addCommand(COMMAND_PLAYID ,PERMISSION_CONTROL, 0, 1,handlePlayId,NULL); addCommand(COMMAND_PLAYID, PERMISSION_CONTROL, 0, 1, handlePlayId,
NULL);
addCommand(COMMAND_STOP, PERMISSION_CONTROL, 0, 0, handleStop, NULL); addCommand(COMMAND_STOP, PERMISSION_CONTROL, 0, 0, handleStop, NULL);
addCommand(COMMAND_CURRENTSONG ,PERMISSION_READ , 0, 0,handleCurrentSong,NULL); addCommand(COMMAND_CURRENTSONG, PERMISSION_READ, 0, 0,
handleCurrentSong, NULL);
addCommand(COMMAND_PAUSE, PERMISSION_CONTROL, 0, 1, handlePause, NULL); addCommand(COMMAND_PAUSE, PERMISSION_CONTROL, 0, 1, handlePause, NULL);
addCommand(COMMAND_STATUS, PERMISSION_READ, 0, 0, commandStatus, NULL); addCommand(COMMAND_STATUS, PERMISSION_READ, 0, 0, commandStatus, NULL);
addCommand(COMMAND_KILL, PERMISSION_ADMIN, -1, -1, handleKill, NULL); addCommand(COMMAND_KILL, PERMISSION_ADMIN, -1, -1, handleKill, NULL);
addCommand(COMMAND_CLOSE, 0, -1, -1, handleClose, NULL); addCommand(COMMAND_CLOSE, 0, -1, -1, handleClose, NULL);
addCommand(COMMAND_ADD, PERMISSION_ADD, 1, 1, handleAdd, NULL); addCommand(COMMAND_ADD, PERMISSION_ADD, 1, 1, handleAdd, NULL);
addCommand(COMMAND_ADDID, PERMISSION_ADD, 1, 1, handleAddId, NULL); addCommand(COMMAND_ADDID, PERMISSION_ADD, 1, 1, handleAddId, NULL);
addCommand(COMMAND_DELETE ,PERMISSION_CONTROL, 1, 1,handleDelete,NULL); addCommand(COMMAND_DELETE, PERMISSION_CONTROL, 1, 1, handleDelete,
addCommand(COMMAND_DELETEID ,PERMISSION_CONTROL, 1, 1,handleDeleteId,NULL); NULL);
addCommand(COMMAND_PLAYLIST ,PERMISSION_READ, 0, 0,handlePlaylist,NULL); addCommand(COMMAND_DELETEID, PERMISSION_CONTROL, 1, 1, handleDeleteId,
addCommand(COMMAND_PLAYLISTID ,PERMISSION_READ, 0, 1,handlePlaylistId,NULL); NULL);
addCommand(COMMAND_SHUFFLE ,PERMISSION_CONTROL, 0, 0,handleShuffle,NULL); addCommand(COMMAND_PLAYLIST, PERMISSION_READ, 0, 0, handlePlaylist,
NULL);
addCommand(COMMAND_PLAYLISTID, PERMISSION_READ, 0, 1, handlePlaylistId,
NULL);
addCommand(COMMAND_SHUFFLE, PERMISSION_CONTROL, 0, 0, handleShuffle,
NULL);
addCommand(COMMAND_CLEAR, PERMISSION_CONTROL, 0, 0, handleClear, NULL); addCommand(COMMAND_CLEAR, PERMISSION_CONTROL, 0, 0, handleClear, NULL);
addCommand(COMMAND_SAVE, PERMISSION_CONTROL, 1, 1, handleSave, NULL); addCommand(COMMAND_SAVE, PERMISSION_CONTROL, 1, 1, handleSave, NULL);
addCommand(COMMAND_LOAD, PERMISSION_ADD, 1, 1, handleLoad, NULL); addCommand(COMMAND_LOAD, PERMISSION_ADD, 1, 1, handleLoad, NULL);
addCommand(COMMAND_LISTPLAYLIST,PERMISSION_READ, 1, 1,handleListPlaylist,NULL); addCommand(COMMAND_LISTPLAYLIST, PERMISSION_READ, 1, 1,
addCommand(COMMAND_LISTPLAYLISTINFO,PERMISSION_READ, 1, 1,handleListPlaylistInfo,NULL); handleListPlaylist, NULL);
addCommand(COMMAND_LISTPLAYLISTINFO, PERMISSION_READ, 1, 1,
handleListPlaylistInfo, NULL);
addCommand(COMMAND_LSINFO, PERMISSION_READ, 0, 1, handleLsInfo, NULL); addCommand(COMMAND_LSINFO, PERMISSION_READ, 0, 1, handleLsInfo, NULL);
addCommand(COMMAND_RM, PERMISSION_CONTROL, 1, 1, handleRm, NULL); addCommand(COMMAND_RM, PERMISSION_CONTROL, 1, 1, handleRm, NULL);
addCommand(COMMAND_PLAYLISTINFO,PERMISSION_READ, 0, 1,handlePlaylistInfo,NULL); addCommand(COMMAND_PLAYLISTINFO, PERMISSION_READ, 0, 1,
handlePlaylistInfo, NULL);
addCommand(COMMAND_FIND, PERMISSION_READ, 2, -1, handleFind, NULL); addCommand(COMMAND_FIND, PERMISSION_READ, 2, -1, handleFind, NULL);
addCommand(COMMAND_SEARCH, PERMISSION_READ, 2, -1, handleSearch, NULL); addCommand(COMMAND_SEARCH, PERMISSION_READ, 2, -1, handleSearch, NULL);
addCommand(COMMAND_UPDATE ,PERMISSION_ADMIN, 0, 1,handleUpdate,listHandleUpdate); addCommand(COMMAND_UPDATE, PERMISSION_ADMIN, 0, 1, handleUpdate,
listHandleUpdate);
addCommand(COMMAND_NEXT, PERMISSION_CONTROL, 0, 0, handleNext, NULL); addCommand(COMMAND_NEXT, PERMISSION_CONTROL, 0, 0, handleNext, NULL);
addCommand(COMMAND_PREVIOUS ,PERMISSION_CONTROL, 0, 0,handlePrevious,NULL); addCommand(COMMAND_PREVIOUS, PERMISSION_CONTROL, 0, 0, handlePrevious,
NULL);
addCommand(COMMAND_LISTALL, PERMISSION_READ, 0, 1, handleListAll, NULL); addCommand(COMMAND_LISTALL, PERMISSION_READ, 0, 1, handleListAll, NULL);
addCommand(COMMAND_VOLUME ,PERMISSION_CONTROL, 1, 1,handleVolume,NULL); addCommand(COMMAND_VOLUME, PERMISSION_CONTROL, 1, 1, handleVolume,
addCommand(COMMAND_REPEAT ,PERMISSION_CONTROL, 1, 1,handleRepeat,NULL); NULL);
addCommand(COMMAND_RANDOM ,PERMISSION_CONTROL, 1, 1,handleRandom,NULL); addCommand(COMMAND_REPEAT, PERMISSION_CONTROL, 1, 1, handleRepeat,
NULL);
addCommand(COMMAND_RANDOM, PERMISSION_CONTROL, 1, 1, handleRandom,
NULL);
addCommand(COMMAND_STATS, PERMISSION_READ, 0, 0, handleStats, NULL); addCommand(COMMAND_STATS, PERMISSION_READ, 0, 0, handleStats, NULL);
addCommand(COMMAND_CLEAR_ERROR ,PERMISSION_CONTROL, 0, 0,handleClearError,NULL); addCommand(COMMAND_CLEAR_ERROR, PERMISSION_CONTROL, 0, 0,
handleClearError, NULL);
addCommand(COMMAND_LIST, PERMISSION_READ, 1, -1, handleList, NULL); addCommand(COMMAND_LIST, PERMISSION_READ, 1, -1, handleList, NULL);
addCommand(COMMAND_MOVE, PERMISSION_CONTROL, 2, 2, handleMove, NULL); addCommand(COMMAND_MOVE, PERMISSION_CONTROL, 2, 2, handleMove, NULL);
addCommand(COMMAND_MOVEID ,PERMISSION_CONTROL, 2, 2,handleMoveId,NULL); addCommand(COMMAND_MOVEID, PERMISSION_CONTROL, 2, 2, handleMoveId,
NULL);
addCommand(COMMAND_SWAP, PERMISSION_CONTROL, 2, 2, handleSwap, NULL); addCommand(COMMAND_SWAP, PERMISSION_CONTROL, 2, 2, handleSwap, NULL);
addCommand(COMMAND_SWAPID ,PERMISSION_CONTROL, 2, 2,handleSwapId,NULL); addCommand(COMMAND_SWAPID, PERMISSION_CONTROL, 2, 2, handleSwapId,
NULL);
addCommand(COMMAND_SEEK, PERMISSION_CONTROL, 2, 2, handleSeek, NULL); addCommand(COMMAND_SEEK, PERMISSION_CONTROL, 2, 2, handleSeek, NULL);
addCommand(COMMAND_SEEKID ,PERMISSION_CONTROL, 2, 2,handleSeekId,NULL); addCommand(COMMAND_SEEKID, PERMISSION_CONTROL, 2, 2, handleSeekId,
addCommand(COMMAND_LISTALLINFO ,PERMISSION_READ, 0, 1,handleListAllInfo,NULL); NULL);
addCommand(COMMAND_LISTALLINFO, PERMISSION_READ, 0, 1,
handleListAllInfo, NULL);
addCommand(COMMAND_PING, 0, 0, 0, handlePing, NULL); addCommand(COMMAND_PING, 0, 0, 0, handlePing, NULL);
addCommand(COMMAND_SETVOL ,PERMISSION_CONTROL, 1, 1,handleSetVol,NULL); addCommand(COMMAND_SETVOL, PERMISSION_CONTROL, 1, 1, handleSetVol,
NULL);
addCommand(COMMAND_PASSWORD, 0, 1, 1, handlePassword, NULL); addCommand(COMMAND_PASSWORD, 0, 1, 1, handlePassword, NULL);
addCommand(COMMAND_CROSSFADE ,PERMISSION_CONTROL, 1, 1,handleCrossfade,NULL); addCommand(COMMAND_CROSSFADE, PERMISSION_CONTROL, 1, 1, handleCrossfade,
addCommand(COMMAND_URL_HANDLERS,PERMISSION_READ, 0, 0,handleUrlHandlers,NULL); NULL);
addCommand(COMMAND_PLCHANGES ,PERMISSION_READ, 1, 1,handlePlaylistChanges,NULL); addCommand(COMMAND_URL_HANDLERS, PERMISSION_READ, 0, 0,
addCommand(COMMAND_PLCHANGESPOSID ,PERMISSION_READ, 1, 1,handlePlaylistChangesPosId,NULL); handleUrlHandlers, NULL);
addCommand(COMMAND_ENABLE_DEV ,PERMISSION_ADMIN, 1, 1,handleEnableDevice,NULL); addCommand(COMMAND_PLCHANGES, PERMISSION_READ, 1, 1,
addCommand(COMMAND_DISABLE_DEV ,PERMISSION_ADMIN, 1, 1,handleDisableDevice,NULL); handlePlaylistChanges, NULL);
addCommand(COMMAND_PLCHANGESPOSID, PERMISSION_READ, 1, 1,
handlePlaylistChangesPosId, NULL);
addCommand(COMMAND_ENABLE_DEV, PERMISSION_ADMIN, 1, 1,
handleEnableDevice, NULL);
addCommand(COMMAND_DISABLE_DEV, PERMISSION_ADMIN, 1, 1,
handleDisableDevice, NULL);
addCommand(COMMAND_DEVICES, PERMISSION_READ, 0, 0, handleDevices, NULL); addCommand(COMMAND_DEVICES, PERMISSION_READ, 0, 0, handleDevices, NULL);
addCommand(COMMAND_COMMANDS, 0, 0, 0, handleCommands, NULL); addCommand(COMMAND_COMMANDS, 0, 0, 0, handleCommands, NULL);
addCommand(COMMAND_NOTCOMMANDS, 0, 0, 0, handleNotcommands, NULL); addCommand(COMMAND_NOTCOMMANDS, 0, 0, 0, handleNotcommands, NULL);
@ -1003,7 +1055,8 @@ void initCommands(void) {
sortList(commandList); sortList(commandList);
} }
void finishCommands(void) { void finishCommands(void)
{
freeList(commandList); freeList(commandList);
} }
@ -1022,7 +1075,8 @@ static int checkArgcAndPermission(CommandEntry * cmd, FILE *fp,
return -1; return -1;
} }
if (min == 0) return 0; if (min == 0)
return 0;
if (min == max && max != argc) { if (min == max && max != argc) {
if (fp) { if (fp) {
@ -1031,35 +1085,37 @@ static int checkArgcAndPermission(CommandEntry * cmd, FILE *fp,
argArray[0]); argArray[0]);
} }
return -1; return -1;
} } else if (argc < min) {
else if (argc < min) {
if (fp) { if (fp) {
commandError(fp, ACK_ERROR_ARG, commandError(fp, ACK_ERROR_ARG,
"too few arguments for \"%s\"", "too few arguments for \"%s\"",
argArray[0]); argArray[0]);
} }
return -1; return -1;
} } else if (argc > max && max /* != 0 */ ) {
else if (argc > max && max /* != 0 */) {
if (fp) { if (fp) {
commandError(fp, ACK_ERROR_ARG, commandError(fp, ACK_ERROR_ARG,
"too many arguments for \"%s\"", "too many arguments for \"%s\"",
argArray[0]); argArray[0]);
} }
return -1; return -1;
} } else
else return 0; return 0;
} }
static CommandEntry *getCommandEntryAndCheckArgcAndPermission(FILE * fp, static CommandEntry *getCommandEntryAndCheckArgcAndPermission(FILE * fp,
int * permission, int argArrayLength, char ** argArray) int *permission,
int
argArrayLength,
char **argArray)
{ {
static char unknown[] = ""; static char unknown[] = "";
CommandEntry *cmd; CommandEntry *cmd;
current_command = unknown; current_command = unknown;
if(argArrayLength == 0) return NULL; if (argArrayLength == 0)
return NULL;
if (!findInList(commandList, argArray[0], (void *)&cmd)) { if (!findInList(commandList, argArray[0], (void *)&cmd)) {
if (fp) { if (fp) {
@ -1072,31 +1128,32 @@ static CommandEntry * getCommandEntryAndCheckArgcAndPermission(FILE * fp,
current_command = cmd->cmd; current_command = cmd->cmd;
if (checkArgcAndPermission(cmd, fp, *permission, argArrayLength, if (checkArgcAndPermission(cmd, fp, *permission, argArrayLength,
argArray) < 0) argArray) < 0) {
{
return NULL; return NULL;
} }
return cmd; return cmd;
} }
static CommandEntry * getCommandEntryFromString(char * string, int * permission) { static CommandEntry *getCommandEntryFromString(char *string, int *permission)
{
CommandEntry *cmd = NULL; CommandEntry *cmd = NULL;
char **argArray; char **argArray;
int argArrayLength = buffer2array(string, &argArray); int argArrayLength = buffer2array(string, &argArray);
if(0==argArrayLength) return NULL; if (0 == argArrayLength)
return NULL;
cmd = getCommandEntryAndCheckArgcAndPermission(NULL, permission, cmd = getCommandEntryAndCheckArgcAndPermission(NULL, permission,
argArrayLength,argArray); argArrayLength,
argArray);
freeArgArray(argArray, argArrayLength); freeArgArray(argArray, argArrayLength);
return cmd; return cmd;
} }
static int processCommandInternal(FILE * fp, int *permission, static int processCommandInternal(FILE * fp, int *permission,
char * commandString, char *commandString, ListNode * commandNode)
ListNode * commandNode)
{ {
int argArrayLength; int argArrayLength;
char **argArray; char **argArray;
@ -1105,16 +1162,16 @@ static int processCommandInternal(FILE * fp, int * permission,
argArrayLength = buffer2array(commandString, &argArray); argArrayLength = buffer2array(commandString, &argArray);
if(argArrayLength == 0) return 0; if (argArrayLength == 0)
return 0;
if ((cmd = getCommandEntryAndCheckArgcAndPermission(fp, permission, if ((cmd = getCommandEntryAndCheckArgcAndPermission(fp, permission,
argArrayLength,argArray))) argArrayLength,
{ argArray))) {
if (NULL == commandNode || NULL == cmd->listHandler) { if (NULL == commandNode || NULL == cmd->listHandler) {
ret = cmd->handler(fp, permission, argArrayLength, ret = cmd->handler(fp, permission, argArrayLength,
argArray); argArray);
} } else {
else {
ret = cmd->listHandler(fp, permission, argArrayLength, ret = cmd->listHandler(fp, permission, argArrayLength,
argArray, commandNode, cmd); argArray, commandNode, cmd);
} }
@ -1145,8 +1202,10 @@ int processListOfCommands(FILE * fp, int * permission, int * expired,
tempNode = node->nextNode; tempNode = node->nextNode;
deleteNodeFromList(list, node); deleteNodeFromList(list, node);
node = tempNode; node = tempNode;
if(ret!=0 || (*expired)!=0) node = NULL; if (ret != 0 || (*expired) != 0)
else if(listOK) myfprintf(fp, "list_OK\n"); node = NULL;
else if (listOK)
myfprintf(fp, "list_OK\n");
command_listNum++; command_listNum++;
} }
@ -1155,6 +1214,7 @@ int processListOfCommands(FILE * fp, int * permission, int * expired,
return ret; return ret;
} }
int processCommand(FILE * fp, int * permission, char * commandString) { int processCommand(FILE * fp, int *permission, char *commandString)
{
return processCommandInternal(fp, permission, commandString, NULL); return processCommandInternal(fp, permission, commandString, NULL);
} }

View File

@ -49,11 +49,14 @@ typedef struct _configEntry {
static List *configEntriesList = NULL; static List *configEntriesList = NULL;
static ConfigParam * newConfigParam(char * value, int line) { static ConfigParam *newConfigParam(char *value, int line)
{
ConfigParam *ret = malloc(sizeof(ConfigParam)); ConfigParam *ret = malloc(sizeof(ConfigParam));
if(!value) ret->value = NULL; if (!value)
else ret->value = strdup(value); ret->value = NULL;
else
ret->value = strdup(value);
ret->line = line; ret->line = line;
@ -63,10 +66,12 @@ static ConfigParam * newConfigParam(char * value, int line) {
return ret; return ret;
} }
static void freeConfigParam(ConfigParam * param) { static void freeConfigParam(ConfigParam * param)
{
int i; int i;
if(param->value) free(param->value); if (param->value)
free(param->value);
for (i = 0; i < param->numberOfBlockParams; i++) { for (i = 0; i < param->numberOfBlockParams; i++) {
if (param->blockParams[i].name) { if (param->blockParams[i].name) {
@ -77,29 +82,36 @@ static void freeConfigParam(ConfigParam * param) {
} }
} }
if(param->numberOfBlockParams) free(param->blockParams); if (param->numberOfBlockParams)
free(param->blockParams);
free(param); free(param);
} }
ConfigEntry * newConfigEntry(int repeatable, int block) { ConfigEntry *newConfigEntry(int repeatable, int block)
{
ConfigEntry *ret = malloc(sizeof(ConfigEntry)); ConfigEntry *ret = malloc(sizeof(ConfigEntry));
ret->mask = 0; ret->mask = 0;
ret->configParamList = makeList((ListFreeDataFunc *)freeConfigParam, 1); ret->configParamList =
makeList((ListFreeDataFunc *) freeConfigParam, 1);
if(repeatable) ret->mask |= CONF_REPEATABLE_MASK; if (repeatable)
if(block) ret->mask |= CONF_BLOCK_MASK; ret->mask |= CONF_REPEATABLE_MASK;
if (block)
ret->mask |= CONF_BLOCK_MASK;
return ret; return ret;
} }
void freeConfigEntry(ConfigEntry * entry) { void freeConfigEntry(ConfigEntry * entry)
{
freeList(entry->configParamList); freeList(entry->configParamList);
free(entry); free(entry);
} }
static void registerConfigParam(char * name, int repeatable, int block) { static void registerConfigParam(char *name, int repeatable, int block)
{
ConfigEntry *entry; ConfigEntry *entry;
if (findInList(configEntriesList, name, NULL)) { if (findInList(configEntriesList, name, NULL)) {
@ -112,11 +124,13 @@ static void registerConfigParam(char * name, int repeatable, int block) {
insertInList(configEntriesList, name, entry); insertInList(configEntriesList, name, entry);
} }
void finishConf(void) { void finishConf(void)
{
freeList(configEntriesList); freeList(configEntriesList);
} }
void initConf(void) { void initConf(void)
{
configEntriesList = makeList((ListFreeDataFunc *) freeConfigEntry, 1); configEntriesList = makeList((ListFreeDataFunc *) freeConfigEntry, 1);
/* registerConfigParam(name, repeatable, block); */ /* registerConfigParam(name, repeatable, block); */
@ -165,14 +179,17 @@ static void addBlockParam(ConfigParam * param, char * name, char * value,
param->numberOfBlockParams++; param->numberOfBlockParams++;
param->blockParams = realloc(param->blockParams, param->blockParams = realloc(param->blockParams,
param->numberOfBlockParams*sizeof(BlockParam)); param->numberOfBlockParams *
sizeof(BlockParam));
param->blockParams[param->numberOfBlockParams - 1].name = strdup(name); param->blockParams[param->numberOfBlockParams - 1].name = strdup(name);
param->blockParams[param->numberOfBlockParams-1].value = strdup(value); param->blockParams[param->numberOfBlockParams - 1].value =
strdup(value);
param->blockParams[param->numberOfBlockParams - 1].line = line; param->blockParams[param->numberOfBlockParams - 1].line = line;
} }
static ConfigParam * readConfigBlock(FILE * fp, int * count, char * string) { static ConfigParam *readConfigBlock(FILE * fp, int *count, char *string)
{
ConfigParam *ret = newConfigParam(NULL, *count); ConfigParam *ret = newConfigParam(NULL, *count);
char **array; char **array;
@ -186,7 +203,8 @@ static ConfigParam * readConfigBlock(FILE * fp, int * count, char * string) {
numberOfArgs = buffer2array(string, &array); numberOfArgs = buffer2array(string, &array);
for (i = 0; i < numberOfArgs; i++) { for (i = 0; i < numberOfArgs; i++) {
if(array[i][0] == CONF_COMMENT) break; if (array[i][0] == CONF_COMMENT)
break;
} }
argsMinusComment = i; argsMinusComment = i;
@ -197,8 +215,7 @@ static ConfigParam * readConfigBlock(FILE * fp, int * count, char * string) {
} }
if (1 == argsMinusComment && if (1 == argsMinusComment &&
0 == strcmp(array[0], CONF_BLOCK_END)) 0 == strcmp(array[0], CONF_BLOCK_END)) {
{
freeArgArray(array, numberOfArgs); freeArgArray(array, numberOfArgs);
break; break;
} }
@ -212,8 +229,7 @@ static ConfigParam * readConfigBlock(FILE * fp, int * count, char * string) {
if (0 == strcmp(array[0], CONF_BLOCK_BEGIN) || if (0 == strcmp(array[0], CONF_BLOCK_BEGIN) ||
0 == strcmp(array[1], CONF_BLOCK_BEGIN) || 0 == strcmp(array[1], CONF_BLOCK_BEGIN) ||
0 == strcmp(array[0], CONF_BLOCK_END) || 0 == strcmp(array[0], CONF_BLOCK_END) ||
0 == strcmp(array[1], CONF_BLOCK_END)) 0 == strcmp(array[1], CONF_BLOCK_END)) {
{
ERROR("improperly formatted config file at line %i:" ERROR("improperly formatted config file at line %i:"
" %s\n", count, string); " %s\n", count, string);
ERROR("in block begining at line %i\n", ret->line); ERROR("in block begining at line %i\n", ret->line);
@ -228,7 +244,8 @@ static ConfigParam * readConfigBlock(FILE * fp, int * count, char * string) {
return ret; return ret;
} }
void readConf(char * file) { void readConf(char *file)
{
FILE *fp; FILE *fp;
char string[MAX_STRING_SIZE + 1]; char string[MAX_STRING_SIZE + 1];
char **array; char **array;
@ -252,7 +269,8 @@ void readConf(char * file) {
numberOfArgs = buffer2array(string, &array); numberOfArgs = buffer2array(string, &array);
for (i = 0; i < numberOfArgs; i++) { for (i = 0; i < numberOfArgs; i++) {
if(array[i][0] == CONF_COMMENT) break; if (array[i][0] == CONF_COMMENT)
break;
} }
argsMinusComment = i; argsMinusComment = i;
@ -277,12 +295,12 @@ void readConf(char * file) {
entry = (ConfigEntry *) voidPtr; entry = (ConfigEntry *) voidPtr;
if (!(entry->mask & CONF_REPEATABLE_MASK) && if (!(entry->mask & CONF_REPEATABLE_MASK) &&
entry->configParamList->numberOfNodes) entry->configParamList->numberOfNodes) {
{
param = entry->configParamList->firstNode->data; param = entry->configParamList->firstNode->data;
ERROR("config parameter \"%s\" is first defined on line " ERROR
"%i and redefined on line %i\n", ("config parameter \"%s\" is first defined on line "
array[0], param->line, count); "%i and redefined on line %i\n", array[0],
param->line, count);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -293,8 +311,8 @@ void readConf(char * file) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
param = readConfigBlock(fp, &count, string); param = readConfigBlock(fp, &count, string);
} } else
else param = newConfigParam(array[1], count); param = newConfigParam(array[1], count);
insertInListWithoutKey(entry->configParamList, param); insertInListWithoutKey(entry->configParamList, param);
@ -303,13 +321,15 @@ void readConf(char * file) {
fclose(fp); fclose(fp);
} }
ConfigParam * getNextConfigParam(char * name, ConfigParam * last) { ConfigParam *getNextConfigParam(char *name, ConfigParam * last)
{
void *voidPtr; void *voidPtr;
ConfigEntry *entry; ConfigEntry *entry;
ListNode *node; ListNode *node;
ConfigParam *param; ConfigParam *param;
if(!findInList(configEntriesList, name, &voidPtr)) return NULL; if (!findInList(configEntriesList, name, &voidPtr))
return NULL;
entry = voidPtr; entry = voidPtr;
@ -319,26 +339,31 @@ ConfigParam * getNextConfigParam(char * name, ConfigParam * last) {
while (node != NULL) { while (node != NULL) {
param = node->data; param = node->data;
node = node->nextNode; node = node->nextNode;
if(param == last) break; if (param == last)
break;
} }
} }
if(node == NULL) return NULL; if (node == NULL)
return NULL;
param = node->data; param = node->data;
return param; return param;
} }
char * getConfigParamValue(char * name) { char *getConfigParamValue(char *name)
{
ConfigParam *param = getConfigParam(name); ConfigParam *param = getConfigParam(name);
if(!param) return NULL; if (!param)
return NULL;
return param->value; return param->value;
} }
BlockParam * getBlockParam(ConfigParam * param, char * name) { BlockParam *getBlockParam(ConfigParam * param, char *name)
{
BlockParam *ret = NULL; BlockParam *ret = NULL;
int i; int i;
@ -356,7 +381,8 @@ BlockParam * getBlockParam(ConfigParam * param, char * name) {
return ret; return ret;
} }
ConfigParam * parseConfigFilePath(char * name, int force) { ConfigParam *parseConfigFilePath(char *name, int force)
{
ConfigParam *param = getConfigParam(name); ConfigParam *param = getConfigParam(name);
char *path; char *path;
@ -365,7 +391,8 @@ ConfigParam * parseConfigFilePath(char * name, int force) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(!param) return NULL; if (!param)
return NULL;
path = param->value; path = param->value;
@ -390,8 +417,7 @@ ConfigParam * parseConfigFilePath(char * name, int force) {
userParam->line); userParam->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} } else {
else {
uid_t uid = geteuid(); uid_t uid = geteuid();
if ((pwd = getpwuid(uid)) == NULL) { if ((pwd = getpwuid(uid)) == NULL) {
ERROR("problems getting passwd entry " ERROR("problems getting passwd entry "
@ -399,12 +425,12 @@ ConfigParam * parseConfigFilePath(char * name, int force) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
} } else {
else {
int foundSlash = 0; int foundSlash = 0;
char *ch = path + 1; char *ch = path + 1;
for (; *ch != '\0' && *ch != '/'; ch++) ; for (; *ch != '\0' && *ch != '/'; ch++) ;
if(*ch=='/') foundSlash = 1; if (*ch == '/')
foundSlash = 1;
*ch = '\0'; *ch = '\0';
pos += ch - path - 1; pos += ch - path - 1;
if ((pwd = getpwnam(path + 1)) == NULL) { if ((pwd = getpwnam(path + 1)) == NULL) {
@ -412,7 +438,8 @@ ConfigParam * parseConfigFilePath(char * name, int force) {
path + 1, param->line); path + 1, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(foundSlash) *ch = '/'; if (foundSlash)
*ch = '/';
} }
newPath = malloc(strlen(pwd->pw_dir) + strlen(path + pos) + 1); newPath = malloc(strlen(pwd->pw_dir) + strlen(path + pos) + 1);
strcpy(newPath, pwd->pw_dir); strcpy(newPath, pwd->pw_dir);

View File

@ -31,7 +31,6 @@
#define LOCATE_TAG_ANY_TYPE TAG_NUM_OF_ITEM_TYPES+20 #define LOCATE_TAG_ANY_TYPE TAG_NUM_OF_ITEM_TYPES+20
#define LOCATE_TAG_ANY_KEY "any" #define LOCATE_TAG_ANY_KEY "any"
typedef struct _ListCommandItem { typedef struct _ListCommandItem {
mpd_sint8 tagType; mpd_sint8 tagType;
int numConditionals; int numConditionals;
@ -43,7 +42,8 @@ typedef struct _LocateTagItemArray {
LocateTagItem *items; LocateTagItem *items;
} LocateTagItemArray; } LocateTagItemArray;
int getLocateTagItemType(char * str) { int getLocateTagItemType(char *str)
{
int i; int i;
if (0 == strcasecmp(str, LOCATE_TAG_FILE_KEY)) { if (0 == strcasecmp(str, LOCATE_TAG_FILE_KEY)) {
@ -55,25 +55,27 @@ int getLocateTagItemType(char * str) {
} }
for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) { for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) {
if(0 == strcasecmp(str, mpdTagItemKeys[i])) return i; if (0 == strcasecmp(str, mpdTagItemKeys[i]))
return i;
} }
return -1; return -1;
} }
static int initLocateTagItem(LocateTagItem * item, char * typeStr, static int initLocateTagItem(LocateTagItem * item, char *typeStr, char *needle)
char * needle)
{ {
item->tagType = getLocateTagItemType(typeStr); item->tagType = getLocateTagItemType(typeStr);
if(item->tagType < 0) return -1; if (item->tagType < 0)
return -1;
item->needle = strdup(needle); item->needle = strdup(needle);
return 0; return 0;
} }
LocateTagItem * newLocateTagItem(char * typeStr, char * needle) { LocateTagItem *newLocateTagItem(char *typeStr, char *needle)
{
LocateTagItem *ret = malloc(sizeof(LocateTagItem)); LocateTagItem *ret = malloc(sizeof(LocateTagItem));
if (initLocateTagItem(ret, typeStr, needle) < 0) { if (initLocateTagItem(ret, typeStr, needle) < 0) {
@ -84,29 +86,33 @@ LocateTagItem * newLocateTagItem(char * typeStr, char * needle) {
return ret; return ret;
} }
void freeLocateTagItemArray(int count, LocateTagItem * array) { void freeLocateTagItemArray(int count, LocateTagItem * array)
{
int i; int i;
for(i = 0; i < count; i++) free(array[i].needle); for (i = 0; i < count; i++)
free(array[i].needle);
free(array); free(array);
} }
int newLocateTagItemArrayFromArgArray(char *argArray[], int newLocateTagItemArrayFromArgArray(char *argArray[],
int numArgs, int numArgs, LocateTagItem ** arrayRet)
LocateTagItem ** arrayRet)
{ {
int i, j; int i, j;
LocateTagItem *item; LocateTagItem *item;
if(numArgs == 0) return 0; if (numArgs == 0)
return 0;
if(numArgs%2 != 0) return -1; if (numArgs % 2 != 0)
return -1;
*arrayRet = malloc(sizeof(LocateTagItem) * numArgs / 2); *arrayRet = malloc(sizeof(LocateTagItem) * numArgs / 2);
for (i = 0, item = *arrayRet; i < numArgs / 2; i++, item++) { for (i = 0, item = *arrayRet; i < numArgs / 2; i++, item++) {
if(initLocateTagItem(item, argArray[i*2], argArray[i*2+1]) < 0) if (initLocateTagItem
(item, argArray[i * 2], argArray[i * 2 + 1]) < 0)
goto fail; goto fail;
} }
@ -122,12 +128,14 @@ fail:
return -1; return -1;
} }
void freeLocateTagItem(LocateTagItem * item) { void freeLocateTagItem(LocateTagItem * item)
{
free(item->needle); free(item->needle);
free(item); free(item);
} }
static int countSongsInDirectory(FILE * fp, Directory * directory, void * data) { static int countSongsInDirectory(FILE * fp, Directory * directory, void *data)
{
int *count = (int *)data; int *count = (int *)data;
*count += directory->songs->numberOfNodes; *count += directory->songs->numberOfNodes;
@ -135,57 +143,63 @@ static int countSongsInDirectory(FILE * fp, Directory * directory, void * data)
return 0; return 0;
} }
static int printDirectoryInDirectory(FILE * fp, Directory * directory, void * data) { static int printDirectoryInDirectory(FILE * fp, Directory * directory,
void *data)
{
if (directory->path) { if (directory->path) {
myfprintf(fp, "directory: %s\n", getDirectoryPath(directory)); myfprintf(fp, "directory: %s\n", getDirectoryPath(directory));
} }
return 0; return 0;
} }
static int printSongInDirectory(FILE * fp, Song * song, void * data) { static int printSongInDirectory(FILE * fp, Song * song, void *data)
{
printSongUrl(fp, song); printSongUrl(fp, song);
return 0; return 0;
} }
static int strstrSearchTag(Song * song, int type, char * str) { static int strstrSearchTag(Song * song, int type, char *str)
{
int i; int i;
char *dup; char *dup;
int ret = 0; int ret = 0;
if (type == LOCATE_TAG_FILE_TYPE || type == LOCATE_TAG_ANY_TYPE) { if (type == LOCATE_TAG_FILE_TYPE || type == LOCATE_TAG_ANY_TYPE) {
dup = strDupToUpper(getSongUrl(song)); dup = strDupToUpper(getSongUrl(song));
if(strstr(dup, str)) ret = 1; if (strstr(dup, str))
ret = 1;
free(dup); free(dup);
if (ret == 1 || type == LOCATE_TAG_FILE_TYPE) { if (ret == 1 || type == LOCATE_TAG_FILE_TYPE) {
return ret; return ret;
} }
} }
if(!song->tag) return 0; if (!song->tag)
return 0;
for (i = 0; i < song->tag->numOfItems && !ret; i++) { for (i = 0; i < song->tag->numOfItems && !ret; i++) {
if (type != LOCATE_TAG_ANY_TYPE && if (type != LOCATE_TAG_ANY_TYPE &&
song->tag->items[i].type != type) song->tag->items[i].type != type) {
{
continue; continue;
} }
dup = strDupToUpper(song->tag->items[i].value); dup = strDupToUpper(song->tag->items[i].value);
if(strstr(dup, str)) ret = 1; if (strstr(dup, str))
ret = 1;
free(dup); free(dup);
} }
return ret; return ret;
} }
static int searchInDirectory(FILE * fp, Song * song, void * data) { static int searchInDirectory(FILE * fp, Song * song, void *data)
{
LocateTagItemArray *array = data; LocateTagItemArray *array = data;
int i; int i;
for (i = 0; i < array->numItems; i++) { for (i = 0; i < array->numItems; i++) {
if (!strstrSearchTag(song, array->items[i].tagType, if (!strstrSearchTag(song, array->items[i].tagType,
array->items[i].needle)) array->items[i].needle)) {
{
return 0; return 0;
} }
} }
@ -195,8 +209,7 @@ static int searchInDirectory(FILE * fp, Song * song, void * data) {
return 0; return 0;
} }
int searchForSongsIn(FILE * fp, char * name, int numItems, int searchForSongsIn(FILE * fp, char *name, int numItems, LocateTagItem * items)
LocateTagItem * items)
{ {
int ret = -1; int ret = -1;
int i; int i;
@ -224,32 +237,37 @@ int searchForSongsIn(FILE * fp, char * name, int numItems,
return ret; return ret;
} }
static int tagItemFoundAndMatches(Song * song, int type, char * str) { static int tagItemFoundAndMatches(Song * song, int type, char *str)
{
int i; int i;
if (type == LOCATE_TAG_FILE_TYPE) { if (type == LOCATE_TAG_FILE_TYPE) {
if(0 == strcmp(str, getSongUrl(song))) return 1; if (0 == strcmp(str, getSongUrl(song)))
return 1;
} }
if(!song->tag) return 0; if (!song->tag)
return 0;
for (i = 0; i < song->tag->numOfItems; i++) { for (i = 0; i < song->tag->numOfItems; i++) {
if(song->tag->items[i].type != type) continue; if (song->tag->items[i].type != type)
continue;
if(0 == strcmp(str, song->tag->items[i].value)) return 1; if (0 == strcmp(str, song->tag->items[i].value))
return 1;
} }
return 0; return 0;
} }
static int findInDirectory(FILE * fp, Song * song, void * data) { static int findInDirectory(FILE * fp, Song * song, void *data)
{
LocateTagItemArray *array = data; LocateTagItemArray *array = data;
int i; int i;
for (i = 0; i < array->numItems; i++) { for (i = 0; i < array->numItems; i++) {
if (!tagItemFoundAndMatches(song, array->items[i].tagType, if (!tagItemFoundAndMatches(song, array->items[i].tagType,
array->items[i].needle)) array->items[i].needle)) {
{
return 0; return 0;
} }
} }
@ -259,46 +277,55 @@ static int findInDirectory(FILE * fp, Song * song, void * data) {
return 0; return 0;
} }
int findSongsIn(FILE * fp, char * name, int numItems, LocateTagItem * items) { int findSongsIn(FILE * fp, char *name, int numItems, LocateTagItem * items)
{
LocateTagItemArray array; LocateTagItemArray array;
array.numItems = numItems; array.numItems = numItems;
array.items = items; array.items = items;
return traverseAllIn(fp, name, findInDirectory, NULL, return traverseAllIn(fp, name, findInDirectory, NULL, (void *)&array);
(void *)&array);
} }
int printAllIn(FILE * fp, char * name) { int printAllIn(FILE * fp, char *name)
{
return traverseAllIn(fp, name, printSongInDirectory, return traverseAllIn(fp, name, printSongInDirectory,
printDirectoryInDirectory, NULL); printDirectoryInDirectory, NULL);
} }
static int directoryAddSongToPlaylist(FILE * fp, Song * song, void * data) { static int directoryAddSongToPlaylist(FILE * fp, Song * song, void *data)
{
return addSongToPlaylist(fp, song, 0); return addSongToPlaylist(fp, song, 0);
} }
int addAllIn(FILE * fp, char * name) { int addAllIn(FILE * fp, char *name)
{
return traverseAllIn(fp, name, directoryAddSongToPlaylist, NULL, NULL); return traverseAllIn(fp, name, directoryAddSongToPlaylist, NULL, NULL);
} }
static int directoryPrintSongInfo(FILE * fp, Song * song, void * data) { static int directoryPrintSongInfo(FILE * fp, Song * song, void *data)
{
return printSongInfo(fp, song); return printSongInfo(fp, song);
} }
static int sumSongTime(FILE * fp, Song * song, void * data) { static int sumSongTime(FILE * fp, Song * song, void *data)
{
unsigned long *time = (unsigned long *)data; unsigned long *time = (unsigned long *)data;
if(song->tag && song->tag->time>=0) *time+=song->tag->time; if (song->tag && song->tag->time >= 0)
*time += song->tag->time;
return 0; return 0;
} }
int printInfoForAllIn(FILE * fp, char * name) { int printInfoForAllIn(FILE * fp, char *name)
return traverseAllIn(fp,name,directoryPrintSongInfo,printDirectoryInDirectory,NULL); {
return traverseAllIn(fp, name, directoryPrintSongInfo,
printDirectoryInDirectory, NULL);
} }
int countSongsIn(FILE * fp, char * name) { int countSongsIn(FILE * fp, char *name)
{
int count = 0; int count = 0;
void *ptr = (void *)&count; void *ptr = (void *)&count;
@ -307,7 +334,8 @@ int countSongsIn(FILE * fp, char * name) {
return count; return count;
} }
unsigned long sumSongTimesIn(FILE * fp, char * name) { unsigned long sumSongTimesIn(FILE * fp, char *name)
{
unsigned long dbPlayTime = 0; unsigned long dbPlayTime = 0;
void *ptr = (void *)&dbPlayTime; void *ptr = (void *)&dbPlayTime;
@ -328,11 +356,13 @@ static ListCommandItem * newListCommandItem(int tagType, int numConditionals,
return item; return item;
} }
static void freeListCommandItem(ListCommandItem * item) { static void freeListCommandItem(ListCommandItem * item)
{
free(item); free(item);
} }
static void visitTag(FILE * fp, Song * song, int tagType) { static void visitTag(FILE * fp, Song * song, int tagType)
{
int i; int i;
MpdTag *tag = song->tag; MpdTag *tag = song->tag;
@ -341,7 +371,8 @@ static void visitTag(FILE * fp, Song * song, int tagType) {
return; return;
} }
if(!tag) return; if (!tag)
return;
for (i = 0; i < tag->numOfItems; i++) { for (i = 0; i < tag->numOfItems; i++) {
if (tag->items[i].type == tagType) { if (tag->items[i].type == tagType) {
@ -350,14 +381,14 @@ static void visitTag(FILE * fp, Song * song, int tagType) {
} }
} }
static int listUniqueTagsInDirectory(FILE * fp, Song * song, void * data) { static int listUniqueTagsInDirectory(FILE * fp, Song * song, void *data)
{
ListCommandItem *item = data; ListCommandItem *item = data;
int i; int i;
for (i = 0; i < item->numConditionals; i++) { for (i = 0; i < item->numConditionals; i++) {
if (!tagItemFoundAndMatches(song, item->conditionals[i].tagType, if (!tagItemFoundAndMatches(song, item->conditionals[i].tagType,
item->conditionals[i].needle)) item->conditionals[i].needle)) {
{
return 0; return 0;
} }
} }
@ -390,10 +421,13 @@ int listAllUniqueTags(FILE * fp, int type, int numConditionals,
return ret; return ret;
} }
static int sumSavedFilenameMemoryInDirectory(FILE * fp, Directory * dir, void * data) { static int sumSavedFilenameMemoryInDirectory(FILE * fp, Directory * dir,
void *data)
{
int *sum = data; int *sum = data;
if(!dir->path) return 0; if (!dir->path)
return 0;
*sum += (strlen(getDirectoryPath(dir)) + 1 - sizeof(Directory *)) * *sum += (strlen(getDirectoryPath(dir)) + 1 - sizeof(Directory *)) *
dir->songs->numberOfNodes; dir->songs->numberOfNodes;
@ -401,7 +435,8 @@ static int sumSavedFilenameMemoryInDirectory(FILE * fp, Directory * dir, void *
return 0; return 0;
} }
static int sumSavedFilenameMemoryInSong(FILE * fp, Song * song, void * data) { static int sumSavedFilenameMemoryInSong(FILE * fp, Song * song, void *data)
{
int *sum = data; int *sum = data;
*sum += strlen(song->url) + 1; *sum += strlen(song->url) + 1;
@ -409,7 +444,8 @@ static int sumSavedFilenameMemoryInSong(FILE * fp, Song * song, void * data) {
return 0; return 0;
} }
void printSavedMemoryFromFilenames(void) { void printSavedMemoryFromFilenames(void)
{
int sum = 0; int sum = 0;
traverseAllIn(stderr, NULL, sumSavedFilenameMemoryInSong, traverseAllIn(stderr, NULL, sumSavedFilenameMemoryInSong,

View File

@ -39,7 +39,6 @@ LocateTagItem * newLocateTagItem(char * typeString, char * needle);
int newLocateTagItemArrayFromArgArray(char *argArray[], int numArgs, int newLocateTagItemArrayFromArgArray(char *argArray[], int numArgs,
LocateTagItem ** arrayRet); LocateTagItem ** arrayRet);
void freeLocateTagItemArray(int count, LocateTagItem * array); void freeLocateTagItemArray(int count, LocateTagItem * array);
void freeLocateTagItem(LocateTagItem * item); void freeLocateTagItem(LocateTagItem * item);
@ -53,8 +52,7 @@ int printInfoForAllIn(FILE * fp, char * name);
int searchForSongsIn(FILE * fp, char *name, int numItems, int searchForSongsIn(FILE * fp, char *name, int numItems,
LocateTagItem * items); LocateTagItem * items);
int findSongsIn(FILE * fp, char * name, int numItems, int findSongsIn(FILE * fp, char *name, int numItems, LocateTagItem * items);
LocateTagItem * items);
int countSongsIn(FILE * fp, char *name); int countSongsIn(FILE * fp, char *name);

View File

@ -39,40 +39,42 @@
static int decode_pid = 0; static int decode_pid = 0;
void decodeSigHandler(int sig, siginfo_t * si, void * v) { void decodeSigHandler(int sig, siginfo_t * si, void *v)
{
if (sig == SIGCHLD) { if (sig == SIGCHLD) {
int status; int status;
if (decode_pid == wait3(&status, WNOHANG, NULL)) { if (decode_pid == wait3(&status, WNOHANG, NULL)) {
if (WIFSIGNALED(status)) { if (WIFSIGNALED(status)) {
if (WTERMSIG(status) != SIGTERM) { if (WTERMSIG(status) != SIGTERM) {
ERROR("decode process died from " ERROR("decode process died from "
"signal: %i\n", "signal: %i\n", WTERMSIG(status));
WTERMSIG(status));
} }
} }
decode_pid = 0; decode_pid = 0;
getPlayerData()->playerControl.decode_pid = 0; getPlayerData()->playerControl.decode_pid = 0;
} }
} } else if (sig == SIGTERM) {
else if(sig==SIGTERM) {
int pid = decode_pid; int pid = decode_pid;
if (pid > 0) { if (pid > 0) {
DEBUG("player (or child) got SIGTERM\n"); DEBUG("player (or child) got SIGTERM\n");
kill(pid, SIGTERM); kill(pid, SIGTERM);
} } else
else DEBUG("decoder (or child) got SIGTERM\n"); DEBUG("decoder (or child) got SIGTERM\n");
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
} }
static void stopDecode(DecoderControl * dc) { static void stopDecode(DecoderControl * dc)
{
if (decode_pid > 0 && (dc->start || dc->state != DECODE_STATE_STOP)) { if (decode_pid > 0 && (dc->start || dc->state != DECODE_STATE_STOP)) {
dc->stop = 1; dc->stop = 1;
while(decode_pid>0 && dc->stop) my_usleep(10000); while (decode_pid > 0 && dc->stop)
my_usleep(10000);
} }
} }
static void quitDecode(PlayerControl * pc, DecoderControl * dc) { static void quitDecode(PlayerControl * pc, DecoderControl * dc)
{
stopDecode(dc); stopDecode(dc);
pc->metadataState = PLAYER_METADATA_STATE_READ; pc->metadataState = PLAYER_METADATA_STATE_READ;
pc->state = PLAYER_STATE_STOP; pc->state = PLAYER_STATE_STOP;
@ -83,10 +85,12 @@ static void quitDecode(PlayerControl * pc, DecoderControl * dc) {
kill(getppid(), SIGUSR1); kill(getppid(), SIGUSR1);
} }
static int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) { static int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af)
{
long chunks; long chunks;
if(pc->crossFade<=0) return 0; if (pc->crossFade <= 0)
return 0;
chunks = (af->sampleRate * af->bits * af->channels / 8.0 / CHUNK_SIZE); chunks = (af->sampleRate * af->bits * af->channels / 8.0 / CHUNK_SIZE);
chunks = (chunks * pc->crossFade + 0.5); chunks = (chunks * pc->crossFade + 0.5);
@ -95,7 +99,8 @@ static int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) {
chunks = buffered_chunks - buffered_before_play; chunks = buffered_chunks - buffered_before_play;
} }
if(chunks<0) chunks = 0; if (chunks < 0)
chunks = 0;
return (int)chunks; return (int)chunks;
} }
@ -136,14 +141,15 @@ static int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) {
} \ } \
} }
static int waitOnDecode(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb, static int waitOnDecode(PlayerControl * pc, DecoderControl * dc,
int * decodeWaitedOn) OutputBuffer * cb, int *decodeWaitedOn)
{ {
MpdTag *tag = NULL; MpdTag *tag = NULL;
strncpy(pc->currentUrl, pc->utf8url, MAXPATHLEN); strncpy(pc->currentUrl, pc->utf8url, MAXPATHLEN);
pc->currentUrl[MAXPATHLEN] = '\0'; pc->currentUrl[MAXPATHLEN] = '\0';
while(decode_pid>0 && dc->start) my_usleep(10000); while (decode_pid > 0 && dc->start)
my_usleep(10000);
if (dc->start || dc->error != DECODE_ERROR_NOERROR) { if (dc->start || dc->error != DECODE_ERROR_NOERROR) {
strncpy(pc->erroredUrl, pc->utf8url, MAXPATHLEN); strncpy(pc->erroredUrl, pc->utf8url, MAXPATHLEN);
@ -168,15 +174,14 @@ static int waitOnDecode(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
return 0; return 0;
} }
static int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb, static int decodeSeek(PlayerControl * pc, DecoderControl * dc,
int * decodeWaitedOn, int * next) OutputBuffer * cb, int *decodeWaitedOn, int *next)
{ {
int ret = -1; int ret = -1;
if (decode_pid > 0) { if (decode_pid > 0) {
if (dc->state == DECODE_STATE_STOP || dc->error || if (dc->state == DECODE_STATE_STOP || dc->error ||
strcmp(dc->utf8url, pc->utf8url)!=0) strcmp(dc->utf8url, pc->utf8url) != 0) {
{
stopDecode(dc); stopDecode(dc);
*next = -1; *next = -1;
cb->begin = 0; cb->begin = 0;
@ -186,16 +191,15 @@ static int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb
waitOnDecode(pc, dc, cb, decodeWaitedOn); waitOnDecode(pc, dc, cb, decodeWaitedOn);
} }
if (decode_pid > 0 && dc->state != DECODE_STATE_STOP && if (decode_pid > 0 && dc->state != DECODE_STATE_STOP &&
dc->seekable) dc->seekable) {
{
*next = -1; *next = -1;
dc->seekWhere = pc->seekWhere > pc->totalTime - 0.1 ? dc->seekWhere = pc->seekWhere > pc->totalTime - 0.1 ?
pc->totalTime-0.1 : pc->totalTime - 0.1 : pc->seekWhere;
pc->seekWhere;
dc->seekWhere = 0 > dc->seekWhere ? 0 : dc->seekWhere; dc->seekWhere = 0 > dc->seekWhere ? 0 : dc->seekWhere;
dc->seekError = 0; dc->seekError = 0;
dc->seek = 1; dc->seek = 1;
while(decode_pid>0 && dc->seek) my_usleep(10000); while (decode_pid > 0 && dc->seek)
my_usleep(10000);
if (!dc->seekError) { if (!dc->seekError) {
pc->elapsedTime = dc->seekWhere; pc->elapsedTime = dc->seekWhere;
ret = 0; ret = 0;
@ -256,7 +260,9 @@ static int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb
return; \ return; \
} }
static void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
DecoderControl * dc)
{
int ret; int ret;
InputStream inStream; InputStream inStream;
InputPlugin *plugin = NULL; InputPlugin *plugin = NULL;
@ -265,8 +271,7 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl *
if (isRemoteUrl(pc->utf8url)) { if (isRemoteUrl(pc->utf8url)) {
path = utf8StrToLatin1Dup(pc->utf8url); path = utf8StrToLatin1Dup(pc->utf8url);
} } else {
else {
relativePath = utf8ToFsCharset(pc->utf8url); relativePath = utf8ToFsCharset(pc->utf8url);
path = strdup(rmp2amp(relativePath)); path = strdup(rmp2amp(relativePath));
free(relativePath); free(relativePath);
@ -297,8 +302,7 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl *
dc->start = 0; dc->start = 0;
while (!inputStreamAtEOF(&inStream) && bufferInputStream(&inStream) < 0 while (!inputStreamAtEOF(&inStream) && bufferInputStream(&inStream) < 0
&& !dc->stop) && !dc->stop) {
{
/* sleep so we don't consume 100% of the cpu */ /* sleep so we don't consume 100% of the cpu */
my_usleep(1000); my_usleep(1000);
} }
@ -325,14 +329,15 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl *
cb->acceptMetadata = 1; cb->acceptMetadata = 1;
/* first we try mime types: */ /* first we try mime types: */
while(ret && (plugin = getInputPluginFromMimeType( while (ret
inStream.mime, next++))) { && (plugin =
getInputPluginFromMimeType(inStream.mime, next++))) {
if (!plugin->streamDecodeFunc) if (!plugin->streamDecodeFunc)
continue; continue;
if (!(plugin->streamTypes & INPUT_PLUGIN_STREAM_URL)) if (!(plugin->streamTypes & INPUT_PLUGIN_STREAM_URL))
continue; continue;
if(plugin->tryDecodeFunc && !plugin->tryDecodeFunc( if (plugin->tryDecodeFunc
&inStream)) && !plugin->tryDecodeFunc(&inStream))
continue; continue;
ret = plugin->streamDecodeFunc(cb, dc, &inStream); ret = plugin->streamDecodeFunc(cb, dc, &inStream);
break; break;
@ -342,19 +347,19 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl *
if (plugin == NULL) { if (plugin == NULL) {
char *s = getSuffix(dc->utf8url); char *s = getSuffix(dc->utf8url);
next = 0; next = 0;
while(ret && (plugin = getInputPluginFromSuffix( while (ret
s, next++))) { && (plugin =
getInputPluginFromSuffix(s, next++))) {
if (!plugin->streamDecodeFunc) if (!plugin->streamDecodeFunc)
continue; continue;
if (!(plugin->streamTypes & if (!(plugin->streamTypes &
INPUT_PLUGIN_STREAM_URL)) INPUT_PLUGIN_STREAM_URL))
continue; continue;
if (plugin->tryDecodeFunc && if (plugin->tryDecodeFunc &&
!plugin->tryDecodeFunc( !plugin->tryDecodeFunc(&inStream))
&inStream))
continue; continue;
ret = plugin->streamDecodeFunc( ret =
cb, dc, &inStream); plugin->streamDecodeFunc(cb, dc, &inStream);
break; break;
} }
} }
@ -368,27 +373,24 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl *
ret = plugin->streamDecodeFunc(cb, dc, ret = plugin->streamDecodeFunc(cb, dc,
&inStream); &inStream);
} }
} } else {
else {
unsigned int next = 0; unsigned int next = 0;
char *s = getSuffix(dc->utf8url); char *s = getSuffix(dc->utf8url);
cb->acceptMetadata = 0; cb->acceptMetadata = 0;
while (ret && (plugin = getInputPluginFromSuffix(s, next++))) { while (ret && (plugin = getInputPluginFromSuffix(s, next++))) {
if (!plugin->streamTypes & INPUT_PLUGIN_STREAM_FILE) if (!plugin->streamTypes & INPUT_PLUGIN_STREAM_FILE)
continue; continue;
if(plugin->tryDecodeFunc && !plugin->tryDecodeFunc( if (plugin->tryDecodeFunc
&inStream)) && !plugin->tryDecodeFunc(&inStream))
continue; continue;
if (plugin->streamDecodeFunc) { if (plugin->streamDecodeFunc) {
ret = plugin->streamDecodeFunc( ret =
cb, dc, &inStream); plugin->streamDecodeFunc(cb, dc, &inStream);
break; break;
} } else if (plugin->fileDecodeFunc) {
else if(plugin->fileDecodeFunc) {
closeInputStream(&inStream); closeInputStream(&inStream);
ret = plugin->fileDecodeFunc( ret = plugin->fileDecodeFunc(cb, dc, path);
cb, dc, path);
} }
} }
} }
@ -396,7 +398,8 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl *
if (ret < 0 || ret == DECODE_ERROR_UNKTYPE) { if (ret < 0 || ret == DECODE_ERROR_UNKTYPE) {
strncpy(pc->erroredUrl, dc->utf8url, MAXPATHLEN); strncpy(pc->erroredUrl, dc->utf8url, MAXPATHLEN);
pc->erroredUrl[MAXPATHLEN] = '\0'; pc->erroredUrl[MAXPATHLEN] = '\0';
if(ret != DECODE_ERROR_UNKTYPE) dc->error = DECODE_ERROR_FILE; if (ret != DECODE_ERROR_UNKTYPE)
dc->error = DECODE_ERROR_FILE;
else { else {
dc->error = DECODE_ERROR_UNKTYPE; dc->error = DECODE_ERROR_UNKTYPE;
closeInputStream(&inStream); closeInputStream(&inStream);
@ -408,7 +411,9 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl *
free(path); free(path);
} }
static int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { static int decoderInit(PlayerControl * pc, OutputBuffer * cb,
DecoderControl * dc)
{
blockSignals(); blockSignals();
getPlayerData()->playerControl.decode_pid = 0; getPlayerData()->playerControl.decode_pid = 0;
decode_pid = fork(); decode_pid = fork();
@ -421,19 +426,18 @@ static int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * d
if (dc->cycleLogFiles) { if (dc->cycleLogFiles) {
myfprintfCloseAndOpenLogFile(); myfprintfCloseAndOpenLogFile();
dc->cycleLogFiles = 0; dc->cycleLogFiles = 0;
} } else if (dc->start || dc->seek)
else if(dc->start || dc->seek) decodeStart(pc, cb, dc); decodeStart(pc, cb, dc);
else if (dc->stop) { else if (dc->stop) {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
} } else
else my_usleep(10000); my_usleep(10000);
} }
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
/* END OF CHILD */ /* END OF CHILD */
} } else if (decode_pid < 0) {
else if(decode_pid<0) {
unblockSignals(); unblockSignals();
strncpy(pc->erroredUrl, pc->utf8url, MAXPATHLEN); strncpy(pc->erroredUrl, pc->utf8url, MAXPATHLEN);
pc->erroredUrl[MAXPATHLEN] = '\0'; pc->erroredUrl[MAXPATHLEN] = '\0';
@ -466,8 +470,7 @@ static void handleMetadata(OutputBuffer * cb, PlayerControl * pc, int * previous
*previous = meta; *previous = meta;
} }
if (!(*currentChunkSent) && pc->metadataState == if (!(*currentChunkSent) && pc->metadataState ==
PLAYER_METADATA_STATE_WRITE) PLAYER_METADATA_STATE_WRITE) {
{
MpdTag *tag = NULL; MpdTag *tag = NULL;
*currentChunkSent = 1; *currentChunkSent = 1;
@ -485,8 +488,8 @@ static void handleMetadata(OutputBuffer * cb, PlayerControl * pc, int * previous
} }
static void advanceOutputBufferTo(OutputBuffer * cb, PlayerControl * pc, static void advanceOutputBufferTo(OutputBuffer * cb, PlayerControl * pc,
int * previous, int * currentChunkSent, MetadataChunk * currentChunk, int *previous, int *currentChunkSent,
int to) MetadataChunk * currentChunk, int to)
{ {
while (cb->begin != to) { while (cb->begin != to) {
handleMetadata(cb, pc, previous, currentChunkSent, handleMetadata(cb, pc, previous, currentChunkSent,
@ -498,7 +501,8 @@ static void advanceOutputBufferTo(OutputBuffer * cb, PlayerControl * pc,
} }
} }
void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb)
{
int pause = 0; int pause = 0;
int quit = 0; int quit = 0;
int bbp = buffered_before_play; int bbp = buffered_before_play;
@ -518,7 +522,8 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
memset(silence, 0, CHUNK_SIZE); memset(silence, 0, CHUNK_SIZE);
if(waitOnDecode(pc,dc,cb,&decodeWaitedOn)<0) return; if (waitOnDecode(pc, dc, cb, &decodeWaitedOn) < 0)
return;
pc->elapsedTime = 0; pc->elapsedTime = 0;
pc->state = PLAYER_STATE_PLAY; pc->state = PLAYER_STATE_PLAY;
@ -527,8 +532,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
while (decode_pid > 0 && cb->end - cb->begin < bbp && while (decode_pid > 0 && cb->end - cb->begin < bbp &&
cb->end != buffered_chunks - 1 && cb->end != buffered_chunks - 1 &&
dc->state!=DECODE_STATE_STOP) dc->state != DECODE_STATE_STOP) {
{
processDecodeInput(); processDecodeInput();
my_usleep(1000); my_usleep(1000);
} }
@ -540,36 +544,35 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
&currentChunkSent, &currentMetadataChunk); &currentChunkSent, &currentMetadataChunk);
if (dc->state == DECODE_STATE_STOP && if (dc->state == DECODE_STATE_STOP &&
pc->queueState == PLAYER_QUEUE_FULL && pc->queueState == PLAYER_QUEUE_FULL &&
pc->queueLockState==PLAYER_QUEUE_UNLOCKED) pc->queueLockState == PLAYER_QUEUE_UNLOCKED) {
{
next = cb->end; next = cb->end;
dc->start = 1; dc->start = 1;
pc->queueState = PLAYER_QUEUE_DECODE; pc->queueState = PLAYER_QUEUE_DECODE;
kill(getppid(), SIGUSR1); kill(getppid(), SIGUSR1);
} }
if (next >= 0 && doCrossFade == 0 && !dc->start && if (next >= 0 && doCrossFade == 0 && !dc->start &&
dc->state!=DECODE_STATE_START) dc->state != DECODE_STATE_START) {
{
nextChunk = -1; nextChunk = -1;
if (isCurrentAudioFormat(&(cb->audioFormat))) { if (isCurrentAudioFormat(&(cb->audioFormat))) {
doCrossFade = 1; doCrossFade = 1;
crossFadeChunks = crossFadeChunks =
calculateCrossFadeChunks(pc, calculateCrossFadeChunks(pc,
&(cb->audioFormat)); &(cb->
if(!crossFadeChunks || audioFormat));
pc->crossFade>=dc->totalTime) if (!crossFadeChunks
{ || pc->crossFade >= dc->totalTime) {
doCrossFade = -1; doCrossFade = -1;
} }
} } else
else doCrossFade = -1; doCrossFade = -1;
} }
/* copy these to local variables to prevent any potential /* copy these to local variables to prevent any potential
race conditions and weirdness */ race conditions and weirdness */
end = cb->end; end = cb->end;
if(pause) my_usleep(10000); if (pause)
my_usleep(10000);
else if (cb->begin != end && cb->begin != next) { else if (cb->begin != end && cb->begin != next) {
if (doCrossFade == 1 && next >= 0 && if (doCrossFade == 1 && next >= 0 &&
((next > cb->begin && ((next > cb->begin &&
@ -577,44 +580,38 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
<= crossFadeChunks) || <= crossFadeChunks) ||
(cb->begin > next && (cb->begin > next &&
(fadePosition = next - cb->begin + (fadePosition = next - cb->begin +
buffered_chunks)<=crossFadeChunks))) buffered_chunks) <= crossFadeChunks))) {
{
if (nextChunk < 0) { if (nextChunk < 0) {
crossFadeChunks = fadePosition; crossFadeChunks = fadePosition;
} }
test = end; test = end;
if(end < cb->begin) test+=buffered_chunks; if (end < cb->begin)
test += buffered_chunks;
nextChunk = cb->begin + crossFadeChunks; nextChunk = cb->begin + crossFadeChunks;
if (nextChunk < test) { if (nextChunk < test) {
if(nextChunk>=buffered_chunks) if (nextChunk >= buffered_chunks) {
{
nextChunk -= buffered_chunks; nextChunk -= buffered_chunks;
} }
pcm_mix(cb->chunks+cb->begin*CHUNK_SIZE, pcm_mix(cb->chunks +
cb->chunks+nextChunk* cb->begin * CHUNK_SIZE,
CHUNK_SIZE, cb->chunks +
cb->chunkSize[ nextChunk * CHUNK_SIZE,
cb->begin], cb->chunkSize[cb->begin],
cb->chunkSize[ cb->chunkSize[nextChunk],
nextChunk],
&(cb->audioFormat), &(cb->audioFormat),
((float)fadePosition) / ((float)fadePosition) /
crossFadeChunks); crossFadeChunks);
if (cb->chunkSize[nextChunk] > if (cb->chunkSize[nextChunk] >
cb->chunkSize[cb->begin] cb->chunkSize[cb->begin]
) ) {
{
cb->chunkSize[cb->begin] cb->chunkSize[cb->begin]
= cb->chunkSize = cb->chunkSize[nextChunk];
[nextChunk];
} }
} } else {
else { if (dc->state == DECODE_STATE_STOP) {
if(dc->state==DECODE_STATE_STOP)
{
doCrossFade = -1; doCrossFade = -1;
} } else
else continue; continue;
} }
} }
pc->elapsedTime = cb->times[cb->begin]; pc->elapsedTime = cb->times[cb->begin];
@ -625,24 +622,23 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
&(cb->audioFormat), &(cb->audioFormat),
pc->softwareVolume); pc->softwareVolume);
if (playAudio(cb->chunks + cb->begin * CHUNK_SIZE, if (playAudio(cb->chunks + cb->begin * CHUNK_SIZE,
cb->chunkSize[cb->begin])<0) cb->chunkSize[cb->begin]) < 0) {
{
quit = 1; quit = 1;
} }
pc->totalPlayTime+= sizeToTime*cb->chunkSize[cb->begin]; pc->totalPlayTime +=
sizeToTime * cb->chunkSize[cb->begin];
if (cb->begin + 1 >= buffered_chunks) { if (cb->begin + 1 >= buffered_chunks) {
cb->begin = 0; cb->begin = 0;
} } else
else cb->begin++; cb->begin++;
} } else if (next == cb->begin) {
else if(next==cb->begin) {
if (doCrossFade == 1 && nextChunk >= 0) { if (doCrossFade == 1 && nextChunk >= 0) {
nextChunk = cb->begin + crossFadeChunks; nextChunk = cb->begin + crossFadeChunks;
test = cb->end; test = cb->end;
if(end < cb->begin) test+=buffered_chunks; if (end < cb->begin)
test += buffered_chunks;
if (nextChunk < test) { if (nextChunk < test) {
if(nextChunk>=buffered_chunks) if (nextChunk >= buffered_chunks) {
{
nextChunk -= buffered_chunks; nextChunk -= buffered_chunks;
} }
advanceOutputBufferTo(cb, pc, advanceOutputBufferTo(cb, pc,
@ -653,8 +649,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
} }
} }
while (pc->queueState == PLAYER_QUEUE_DECODE || while (pc->queueState == PLAYER_QUEUE_DECODE ||
pc->queueLockState==PLAYER_QUEUE_LOCKED) pc->queueLockState == PLAYER_QUEUE_LOCKED) {
{
processDecodeInput(); processDecodeInput();
if (quit) { if (quit) {
quitDecode(pc, dc); quitDecode(pc, dc);
@ -665,10 +660,10 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
if (pc->queueState != PLAYER_QUEUE_PLAY) { if (pc->queueState != PLAYER_QUEUE_PLAY) {
quit = 1; quit = 1;
break; break;
} } else {
else {
next = -1; next = -1;
if(waitOnDecode(pc,dc,cb,&decodeWaitedOn)<0) { if (waitOnDecode(pc, dc, cb, &decodeWaitedOn) <
0) {
return; return;
} }
nextChunk = -1; nextChunk = -1;
@ -677,15 +672,13 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
pc->queueState = PLAYER_QUEUE_EMPTY; pc->queueState = PLAYER_QUEUE_EMPTY;
kill(getppid(), SIGUSR1); kill(getppid(), SIGUSR1);
} }
} } else if (decode_pid <= 0 ||
else if(decode_pid<=0 || (dc->state == DECODE_STATE_STOP && !dc->start)) {
(dc->state==DECODE_STATE_STOP && !dc->start))
{
quit = 1; quit = 1;
break; break;
} } else {
else { if (playAudio(silence, CHUNK_SIZE) < 0)
if(playAudio(silence, CHUNK_SIZE) < 0) quit = 1; quit = 1;
} }
} }
@ -697,7 +690,8 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
* child process does decoding * child process does decoding
* parent process does playing audio * parent process does playing audio
*/ */
void decode() { void decode()
{
OutputBuffer *cb; OutputBuffer *cb;
PlayerControl *pc; PlayerControl *pc;
DecoderControl *dc; DecoderControl *dc;
@ -715,7 +709,8 @@ void decode() {
dc->start = 1; dc->start = 1;
if (decode_pid <= 0) { if (decode_pid <= 0) {
if(decoderInit(pc,cb,dc)<0) return; if (decoderInit(pc, cb, dc) < 0)
return;
} }
decodeParent(pc, dc, cb); decodeParent(pc, dc, cb);

File diff suppressed because it is too large Load Diff

View File

@ -67,8 +67,7 @@ time_t getDbModTime();
int traverseAllIn(FILE * fp, char *name, int traverseAllIn(FILE * fp, char *name,
int (*forEachSong) (FILE *, Song *, void *), int (*forEachSong) (FILE *, Song *, void *),
int (*forEachDir)(FILE *, Directory *, void *), int (*forEachDir) (FILE *, Directory *, void *), void *data);
void * data);
#define getDirectoryPath(dir) ((dir && dir->path) ? dir->path : "") #define getDirectoryPath(dir) ((dir && dir->path) ? dir->path : "")

View File

@ -26,39 +26,51 @@
static List *inputPlugin_list = NULL; static List *inputPlugin_list = NULL;
void loadInputPlugin(InputPlugin * inputPlugin) { void loadInputPlugin(InputPlugin * inputPlugin)
if(!inputPlugin) return; {
if(!inputPlugin->name) return; if (!inputPlugin)
return;
if (!inputPlugin->name)
return;
if(inputPlugin->initFunc && inputPlugin->initFunc() < 0) return; if (inputPlugin->initFunc && inputPlugin->initFunc() < 0)
return;
insertInList(inputPlugin_list, inputPlugin->name, (void *)inputPlugin); insertInList(inputPlugin_list, inputPlugin->name, (void *)inputPlugin);
} }
void unloadInputPlugin(InputPlugin * inputPlugin) { void unloadInputPlugin(InputPlugin * inputPlugin)
if(inputPlugin->finishFunc) inputPlugin->finishFunc(); {
if (inputPlugin->finishFunc)
inputPlugin->finishFunc();
deleteFromList(inputPlugin_list, inputPlugin->name); deleteFromList(inputPlugin_list, inputPlugin->name);
} }
static int stringFoundInStringArray(char ** array, char * suffix) { static int stringFoundInStringArray(char **array, char *suffix)
{
while (array && *array) { while (array && *array) {
if(strcasecmp(*array, suffix) == 0) return 1; if (strcasecmp(*array, suffix) == 0)
return 1;
array++; array++;
} }
return 0; return 0;
} }
InputPlugin * getInputPluginFromSuffix(char * suffix, unsigned int next) { InputPlugin *getInputPluginFromSuffix(char *suffix, unsigned int next)
{
static ListNode *pos = NULL; static ListNode *pos = NULL;
ListNode *node; ListNode *node;
InputPlugin *plugin; InputPlugin *plugin;
if(suffix == NULL) return NULL; if (suffix == NULL)
return NULL;
if (next) { if (next) {
if (pos) node = pos; if (pos)
else return NULL; node = pos;
else
return NULL;
} else } else
node = inputPlugin_list->firstNode; node = inputPlugin_list->firstNode;
@ -74,12 +86,14 @@ InputPlugin * getInputPluginFromSuffix(char * suffix, unsigned int next) {
return NULL; return NULL;
} }
InputPlugin * getInputPluginFromMimeType(char * mimeType, unsigned int next) { InputPlugin *getInputPluginFromMimeType(char *mimeType, unsigned int next)
{
static ListNode *pos = NULL; static ListNode *pos = NULL;
ListNode *node; ListNode *node;
InputPlugin *plugin; InputPlugin *plugin;
if(mimeType == NULL) return NULL; if (mimeType == NULL)
return NULL;
node = (next && pos) ? pos : inputPlugin_list->firstNode; node = (next && pos) ? pos : inputPlugin_list->firstNode;
@ -95,7 +109,8 @@ InputPlugin * getInputPluginFromMimeType(char * mimeType, unsigned int next) {
return NULL; return NULL;
} }
InputPlugin * getInputPluginFromName(char * name) { InputPlugin *getInputPluginFromName(char *name)
{
void *plugin = NULL; void *plugin = NULL;
findInList(inputPlugin_list, name, &plugin); findInList(inputPlugin_list, name, &plugin);
@ -103,7 +118,8 @@ InputPlugin * getInputPluginFromName(char * name) {
return (InputPlugin *) plugin; return (InputPlugin *) plugin;
} }
void printAllInputPluginSuffixes(FILE * fp) { void printAllInputPluginSuffixes(FILE * fp)
{
ListNode *node = inputPlugin_list->firstNode; ListNode *node = inputPlugin_list->firstNode;
InputPlugin *plugin; InputPlugin *plugin;
char **suffixes; char **suffixes;
@ -130,7 +146,8 @@ extern InputPlugin mpcPlugin;
extern InputPlugin aacPlugin; extern InputPlugin aacPlugin;
extern InputPlugin modPlugin; extern InputPlugin modPlugin;
void initInputPlugins(void) { void initInputPlugins(void)
{
inputPlugin_list = makeList(NULL, 1); inputPlugin_list = makeList(NULL, 1);
/* load plugins here */ /* load plugins here */
@ -144,6 +161,7 @@ void initInputPlugins(void) {
loadInputPlugin(&modPlugin); loadInputPlugin(&modPlugin);
} }
void finishInputPlugins(void) { void finishInputPlugins(void)
{
freeList(inputPlugin_list); freeList(inputPlugin_list);
} }

View File

@ -55,8 +55,8 @@ void init_FlacData (FlacData * data, OutputBuffer * cb,
static int flacFindVorbisCommentFloat(const FLAC__StreamMetadata * block, static int flacFindVorbisCommentFloat(const FLAC__StreamMetadata * block,
char *cmnt, float *fl) char *cmnt, float *fl)
{ {
int offset = FLAC__metadata_object_vorbiscomment_find_entry_from( int offset =
block,0,cmnt); FLAC__metadata_object_vorbiscomment_find_entry_from(block, 0, cmnt);
if (offset >= 0) { if (offset >= 0) {
size_t pos = strlen(cmnt) + 1; /* 1 is for '=' */ size_t pos = strlen(cmnt) + 1; /* 1 is for '=' */
@ -80,7 +80,8 @@ static int flacFindVorbisCommentFloat(const FLAC__StreamMetadata * block,
/* replaygain stuff by AliasMrJones */ /* replaygain stuff by AliasMrJones */
static void flacParseReplayGain(const FLAC__StreamMetadata * block, static void flacParseReplayGain(const FLAC__StreamMetadata * block,
FlacData * data) { FlacData * data)
{
unsigned int found = 0; unsigned int found = 0;
if (data->replayGainInfo) if (data->replayGainInfo)
@ -108,9 +109,9 @@ static void flacParseReplayGain(const FLAC__StreamMetadata *block,
static const char *VORBIS_COMMENT_TRACK_KEY = "tracknumber"; static const char *VORBIS_COMMENT_TRACK_KEY = "tracknumber";
static const char *VORBIS_COMMENT_DISC_KEY = "discnumber"; static const char *VORBIS_COMMENT_DISC_KEY = "discnumber";
static unsigned int commentMatchesAddToTag( static unsigned int commentMatchesAddToTag(const
const FLAC__StreamMetadata_VorbisComment_Entry * entry, FLAC__StreamMetadata_VorbisComment_Entry
unsigned int itemType, * entry, unsigned int itemType,
MpdTag ** tag) MpdTag ** tag)
{ {
const char *str; const char *str;
@ -118,9 +119,14 @@ static unsigned int commentMatchesAddToTag(
int vlen; int vlen;
switch (itemType) { switch (itemType) {
case TAG_ITEM_TRACK: str = VORBIS_COMMENT_TRACK_KEY; break; case TAG_ITEM_TRACK:
case TAG_ITEM_DISC: str = VORBIS_COMMENT_DISC_KEY; break; str = VORBIS_COMMENT_TRACK_KEY;
default: str = mpdTagItemKeys[itemType]; break;
case TAG_ITEM_DISC:
str = VORBIS_COMMENT_DISC_KEY;
break;
default:
str = mpdTagItemKeys[itemType];
} }
slen = strlen(str); slen = strlen(str);
vlen = entry->length - slen - 1; vlen = entry->length - slen - 1;
@ -158,7 +164,8 @@ MpdTag * copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
return tag; return tag;
} }
void flac_metadata_common_cb(const FLAC__StreamMetadata *block, FlacData *data) void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
FlacData * data)
{ {
DecoderControl *dc = data->dc; DecoderControl *dc = data->dc;
const FLAC__StreamMetadata_StreamInfo *si = &(block->data.stream_info); const FLAC__StreamMetadata_StreamInfo *si = &(block->data.stream_info);
@ -183,7 +190,8 @@ void flac_error_common_cb( const char * plugin,
const FLAC__StreamDecoderErrorStatus status, const FLAC__StreamDecoderErrorStatus status,
FlacData * data) FlacData * data)
{ {
if(data->dc->stop) return; if (data->dc->stop)
return;
switch (status) { switch (status) {
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC: case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:

View File

@ -64,15 +64,15 @@ MpdTag * copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
static inline int flacSendChunk(FlacData * data) static inline int flacSendChunk(FlacData * data)
{ {
if (sendDataToOutputBuffer(data->cb, NULL, data->dc, 1, data->chunk, if (sendDataToOutputBuffer(data->cb, NULL, data->dc, 1, data->chunk,
data->chunk_length, data->time, data->bitRate, data->chunk_length, data->time,
data->replayGainInfo) == OUTPUT_BUFFER_DC_STOP) data->bitRate,
data->replayGainInfo) ==
OUTPUT_BUFFER_DC_STOP)
return -1; return -1;
return 0; return 0;
} }
#endif /* HAVE_FLAC || HAVE_OGGFLAC */ #endif /* HAVE_FLAC || HAVE_OGGFLAC */
#endif /* _FLAC_COMMON_H */ #endif /* _FLAC_COMMON_H */

View File

@ -51,15 +51,23 @@ ogg_stream_type ogg_stream_type_detect(InputStream * inStream)
seekInputStream(inStream, 0, SEEK_SET); seekInputStream(inStream, 0, SEEK_SET);
if (r >= 32 && memcmp(buf, "OggS", 4) == 0 && ( if (r >= 32 && memcmp(buf, "OggS", 4) == 0 && ((memcmp
(memcmp(buf+29, "FLAC", 4) == 0 (buf + 29, "FLAC",
&& memcmp(buf+37, "fLaC", 4) == 0) 4) == 0
|| (memcmp(buf+28, "FLAC", 4) == 0) && memcmp(buf + 37,
|| (memcmp(buf+28, "fLaC", 4) == 0))) { "fLaC",
4) == 0)
||
(memcmp
(buf + 28, "FLAC",
4) == 0)
||
(memcmp
(buf + 28, "fLaC",
4) == 0))) {
return FLAC; return FLAC;
} }
return VORBIS; return VORBIS;
} }
#endif /* defined(HAVE_OGGFLAC || defined(HAVE_OGGVORBIS) */ #endif /* defined(HAVE_OGGFLAC || defined(HAVE_OGGVORBIS) */

View File

@ -44,27 +44,33 @@ typedef struct {
int atEof; int atEof;
} AacBuffer; } AacBuffer;
static void fillAacBuffer(AacBuffer *b) { static void fillAacBuffer(AacBuffer * b)
{
if (b->bytesConsumed > 0) { if (b->bytesConsumed > 0) {
int bread; int bread;
if (b->bytesIntoBuffer) { if (b->bytesIntoBuffer) {
memmove((void *)b->buffer, (void *)(b->buffer + memmove((void *)b->buffer, (void *)(b->buffer +
b->bytesConsumed),b->bytesIntoBuffer); b->bytesConsumed),
b->bytesIntoBuffer);
} }
if (!b->atEof) { if (!b->atEof) {
bread = readFromInputStream(b->inStream, bread = readFromInputStream(b->inStream,
(void *)(b->buffer+b->bytesIntoBuffer), (void *)(b->buffer +
b->
bytesIntoBuffer),
1, b->bytesConsumed); 1, b->bytesConsumed);
if(bread!=b->bytesConsumed) b->atEof = 1; if (bread != b->bytesConsumed)
b->atEof = 1;
b->bytesIntoBuffer += bread; b->bytesIntoBuffer += bread;
} }
b->bytesConsumed = 0; b->bytesConsumed = 0;
if (b->bytesIntoBuffer > 3) { if (b->bytesIntoBuffer > 3) {
if(memcmp(b->buffer,"TAG",3)==0) b->bytesIntoBuffer = 0; if (memcmp(b->buffer, "TAG", 3) == 0)
b->bytesIntoBuffer = 0;
} }
if (b->bytesIntoBuffer > 11) { if (b->bytesIntoBuffer > 11) {
if (memcmp(b->buffer, "LYRICSBEGIN", 11) == 0) { if (memcmp(b->buffer, "LYRICSBEGIN", 11) == 0) {
@ -79,16 +85,20 @@ static void fillAacBuffer(AacBuffer *b) {
} }
} }
static void advanceAacBuffer(AacBuffer * b, int bytes) { static void advanceAacBuffer(AacBuffer * b, int bytes)
{
b->fileOffset += bytes; b->fileOffset += bytes;
b->bytesConsumed = bytes; b->bytesConsumed = bytes;
b->bytesIntoBuffer -= bytes; b->bytesIntoBuffer -= bytes;
} }
static int adtsSampleRates[] = {96000,88200,64000,48000,44100,32000,24000,22050, static int adtsSampleRates[] =
16000,12000,11025,8000,7350,0,0,0}; { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
16000, 12000, 11025, 8000, 7350, 0, 0, 0
};
static int adtsParse(AacBuffer * b, float * length) { static int adtsParse(AacBuffer * b, float *length)
{
int frames, frameLength; int frames, frameLength;
int tFrameLength = 0; int tFrameLength = 0;
int sampleRate = 0; int sampleRate = 0;
@ -101,14 +111,14 @@ static int adtsParse(AacBuffer * b, float * length) {
if (b->bytesIntoBuffer > 7) { if (b->bytesIntoBuffer > 7) {
/* check syncword */ /* check syncword */
if (!((b->buffer[0] == 0xFF) && if (!((b->buffer[0] == 0xFF) &&
((b->buffer[1] & 0xF6) == 0xF0))) ((b->buffer[1] & 0xF6) == 0xF0))) {
{
break; break;
} }
if (frames == 0) { if (frames == 0) {
sampleRate = adtsSampleRates[ sampleRate = adtsSampleRates[(b->
(b->buffer[2]&0x3c)>>2]; buffer[2] & 0x3c)
>> 2];
} }
frameLength = ((((unsigned int)b->buffer[3] & 0x3)) frameLength = ((((unsigned int)b->buffer[3] & 0x3))
@ -117,19 +127,21 @@ static int adtsParse(AacBuffer * b, float * length) {
tFrameLength += frameLength; tFrameLength += frameLength;
if(frameLength > b->bytesIntoBuffer) break; if (frameLength > b->bytesIntoBuffer)
break;
advanceAacBuffer(b, frameLength); advanceAacBuffer(b, frameLength);
} } else
else break; break;
} }
framesPerSec = (float)sampleRate / 1024.0; framesPerSec = (float)sampleRate / 1024.0;
if (frames != 0) { if (frames != 0) {
bytesPerFrame = (float)tFrameLength / (float)(frames * 1000); bytesPerFrame = (float)tFrameLength / (float)(frames * 1000);
} } else
else bytesPerFrame = 0; bytesPerFrame = 0;
if(framesPerSec!=0) *length = (float)frames/framesPerSec; if (framesPerSec != 0)
*length = (float)frames / framesPerSec;
return 1; return 1;
} }
@ -141,7 +153,8 @@ static void initAacBuffer(InputStream * inStream, AacBuffer * b, float * length,
size_t bread; size_t bread;
size_t tagsize; size_t tagsize;
if(length) *length = -1; if (length)
*length = -1;
memset(b, 0, sizeof(AacBuffer)); memset(b, 0, sizeof(AacBuffer));
@ -158,7 +171,8 @@ static void initAacBuffer(InputStream * inStream, AacBuffer * b, float * length,
b->bytesConsumed = 0; b->bytesConsumed = 0;
b->fileOffset = 0; b->fileOffset = 0;
if(bread!=FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS) b->atEof = 1; if (bread != FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS)
b->atEof = 1;
tagsize = 0; tagsize = 0;
if (!memcmp(b->buffer, "ID3", 3)) { if (!memcmp(b->buffer, "ID3", 3)) {
@ -170,37 +184,53 @@ static void initAacBuffer(InputStream * inStream, AacBuffer * b, float * length,
fillAacBuffer(b); fillAacBuffer(b);
} }
if(retFileread) *retFileread = fileread; if (retFileread)
if(retTagsize) *retTagsize = tagsize; *retFileread = fileread;
if (retTagsize)
*retTagsize = tagsize;
if(length==NULL) return; if (length == NULL)
return;
if ((b->buffer[0] == 0xFF) && ((b->buffer[1] & 0xF6) == 0xF0)) { if ((b->buffer[0] == 0xFF) && ((b->buffer[1] & 0xF6) == 0xF0)) {
adtsParse(b, length); adtsParse(b, length);
seekInputStream(b->inStream, tagsize, SEEK_SET); seekInputStream(b->inStream, tagsize, SEEK_SET);
bread = readFromInputStream(b->inStream, b->buffer, 1, bread = readFromInputStream(b->inStream, b->buffer, 1,
FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); FAAD_MIN_STREAMSIZE *
if(bread != FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS) b->atEof = 1; AAC_MAX_CHANNELS);
else b->atEof = 0; if (bread != FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS)
b->atEof = 1;
else
b->atEof = 0;
b->bytesIntoBuffer = bread; b->bytesIntoBuffer = bread;
b->bytesConsumed = 0; b->bytesConsumed = 0;
b->fileOffset = tagsize; b->fileOffset = tagsize;
} } else if (memcmp(b->buffer, "ADIF", 4) == 0) {
else if(memcmp(b->buffer,"ADIF",4) == 0) {
int bitRate; int bitRate;
int skipSize = (b->buffer[4] & 0x80) ? 9 : 0; int skipSize = (b->buffer[4] & 0x80) ? 9 : 0;
bitRate = ((unsigned int)(b->buffer[4 + skipSize] & 0x0F)<<19) | bitRate =
((unsigned int)b->buffer[5 + skipSize]<<11) | ((unsigned int)(b->
((unsigned int)b->buffer[6 + skipSize]<<3) | buffer[4 +
((unsigned int)b->buffer[7 + skipSize] & 0xE0); skipSize] & 0x0F) << 19) | ((unsigned
int)b->
buffer[5
+
skipSize]
<< 11) |
((unsigned int)b->
buffer[6 + skipSize] << 3) | ((unsigned int)b->buffer[7 +
skipSize]
& 0xE0);
*length = fileread; *length = fileread;
if(*length!=0 && bitRate!=0) *length = *length*8.0/bitRate; if (*length != 0 && bitRate != 0)
*length = *length * 8.0 / bitRate;
} }
} }
static float getAacFloatTotalTime(char * file) { static float getAacFloatTotalTime(char *file)
{
AacBuffer b; AacBuffer b;
float length; float length;
size_t fileread, tagsize; size_t fileread, tagsize;
@ -211,7 +241,8 @@ static float getAacFloatTotalTime(char * file) {
InputStream inStream; InputStream inStream;
size_t bread; size_t bread;
if(openInputStream(&inStream,file) < 0) return -1; if (openInputStream(&inStream, file) < 0)
return -1;
initAacBuffer(&inStream, &b, &length, &fileread, &tagsize); initAacBuffer(&inStream, &b, &length, &fileread, &tagsize);
@ -229,28 +260,32 @@ static float getAacFloatTotalTime(char * file) {
#else #else
bread = faacDecInit(decoder, b.buffer, &sampleRate, &channels); bread = faacDecInit(decoder, b.buffer, &sampleRate, &channels);
#endif #endif
if(bread >= 0 && sampleRate > 0 && channels > 0) length = 0; if (bread >= 0 && sampleRate > 0 && channels > 0)
length = 0;
faacDecClose(decoder); faacDecClose(decoder);
} }
if(b.buffer) free(b.buffer); if (b.buffer)
free(b.buffer);
closeInputStream(&inStream); closeInputStream(&inStream);
return length; return length;
} }
static int getAacTotalTime(char * file) { static int getAacTotalTime(char *file)
{
int time = -1; int time = -1;
float length; float length;
if((length = getAacFloatTotalTime(file))>=0) time = length+0.5; if ((length = getAacFloatTotalTime(file)) >= 0)
time = length + 0.5;
return time; return time;
} }
static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) { {
float time; float time;
float totalTime; float totalTime;
faacDecHandle decoder; faacDecHandle decoder;
@ -270,9 +305,11 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
AacBuffer b; AacBuffer b;
InputStream inStream; InputStream inStream;
if((totalTime = getAacFloatTotalTime(path)) < 0) return -1; if ((totalTime = getAacFloatTotalTime(path)) < 0)
return -1;
if(openInputStream(&inStream, path) < 0) return -1; if (openInputStream(&inStream, path) < 0)
return -1;
initAacBuffer(&inStream, &b, NULL, NULL, NULL); initAacBuffer(&inStream, &b, NULL, NULL, NULL);
@ -300,7 +337,8 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
ERROR("Error not a AAC stream.\n"); ERROR("Error not a AAC stream.\n");
faacDecClose(decoder); faacDecClose(decoder);
closeInputStream(b.inStream); closeInputStream(b.inStream);
if(b.buffer) free(b.buffer); if (b.buffer)
free(b.buffer);
return -1; return -1;
} }
@ -319,7 +357,6 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
eof = 1; eof = 1;
break; break;
} }
#ifdef HAVE_FAAD_BUFLEN_FUNCS #ifdef HAVE_FAAD_BUFLEN_FUNCS
sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer, sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer,
b.bytesIntoBuffer); b.bytesIntoBuffer);
@ -334,7 +371,6 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
eof = 1; eof = 1;
break; break;
} }
#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE #ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
sampleRate = frameInfo.samplerate; sampleRate = frameInfo.samplerate;
#endif #endif
@ -355,7 +391,8 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
bitRate = frameInfo.bytesconsumed * 8.0 * bitRate = frameInfo.bytesconsumed * 8.0 *
frameInfo.channels * sampleRate / frameInfo.channels * sampleRate /
frameInfo.samples / 1000 + 0.5; frameInfo.samples / 1000 + 0.5;
time+= (float)(frameInfo.samples)/frameInfo.channels/ time +=
(float)(frameInfo.samples) / frameInfo.channels /
sampleRate; sampleRate;
} }
@ -366,8 +403,7 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
if (dc->seek) { if (dc->seek) {
dc->seekError = 1; dc->seekError = 1;
dc->seek = 0; dc->seek = 0;
} } else if (dc->stop) {
else if(dc->stop) {
eof = 1; eof = 1;
break; break;
} }
@ -377,9 +413,11 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
faacDecClose(decoder); faacDecClose(decoder);
closeInputStream(b.inStream); closeInputStream(b.inStream);
if(b.buffer) free(b.buffer); if (b.buffer)
free(b.buffer);
if(dc->state != DECODE_STATE_DECODE) return -1; if (dc->state != DECODE_STATE_DECODE)
return -1;
if (dc->seek) { if (dc->seek) {
dc->seekError = 1; dc->seekError = 1;
@ -389,24 +427,26 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
if (dc->stop) { if (dc->stop) {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
} } else
else dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
return 0; return 0;
} }
static MpdTag * aacTagDup(char * file) { static MpdTag *aacTagDup(char *file)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
int time; int time;
time = getAacTotalTime(file); time = getAacTotalTime(file);
if (time >= 0) { if (time >= 0) {
if((ret = id3Dup(file))==NULL) ret = newMpdTag(); if ((ret = id3Dup(file)) == NULL)
ret = newMpdTag();
ret->time = time; ret->time = time;
} } else {
else { DEBUG("aacTagDup: Failed to get total song time from: %s\n",
DEBUG("aacTagDup: Failed to get total song time from: %s\n", file); file);
} }
return ret; return ret;
@ -414,8 +454,7 @@ static MpdTag * aacTagDup(char * file) {
static char *aacSuffixes[] = { "aac", NULL }; static char *aacSuffixes[] = { "aac", NULL };
InputPlugin aacPlugin = InputPlugin aacPlugin = {
{
"aac", "aac",
NULL, NULL,
NULL, NULL,
@ -430,8 +469,7 @@ InputPlugin aacPlugin =
#else #else
InputPlugin aacPlugin = InputPlugin aacPlugin = {
{
NULL, NULL,
NULL, NULL,
NULL, NULL,

View File

@ -51,7 +51,8 @@ static int getAudiofileTotalTime(char * file)
return time; return time;
} }
static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char * path) { static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
{
int fs, frame_count; int fs, frame_count;
AFfilehandle af_fp; AFfilehandle af_fp;
int bits; int bits;
@ -77,7 +78,8 @@ static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char * path)
frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK); frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK);
dc->totalTime = ((float)frame_count/(float)dc->audioFormat.sampleRate); dc->totalTime =
((float)frame_count / (float)dc->audioFormat.sampleRate);
bitRate = st.st_size * 8.0 / dc->totalTime / 1000.0 + 0.5; bitRate = st.st_size * 8.0 / dc->totalTime / 1000.0 + 0.5;
@ -104,8 +106,11 @@ static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char * path)
dc->seek = 0; dc->seek = 0;
} }
ret = afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk, CHUNK_SIZE/fs); ret =
if(ret<=0) eof = 1; afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk,
CHUNK_SIZE / fs);
if (ret <= 0)
eof = 1;
else { else {
current += ret; current += ret;
sendDataToOutputBuffer(cb, sendDataToOutputBuffer(cb,
@ -115,10 +120,11 @@ static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char * path)
chunk, chunk,
ret * fs, ret * fs,
(float)current / (float)current /
(float)dc->audioFormat.sampleRate, (float)dc->audioFormat.
bitRate, sampleRate, bitRate,
NULL); NULL);
if(dc->stop) break; if (dc->stop)
break;
} }
} }
@ -132,24 +138,27 @@ static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char * path)
if (dc->stop) { if (dc->stop) {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
} } else
else dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
} }
afCloseFile(af_fp); afCloseFile(af_fp);
return 0; return 0;
} }
static MpdTag * audiofileTagDup(char * file) { static MpdTag *audiofileTagDup(char *file)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
int time = getAudiofileTotalTime(file); int time = getAudiofileTotalTime(file);
if (time >= 0) { if (time >= 0) {
if(!ret) ret = newMpdTag(); if (!ret)
ret = newMpdTag();
ret->time = time; ret->time = time;
} } else {
else { DEBUG
DEBUG("audiofileTagDup: Failed to get total song time from: %s\n", file); ("audiofileTagDup: Failed to get total song time from: %s\n",
file);
} }
return ret; return ret;
@ -157,8 +166,7 @@ static MpdTag * audiofileTagDup(char * file) {
static char *audiofileSuffixes[] = { "wav", "au", "aiff", "aif", NULL }; static char *audiofileSuffixes[] = { "wav", "au", "aiff", "aif", NULL };
InputPlugin audiofilePlugin = InputPlugin audiofilePlugin = {
{
"audiofile", "audiofile",
NULL, NULL,
NULL, NULL,
@ -173,8 +181,7 @@ InputPlugin audiofilePlugin =
#else #else
InputPlugin audiofilePlugin = InputPlugin audiofilePlugin = {
{
NULL, NULL,
NULL, NULL,
NULL, NULL,

View File

@ -43,20 +43,30 @@ static void flacError(const FLAC__SeekableStreamDecoder *,
static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state); static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state);
static void flacMetadata(const FLAC__SeekableStreamDecoder *, static void flacMetadata(const FLAC__SeekableStreamDecoder *,
const FLAC__StreamMetadata *, void *); const FLAC__StreamMetadata *, void *);
static FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *, static FLAC__StreamDecoderWriteStatus flacWrite(const
const FLAC__Frame *, const FLAC__int32 * const buf[], void *); FLAC__SeekableStreamDecoder *,
static FLAC__SeekableStreamDecoderReadStatus flacRead( const FLAC__Frame *,
const FLAC__SeekableStreamDecoder *, FLAC__byte buf[], const FLAC__int32 * const buf[],
void *);
static FLAC__SeekableStreamDecoderReadStatus flacRead(const
FLAC__SeekableStreamDecoder
*, FLAC__byte buf[],
unsigned *, void *); unsigned *, void *);
static FLAC__SeekableStreamDecoderSeekStatus flacSeek( static FLAC__SeekableStreamDecoderSeekStatus flacSeek(const
const FLAC__SeekableStreamDecoder *, FLAC__uint64, void *); FLAC__SeekableStreamDecoder
static FLAC__SeekableStreamDecoderTellStatus flacTell( *, FLAC__uint64, void *);
const FLAC__SeekableStreamDecoder *, FLAC__uint64 *, void *); static FLAC__SeekableStreamDecoderTellStatus flacTell(const
static FLAC__SeekableStreamDecoderLengthStatus flacLength( FLAC__SeekableStreamDecoder
const FLAC__SeekableStreamDecoder *, FLAC__uint64 *, void *); *, FLAC__uint64 *,
void *);
static FLAC__SeekableStreamDecoderLengthStatus flacLength(const
FLAC__SeekableStreamDecoder
*, FLAC__uint64 *,
void *);
static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder *, void *); static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder *, void *);
static int flac_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) static int flac_decode(OutputBuffer * cb, DecoderControl * dc,
InputStream * inStream)
{ {
FLAC__SeekableStreamDecoder *flacDec = NULL; FLAC__SeekableStreamDecoder *flacDec = NULL;
FlacData data; FlacData data;
@ -78,39 +88,45 @@ static int flac_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inS
flacTell); flacTell);
status &= FLAC__seekable_stream_decoder_set_length_callback(flacDec, status &= FLAC__seekable_stream_decoder_set_length_callback(flacDec,
flacLength); flacLength);
status&=FLAC__seekable_stream_decoder_set_eof_callback(flacDec,flacEOF); status &=
status&=FLAC__seekable_stream_decoder_set_write_callback(flacDec, FLAC__seekable_stream_decoder_set_eof_callback(flacDec, flacEOF);
status &=
FLAC__seekable_stream_decoder_set_write_callback(flacDec,
flacWrite); flacWrite);
status&=FLAC__seekable_stream_decoder_set_metadata_callback(flacDec, status &=
FLAC__seekable_stream_decoder_set_metadata_callback(flacDec,
flacMetadata); flacMetadata);
status&=FLAC__seekable_stream_decoder_set_metadata_respond(flacDec, status &=
FLAC__seekable_stream_decoder_set_metadata_respond(flacDec,
FLAC__METADATA_TYPE_VORBIS_COMMENT); FLAC__METADATA_TYPE_VORBIS_COMMENT);
status&=FLAC__seekable_stream_decoder_set_error_callback(flacDec, status &=
FLAC__seekable_stream_decoder_set_error_callback(flacDec,
flacError); flacError);
status&=FLAC__seekable_stream_decoder_set_client_data(flacDec, status &=
FLAC__seekable_stream_decoder_set_client_data(flacDec,
(void *)&data); (void *)&data);
if (!status) { if (!status) {
ERROR("flac problem before init()\n"); ERROR("flac problem before init()\n");
flacPrintErroredState( flacPrintErroredState(FLAC__seekable_stream_decoder_get_state
FLAC__seekable_stream_decoder_get_state(flacDec)); (flacDec));
ret = -1; ret = -1;
goto fail; goto fail;
} }
if (FLAC__seekable_stream_decoder_init(flacDec) != if (FLAC__seekable_stream_decoder_init(flacDec) !=
FLAC__SEEKABLE_STREAM_DECODER_OK) FLAC__SEEKABLE_STREAM_DECODER_OK) {
{
ERROR("flac problem doing init()\n"); ERROR("flac problem doing init()\n");
flacPrintErroredState( flacPrintErroredState(FLAC__seekable_stream_decoder_get_state
FLAC__seekable_stream_decoder_get_state(flacDec)); (flacDec));
ret = -1; ret = -1;
goto fail; goto fail;
} }
if(!FLAC__seekable_stream_decoder_process_until_end_of_metadata(flacDec)) { if (!FLAC__seekable_stream_decoder_process_until_end_of_metadata
(flacDec)) {
ERROR("flac problem reading metadata\n"); ERROR("flac problem reading metadata\n");
flacPrintErroredState( flacPrintErroredState(FLAC__seekable_stream_decoder_get_state
FLAC__seekable_stream_decoder_get_state(flacDec)); (flacDec));
ret = -1; ret = -1;
goto fail; goto fail;
} }
@ -120,8 +136,7 @@ static int flac_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inS
while (1) { while (1) {
FLAC__seekable_stream_decoder_process_single(flacDec); FLAC__seekable_stream_decoder_process_single(flacDec);
if (FLAC__seekable_stream_decoder_get_state(flacDec) != if (FLAC__seekable_stream_decoder_get_state(flacDec) !=
FLAC__SEEKABLE_STREAM_DECODER_OK) FLAC__SEEKABLE_STREAM_DECODER_OK) {
{
break; break;
} }
if (dc->seek) { if (dc->seek) {
@ -134,16 +149,16 @@ static int flac_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inS
data.time = ((float)sampleToSeek) / data.time = ((float)sampleToSeek) /
dc->audioFormat.sampleRate; dc->audioFormat.sampleRate;
data.position = 0; data.position = 0;
} } else
else dc->seekError = 1; dc->seekError = 1;
dc->seek = 0; dc->seek = 0;
} }
} }
/* I don't think we need this bit here! -shank */ /* I don't think we need this bit here! -shank */
/*FLAC__file_decoder_process_until_end_of_file(flacDec); */ /*FLAC__file_decoder_process_until_end_of_file(flacDec); */
if (!dc->stop) { if (!dc->stop) {
flacPrintErroredState( flacPrintErroredState(FLAC__seekable_stream_decoder_get_state
FLAC__seekable_stream_decoder_get_state(flacDec)); (flacDec));
FLAC__seekable_stream_decoder_finish(flacDec); FLAC__seekable_stream_decoder_finish(flacDec);
} }
/* send last little bit */ /* send last little bit */
@ -161,18 +176,24 @@ static int flac_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inS
dc->stop = 0; dc->stop = 0;
fail: fail:
if(data.replayGainInfo) freeReplayGainInfo(data.replayGainInfo); if (data.replayGainInfo)
freeReplayGainInfo(data.replayGainInfo);
if(flacDec) FLAC__seekable_stream_decoder_delete(flacDec); if (flacDec)
FLAC__seekable_stream_decoder_delete(flacDec);
closeInputStream(inStream); closeInputStream(inStream);
return ret; return ret;
} }
static FLAC__SeekableStreamDecoderReadStatus flacRead( static FLAC__SeekableStreamDecoderReadStatus flacRead(const
const FLAC__SeekableStreamDecoder * flacDec, FLAC__byte buf[], FLAC__SeekableStreamDecoder
unsigned * bytes, void * fdata) { * flacDec,
FLAC__byte buf[],
unsigned *bytes,
void *fdata)
{
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
size_t r; size_t r;
@ -192,9 +213,11 @@ static FLAC__SeekableStreamDecoderReadStatus flacRead(
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
} }
static FLAC__SeekableStreamDecoderSeekStatus flacSeek( static FLAC__SeekableStreamDecoderSeekStatus flacSeek(const
const FLAC__SeekableStreamDecoder * flacDec, FLAC__SeekableStreamDecoder
FLAC__uint64 offset, void * fdata) * flacDec,
FLAC__uint64 offset,
void *fdata)
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
@ -205,9 +228,11 @@ static FLAC__SeekableStreamDecoderSeekStatus flacSeek(
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
} }
static FLAC__SeekableStreamDecoderTellStatus flacTell( static FLAC__SeekableStreamDecoderTellStatus flacTell(const
const FLAC__SeekableStreamDecoder * flacDec, FLAC__SeekableStreamDecoder
FLAC__uint64 * offset, void * fdata) * flacDec,
FLAC__uint64 * offset,
void *fdata)
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
@ -216,9 +241,11 @@ static FLAC__SeekableStreamDecoderTellStatus flacTell(
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
} }
static FLAC__SeekableStreamDecoderLengthStatus flacLength( static FLAC__SeekableStreamDecoderLengthStatus flacLength(const
const FLAC__SeekableStreamDecoder * flacDec, FLAC__SeekableStreamDecoder
FLAC__uint64 * length, void * fdata) * flacDec,
FLAC__uint64 * length,
void *fdata)
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
@ -227,7 +254,9 @@ static FLAC__SeekableStreamDecoderLengthStatus flacLength(
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
} }
static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec, void * fdata) { static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec,
void *fdata)
{
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
if (inputStreamAtEOF(data->inStream) == 1) if (inputStreamAtEOF(data->inStream) == 1)
@ -278,8 +307,10 @@ static void flacMetadata(const FLAC__SeekableStreamDecoder *dec,
flac_metadata_common_cb(block, (FlacData *) vdata); flac_metadata_common_cb(block, (FlacData *) vdata);
} }
static FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *dec, static FLAC__StreamDecoderWriteStatus flacWrite(const
const FLAC__Frame *frame, const FLAC__int32 * const buf[], FLAC__SeekableStreamDecoder *
dec, const FLAC__Frame * frame,
const FLAC__int32 * const buf[],
void *vdata) void *vdata)
{ {
FlacData *data = (FlacData *) vdata; FlacData *data = (FlacData *) vdata;
@ -296,7 +327,8 @@ static FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecode
FLAC__seekable_stream_decoder_get_decode_position(dec, &newPosition); FLAC__seekable_stream_decoder_get_decode_position(dec, &newPosition);
if (data->position) { if (data->position) {
data->bitRate = ((newPosition-data->position)*8.0/timeChange) data->bitRate =
((newPosition - data->position) * 8.0 / timeChange)
/ 1000 + 0.5; / 1000 + 0.5;
} }
data->position = newPosition; data->position = newPosition;
@ -309,11 +341,13 @@ static FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecode
for (i = 0; i < (data->dc->audioFormat.bits / 8); i++) { for (i = 0; i < (data->dc->audioFormat.bits / 8); i++) {
if (data->chunk_length >= FLAC_CHUNK_SIZE) { if (data->chunk_length >= FLAC_CHUNK_SIZE) {
if (flacSendChunk(data) < 0) { if (flacSendChunk(data) < 0) {
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; return
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
} }
data->chunk_length = 0; data->chunk_length = 0;
if (data->dc->seek) { if (data->dc->seek) {
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; return
FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
} }
} }
data->chunk[data->chunk_length++] = *(uc++); data->chunk[data->chunk_length++] = *(uc++);
@ -324,7 +358,8 @@ static FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecode
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
} }
static MpdTag * flacMetadataDup(char * file, int * vorbisCommentFound) { static MpdTag *flacMetadataDup(char *file, int *vorbisCommentFound)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
FLAC__Metadata_SimpleIterator *it; FLAC__Metadata_SimpleIterator *it;
FLAC__StreamMetadata *block = NULL; FLAC__StreamMetadata *block = NULL;
@ -335,16 +370,23 @@ static MpdTag * flacMetadataDup(char * file, int * vorbisCommentFound) {
if (!FLAC__metadata_simple_iterator_init(it, file, 1, 0)) { if (!FLAC__metadata_simple_iterator_init(it, file, 1, 0)) {
switch (FLAC__metadata_simple_iterator_status(it)) { switch (FLAC__metadata_simple_iterator_status(it)) {
case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT: case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT:
DEBUG("flacMetadataDup: Reading '%s' metadata gave the following error: Illegal Input\n",file); DEBUG
("flacMetadataDup: Reading '%s' metadata gave the following error: Illegal Input\n",
file);
break; break;
case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE: case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE:
DEBUG("flacMetadataDup: Reading '%s' metadata gave the following error: Error Opening File\n",file); DEBUG
("flacMetadataDup: Reading '%s' metadata gave the following error: Error Opening File\n",
file);
break; break;
case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE: case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE:
DEBUG("flacMetadataDup: Reading '%s' metadata gave the following error: Not A Flac File\n",file); DEBUG
("flacMetadataDup: Reading '%s' metadata gave the following error: Not A Flac File\n",
file);
break; break;
default: default:
DEBUG("flacMetadataDup: Reading '%s' metadata failed\n",file); DEBUG("flacMetadataDup: Reading '%s' metadata failed\n",
file);
} }
FLAC__metadata_simple_iterator_delete(it); FLAC__metadata_simple_iterator_delete(it);
return ret; return ret;
@ -352,18 +394,19 @@ static MpdTag * flacMetadataDup(char * file, int * vorbisCommentFound) {
do { do {
block = FLAC__metadata_simple_iterator_get_block(it); block = FLAC__metadata_simple_iterator_get_block(it);
if(!block) break; if (!block)
break;
if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
ret = copyVorbisCommentBlockToMpdTag(block, ret); ret = copyVorbisCommentBlockToMpdTag(block, ret);
if(ret) *vorbisCommentFound = 1; if (ret)
} *vorbisCommentFound = 1;
else if(block->type == FLAC__METADATA_TYPE_STREAMINFO) { } else if (block->type == FLAC__METADATA_TYPE_STREAMINFO) {
if(!ret) ret = newMpdTag(); if (!ret)
ret = newMpdTag();
ret->time = ((float)block->data.stream_info. ret->time = ((float)block->data.stream_info.
total_samples) / total_samples) /
block->data.stream_info.sample_rate + block->data.stream_info.sample_rate + 0.5;
0.5;
} }
FLAC__metadata_object_delete(block); FLAC__metadata_object_delete(block);
} while (FLAC__metadata_simple_iterator_next(it)); } while (FLAC__metadata_simple_iterator_next(it));
@ -372,13 +415,15 @@ static MpdTag * flacMetadataDup(char * file, int * vorbisCommentFound) {
return ret; return ret;
} }
static MpdTag * flacTagDup(char * file) { static MpdTag *flacTagDup(char *file)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
int foundVorbisComment = 0; int foundVorbisComment = 0;
ret = flacMetadataDup(file, &foundVorbisComment); ret = flacMetadataDup(file, &foundVorbisComment);
if (!ret) { if (!ret) {
DEBUG("flacTagDup: Failed to grab information from: %s\n", file); DEBUG("flacTagDup: Failed to grab information from: %s\n",
file);
return NULL; return NULL;
} }
if (!foundVorbisComment) { if (!foundVorbisComment) {
@ -396,8 +441,7 @@ static MpdTag * flacTagDup(char * file) {
static char *flacSuffixes[] = { "flac", NULL }; static char *flacSuffixes[] = { "flac", NULL };
static char *flac_mime_types[] = { "application/x-flac", NULL }; static char *flac_mime_types[] = { "application/x-flac", NULL };
InputPlugin flacPlugin = InputPlugin flacPlugin = {
{
"flac", "flac",
NULL, NULL,
NULL, NULL,
@ -412,8 +456,7 @@ InputPlugin flacPlugin =
#else /* !HAVE_FLAC */ #else /* !HAVE_FLAC */
InputPlugin flacPlugin = InputPlugin flacPlugin = {
{
NULL, NULL,
NULL, NULL,
NULL, NULL,

View File

@ -39,23 +39,26 @@
#define MIKMOD_FRAME_SIZE 4096 #define MIKMOD_FRAME_SIZE 4096
static BOOL mod_mpd_Init(void) { static BOOL mod_mpd_Init(void)
{
return VC_Init(); return VC_Init();
} }
static void mod_mpd_Exit(void) { static void mod_mpd_Exit(void)
{
VC_Exit(); VC_Exit();
} }
static void mod_mpd_Update(void) { static void mod_mpd_Update(void)
{
} }
static BOOL mod_mpd_IsThere(void) { static BOOL mod_mpd_IsThere(void)
{
return 1; return 1;
} }
static MDRIVER drv_mpd = static MDRIVER drv_mpd = {
{
NULL, NULL,
"MPD", "MPD",
"MPD Output Driver v0.1", "MPD Output Driver v0.1",
@ -92,8 +95,10 @@ static MDRIVER drv_mpd =
static int mod_mikModInitiated = 0; static int mod_mikModInitiated = 0;
static int mod_mikModInitError = 0; static int mod_mikModInitError = 0;
static int mod_initMikMod(void) { static int mod_initMikMod(void)
if(mod_mikModInitError) return -1; {
if (mod_mikModInitError)
return -1;
if (!mod_mikModInitiated) { if (!mod_mikModInitiated) {
mod_mikModInitiated = 1; mod_mikModInitiated = 1;
@ -120,7 +125,8 @@ static int mod_initMikMod(void) {
return 0; return 0;
} }
static void mod_finishMikMod(void) { static void mod_finishMikMod(void)
{
MikMod_Exit(); MikMod_Exit();
} }
@ -129,11 +135,13 @@ typedef struct _mod_Data {
SBYTE *audio_buffer; SBYTE *audio_buffer;
} mod_Data; } mod_Data;
static mod_Data * mod_open(char * path) { static mod_Data *mod_open(char *path)
{
MODULE *moduleHandle; MODULE *moduleHandle;
mod_Data *data; mod_Data *data;
if(!(moduleHandle = Player_Load(path, 128, 0))) return NULL; if (!(moduleHandle = Player_Load(path, 128, 0)))
return NULL;
data = malloc(sizeof(mod_Data)); data = malloc(sizeof(mod_Data));
@ -145,20 +153,23 @@ static mod_Data * mod_open(char * path) {
return data; return data;
} }
static void mod_close(mod_Data * data) { static void mod_close(mod_Data * data)
{
Player_Stop(); Player_Stop();
Player_Free(data->moduleHandle); Player_Free(data->moduleHandle);
free(data->audio_buffer); free(data->audio_buffer);
free(data); free(data);
} }
static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char * path) { static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
{
mod_Data *data; mod_Data *data;
float time = 0.0; float time = 0.0;
int ret; int ret;
float secPerByte; float secPerByte;
if(mod_initMikMod() < 0) return -1; if (mod_initMikMod() < 0)
return -1;
if (!(data = mod_open(path))) { if (!(data = mod_open(path))) {
ERROR("failed to open mod: %s\n", path); ERROR("failed to open mod: %s\n", path);
@ -171,7 +182,8 @@ static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
dc->audioFormat.channels = 2; dc->audioFormat.channels = 2;
getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat)); getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat));
secPerByte = 1.0/((dc->audioFormat.bits*dc->audioFormat.channels/8.0)* secPerByte =
1.0 / ((dc->audioFormat.bits * dc->audioFormat.channels / 8.0) *
(float)dc->audioFormat.sampleRate); (float)dc->audioFormat.sampleRate);
dc->state = DECODE_STATE_DECODE; dc->state = DECODE_STATE_DECODE;
@ -181,9 +193,11 @@ static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
dc->seek = 0; dc->seek = 0;
} }
if(dc->stop) break; if (dc->stop)
break;
if(!Player_Active()) break; if (!Player_Active())
break;
ret = VC_WriteBytes(data->audio_buffer, MIKMOD_FRAME_SIZE); ret = VC_WriteBytes(data->audio_buffer, MIKMOD_FRAME_SIZE);
time += ret * secPerByte; time += ret * secPerByte;
@ -201,13 +215,14 @@ static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
if (dc->stop) { if (dc->stop) {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
} } else
else dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
return 0; return 0;
} }
static MpdTag * modTagDup(char * file) { static MpdTag *modTagDup(char *file)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
MODULE *moduleHandle; MODULE *moduleHandle;
char *title; char *title;
@ -229,7 +244,8 @@ static MpdTag * modTagDup(char * file) {
ret->time = 0; ret->time = 0;
title = strdup(Player_LoadTitle(file)); title = strdup(Player_LoadTitle(file));
if(title) addItemToMpdTag(ret, TAG_ITEM_TITLE, title); if (title)
addItemToMpdTag(ret, TAG_ITEM_TITLE, title);
MikMod_Exit(); MikMod_Exit();
@ -251,10 +267,10 @@ static char * modSuffixes[] = {"amf",
"ult", "ult",
"uni", "uni",
"xm", "xm",
NULL}; NULL
};
InputPlugin modPlugin = InputPlugin modPlugin = {
{
"mod", "mod",
NULL, NULL,
mod_finishMikMod, mod_finishMikMod,
@ -269,8 +285,7 @@ InputPlugin modPlugin =
#else #else
InputPlugin modPlugin = InputPlugin modPlugin = {
{
NULL, NULL,
NULL, NULL,
NULL, NULL,

View File

@ -58,11 +58,14 @@ struct audio_dither {
mad_fixed_t random; mad_fixed_t random;
}; };
static unsigned long prng(unsigned long state) { static unsigned long prng(unsigned long state)
{
return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL; return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
} }
static signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample, struct audio_dither *dither) { static signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample,
struct audio_dither *dither)
{
unsigned int scalebits; unsigned int scalebits;
mad_fixed_t output, mask, random; mad_fixed_t output, mask, random;
@ -91,8 +94,7 @@ static signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample, st
if (sample > MAX) if (sample > MAX)
sample = MAX; sample = MAX;
} } else if (output < MIN) {
else if (output < MIN) {
output = MIN; output = MIN;
if (sample < MIN) if (sample < MIN)
@ -105,6 +107,7 @@ static signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample, st
return output >> scalebits; return output >> scalebits;
} }
/* end of stolen stuff from mpg321 */ /* end of stolen stuff from mpg321 */
/* decoder stuff is based on madlld */ /* decoder stuff is based on madlld */
@ -134,9 +137,11 @@ typedef struct _mp3DecodeData {
struct audio_dither dither; struct audio_dither dither;
} mp3DecodeData; } mp3DecodeData;
static void initMp3DecodeData(mp3DecodeData * data, InputStream * inStream) { static void initMp3DecodeData(mp3DecodeData * data, InputStream * inStream)
{
data->outputPtr = data->outputBuffer; data->outputPtr = data->outputBuffer;
data->outputBufferEnd = data->outputBuffer+MP3_DATA_OUTPUT_BUFFER_SIZE; data->outputBufferEnd =
data->outputBuffer + MP3_DATA_OUTPUT_BUFFER_SIZE;
data->muteFrame = 0; data->muteFrame = 0;
data->highestFrame = 0; data->highestFrame = 0;
data->maxFrames = 0; data->maxFrames = 0;
@ -154,7 +159,8 @@ static void initMp3DecodeData(mp3DecodeData * data, InputStream * inStream) {
mad_timer_reset(&data->timer); mad_timer_reset(&data->timer);
} }
static int seekMp3InputBuffer(mp3DecodeData * data, long offset) { static int seekMp3InputBuffer(mp3DecodeData * data, long offset)
{
if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) { if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) {
return -1; return -1;
} }
@ -165,7 +171,8 @@ static int seekMp3InputBuffer(mp3DecodeData * data, long offset) {
return 0; return 0;
} }
static int fillMp3InputBuffer(mp3DecodeData * data) { static int fillMp3InputBuffer(mp3DecodeData * data)
{
size_t readSize; size_t readSize;
size_t remaining; size_t remaining;
size_t readed; size_t readed;
@ -176,20 +183,20 @@ static int fillMp3InputBuffer(mp3DecodeData * data) {
memmove(data->readBuffer, (data->stream).next_frame, remaining); memmove(data->readBuffer, (data->stream).next_frame, remaining);
readStart = (data->readBuffer) + remaining; readStart = (data->readBuffer) + remaining;
readSize = READ_BUFFER_SIZE - remaining; readSize = READ_BUFFER_SIZE - remaining;
} } else {
else {
readSize = READ_BUFFER_SIZE; readSize = READ_BUFFER_SIZE;
readStart = data->readBuffer, readStart = data->readBuffer, remaining = 0;
remaining = 0;
} }
/* we've exhausted the read buffer, so give up!, these potential /* we've exhausted the read buffer, so give up!, these potential
* mp3 frames are way too big, and thus unlikely to be mp3 frames */ * mp3 frames are way too big, and thus unlikely to be mp3 frames */
if(readSize == 0) return -1; if (readSize == 0)
return -1;
readed = readFromInputStream(data->inStream, readStart, (size_t) 1, readed = readFromInputStream(data->inStream, readStart, (size_t) 1,
readSize); readSize);
if(readed <= 0 && inputStreamAtEOF(data->inStream)) return -1; if (readed <= 0 && inputStreamAtEOF(data->inStream))
return -1;
/* sleep for a fraction of a second! */ /* sleep for a fraction of a second! */
else if (readed <= 0) { else if (readed <= 0) {
readed = 0; readed = 0;
@ -203,7 +210,8 @@ static int fillMp3InputBuffer(mp3DecodeData * data) {
} }
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
static ReplayGainInfo * parseId3ReplayGainInfo(struct id3_tag * tag) { static ReplayGainInfo *parseId3ReplayGainInfo(struct id3_tag *tag)
{
int i; int i;
char *key; char *key;
char *value; char *value;
@ -214,24 +222,28 @@ static ReplayGainInfo * parseId3ReplayGainInfo(struct id3_tag * tag) {
replayGainInfo = newReplayGainInfo(); replayGainInfo = newReplayGainInfo();
for (i = 0; (frame = id3_tag_findframe(tag, "TXXX", i)); i++) { for (i = 0; (frame = id3_tag_findframe(tag, "TXXX", i)); i++) {
if(frame->nfields < 3) continue; if (frame->nfields < 3)
continue;
key = (char *) id3_ucs4_latin1duplicate(id3_field_getstring(&frame->fields[1])); key =
value = (char *) id3_ucs4_latin1duplicate(id3_field_getstring(&frame->fields[2])); (char *)
id3_ucs4_latin1duplicate(id3_field_getstring
(&frame->fields[1]));
value =
(char *)
id3_ucs4_latin1duplicate(id3_field_getstring
(&frame->fields[2]));
if (strcmp(key, "replaygain_track_gain") == 0) { if (strcmp(key, "replaygain_track_gain") == 0) {
replayGainInfo->trackGain = atof(value); replayGainInfo->trackGain = atof(value);
found = 1; found = 1;
} } else if (strcmp(key, "replaygain_album_gain") == 0) {
else if(strcmp(key, "replaygain_album_gain") == 0) {
replayGainInfo->albumGain = atof(value); replayGainInfo->albumGain = atof(value);
found = 1; found = 1;
} } else if (strcmp(key, "replaygain_track_peak") == 0) {
else if(strcmp(key, "replaygain_track_peak") == 0) {
replayGainInfo->trackPeak = atof(value); replayGainInfo->trackPeak = atof(value);
found = 1; found = 1;
} } else if (strcmp(key, "replaygain_album_peak") == 0) {
else if(strcmp(key, "replaygain_album_peak") == 0) {
replayGainInfo->albumPeak = atof(value); replayGainInfo->albumPeak = atof(value);
found = 1; found = 1;
} }
@ -240,14 +252,17 @@ static ReplayGainInfo * parseId3ReplayGainInfo(struct id3_tag * tag) {
free(value); free(value);
} }
if(found) return replayGainInfo; if (found)
return replayGainInfo;
freeReplayGainInfo(replayGainInfo); freeReplayGainInfo(replayGainInfo);
return NULL; return NULL;
} }
#endif #endif
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
static void mp3_parseId3Tag(mp3DecodeData * data, signed long tagsize, MpdTag ** mpdTag, ReplayGainInfo ** replayGainInfo) { static void mp3_parseId3Tag(mp3DecodeData * data, signed long tagsize,
MpdTag ** mpdTag, ReplayGainInfo ** replayGainInfo)
{
struct id3_tag *id3Tag = NULL; struct id3_tag *id3Tag = NULL;
id3_length_t count; id3_length_t count;
id3_byte_t const *id3_data; id3_byte_t const *id3_data;
@ -260,10 +275,10 @@ static void mp3_parseId3Tag(mp3DecodeData * data, signed long tagsize, MpdTag **
if (tagsize <= count) { if (tagsize <= count) {
id3_data = data->stream.this_frame; id3_data = data->stream.this_frame;
mad_stream_skip(&(data->stream), tagsize); mad_stream_skip(&(data->stream), tagsize);
} } else {
else {
allocated = malloc(tagsize); allocated = malloc(tagsize);
if(!allocated) goto fail; if (!allocated)
goto fail;
memcpy(allocated, data->stream.this_frame, count); memcpy(allocated, data->stream.this_frame, count);
mad_stream_skip(&(data->stream), count); mad_stream_skip(&(data->stream), count);
@ -276,9 +291,10 @@ static void mp3_parseId3Tag(mp3DecodeData * data, signed long tagsize, MpdTag **
tagsize - count); tagsize - count);
if (len <= 0 && inputStreamAtEOF(data->inStream)) { if (len <= 0 && inputStreamAtEOF(data->inStream)) {
break; break;
} } else if (len <= 0)
else if(len <= 0) my_usleep(10000); my_usleep(10000);
else count += len; else
count += len;
} }
if (count != tagsize) { if (count != tagsize) {
@ -290,12 +306,14 @@ static void mp3_parseId3Tag(mp3DecodeData * data, signed long tagsize, MpdTag **
} }
id3Tag = id3_tag_parse(id3_data, tagsize); id3Tag = id3_tag_parse(id3_data, tagsize);
if(!id3Tag) goto fail; if (!id3Tag)
goto fail;
if (mpdTag) { if (mpdTag) {
tmpMpdTag = parseId3Tag(id3Tag); tmpMpdTag = parseId3Tag(id3Tag);
if (tmpMpdTag) { if (tmpMpdTag) {
if(*mpdTag) freeMpdTag(*mpdTag); if (*mpdTag)
freeMpdTag(*mpdTag);
*mpdTag = tmpMpdTag; *mpdTag = tmpMpdTag;
} }
} }
@ -303,19 +321,24 @@ static void mp3_parseId3Tag(mp3DecodeData * data, signed long tagsize, MpdTag **
if (replayGainInfo) { if (replayGainInfo) {
tmpReplayGainInfo = parseId3ReplayGainInfo(id3Tag); tmpReplayGainInfo = parseId3ReplayGainInfo(id3Tag);
if (tmpReplayGainInfo) { if (tmpReplayGainInfo) {
if(*replayGainInfo) freeReplayGainInfo(*replayGainInfo); if (*replayGainInfo)
freeReplayGainInfo(*replayGainInfo);
*replayGainInfo = tmpReplayGainInfo; *replayGainInfo = tmpReplayGainInfo;
} }
} }
id3_tag_delete(id3Tag); id3_tag_delete(id3Tag);
fail: fail:
if(allocated) free(allocated); if (allocated)
free(allocated);
} }
#endif #endif
static int decodeNextFrameHeader(mp3DecodeData * data, MpdTag ** tag, ReplayGainInfo ** replayGainInfo) { static int decodeNextFrameHeader(mp3DecodeData * data, MpdTag ** tag,
if((data->stream).buffer==NULL || (data->stream).error==MAD_ERROR_BUFLEN) { ReplayGainInfo ** replayGainInfo)
{
if ((data->stream).buffer == NULL
|| (data->stream).error == MAD_ERROR_BUFLEN) {
if (fillMp3InputBuffer(data) < 0) { if (fillMp3InputBuffer(data) < 0) {
return DECODE_BREAK; return DECODE_BREAK;
} }
@ -323,18 +346,19 @@ static int decodeNextFrameHeader(mp3DecodeData * data, MpdTag ** tag, ReplayGain
if (mad_header_decode(&data->frame.header, &data->stream)) { if (mad_header_decode(&data->frame.header, &data->stream)) {
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
if ((data->stream).error == MAD_ERROR_LOSTSYNC && if ((data->stream).error == MAD_ERROR_LOSTSYNC &&
(data->stream).this_frame) (data->stream).this_frame) {
{ signed long tagsize = id3_tag_query((data->stream).
signed long tagsize = id3_tag_query( this_frame,
(data->stream).this_frame, (data->stream).
(data->stream).bufend- bufend -
(data->stream).this_frame); (data->stream).
this_frame);
if (tagsize > 0) { if (tagsize > 0) {
if (tag && !(*tag)) { if (tag && !(*tag)) {
mp3_parseId3Tag(data, tagsize, tag, replayGainInfo); mp3_parseId3Tag(data, tagsize, tag,
} replayGainInfo);
else { } else {
mad_stream_skip(&(data->stream), mad_stream_skip(&(data->stream),
tagsize); tagsize);
} }
@ -344,11 +368,10 @@ static int decodeNextFrameHeader(mp3DecodeData * data, MpdTag ** tag, ReplayGain
#endif #endif
if (MAD_RECOVERABLE((data->stream).error)) { if (MAD_RECOVERABLE((data->stream).error)) {
return DECODE_SKIP; return DECODE_SKIP;
} } else {
if ((data->stream).error == MAD_ERROR_BUFLEN)
return DECODE_CONT;
else { else {
if((data->stream).error==MAD_ERROR_BUFLEN) return DECODE_CONT;
else
{
ERROR("unrecoverable frame level error " ERROR("unrecoverable frame level error "
"(%s).\n", "(%s).\n",
mad_stream_errorstr(&data->stream)); mad_stream_errorstr(&data->stream));
@ -364,8 +387,10 @@ static int decodeNextFrameHeader(mp3DecodeData * data, MpdTag ** tag, ReplayGain
return DECODE_OK; return DECODE_OK;
} }
static int decodeNextFrame(mp3DecodeData * data) { static int decodeNextFrame(mp3DecodeData * data)
if((data->stream).buffer==NULL || (data->stream).error==MAD_ERROR_BUFLEN) { {
if ((data->stream).buffer == NULL
|| (data->stream).error == MAD_ERROR_BUFLEN) {
if (fillMp3InputBuffer(data) < 0) { if (fillMp3InputBuffer(data) < 0) {
return DECODE_BREAK; return DECODE_BREAK;
} }
@ -373,10 +398,12 @@ static int decodeNextFrame(mp3DecodeData * data) {
if (mad_frame_decode(&data->frame, &data->stream)) { if (mad_frame_decode(&data->frame, &data->stream)) {
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
if ((data->stream).error == MAD_ERROR_LOSTSYNC) { if ((data->stream).error == MAD_ERROR_LOSTSYNC) {
signed long tagsize = id3_tag_query( signed long tagsize = id3_tag_query((data->stream).
(data->stream).this_frame, this_frame,
(data->stream).bufend- (data->stream).
(data->stream).this_frame); bufend -
(data->stream).
this_frame);
if (tagsize > 0) { if (tagsize > 0) {
mad_stream_skip(&(data->stream), tagsize); mad_stream_skip(&(data->stream), tagsize);
return DECODE_CONT; return DECODE_CONT;
@ -385,11 +412,10 @@ static int decodeNextFrame(mp3DecodeData * data) {
#endif #endif
if (MAD_RECOVERABLE((data->stream).error)) { if (MAD_RECOVERABLE((data->stream).error)) {
return DECODE_SKIP; return DECODE_SKIP;
} } else {
if ((data->stream).error == MAD_ERROR_BUFLEN)
return DECODE_CONT;
else { else {
if((data->stream).error==MAD_ERROR_BUFLEN) return DECODE_CONT;
else
{
ERROR("unrecoverable frame level error " ERROR("unrecoverable frame level error "
"(%s).\n", "(%s).\n",
mad_stream_errorstr(&data->stream)); mad_stream_errorstr(&data->stream));
@ -438,49 +464,62 @@ static int parse_xing(struct xing *xing, struct mad_bitptr *ptr, int bitlen)
oldbitlen = bitlen; oldbitlen = bitlen;
if (bitlen < 16) goto fail; if (bitlen < 16)
goto fail;
bits = mad_bit_read(ptr, 16); bits = mad_bit_read(ptr, 16);
bitlen -= 16; bitlen -= 16;
if (bits == XI_MAGIC) { if (bits == XI_MAGIC) {
if (bitlen < 16) goto fail; if (bitlen < 16)
if (mad_bit_read(ptr, 16) != NG_MAGIC) goto fail; goto fail;
if (mad_bit_read(ptr, 16) != NG_MAGIC)
goto fail;
bitlen -= 16; bitlen -= 16;
xing->magic = XING_MAGIC_XING; xing->magic = XING_MAGIC_XING;
} else if (bits == IN_MAGIC) { } else if (bits == IN_MAGIC) {
if (bitlen < 16) goto fail; if (bitlen < 16)
if (mad_bit_read(ptr, 16) != FO_MAGIC) goto fail; goto fail;
if (mad_bit_read(ptr, 16) != FO_MAGIC)
goto fail;
bitlen -= 16; bitlen -= 16;
xing->magic = XING_MAGIC_INFO; xing->magic = XING_MAGIC_INFO;
} } else if (bits == NG_MAGIC)
else if (bits == NG_MAGIC) xing->magic = XING_MAGIC_XING; xing->magic = XING_MAGIC_XING;
else if (bits == FO_MAGIC) xing->magic = XING_MAGIC_INFO; else if (bits == FO_MAGIC)
else goto fail; xing->magic = XING_MAGIC_INFO;
else
goto fail;
if (bitlen < 32) goto fail; if (bitlen < 32)
goto fail;
xing->flags = mad_bit_read(ptr, 32); xing->flags = mad_bit_read(ptr, 32);
bitlen -= 32; bitlen -= 32;
if (xing->flags & XING_FRAMES) { if (xing->flags & XING_FRAMES) {
if (bitlen < 32) goto fail; if (bitlen < 32)
goto fail;
xing->frames = mad_bit_read(ptr, 32); xing->frames = mad_bit_read(ptr, 32);
bitlen -= 32; bitlen -= 32;
} }
if (xing->flags & XING_BYTES) { if (xing->flags & XING_BYTES) {
if (bitlen < 32) goto fail; if (bitlen < 32)
goto fail;
xing->bytes = mad_bit_read(ptr, 32); xing->bytes = mad_bit_read(ptr, 32);
bitlen -= 32; bitlen -= 32;
} }
if (xing->flags & XING_TOC) { if (xing->flags & XING_TOC) {
if (bitlen < 800) goto fail; if (bitlen < 800)
for (i = 0; i < 100; ++i) xing->toc[i] = mad_bit_read(ptr, 8); goto fail;
for (i = 0; i < 100; ++i)
xing->toc[i] = mad_bit_read(ptr, 8);
bitlen -= 800; bitlen -= 800;
} }
if (xing->flags & XING_SCALE) { if (xing->flags & XING_SCALE) {
if (bitlen < 32) goto fail; if (bitlen < 32)
goto fail;
xing->scale = mad_bit_read(ptr, 32); xing->scale = mad_bit_read(ptr, 32);
bitlen -= 32; bitlen -= 32;
} }
@ -488,7 +527,8 @@ static int parse_xing(struct xing *xing, struct mad_bitptr *ptr, int bitlen)
/* Make sure we consume no less than 120 bytes (960 bits) in hopes that /* Make sure we consume no less than 120 bytes (960 bits) in hopes that
* the LAME tag is found there, and not right after the Xing header */ * the LAME tag is found there, and not right after the Xing header */
bitsleft = 960 - (oldbitlen - bitlen); bitsleft = 960 - (oldbitlen - bitlen);
if (bitsleft < 0) goto fail; if (bitsleft < 0)
goto fail;
else if (bitsleft > 0) { else if (bitsleft > 0) {
mad_bit_read(ptr, bitsleft); mad_bit_read(ptr, bitsleft);
bitlen -= bitsleft; bitlen -= bitsleft;
@ -504,7 +544,8 @@ static int parse_extension_headers(struct xing *xing, struct mad_bitptr ptr,
int bitlen) int bitlen)
{ {
bitlen = parse_xing(xing, &ptr, bitlen); bitlen = parse_xing(xing, &ptr, bitlen);
if (bitlen < 0) return 0; if (bitlen < 0)
return 0;
return 1; return 1;
} }
@ -521,14 +562,20 @@ static int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc,
while (1) { while (1) {
skip = 0; skip = 0;
while((ret = decodeNextFrameHeader(data, tag, replayGainInfo))==DECODE_CONT && while ((ret =
(!dc || !dc->stop)); decodeNextFrameHeader(data, tag,
if(ret==DECODE_SKIP) skip = 1; replayGainInfo)) == DECODE_CONT
else if(ret==DECODE_BREAK || (dc && dc->stop)) return -1; && (!dc || !dc->stop)) ;
if (ret == DECODE_SKIP)
skip = 1;
else if (ret == DECODE_BREAK || (dc && dc->stop))
return -1;
while ((ret = decodeNextFrame(data)) == DECODE_CONT && while ((ret = decodeNextFrame(data)) == DECODE_CONT &&
(!dc || !dc->stop)) ; (!dc || !dc->stop)) ;
if(ret==DECODE_BREAK || (dc && dc->stop)) return -1; if (ret == DECODE_BREAK || (dc && dc->stop))
if(!skip && ret==DECODE_OK) break; return -1;
if (!skip && ret == DECODE_OK)
break;
} }
if (parse_extension_headers(&xing, data->stream.anc_ptr, if (parse_extension_headers(&xing, data->stream.anc_ptr,
@ -538,28 +585,28 @@ static int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc,
mad_timer_multiply(&duration, xing.frames); mad_timer_multiply(&duration, xing.frames);
data->muteFrame = MUTEFRAME_SKIP; data->muteFrame = MUTEFRAME_SKIP;
data->totalTime = ((float)mad_timer_count(duration, data->totalTime = ((float)mad_timer_count(duration,
MAD_UNITS_MILLISECONDS))/1000; MAD_UNITS_MILLISECONDS))
/ 1000;
data->maxFrames = xing.frames; data->maxFrames = xing.frames;
} }
} } else {
else {
size_t offset = data->inStream->offset; size_t offset = data->inStream->offset;
mad_timer_t duration = data->frame.header.duration; mad_timer_t duration = data->frame.header.duration;
float frameTime = ((float)mad_timer_count(duration, float frameTime = ((float)mad_timer_count(duration,
MAD_UNITS_MILLISECONDS))/1000; MAD_UNITS_MILLISECONDS))
/ 1000;
if (data->stream.this_frame != NULL) { if (data->stream.this_frame != NULL) {
offset -= data->stream.bufend - data->stream.this_frame; offset -= data->stream.bufend - data->stream.this_frame;
} } else {
else {
offset -= data->stream.bufend - data->stream.buffer; offset -= data->stream.bufend - data->stream.buffer;
} }
if (data->inStream->size >= offset) { if (data->inStream->size >= offset) {
data->totalTime = ((data->inStream->size-offset)*8.0)/ data->totalTime =
(data->frame).header.bitrate; ((data->inStream->size -
offset) * 8.0) / (data->frame).header.bitrate;
data->maxFrames = data->maxFrames =
data->totalTime / frameTime + FRAMES_CUSHION; data->totalTime / frameTime + FRAMES_CUSHION;
} } else {
else {
data->maxFrames = FRAMES_CUSHION; data->maxFrames = FRAMES_CUSHION;
data->totalTime = 0; data->totalTime = 0;
} }
@ -571,25 +618,32 @@ static int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc,
return 0; return 0;
} }
static void mp3DecodeDataFinalize(mp3DecodeData * data) { static void mp3DecodeDataFinalize(mp3DecodeData * data)
{
mad_synth_finish(&data->synth); mad_synth_finish(&data->synth);
mad_frame_finish(&data->frame); mad_frame_finish(&data->frame);
mad_stream_finish(&data->stream); mad_stream_finish(&data->stream);
if(data->frameOffset) free(data->frameOffset); if (data->frameOffset)
if(data->times) free(data->times); free(data->frameOffset);
if (data->times)
free(data->times);
} }
/* this is primarily used for getting total time for tags */ /* this is primarily used for getting total time for tags */
static int getMp3TotalTime(char * file) { static int getMp3TotalTime(char *file)
{
InputStream inStream; InputStream inStream;
mp3DecodeData data; mp3DecodeData data;
int ret; int ret;
if(openInputStream(&inStream, file) < 0) return -1; if (openInputStream(&inStream, file) < 0)
return -1;
initMp3DecodeData(&data, &inStream); initMp3DecodeData(&data, &inStream);
if(decodeFirstFrame(&data, NULL, NULL,NULL)<0) ret = -1; if (decodeFirstFrame(&data, NULL, NULL, NULL) < 0)
else ret = data.totalTime+0.5; ret = -1;
else
ret = data.totalTime + 0.5;
mp3DecodeDataFinalize(&data); mp3DecodeDataFinalize(&data);
closeInputStream(&inStream); closeInputStream(&inStream);
@ -597,20 +651,24 @@ static int getMp3TotalTime(char * file) {
} }
static int openMp3FromInputStream(InputStream * inStream, mp3DecodeData * data, static int openMp3FromInputStream(InputStream * inStream, mp3DecodeData * data,
DecoderControl * dc, MpdTag ** tag, ReplayGainInfo ** replayGainInfo) DecoderControl * dc, MpdTag ** tag,
ReplayGainInfo ** replayGainInfo)
{ {
initMp3DecodeData(data, inStream); initMp3DecodeData(data, inStream);
*tag = NULL; *tag = NULL;
if (decodeFirstFrame(data, dc, tag, replayGainInfo) < 0) { if (decodeFirstFrame(data, dc, tag, replayGainInfo) < 0) {
mp3DecodeDataFinalize(data); mp3DecodeDataFinalize(data);
if(tag && *tag) freeMpdTag(*tag); if (tag && *tag)
freeMpdTag(*tag);
return -1; return -1;
} }
return 0; return 0;
} }
static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc, ReplayGainInfo ** replayGainInfo) { static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
ReplayGainInfo ** replayGainInfo)
{
int i; int i;
int ret; int ret;
int skip; int skip;
@ -620,23 +678,23 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
data->bitRate = (data->frame).header.bitrate; data->bitRate = (data->frame).header.bitrate;
if (data->currentFrame >= data->maxFrames) { if (data->currentFrame >= data->maxFrames) {
data->currentFrame = data->maxFrames - 1; data->currentFrame = data->maxFrames - 1;
} } else
else data->highestFrame++; data->highestFrame++;
data->frameOffset[data->currentFrame] = data->inStream->offset; data->frameOffset[data->currentFrame] = data->inStream->offset;
if (data->stream.this_frame != NULL) { if (data->stream.this_frame != NULL) {
data->frameOffset[data->currentFrame] -= data->frameOffset[data->currentFrame] -=
data->stream.bufend- data->stream.bufend - data->stream.this_frame;
data->stream.this_frame; } else {
}
else {
data->frameOffset[data->currentFrame] -= data->frameOffset[data->currentFrame] -=
data->stream.bufend - data->stream.buffer; data->stream.bufend - data->stream.buffer;
} }
data->times[data->currentFrame] = data->timer; data->times[data->currentFrame] = data->timer;
} } else
else data->timer = data->times[data->currentFrame]; data->timer = data->times[data->currentFrame];
data->currentFrame++; data->currentFrame++;
data->elapsedTime = ((float)mad_timer_count(data->timer,MAD_UNITS_MILLISECONDS))/1000; data->elapsedTime =
((float)mad_timer_count(data->timer, MAD_UNITS_MILLISECONDS)) /
1000;
switch (data->muteFrame) { switch (data->muteFrame) {
case MUTEFRAME_SKIP: case MUTEFRAME_SKIP:
@ -673,15 +731,26 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
sample = (mpd_sint16 *) data->outputPtr; sample = (mpd_sint16 *) data->outputPtr;
*sample = (mpd_sint16) audio_linear_dither(16, *sample = (mpd_sint16) audio_linear_dither(16,
(data->synth).pcm.samples[0][i], (data->
&(data->dither)); synth).pcm.
samples[0]
[i],
&(data->
dither));
data->outputPtr += 2; data->outputPtr += 2;
if (MAD_NCHANNELS(&(data->frame).header) == 2) { if (MAD_NCHANNELS(&(data->frame).header) == 2) {
sample = (mpd_sint16 *) data->outputPtr; sample = (mpd_sint16 *) data->outputPtr;
*sample = (mpd_sint16) audio_linear_dither(16, *sample = (mpd_sint16) audio_linear_dither(16,
(data->synth).pcm.samples[1][i], (data->
&(data->dither)); synth).
pcm.
samples
[1]
[i],
&
(data->
dither));
data->outputPtr += 2; data->outputPtr += 2;
} }
@ -690,13 +759,18 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
ret = sendDataToOutputBuffer(cb, ret = sendDataToOutputBuffer(cb,
data->inStream, data->inStream,
dc, dc,
data->inStream->seekable, data->inStream->
seekable,
data->outputBuffer, data->outputBuffer,
data->outputPtr - data->outputPtr -
data->outputBuffer, data->outputBuffer,
data->elapsedTime, data->elapsedTime,
data->bitRate/1000, data->bitRate /
(replayGainInfo != NULL) ? *replayGainInfo : NULL); 1000,
(replayGainInfo !=
NULL) ?
*replayGainInfo :
NULL);
if (ret == OUTPUT_BUFFER_DC_STOP) { if (ret == OUTPUT_BUFFER_DC_STOP) {
data->flush = 0; data->flush = 0;
return DECODE_BREAK; return DECODE_BREAK;
@ -704,7 +778,8 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
data->outputPtr = data->outputBuffer; data->outputPtr = data->outputBuffer;
if(ret == OUTPUT_BUFFER_DC_SEEK) break; if (ret == OUTPUT_BUFFER_DC_SEEK)
break;
} }
} }
@ -713,24 +788,23 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
data->muteFrame = MUTEFRAME_SEEK; data->muteFrame = MUTEFRAME_SEEK;
while (i < data->highestFrame && dc->seekWhere > while (i < data->highestFrame && dc->seekWhere >
((float)mad_timer_count(data->times[i], ((float)mad_timer_count(data->times[i],
MAD_UNITS_MILLISECONDS))/1000) MAD_UNITS_MILLISECONDS))
{ / 1000) {
i++; i++;
} }
if (i < data->highestFrame) { if (i < data->highestFrame) {
if (seekMp3InputBuffer(data, if (seekMp3InputBuffer(data,
data->frameOffset[i]) == 0) data->frameOffset[i]) ==
{ 0) {
data->outputPtr = data->outputBuffer; data->outputPtr = data->outputBuffer;
clearOutputBuffer(cb); clearOutputBuffer(cb);
data->currentFrame = i; data->currentFrame = i;
} } else
else dc->seekError = 1; dc->seekError = 1;
data->muteFrame = 0; data->muteFrame = 0;
dc->seek = 0; dc->seek = 0;
} }
} } else if (dc->seek && !data->inStream->seekable) {
else if(dc->seek && !data->inStream->seekable) {
dc->seek = 0; dc->seek = 0;
dc->seekError = 1; dc->seekError = 1;
} }
@ -738,41 +812,53 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
while (1) { while (1) {
skip = 0; skip = 0;
while((ret = decodeNextFrameHeader(data, NULL, replayGainInfo))==DECODE_CONT && while ((ret =
!dc->stop); decodeNextFrameHeader(data, NULL,
if(ret==DECODE_BREAK || dc->stop || dc->seek) break; replayGainInfo)) == DECODE_CONT
else if(ret==DECODE_SKIP) skip = 1; && !dc->stop) ;
if (ret == DECODE_BREAK || dc->stop || dc->seek)
break;
else if (ret == DECODE_SKIP)
skip = 1;
if (!data->muteFrame) { if (!data->muteFrame) {
while ((ret = decodeNextFrame(data)) == DECODE_CONT && while ((ret = decodeNextFrame(data)) == DECODE_CONT &&
!dc->stop && !dc->seek) ; !dc->stop && !dc->seek) ;
if(ret==DECODE_BREAK || dc->stop || dc->seek) break; if (ret == DECODE_BREAK || dc->stop || dc->seek)
break;
} }
if(!skip && ret==DECODE_OK) break; if (!skip && ret == DECODE_OK)
break;
} }
if(dc->stop) return DECODE_BREAK; if (dc->stop)
return DECODE_BREAK;
return ret; return ret;
} }
static void initAudioFormatFromMp3DecodeData(mp3DecodeData * data, AudioFormat * af) { static void initAudioFormatFromMp3DecodeData(mp3DecodeData * data,
AudioFormat * af)
{
af->bits = 16; af->bits = 16;
af->sampleRate = (data->frame).header.samplerate; af->sampleRate = (data->frame).header.samplerate;
af->channels = MAD_NCHANNELS(&(data->frame).header); af->channels = MAD_NCHANNELS(&(data->frame).header);
} }
static int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) { static int mp3_decode(OutputBuffer * cb, DecoderControl * dc,
InputStream * inStream)
{
mp3DecodeData data; mp3DecodeData data;
MpdTag *tag = NULL; MpdTag *tag = NULL;
ReplayGainInfo *replayGainInfo = NULL; ReplayGainInfo *replayGainInfo = NULL;
if(openMp3FromInputStream(inStream, &data, dc, &tag, &replayGainInfo) < 0) { if (openMp3FromInputStream(inStream, &data, dc, &tag, &replayGainInfo) <
0) {
closeInputStream(inStream); closeInputStream(inStream);
if (!dc->stop) { if (!dc->stop) {
ERROR("Input does not appear to be a mp3 bit stream.\n"); ERROR
("Input does not appear to be a mp3 bit stream.\n");
return -1; return -1;
} } else {
else {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
} }
@ -785,32 +871,28 @@ static int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inSt
dc->totalTime = data.totalTime; dc->totalTime = data.totalTime;
if (inStream->metaTitle) { if (inStream->metaTitle) {
if(tag) freeMpdTag(tag); if (tag)
freeMpdTag(tag);
tag = newMpdTag(); tag = newMpdTag();
addItemToMpdTag(tag, TAG_ITEM_TITLE, inStream->metaTitle); addItemToMpdTag(tag, TAG_ITEM_TITLE, inStream->metaTitle);
free(inStream->metaTitle); free(inStream->metaTitle);
inStream->metaTitle = NULL; inStream->metaTitle = NULL;
if (inStream->metaName) { if (inStream->metaName) {
addItemToMpdTag(tag, TAG_ITEM_NAME, addItemToMpdTag(tag, TAG_ITEM_NAME, inStream->metaName);
inStream->metaName);
} }
copyMpdTagToOutputBuffer(cb, tag); copyMpdTagToOutputBuffer(cb, tag);
freeMpdTag(tag); freeMpdTag(tag);
} } else if (tag) {
else if(tag) {
if (inStream->metaName) { if (inStream->metaName) {
clearItemsFromMpdTag(tag, TAG_ITEM_NAME); clearItemsFromMpdTag(tag, TAG_ITEM_NAME);
addItemToMpdTag(tag, TAG_ITEM_NAME, addItemToMpdTag(tag, TAG_ITEM_NAME, inStream->metaName);
inStream->metaName);
} }
copyMpdTagToOutputBuffer(cb, tag); copyMpdTagToOutputBuffer(cb, tag);
freeMpdTag(tag); freeMpdTag(tag);
} } else if (inStream->metaName) {
else if(inStream->metaName) {
tag = newMpdTag(); tag = newMpdTag();
if (inStream->metaName) { if (inStream->metaName) {
addItemToMpdTag(tag, TAG_ITEM_NAME, addItemToMpdTag(tag, TAG_ITEM_NAME, inStream->metaName);
inStream->metaName);
} }
copyMpdTagToOutputBuffer(cb, tag); copyMpdTagToOutputBuffer(cb, tag);
freeMpdTag(tag); freeMpdTag(tag);
@ -829,7 +911,8 @@ static int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inSt
replayGainInfo); replayGainInfo);
} }
if (replayGainInfo) freeReplayGainInfo(replayGainInfo); if (replayGainInfo)
freeReplayGainInfo(replayGainInfo);
closeInputStream(inStream); closeInputStream(inStream);
@ -844,13 +927,14 @@ static int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inSt
if (dc->stop) { if (dc->stop) {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
} } else
else dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
return 0; return 0;
} }
static MpdTag * mp3_tagDup(char * file) { static MpdTag *mp3_tagDup(char *file)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
int time; int time;
@ -859,11 +943,12 @@ static MpdTag * mp3_tagDup(char * file) {
time = getMp3TotalTime(file); time = getMp3TotalTime(file);
if (time >= 0) { if (time >= 0) {
if(!ret) ret = newMpdTag(); if (!ret)
ret = newMpdTag();
ret->time = time; ret->time = time;
} } else {
else { DEBUG("mp3_tagDup: Failed to get total song time from: %s\n",
DEBUG("mp3_tagDup: Failed to get total song time from: %s\n", file); file);
} }
return ret; return ret;
@ -872,8 +957,7 @@ static MpdTag * mp3_tagDup(char * file) {
static char *mp3_suffixes[] = { "mp3", NULL }; static char *mp3_suffixes[] = { "mp3", NULL };
static char *mp3_mimeTypes[] = { "audio/mpeg", NULL }; static char *mp3_mimeTypes[] = { "audio/mpeg", NULL };
InputPlugin mp3Plugin = InputPlugin mp3Plugin = {
{
"mp3", "mp3",
NULL, NULL,
NULL, NULL,
@ -887,8 +971,7 @@ InputPlugin mp3Plugin =
}; };
#else #else
InputPlugin mp3Plugin = InputPlugin mp3Plugin = {
{
NULL, NULL,
NULL, NULL,
NULL, NULL,

View File

@ -37,7 +37,8 @@
/* all code here is either based on or copied from FAAD2's frontend code */ /* all code here is either based on or copied from FAAD2's frontend code */
static int mp4_getAACTrack(mp4ff_t *infile) { static int mp4_getAACTrack(mp4ff_t * infile)
{
/* find AAC track */ /* find AAC track */
int i, rc; int i, rc;
int numTracks = mp4ff_total_tracks(infile); int numTracks = mp4ff_total_tracks(infile);
@ -60,11 +61,13 @@ static int mp4_getAACTrack(mp4ff_t *infile) {
rc = AudioSpecificConfig(buff, *buff_size, &mp4ASC); rc = AudioSpecificConfig(buff, *buff_size, &mp4ASC);
#else #else
rc = AudioSpecificConfig(buff, &dummy1_32, &dummy2_8, rc = AudioSpecificConfig(buff, &dummy1_32, &dummy2_8,
&dummy3_8, &dummy4_8, &dummy5_8, &dummy3_8, &dummy4_8,
&dummy6_8, &dummy7_8, &dummy8_8); &dummy5_8, &dummy6_8,
&dummy7_8, &dummy8_8);
#endif #endif
free(buff); free(buff);
if (rc < 0) continue; if (rc < 0)
continue;
return i; return i;
} }
} }
@ -79,11 +82,13 @@ static uint32_t mp4_inputStreamReadCallback(void *inStream, void *buffer,
return readFromInputStream((InputStream *) inStream, buffer, 1, length); return readFromInputStream((InputStream *) inStream, buffer, 1, length);
} }
static uint32_t mp4_inputStreamSeekCallback(void *inStream, uint64_t position) { static uint32_t mp4_inputStreamSeekCallback(void *inStream, uint64_t position)
{
return seekInputStream((InputStream *) inStream, position, SEEK_SET); return seekInputStream((InputStream *) inStream, position, SEEK_SET);
} }
static faacDecHandle * openConfigureFaad() { static faacDecHandle *openConfigureFaad()
{
faacDecConfigurationPtr config; faacDecConfigurationPtr config;
faacDecHandle decoder = faacDecOpen(); faacDecHandle decoder = faacDecOpen();
@ -100,7 +105,8 @@ static faacDecHandle * openConfigureFaad() {
return decoder; return decoder;
} }
static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) { static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
{
mp4ff_t *mp4fh; mp4ff_t *mp4fh;
mp4ff_callback_t *mp4cb; mp4ff_callback_t *mp4cb;
int32_t track; int32_t track;
@ -163,9 +169,9 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
mp4BufferSize = 0; mp4BufferSize = 0;
mp4ff_get_decoder_config(mp4fh, track, &mp4Buffer, &mp4BufferSize); mp4ff_get_decoder_config(mp4fh, track, &mp4Buffer, &mp4BufferSize);
if(faacDecInit2(decoder,mp4Buffer,mp4BufferSize,&sampleRate,&channels) if (faacDecInit2
< 0) (decoder, mp4Buffer, mp4BufferSize, &sampleRate, &channels)
{ < 0) {
ERROR("Error not a AAC stream.\n"); ERROR("Error not a AAC stream.\n");
faacDecClose(decoder); faacDecClose(decoder);
mp4ff_close(mp4fh); mp4ff_close(mp4fh);
@ -179,7 +185,8 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
time = mp4ff_get_track_duration_use_offsets(mp4fh, track); time = mp4ff_get_track_duration_use_offsets(mp4fh, track);
scale = mp4ff_time_scale(mp4fh, track); scale = mp4ff_time_scale(mp4fh, track);
if(mp4Buffer) free(mp4Buffer); if (mp4Buffer)
free(mp4Buffer);
if (scale < 0) { if (scale < 0) {
ERROR("Error getting audio format of mp4 AAC track.\n"); ERROR("Error getting audio format of mp4 AAC track.\n");
@ -198,13 +205,14 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
seekTable = malloc(sizeof(float) * numSamples); seekTable = malloc(sizeof(float) * numSamples);
for (sampleId = 0; sampleId < numSamples && !eof; sampleId++) { for (sampleId = 0; sampleId < numSamples && !eof; sampleId++) {
if(dc->seek) seeking = 1; if (dc->seek)
seeking = 1;
if (seeking && seekTableEnd > 1 && if (seeking && seekTableEnd > 1 &&
seekTable[seekTableEnd]>=dc->seekWhere) seekTable[seekTableEnd] >= dc->seekWhere) {
{
int i = 2; int i = 2;
while(seekTable[i]<dc->seekWhere) i++; while (seekTable[i] < dc->seekWhere)
i++;
sampleId = i - 1; sampleId = i - 1;
time = seekTable[sampleId]; time = seekTable[sampleId];
} }
@ -217,12 +225,16 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
seekTableEnd = sampleId; seekTableEnd = sampleId;
} }
if(sampleId==0) dur = 0; if (sampleId == 0)
if(offset>dur) dur = 0; dur = 0;
else dur-=offset; if (offset > dur)
dur = 0;
else
dur -= offset;
time += ((float)dur) / scale; time += ((float)dur) / scale;
if(seeking && time>dc->seekWhere) seekPositionFound = 1; if (seeking && time > dc->seekWhere)
seekPositionFound = 1;
if (seeking && seekPositionFound) { if (seeking && seekPositionFound) {
seekPositionFound = 0; seekPositionFound = 0;
@ -231,15 +243,14 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
dc->seek = 0; dc->seek = 0;
} }
if(seeking) continue; if (seeking)
continue;
if (mp4ff_read_sample(mp4fh, track, sampleId, &mp4Buffer, if (mp4ff_read_sample(mp4fh, track, sampleId, &mp4Buffer,
&mp4BufferSize) == 0) &mp4BufferSize) == 0) {
{
eof = 1; eof = 1;
continue; continue;
} }
#ifdef HAVE_FAAD_BUFLEN_FUNCS #ifdef HAVE_FAAD_BUFLEN_FUNCS
sampleBuffer = faacDecDecode(decoder, &frameInfo, mp4Buffer, sampleBuffer = faacDecDecode(decoder, &frameInfo, mp4Buffer,
mp4BufferSize); mp4BufferSize);
@ -247,7 +258,8 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
sampleBuffer = faacDecDecode(decoder, &frameInfo, mp4Buffer); sampleBuffer = faacDecDecode(decoder, &frameInfo, mp4Buffer);
#endif #endif
if(mp4Buffer) free(mp4Buffer); if (mp4Buffer)
free(mp4Buffer);
if (frameInfo.error > 0) { if (frameInfo.error > 0) {
ERROR("error decoding MP4 file: %s\n", path); ERROR("error decoding MP4 file: %s\n", path);
ERROR("faad2 error: %s\n", ERROR("faad2 error: %s\n",
@ -282,7 +294,6 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
frameInfo.samples / 1000 + 0.5; frameInfo.samples / 1000 + 0.5;
} }
sampleBufferLen = sampleCount * 2; sampleBufferLen = sampleCount * 2;
sampleBuffer += offset * channels * 2; sampleBuffer += offset * channels * 2;
@ -301,7 +312,8 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
closeInputStream(&inStream); closeInputStream(&inStream);
free(mp4cb); free(mp4cb);
if(dc->state != DECODE_STATE_DECODE) return -1; if (dc->state != DECODE_STATE_DECODE)
return -1;
if (dc->seek && seeking) { if (dc->seek && seeking) {
clearOutputBuffer(cb); clearOutputBuffer(cb);
@ -309,13 +321,15 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
} }
flushOutputBuffer(cb); flushOutputBuffer(cb);
if(dc->stop) dc->stop = 0; if (dc->stop)
dc->stop = 0;
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
return 0; return 0;
} }
static MpdTag * mp4DataDup(char * file, int * mp4MetadataFound) { static MpdTag *mp4DataDup(char *file, int *mp4MetadataFound)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
InputStream inStream; InputStream inStream;
mp4ff_t *mp4fh; mp4ff_t *mp4fh;
@ -373,28 +387,22 @@ static MpdTag * mp4DataDup(char * file, int * mp4MetadataFound) {
if (0 == strcasecmp("artist", item)) { if (0 == strcasecmp("artist", item)) {
addItemToMpdTag(ret, TAG_ITEM_ARTIST, value); addItemToMpdTag(ret, TAG_ITEM_ARTIST, value);
*mp4MetadataFound = 1; *mp4MetadataFound = 1;
} } else if (0 == strcasecmp("title", item)) {
else if(0 == strcasecmp("title", item)) {
addItemToMpdTag(ret, TAG_ITEM_TITLE, value); addItemToMpdTag(ret, TAG_ITEM_TITLE, value);
*mp4MetadataFound = 1; *mp4MetadataFound = 1;
} } else if (0 == strcasecmp("album", item)) {
else if(0 == strcasecmp("album", item)) {
addItemToMpdTag(ret, TAG_ITEM_ALBUM, value); addItemToMpdTag(ret, TAG_ITEM_ALBUM, value);
*mp4MetadataFound = 1; *mp4MetadataFound = 1;
} } else if (0 == strcasecmp("track", item)) {
else if(0 == strcasecmp("track", item)) {
addItemToMpdTag(ret, TAG_ITEM_TRACK, value); addItemToMpdTag(ret, TAG_ITEM_TRACK, value);
*mp4MetadataFound = 1; *mp4MetadataFound = 1;
} } else if (0 == strcasecmp("disc", item)) { /* Is that the correct id? */
else if(0 == strcasecmp("disc", item)) { /* Is that the correct id? */
addItemToMpdTag(ret, TAG_ITEM_DISC, value); addItemToMpdTag(ret, TAG_ITEM_DISC, value);
*mp4MetadataFound = 1; *mp4MetadataFound = 1;
} } else if (0 == strcasecmp("genre", item)) {
else if(0 == strcasecmp("genre", item)) {
addItemToMpdTag(ret, TAG_ITEM_GENRE, value); addItemToMpdTag(ret, TAG_ITEM_GENRE, value);
*mp4MetadataFound = 1; *mp4MetadataFound = 1;
} } else if (0 == strcasecmp("date", item)) {
else if(0 == strcasecmp("date", item)) {
addItemToMpdTag(ret, TAG_ITEM_DATE, value); addItemToMpdTag(ret, TAG_ITEM_DATE, value);
*mp4MetadataFound = 1; *mp4MetadataFound = 1;
} }
@ -410,12 +418,14 @@ static MpdTag * mp4DataDup(char * file, int * mp4MetadataFound) {
return ret; return ret;
} }
static MpdTag * mp4TagDup(char * file) { static MpdTag *mp4TagDup(char *file)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
int mp4MetadataFound = 0; int mp4MetadataFound = 0;
ret = mp4DataDup(file, &mp4MetadataFound); ret = mp4DataDup(file, &mp4MetadataFound);
if(!ret) return NULL; if (!ret)
return NULL;
if (!mp4MetadataFound) { if (!mp4MetadataFound) {
MpdTag *temp = id3Dup(file); MpdTag *temp = id3Dup(file);
if (temp) { if (temp) {
@ -430,8 +440,7 @@ static MpdTag * mp4TagDup(char * file) {
static char *mp4Suffixes[] = { "m4a", "mp4", NULL }; static char *mp4Suffixes[] = { "m4a", "mp4", NULL };
InputPlugin mp4Plugin = InputPlugin mp4Plugin = {
{
"mp4", "mp4",
NULL, NULL,
NULL, NULL,
@ -446,8 +455,7 @@ InputPlugin mp4Plugin =
#else #else
InputPlugin mp4Plugin = InputPlugin mp4Plugin = {
{
NULL, NULL,
NULL, NULL,
NULL, NULL,

View File

@ -41,49 +41,54 @@ typedef struct _MpcCallbackData {
DecoderControl *dc; DecoderControl *dc;
} MpcCallbackData; } MpcCallbackData;
static mpc_int32_t mpc_read_cb(void * vdata, void * ptr, mpc_int32_t size) { static mpc_int32_t mpc_read_cb(void *vdata, void *ptr, mpc_int32_t size)
{
mpc_int32_t ret = 0; mpc_int32_t ret = 0;
MpcCallbackData *data = (MpcCallbackData *) vdata; MpcCallbackData *data = (MpcCallbackData *) vdata;
while (1) { while (1) {
ret = readFromInputStream(data->inStream, ptr, 1, size); ret = readFromInputStream(data->inStream, ptr, 1, size);
if (ret == 0 && !inputStreamAtEOF(data->inStream) && if (ret == 0 && !inputStreamAtEOF(data->inStream) &&
(data->dc && !data->dc->stop)) (data->dc && !data->dc->stop)) {
{
my_usleep(10000); my_usleep(10000);
} } else
else break; break;
} }
return ret; return ret;
} }
static mpc_bool_t mpc_seek_cb(void * vdata, mpc_int32_t offset) { static mpc_bool_t mpc_seek_cb(void *vdata, mpc_int32_t offset)
{
MpcCallbackData *data = (MpcCallbackData *) vdata; MpcCallbackData *data = (MpcCallbackData *) vdata;
return seekInputStream(data->inStream, offset, SEEK_SET) < 0 ? 0 : 1; return seekInputStream(data->inStream, offset, SEEK_SET) < 0 ? 0 : 1;
} }
static mpc_int32_t mpc_tell_cb(void * vdata) { static mpc_int32_t mpc_tell_cb(void *vdata)
{
MpcCallbackData *data = (MpcCallbackData *) vdata; MpcCallbackData *data = (MpcCallbackData *) vdata;
return (long)(data->inStream->offset); return (long)(data->inStream->offset);
} }
static mpc_bool_t mpc_canseek_cb(void * vdata) { static mpc_bool_t mpc_canseek_cb(void *vdata)
{
MpcCallbackData *data = (MpcCallbackData *) vdata; MpcCallbackData *data = (MpcCallbackData *) vdata;
return data->inStream->seekable; return data->inStream->seekable;
} }
static mpc_int32_t mpc_getsize_cb(void * vdata) { static mpc_int32_t mpc_getsize_cb(void *vdata)
{
MpcCallbackData *data = (MpcCallbackData *) vdata; MpcCallbackData *data = (MpcCallbackData *) vdata;
return data->inStream->size; return data->inStream->size;
} }
/* this _looks_ performance-critical, don't de-inline -- eric */ /* this _looks_ performance-critical, don't de-inline -- eric */
static inline mpd_sint16 convertSample(MPC_SAMPLE_FORMAT sample) { static inline mpd_sint16 convertSample(MPC_SAMPLE_FORMAT sample)
{
/* only doing 16-bit audio for now */ /* only doing 16-bit audio for now */
mpd_sint32 val; mpd_sint32 val;
@ -95,8 +100,7 @@ static inline mpd_sint16 convertSample(MPC_SAMPLE_FORMAT sample) {
if (ssample > 0) { if (ssample > 0) {
sample <<= shift; sample <<= shift;
} } else if (shift < 0) {
else if ( shift < 0 ) {
sample >>= -shift; sample >>= -shift;
} }
val = sample; val = sample;
@ -106,8 +110,10 @@ static inline mpd_sint16 convertSample(MPC_SAMPLE_FORMAT sample) {
val = sample * float_scale; val = sample * float_scale;
#endif #endif
if( val < clip_min) val = clip_min; if (val < clip_min)
else if ( val > clip_max ) val = clip_max; val = clip_min;
else if (val > clip_max)
val = clip_max;
return val; return val;
} }
@ -154,8 +160,7 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
if (!dc->stop) { if (!dc->stop) {
ERROR("Not a valid musepack stream"); ERROR("Not a valid musepack stream");
return -1; return -1;
} } else {
else {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
} }
@ -168,8 +173,7 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
closeInputStream(inStream); closeInputStream(inStream);
if (!dc->stop) { if (!dc->stop) {
ERROR("Not a valid musepack stream"); ERROR("Not a valid musepack stream");
} } else {
else {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
} }
@ -197,8 +201,8 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
if (mpc_decoder_seek_sample(&decoder, samplePos)) { if (mpc_decoder_seek_sample(&decoder, samplePos)) {
clearOutputBuffer(cb); clearOutputBuffer(cb);
chunkpos = 0; chunkpos = 0;
} } else
else dc->seekError = 1; dc->seekError = 1;
dc->seek = 0; dc->seek = 0;
} }
@ -228,15 +232,13 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
dc->audioFormat.sampleRate; dc->audioFormat.sampleRate;
bitRate = vbrUpdateBits * bitRate = vbrUpdateBits *
dc->audioFormat.sampleRate / dc->audioFormat.sampleRate / 1152 / 1000;
1152 / 1000;
sendDataToOutputBuffer(cb, inStream, dc, sendDataToOutputBuffer(cb, inStream, dc,
inStream->seekable, inStream->seekable,
chunk, chunkpos, chunk, chunkpos,
time, time,
bitRate, bitRate, replayGainInfo);
replayGainInfo);
chunkpos = 0; chunkpos = 0;
s16 = (mpd_sint16 *) chunk; s16 = (mpd_sint16 *) chunk;
@ -251,7 +253,8 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
if (!dc->stop && chunkpos > 0) { if (!dc->stop && chunkpos > 0) {
time = ((float)samplePos) / dc->audioFormat.sampleRate; time = ((float)samplePos) / dc->audioFormat.sampleRate;
bitRate = vbrUpdateBits * dc->audioFormat.sampleRate / 1152 / 1000; bitRate =
vbrUpdateBits * dc->audioFormat.sampleRate / 1152 / 1000;
sendDataToOutputBuffer(cb, NULL, dc, inStream->seekable, sendDataToOutputBuffer(cb, NULL, dc, inStream->seekable,
chunk, chunkpos, time, bitRate, chunk, chunkpos, time, bitRate,
@ -267,15 +270,15 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
if (dc->stop) { if (dc->stop) {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
} } else {
else {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
} }
return 0; return 0;
} }
static float mpcGetTime(char * file) { static float mpcGetTime(char *file)
{
InputStream inStream; InputStream inStream;
float time = -1; float time = -1;
@ -312,18 +315,22 @@ static float mpcGetTime(char * file) {
return time; return time;
} }
static MpdTag * mpcTagDup(char * file) { static MpdTag *mpcTagDup(char *file)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
float time = mpcGetTime(file); float time = mpcGetTime(file);
if (time < 0) { if (time < 0) {
DEBUG("mpcTagDup: Failed to get Songlength of file: %s\n",file); DEBUG("mpcTagDup: Failed to get Songlength of file: %s\n",
file);
return NULL; return NULL;
} }
ret = apeDup(file); ret = apeDup(file);
if(!ret) ret = id3Dup(file); if (!ret)
if(!ret) ret = newMpdTag(); ret = id3Dup(file);
if (!ret)
ret = newMpdTag();
ret->time = time; ret->time = time;
return ret; return ret;
@ -332,8 +339,7 @@ static MpdTag * mpcTagDup(char * file) {
static char *mpcSuffixes[] = { "mpc", NULL }; static char *mpcSuffixes[] = { "mpc", NULL };
static char *mpcMimeTypes[] = { NULL }; static char *mpcMimeTypes[] = { NULL };
InputPlugin mpcPlugin = InputPlugin mpcPlugin = {
{
"mpc", "mpc",
NULL, NULL,
NULL, NULL,
@ -348,8 +354,7 @@ InputPlugin mpcPlugin =
#else #else
InputPlugin mpcPlugin = InputPlugin mpcPlugin = {
{
NULL, NULL,
NULL, NULL,
NULL, NULL,

View File

@ -51,9 +51,13 @@ static void oggflac_cleanup(InputStream * inStream,
closeInputStream(inStream); closeInputStream(inStream);
} }
static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb( static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb(const
const OggFLAC__SeekableStreamDecoder * decoder, OggFLAC__SeekableStreamDecoder
FLAC__byte buf[], unsigned * bytes, void * fdata) { * decoder,
FLAC__byte buf[],
unsigned *bytes,
void *fdata)
{
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
size_t r; size_t r;
@ -73,9 +77,11 @@ static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb(
return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
} }
static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb( static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb(const
const OggFLAC__SeekableStreamDecoder * decoder, OggFLAC__SeekableStreamDecoder
FLAC__uint64 offset, void * fdata) * decoder,
FLAC__uint64 offset,
void *fdata)
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
@ -86,9 +92,11 @@ static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb(
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
} }
static OggFLAC__SeekableStreamDecoderTellStatus of_tell_cb( static OggFLAC__SeekableStreamDecoderTellStatus of_tell_cb(const
const OggFLAC__SeekableStreamDecoder * decoder, OggFLAC__SeekableStreamDecoder
FLAC__uint64 * offset, void * fdata) * decoder,
FLAC__uint64 *
offset, void *fdata)
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
@ -97,9 +105,12 @@ static OggFLAC__SeekableStreamDecoderTellStatus of_tell_cb(
return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
} }
static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb( static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(const
const OggFLAC__SeekableStreamDecoder * decoder, OggFLAC__SeekableStreamDecoder
FLAC__uint64 * length, void * fdata) * decoder,
FLAC__uint64 *
length,
void *fdata)
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
@ -109,7 +120,8 @@ static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(
} }
static FLAC__bool of_EOF_cb(const OggFLAC__SeekableStreamDecoder * decoder, static FLAC__bool of_EOF_cb(const OggFLAC__SeekableStreamDecoder * decoder,
void * fdata) { void *fdata)
{
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
if (inputStreamAtEOF(data->inStream) == 1) if (inputStreamAtEOF(data->inStream) == 1)
@ -154,10 +166,12 @@ static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state)
} }
} }
static FLAC__StreamDecoderWriteStatus oggflacWrite( static FLAC__StreamDecoderWriteStatus oggflacWrite(const
const OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoder
const FLAC__Frame *frame, const FLAC__int32 * const buf[], * decoder,
void * vdata) const FLAC__Frame * frame,
const FLAC__int32 *
const buf[], void *vdata)
{ {
FlacData *data = (FlacData *) vdata; FlacData *data = (FlacData *) vdata;
FLAC__uint32 samples = frame->header.blocksize; FLAC__uint32 samples = frame->header.blocksize;
@ -190,11 +204,13 @@ static FLAC__StreamDecoderWriteStatus oggflacWrite(
for (i = 0; i < (data->dc->audioFormat.bits / 8); i++) { for (i = 0; i < (data->dc->audioFormat.bits / 8); i++) {
if (data->chunk_length >= FLAC_CHUNK_SIZE) { if (data->chunk_length >= FLAC_CHUNK_SIZE) {
if (flacSendChunk(data) < 0) { if (flacSendChunk(data) < 0) {
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; return
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
} }
data->chunk_length = 0; data->chunk_length = 0;
if (data->dc->seek) { if (data->dc->seek) {
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; return
FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
} }
} }
data->chunk[data->chunk_length++] = *(uc++); data->chunk[data->chunk_length++] = *(uc++);
@ -206,19 +222,18 @@ static FLAC__StreamDecoderWriteStatus oggflacWrite(
} }
/* used by TagDup */ /* used by TagDup */
static void of_metadata_dup_cb( static void of_metadata_dup_cb(const OggFLAC__SeekableStreamDecoder * decoder,
const OggFLAC__SeekableStreamDecoder * decoder,
const FLAC__StreamMetadata * block, void *vdata) const FLAC__StreamMetadata * block, void *vdata)
{ {
FlacData *data = (FlacData *) vdata; FlacData *data = (FlacData *) vdata;
switch (block->type) { switch (block->type) {
case FLAC__METADATA_TYPE_STREAMINFO: case FLAC__METADATA_TYPE_STREAMINFO:
if (!data->tag) data->tag = newMpdTag(); if (!data->tag)
data->tag = newMpdTag();
data->tag->time = ((float)block->data.stream_info. data->tag->time = ((float)block->data.stream_info.
total_samples) / total_samples) /
block->data.stream_info.sample_rate + block->data.stream_info.sample_rate + 0.5;
0.5;
return; return;
case FLAC__METADATA_TYPE_VORBIS_COMMENT: case FLAC__METADATA_TYPE_VORBIS_COMMENT:
copyVorbisCommentBlockToMpdTag(block, data->tag); copyVorbisCommentBlockToMpdTag(block, data->tag);
@ -229,13 +244,14 @@ static void of_metadata_dup_cb(
/* used by decode */ /* used by decode */
static void of_metadata_decode_cb(const OggFLAC__SeekableStreamDecoder * dec, static void of_metadata_decode_cb(const OggFLAC__SeekableStreamDecoder * dec,
const FLAC__StreamMetadata *block, void *vdata) const FLAC__StreamMetadata * block,
void *vdata)
{ {
flac_metadata_common_cb(block, (FlacData *) vdata); flac_metadata_common_cb(block, (FlacData *) vdata);
} }
static OggFLAC__SeekableStreamDecoder * full_decoder_init_and_read_metadata( static OggFLAC__SeekableStreamDecoder
FlacData * data, *full_decoder_init_and_read_metadata(FlacData * data,
unsigned int metadata_only) unsigned int metadata_only)
{ {
OggFLAC__SeekableStreamDecoder *decoder = NULL; OggFLAC__SeekableStreamDecoder *decoder = NULL;
@ -245,14 +261,13 @@ static OggFLAC__SeekableStreamDecoder * full_decoder_init_and_read_metadata(
return NULL; return NULL;
if (metadata_only) { if (metadata_only) {
s &= OggFLAC__seekable_stream_decoder_set_metadata_callback( s &= OggFLAC__seekable_stream_decoder_set_metadata_callback
decoder, of_metadata_dup_cb); (decoder, of_metadata_dup_cb);
s &= OggFLAC__seekable_stream_decoder_set_metadata_respond( s &= OggFLAC__seekable_stream_decoder_set_metadata_respond
decoder, (decoder, FLAC__METADATA_TYPE_STREAMINFO);
FLAC__METADATA_TYPE_STREAMINFO);
} else { } else {
s &= OggFLAC__seekable_stream_decoder_set_metadata_callback( s &= OggFLAC__seekable_stream_decoder_set_metadata_callback
decoder, of_metadata_decode_cb); (decoder, of_metadata_decode_cb);
} }
s &= OggFLAC__seekable_stream_decoder_set_read_callback(decoder, s &= OggFLAC__seekable_stream_decoder_set_read_callback(decoder,
@ -279,13 +294,12 @@ static OggFLAC__SeekableStreamDecoder * full_decoder_init_and_read_metadata(
goto fail; goto fail;
} }
if (OggFLAC__seekable_stream_decoder_init(decoder) != if (OggFLAC__seekable_stream_decoder_init(decoder) !=
OggFLAC__SEEKABLE_STREAM_DECODER_OK) OggFLAC__SEEKABLE_STREAM_DECODER_OK) {
{
ERROR("oggflac problem doing init()\n"); ERROR("oggflac problem doing init()\n");
goto fail; goto fail;
} }
if (!OggFLAC__seekable_stream_decoder_process_until_end_of_metadata( if (!OggFLAC__seekable_stream_decoder_process_until_end_of_metadata
decoder)) { (decoder)) {
ERROR("oggflac problem reading metadata\n"); ERROR("oggflac problem reading metadata\n");
goto fail; goto fail;
} }
@ -293,8 +307,8 @@ static OggFLAC__SeekableStreamDecoder * full_decoder_init_and_read_metadata(
return decoder; return decoder;
fail: fail:
oggflacPrintErroredState( oggflacPrintErroredState(OggFLAC__seekable_stream_decoder_get_state
OggFLAC__seekable_stream_decoder_get_state(decoder)); (decoder));
OggFLAC__seekable_stream_decoder_delete(decoder); OggFLAC__seekable_stream_decoder_delete(decoder);
return NULL; return NULL;
} }
@ -348,29 +362,27 @@ static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc,
while (1) { while (1) {
OggFLAC__seekable_stream_decoder_process_single(decoder); OggFLAC__seekable_stream_decoder_process_single(decoder);
if (OggFLAC__seekable_stream_decoder_get_state(decoder) != if (OggFLAC__seekable_stream_decoder_get_state(decoder) !=
OggFLAC__SEEKABLE_STREAM_DECODER_OK) OggFLAC__SEEKABLE_STREAM_DECODER_OK) {
{
break; break;
} }
if (dc->seek) { if (dc->seek) {
FLAC__uint64 sampleToSeek = dc->seekWhere * FLAC__uint64 sampleToSeek = dc->seekWhere *
dc->audioFormat.sampleRate + 0.5; dc->audioFormat.sampleRate + 0.5;
if(OggFLAC__seekable_stream_decoder_seek_absolute( if (OggFLAC__seekable_stream_decoder_seek_absolute
decoder, sampleToSeek)) (decoder, sampleToSeek)) {
{
clearOutputBuffer(cb); clearOutputBuffer(cb);
data.time = ((float)sampleToSeek) / data.time = ((float)sampleToSeek) /
dc->audioFormat.sampleRate; dc->audioFormat.sampleRate;
data.position = 0; data.position = 0;
} } else
else dc->seekError = 1; dc->seekError = 1;
dc->seek = 0; dc->seek = 0;
} }
} }
if (!dc->stop) { if (!dc->stop) {
oggflacPrintErroredState( oggflacPrintErroredState
OggFLAC__seekable_stream_decoder_get_state(decoder)); (OggFLAC__seekable_stream_decoder_get_state(decoder));
OggFLAC__seekable_stream_decoder_finish(decoder); OggFLAC__seekable_stream_decoder_finish(decoder);
} }
/* send last little bit */ /* send last little bit */
@ -391,8 +403,7 @@ fail:
static char *oggflac_Suffixes[] = { "ogg", NULL }; static char *oggflac_Suffixes[] = { "ogg", NULL };
static char *oggflac_mime_types[] = { "application/ogg", NULL }; static char *oggflac_mime_types[] = { "application/ogg", NULL };
InputPlugin oggflacPlugin = InputPlugin oggflacPlugin = {
{
"oggflac", "oggflac",
NULL, NULL,
NULL, NULL,
@ -407,8 +418,7 @@ InputPlugin oggflacPlugin =
#else /* !HAVE_FLAC */ #else /* !HAVE_FLAC */
InputPlugin oggflacPlugin = InputPlugin oggflacPlugin = {
{
NULL, NULL,
NULL, NULL,
NULL, NULL,
@ -422,4 +432,3 @@ InputPlugin oggflacPlugin =
}; };
#endif /* HAVE_OGGFLAC */ #endif /* HAVE_OGGFLAC */

View File

@ -73,11 +73,10 @@ static size_t ogg_read_cb(void * ptr, size_t size, size_t nmemb, void * vdata)
while (1) { while (1) {
ret = readFromInputStream(data->inStream, ptr, size, nmemb); ret = readFromInputStream(data->inStream, ptr, size, nmemb);
if (ret == 0 && !inputStreamAtEOF(data->inStream) && if (ret == 0 && !inputStreamAtEOF(data->inStream) &&
!data->dc->stop) !data->dc->stop) {
{
my_usleep(10000); my_usleep(10000);
} } else
else break; break;
} }
errno = 0; errno = 0;
/*if(ret<0) errno = ((InputStream *)inStream)->error; */ /*if(ret<0) errno = ((InputStream *)inStream)->error; */
@ -85,25 +84,29 @@ static size_t ogg_read_cb(void * ptr, size_t size, size_t nmemb, void * vdata)
return ret; return ret;
} }
static int ogg_seek_cb(void * vdata, ogg_int64_t offset, int whence) { static int ogg_seek_cb(void *vdata, ogg_int64_t offset, int whence)
{
OggCallbackData *data = (OggCallbackData *) vdata; OggCallbackData *data = (OggCallbackData *) vdata;
return seekInputStream(data->inStream, offset, whence); return seekInputStream(data->inStream, offset, whence);
} }
static int ogg_close_cb(void * vdata) { static int ogg_close_cb(void *vdata)
{
OggCallbackData *data = (OggCallbackData *) vdata; OggCallbackData *data = (OggCallbackData *) vdata;
return closeInputStream(data->inStream); return closeInputStream(data->inStream);
} }
static long ogg_tell_cb(void * vdata) { static long ogg_tell_cb(void *vdata)
{
OggCallbackData *data = (OggCallbackData *) vdata; OggCallbackData *data = (OggCallbackData *) vdata;
return (long)(data->inStream->offset); return (long)(data->inStream->offset);
} }
static char * ogg_parseComment(char * comment, char * needle) { static char *ogg_parseComment(char *comment, char *needle)
{
int len = strlen(needle); int len = strlen(needle);
if (strncasecmp(comment, needle, len) == 0 && *(comment + len) == '=') { if (strncasecmp(comment, needle, len) == 0 && *(comment + len) == '=') {
@ -113,34 +116,30 @@ static char * ogg_parseComment(char * comment, char * needle) {
return NULL; return NULL;
} }
static void ogg_getReplayGainInfo(char ** comments, ReplayGainInfo ** infoPtr) { static void ogg_getReplayGainInfo(char **comments, ReplayGainInfo ** infoPtr)
{
char *temp; char *temp;
int found = 0; int found = 0;
if(*infoPtr) freeReplayGainInfo(*infoPtr); if (*infoPtr)
freeReplayGainInfo(*infoPtr);
*infoPtr = newReplayGainInfo(); *infoPtr = newReplayGainInfo();
while (*comments) { while (*comments) {
if((temp = ogg_parseComment(*comments,"replaygain_track_gain"))) if ((temp =
{ ogg_parseComment(*comments, "replaygain_track_gain"))) {
(*infoPtr)->trackGain = atof(temp); (*infoPtr)->trackGain = atof(temp);
found = 1; found = 1;
} } else if ((temp = ogg_parseComment(*comments,
else if((temp = ogg_parseComment(*comments, "replaygain_album_gain"))) {
"replaygain_album_gain")))
{
(*infoPtr)->albumGain = atof(temp); (*infoPtr)->albumGain = atof(temp);
found = 1; found = 1;
} } else if ((temp = ogg_parseComment(*comments,
else if((temp = ogg_parseComment(*comments, "replaygain_track_peak"))) {
"replaygain_track_peak")))
{
(*infoPtr)->trackPeak = atof(temp); (*infoPtr)->trackPeak = atof(temp);
found = 1; found = 1;
} } else if ((temp = ogg_parseComment(*comments,
else if((temp = ogg_parseComment(*comments, "replaygain_album_peak"))) {
"replaygain_album_peak")))
{
(*infoPtr)->albumPeak = atof(temp); (*infoPtr)->albumPeak = atof(temp);
found = 1; found = 1;
} }
@ -158,14 +157,20 @@ static const char * VORBIS_COMMENT_TRACK_KEY = "tracknumber";
static const char *VORBIS_COMMENT_DISC_KEY = "discnumber"; static const char *VORBIS_COMMENT_DISC_KEY = "discnumber";
static unsigned int ogg_parseCommentAddToTag(char *comment, static unsigned int ogg_parseCommentAddToTag(char *comment,
unsigned int itemType, MpdTag ** tag) unsigned int itemType,
MpdTag ** tag)
{ {
const char *needle; const char *needle;
unsigned int len; unsigned int len;
switch (itemType) { switch (itemType) {
case TAG_ITEM_TRACK: needle = VORBIS_COMMENT_TRACK_KEY; break; case TAG_ITEM_TRACK:
case TAG_ITEM_DISC: needle = VORBIS_COMMENT_DISC_KEY; break; needle = VORBIS_COMMENT_TRACK_KEY;
default: needle = mpdTagItemKeys[itemType]; break;
case TAG_ITEM_DISC:
needle = VORBIS_COMMENT_DISC_KEY;
break;
default:
needle = mpdTagItemKeys[itemType];
} }
len = strlen(needle); len = strlen(needle);
@ -181,7 +186,8 @@ static unsigned int ogg_parseCommentAddToTag(char * comment,
return 0; return 0;
} }
static MpdTag * oggCommentsParse(char ** comments) { static MpdTag *oggCommentsParse(char **comments)
{
MpdTag *tag = NULL; MpdTag *tag = NULL;
while (*comments) { while (*comments) {
@ -205,7 +211,8 @@ static void putOggCommentsIntoOutputBuffer(OutputBuffer * cb, char * streamName,
if (!tag && streamName) { if (!tag && streamName) {
tag = newMpdTag(); tag = newMpdTag();
} }
if(!tag) return; if (!tag)
return;
/*if(tag->artist) printf("Artist: %s\n", tag->artist); /*if(tag->artist) printf("Artist: %s\n", tag->artist);
if(tag->album) printf("Album: %s\n", tag->album); if(tag->album) printf("Album: %s\n", tag->album);
@ -276,8 +283,7 @@ static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
ERROR("Error decoding Ogg Vorbis stream: %s\n", ERROR("Error decoding Ogg Vorbis stream: %s\n",
errorStr); errorStr);
return -1; return -1;
} } else {
else {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
} }
@ -285,7 +291,8 @@ static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
} }
dc->totalTime = ov_time_total(&vf, -1); dc->totalTime = ov_time_total(&vf, -1);
if(dc->totalTime < 0) dc->totalTime = 0; if (dc->totalTime < 0)
dc->totalTime = 0;
dc->audioFormat.bits = 16; dc->audioFormat.bits = 16;
@ -294,14 +301,13 @@ static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
if (0 == ov_time_seek_page(&vf, dc->seekWhere)) { if (0 == ov_time_seek_page(&vf, dc->seekWhere)) {
clearOutputBuffer(cb); clearOutputBuffer(cb);
chunkpos = 0; chunkpos = 0;
} } else
else dc->seekError = 1; dc->seekError = 1;
dc->seek = 0; dc->seek = 0;
} }
ret = ov_read(&vf, chunk + chunkpos, ret = ov_read(&vf, chunk + chunkpos,
OGG_CHUNK_SIZE - chunkpos, OGG_CHUNK_SIZE - chunkpos,
OGG_DECODE_USE_BIGENDIAN, OGG_DECODE_USE_BIGENDIAN, 2, 1, &current_section);
2, 1, &current_section);
if (current_section != prev_section) { if (current_section != prev_section) {
/*printf("new song!\n"); */ /*printf("new song!\n"); */
@ -325,7 +331,8 @@ static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
eof = 1; eof = 1;
break; break;
} }
if(ret == OV_HOLE) ret = 0; if (ret == OV_HOLE)
ret = 0;
chunkpos += ret; chunkpos += ret;
@ -338,20 +345,22 @@ static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
chunk, chunkpos, chunk, chunkpos,
ov_pcm_tell(&vf) / ov_pcm_tell(&vf) /
dc->audioFormat.sampleRate, dc->audioFormat.sampleRate,
bitRate, bitRate, replayGainInfo);
replayGainInfo);
chunkpos = 0; chunkpos = 0;
if(dc->stop) break; if (dc->stop)
break;
} }
} }
if (!dc->stop && chunkpos > 0) { if (!dc->stop && chunkpos > 0) {
sendDataToOutputBuffer(cb, NULL, dc, inStream->seekable, sendDataToOutputBuffer(cb, NULL, dc, inStream->seekable,
chunk, chunkpos, chunk, chunkpos,
ov_time_tell(&vf), bitRate, replayGainInfo); ov_time_tell(&vf), bitRate,
replayGainInfo);
} }
if(replayGainInfo) freeReplayGainInfo(replayGainInfo); if (replayGainInfo)
freeReplayGainInfo(replayGainInfo);
ov_clear(&vf); ov_clear(&vf);
@ -360,21 +369,22 @@ static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
if (dc->stop) { if (dc->stop) {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
} } else
else dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
return 0; return 0;
} }
static MpdTag * oggvorbis_TagDup(char * file) { static MpdTag *oggvorbis_TagDup(char *file)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
FILE *fp; FILE *fp;
OggVorbis_File vf; OggVorbis_File vf;
fp = fopen(file, "r"); fp = fopen(file, "r");
if(!fp) if (!fp) {
{ DEBUG("oggTagDup: Failed to open file: '%s', %s\n", file,
DEBUG("oggTagDup: Failed to open file: '%s', %s\n", file, strerror(errno)); strerror(errno));
return NULL; return NULL;
} }
if (ov_open(fp, &vf, NULL, 0) < 0) { if (ov_open(fp, &vf, NULL, 0) < 0) {
@ -384,7 +394,8 @@ static MpdTag * oggvorbis_TagDup(char * file) {
ret = oggCommentsParse(ov_comment(&vf, -1)->user_comments); ret = oggCommentsParse(ov_comment(&vf, -1)->user_comments);
if(!ret) ret = newMpdTag(); if (!ret)
ret = newMpdTag();
ret->time = (int)(ov_time_total(&vf, -1) + 0.5); ret->time = (int)(ov_time_total(&vf, -1) + 0.5);
ov_clear(&vf); ov_clear(&vf);
@ -397,12 +408,10 @@ static unsigned int oggvorbis_try_decode(InputStream * inStream)
return (ogg_stream_type_detect(inStream) == VORBIS) ? 1 : 0; return (ogg_stream_type_detect(inStream) == VORBIS) ? 1 : 0;
} }
static char *oggvorbis_Suffixes[] = { "ogg", NULL }; static char *oggvorbis_Suffixes[] = { "ogg", NULL };
static char *oggvorbis_MimeTypes[] = { "application/ogg", NULL }; static char *oggvorbis_MimeTypes[] = { "application/ogg", NULL };
InputPlugin oggvorbisPlugin = InputPlugin oggvorbisPlugin = {
{
"oggvorbis", "oggvorbis",
NULL, NULL,
NULL, NULL,
@ -417,8 +426,7 @@ InputPlugin oggvorbisPlugin =
#else /* !HAVE_OGGVORBIS */ #else /* !HAVE_OGGVORBIS */
InputPlugin oggvorbisPlugin = InputPlugin oggvorbisPlugin = {
{
NULL, NULL,
NULL, NULL,
NULL, NULL,

View File

@ -25,12 +25,14 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
void initInputStream(void) { void initInputStream(void)
{
inputStream_initFile(); inputStream_initFile();
inputStream_initHttp(); inputStream_initHttp();
} }
int openInputStream(InputStream * inStream, char * url) { int openInputStream(InputStream * inStream, char *url)
{
inStream->offset = 0; inStream->offset = 0;
inStream->size = 0; inStream->size = 0;
inStream->error = 0; inStream->error = 0;
@ -39,13 +41,16 @@ int openInputStream(InputStream * inStream, char * url) {
inStream->metaName = NULL; inStream->metaName = NULL;
inStream->metaTitle = NULL; inStream->metaTitle = NULL;
if(inputStream_fileOpen(inStream,url) == 0) return 0; if (inputStream_fileOpen(inStream, url) == 0)
if(inputStream_httpOpen(inStream,url) == 0) return 0; return 0;
if (inputStream_httpOpen(inStream, url) == 0)
return 0;
return -1; return -1;
} }
int seekInputStream(InputStream * inStream, long offset, int whence) { int seekInputStream(InputStream * inStream, long offset, int whence)
{
return inStream->seekFunc(inStream, offset, whence); return inStream->seekFunc(inStream, offset, whence);
} }
@ -55,18 +60,24 @@ size_t readFromInputStream(InputStream * inStream, void * ptr, size_t size,
return inStream->readFunc(inStream, ptr, size, nmemb); return inStream->readFunc(inStream, ptr, size, nmemb);
} }
int closeInputStream(InputStream * inStream) { int closeInputStream(InputStream * inStream)
if(inStream->mime) free(inStream->mime); {
if(inStream->metaName) free(inStream->metaName); if (inStream->mime)
if(inStream->metaTitle) free(inStream->metaTitle); free(inStream->mime);
if (inStream->metaName)
free(inStream->metaName);
if (inStream->metaTitle)
free(inStream->metaTitle);
return inStream->closeFunc(inStream); return inStream->closeFunc(inStream);
} }
int inputStreamAtEOF(InputStream * inStream) { int inputStreamAtEOF(InputStream * inStream)
{
return inStream->atEOFFunc(inStream); return inStream->atEOFFunc(inStream);
} }
int bufferInputStream(InputStream * inStream) { int bufferInputStream(InputStream * inStream)
{
return inStream->bufferFunc(inStream); return inStream->bufferFunc(inStream);
} }

View File

@ -25,8 +25,8 @@ typedef struct _InputStream InputStream;
typedef int (*InputStreamSeekFunc) (InputStream * inStream, long offset, typedef int (*InputStreamSeekFunc) (InputStream * inStream, long offset,
int whence); int whence);
typedef size_t (* InputStreamReadFunc) (InputStream * inStream, void * ptr, size_t size, typedef size_t(*InputStreamReadFunc) (InputStream * inStream, void *ptr,
size_t nmemb); size_t size, size_t nmemb);
typedef int (*InputStreamCloseFunc) (InputStream * inStream); typedef int (*InputStreamCloseFunc) (InputStream * inStream);
typedef int (*InputStreamAtEOFFunc) (InputStream * inStream); typedef int (*InputStreamAtEOFFunc) (InputStream * inStream);
typedef int (*InputStreamBufferFunc) (InputStream * inStream); typedef int (*InputStreamBufferFunc) (InputStream * inStream);

View File

@ -26,10 +26,12 @@
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
void inputStream_initFile(void) { void inputStream_initFile(void)
{
} }
int inputStream_fileOpen(InputStream * inStream, char * filename) { int inputStream_fileOpen(InputStream * inStream, char *filename)
{
FILE *fp; FILE *fp;
fp = fopen(filename, "r"); fp = fopen(filename, "r");
@ -54,11 +56,11 @@ int inputStream_fileOpen(InputStream * inStream, char * filename) {
return 0; return 0;
} }
int inputStream_fileSeek(InputStream * inStream, long offset, int whence) { int inputStream_fileSeek(InputStream * inStream, long offset, int whence)
{
if (fseek((FILE *) inStream->data, offset, whence) == 0) { if (fseek((FILE *) inStream->data, offset, whence) == 0) {
inStream->offset = ftell((FILE *) inStream->data); inStream->offset = ftell((FILE *) inStream->data);
} } else {
else {
inStream->error = errno; inStream->error = errno;
return -1; return -1;
} }
@ -83,7 +85,8 @@ size_t inputStream_fileRead(InputStream * inStream, void * ptr, size_t size,
return readSize; return readSize;
} }
int inputStream_fileClose(InputStream * inStream) { int inputStream_fileClose(InputStream * inStream)
{
if (fclose((FILE *) inStream->data) < 0) { if (fclose((FILE *) inStream->data) < 0) {
inStream->error = errno; inStream->error = errno;
return -1; return -1;
@ -92,8 +95,10 @@ int inputStream_fileClose(InputStream * inStream) {
return 0; return 0;
} }
int inputStream_fileAtEOF(InputStream * inStream) { int inputStream_fileAtEOF(InputStream * inStream)
if(feof((FILE *)inStream->data)) return 1; {
if (feof((FILE *) inStream->data))
return 1;
if (ferror((FILE *) inStream->data) && inStream->error != EINTR) { if (ferror((FILE *) inStream->data) && inStream->error != EINTR) {
return 1; return 1;
@ -102,6 +107,7 @@ int inputStream_fileAtEOF(InputStream * inStream) {
return 0; return 0;
} }
int inputStream_fileBuffer(InputStream * inStream) { int inputStream_fileBuffer(InputStream * inStream)
{
return 0; return 0;
} }

View File

@ -70,7 +70,8 @@ typedef struct _InputStreemHTTPData {
char *httpAuth; char *httpAuth;
} InputStreamHTTPData; } InputStreamHTTPData;
void inputStream_initHttp(void) { void inputStream_initHttp(void)
{
ConfigParam *param = getConfigParam(CONF_HTTP_PROXY_HOST); ConfigParam *param = getConfigParam(CONF_HTTP_PROXY_HOST);
char *test; char *test;
@ -110,20 +111,15 @@ void inputStream_initHttp(void) {
CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_USER); CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_USER);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} } else if ((param = getConfigParam(CONF_HTTP_PROXY_PORT))) {
else if((param = getConfigParam(CONF_HTTP_PROXY_PORT))) {
ERROR("%s specified but not %s, line %i\n", ERROR("%s specified but not %s, line %i\n",
CONF_HTTP_PROXY_PORT, CONF_HTTP_PROXY_HOST, CONF_HTTP_PROXY_PORT, CONF_HTTP_PROXY_HOST, param->line);
param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} } else if ((param = getConfigParam(CONF_HTTP_PROXY_USER))) {
else if((param = getConfigParam(CONF_HTTP_PROXY_USER))) {
ERROR("%s specified but not %s, line %i\n", ERROR("%s specified but not %s, line %i\n",
CONF_HTTP_PROXY_USER, CONF_HTTP_PROXY_HOST, CONF_HTTP_PROXY_USER, CONF_HTTP_PROXY_HOST, param->line);
param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} } else if ((param = getConfigParam(CONF_HTTP_PROXY_PASSWORD))) {
else if((param = getConfigParam(CONF_HTTP_PROXY_PASSWORD))) {
ERROR("%s specified but not %s, line %i\n", ERROR("%s specified but not %s, line %i\n",
CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_HOST, CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_HOST,
param->line); param->line);
@ -138,14 +134,14 @@ void inputStream_initHttp(void) {
if (bufferSize <= 0 || *test != '\0') { if (bufferSize <= 0 || *test != '\0') {
ERROR("\"%s\" specified for %s at line %i is not a " ERROR("\"%s\" specified for %s at line %i is not a "
"positive integer\n", "positive integer\n",
param->value, CONF_HTTP_BUFFER_SIZE, param->value, CONF_HTTP_BUFFER_SIZE, param->line);
param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
bufferSize *= 1024; bufferSize *= 1024;
if(prebufferSize > bufferSize) prebufferSize = bufferSize; if (prebufferSize > bufferSize)
prebufferSize = bufferSize;
} }
param = getConfigParam(CONF_HTTP_PREBUFFER_SIZE); param = getConfigParam(CONF_HTTP_PREBUFFER_SIZE);
@ -164,14 +160,16 @@ void inputStream_initHttp(void) {
prebufferSize *= 1024; prebufferSize *= 1024;
} }
if(prebufferSize > bufferSize) prebufferSize = bufferSize; if (prebufferSize > bufferSize)
prebufferSize = bufferSize;
} }
/* base64 code taken from xmms */ /* base64 code taken from xmms */
#define BASE64_LENGTH(len) (4 * (((len) + 2) / 3)) #define BASE64_LENGTH(len) (4 * (((len) + 2) / 3))
static char * base64Dup(char * s) { static char *base64Dup(char *s)
{
int i; int i;
int len = strlen(s); int len = strlen(s);
char *ret = calloc(BASE64_LENGTH(len) + 1, 1); char *ret = calloc(BASE64_LENGTH(len) + 1, 1);
@ -207,13 +205,15 @@ static char * base64Dup(char * s) {
return ret; return ret;
} }
static char * authString(char * header, char * user, char * password) { static char *authString(char *header, char *user, char *password)
{
char *ret = NULL; char *ret = NULL;
int templen; int templen;
char *temp; char *temp;
char *temp64; char *temp64;
if(!user || !password) return NULL; if (!user || !password)
return NULL;
templen = strlen(user) + strlen(password) + 2; templen = strlen(user) + strlen(password) + 2;
temp = malloc(templen); temp = malloc(templen);
@ -238,13 +238,14 @@ static char * authString(char * header, char * user, char * password) {
#define proxyAuthString(x, y) authString(PROXY_AUTH_HEADER, x, y) #define proxyAuthString(x, y) authString(PROXY_AUTH_HEADER, x, y)
#define httpAuthString(x, y) authString(HTTP_AUTH_HEADER, x, y) #define httpAuthString(x, y) authString(HTTP_AUTH_HEADER, x, y)
static InputStreamHTTPData * newInputStreamHTTPData(void) { static InputStreamHTTPData *newInputStreamHTTPData(void)
{
InputStreamHTTPData *ret = malloc(sizeof(InputStreamHTTPData)); InputStreamHTTPData *ret = malloc(sizeof(InputStreamHTTPData));
if (proxyHost) { if (proxyHost) {
ret->proxyAuth = proxyAuthString(proxyUser, proxyPassword); ret->proxyAuth = proxyAuthString(proxyUser, proxyPassword);
} } else
else ret->proxyAuth = NULL; ret->proxyAuth = NULL;
ret->httpAuth = NULL; ret->httpAuth = NULL;
ret->host = NULL; ret->host = NULL;
@ -260,26 +261,34 @@ static InputStreamHTTPData * newInputStreamHTTPData(void) {
return ret; return ret;
} }
static void freeInputStreamHTTPData(InputStreamHTTPData * data) { static void freeInputStreamHTTPData(InputStreamHTTPData * data)
if(data->host) free(data->host); {
if(data->path) free(data->path); if (data->host)
if(data->port) free(data->port); free(data->host);
if(data->proxyAuth) free(data->proxyAuth); if (data->path)
if(data->httpAuth) free(data->httpAuth); free(data->path);
if (data->port)
free(data->port);
if (data->proxyAuth)
free(data->proxyAuth);
if (data->httpAuth)
free(data->httpAuth);
free(data->buffer); free(data->buffer);
free(data); free(data);
} }
static int parseUrl(InputStreamHTTPData * data, char * url) { static int parseUrl(InputStreamHTTPData * data, char *url)
{
char *temp; char *temp;
char *colon; char *colon;
char *slash; char *slash;
char *at; char *at;
int len; int len;
if(strncmp("http://",url,strlen("http://"))!=0) return -1; if (strncmp("http://", url, strlen("http://")) != 0)
return -1;
temp = url + strlen("http://"); temp = url + strlen("http://");
@ -303,8 +312,7 @@ static int parseUrl(InputStreamHTTPData * data, char * url) {
passwd = malloc(at - colon); passwd = malloc(at - colon);
strncpy(passwd, colon + 1, at - colon - 1); strncpy(passwd, colon + 1, at - colon - 1);
passwd[at - colon - 1] = '\0'; passwd[at - colon - 1] = '\0';
} } else {
else {
user = malloc(at - temp + 1); user = malloc(at - temp + 1);
strncpy(user, temp, at - temp); strncpy(user, temp, at - temp);
user[at - temp] = '\0'; user[at - temp] = '\0';
@ -323,14 +331,19 @@ static int parseUrl(InputStreamHTTPData * data, char * url) {
slash = strchr(temp, '/'); slash = strchr(temp, '/');
if(slash && colon && slash <= colon) return -1; if (slash && colon && slash <= colon)
return -1;
/* fetch the host portion */ /* fetch the host portion */
if(colon) len = colon-temp+1; if (colon)
else if(slash) len = slash-temp+1; len = colon - temp + 1;
else len = strlen(temp)+1; else if (slash)
len = slash - temp + 1;
else
len = strlen(temp) + 1;
if(len<=1) return -1; if (len <= 1)
return -1;
data->host = malloc(len); data->host = malloc(len);
strncpy(data->host, temp, len - 1); strncpy(data->host, temp, len - 1);
@ -338,24 +351,27 @@ static int parseUrl(InputStreamHTTPData * data, char * url) {
/* fetch the port */ /* fetch the port */
if (colon && (!slash || slash != colon + 1)) { if (colon && (!slash || slash != colon + 1)) {
len = strlen(colon) - 1; len = strlen(colon) - 1;
if(slash) len -= strlen(slash); if (slash)
len -= strlen(slash);
data->port = malloc(len + 1); data->port = malloc(len + 1);
strncpy(data->port, colon + 1, len); strncpy(data->port, colon + 1, len);
data->port[len] = '\0'; data->port[len] = '\0';
DEBUG(__FILE__ ": Port: %s\n", data->port); DEBUG(__FILE__ ": Port: %s\n", data->port);
} } else {
else {
data->port = strdup("80"); data->port = strdup("80");
} }
/* fetch the path */ /* fetch the path */
if(proxyHost) data->path = strdup(url); if (proxyHost)
else data->path = strdup(slash ? slash : "/"); data->path = strdup(url);
else
data->path = strdup(slash ? slash : "/");
return 0; return 0;
} }
static int initHTTPConnection(InputStream * inStream) { static int initHTTPConnection(InputStream * inStream)
{
char *connHost; char *connHost;
char *connPort; char *connPort;
struct addrinfo *ans = NULL; struct addrinfo *ans = NULL;
@ -375,21 +391,18 @@ static int initHTTPConnection(InputStream * inStream) {
hints.ai_canonname = NULL; hints.ai_canonname = NULL;
hints.ai_next = NULL; hints.ai_next = NULL;
if (proxyHost) { if (proxyHost) {
connHost = proxyHost; connHost = proxyHost;
connPort = proxyPort; connPort = proxyPort;
} } else {
else {
connHost = data->host; connHost = data->host;
connPort = data->port; connPort = data->port;
} }
error = getaddrinfo(connHost, connPort, &hints, &ans); error = getaddrinfo(connHost, connPort, &hints, &ans);
if (error) { if (error) {
DEBUG(__FILE__ ": Error getting address info: %s\n", gai_strerror(error)); DEBUG(__FILE__ ": Error getting address info: %s\n",
gai_strerror(error));
return -1; return -1;
} }
@ -397,7 +410,8 @@ static int initHTTPConnection(InputStream * inStream) {
for (ap = ans; ap != NULL; ap = ap->ai_next) { for (ap = ans; ap != NULL; ap = ap->ai_next) {
if ((data->sock = socket(ap->ai_family, ap->ai_socktype, if ((data->sock = socket(ap->ai_family, ap->ai_socktype,
ap->ai_protocol)) < 0) { ap->ai_protocol)) < 0) {
DEBUG(__FILE__ ": unable to connect: %s\n", strerror(errno)); DEBUG(__FILE__ ": unable to connect: %s\n",
strerror(errno));
freeaddrinfo(ans); freeaddrinfo(ans);
return -1; return -1;
} }
@ -406,8 +420,7 @@ static int initHTTPConnection(InputStream * inStream) {
fcntl(data->sock, F_SETFL, flags | O_NONBLOCK); fcntl(data->sock, F_SETFL, flags | O_NONBLOCK);
if (connect(data->sock, ap->ai_addr, ap->ai_addrlen) >= 0 if (connect(data->sock, ap->ai_addr, ap->ai_addrlen) >= 0
|| errno == EINPROGRESS || errno == EINPROGRESS) {
) {
data->connState = HTTP_CONN_STATE_INIT; data->connState = HTTP_CONN_STATE_INIT;
data->buflen = 0; data->buflen = 0;
freeaddrinfo(ans); freeaddrinfo(ans);
@ -424,7 +437,8 @@ static int initHTTPConnection(InputStream * inStream) {
return -1; /* failed */ return -1; /* failed */
} }
static int finishHTTPInit(InputStream * inStream) { static int finishHTTPInit(InputStream * inStream)
{
InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data; InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
struct timeval tv; struct timeval tv;
fd_set writeSet; fd_set writeSet;
@ -444,7 +458,8 @@ static int finishHTTPInit(InputStream * inStream) {
ret = select(data->sock + 1, NULL, &writeSet, &errorSet, &tv); ret = select(data->sock + 1, NULL, &writeSet, &errorSet, &tv);
if(ret == 0 || (ret < 0 && errno==EINTR)) return 0; if (ret == 0 || (ret < 0 && errno == EINTR))
return 0;
if (ret < 0) { if (ret < 0) {
DEBUG(__FILE__ ": problem select'ing: %s\n", strerror(errno)); DEBUG(__FILE__ ": problem select'ing: %s\n", strerror(errno));
@ -462,19 +477,13 @@ static int finishHTTPInit(InputStream * inStream) {
memset(request, 0, 2049); memset(request, 0, 2049);
/* deal with ICY metadata later, for now its fucking up stuff! */ /* deal with ICY metadata later, for now its fucking up stuff! */
snprintf(request, 2048, "GET %s HTTP/1.0\r\n" snprintf(request, 2048, "GET %s HTTP/1.0\r\n" "Host: %s\r\n"
"Host: %s\r\n"
/*"Connection: close\r\n" */ /*"Connection: close\r\n" */
"User-Agent: %s/%s\r\n" "User-Agent: %s/%s\r\n"
/*"Range: bytes=%ld-\r\n" */ /*"Range: bytes=%ld-\r\n" */
"%s" /* authorization */ "%s" /* authorization */
"Icy-Metadata:1\r\n" "Icy-Metadata:1\r\n"
"\r\n", "\r\n", data->path, data->host, PACKAGE_NAME, PACKAGE_VERSION,
data->path,
data->host,
PACKAGE_NAME,
PACKAGE_VERSION,
/*inStream->offset, */ /*inStream->offset, */
data->proxyAuth ? data->proxyAuth : data->proxyAuth ? data->proxyAuth :
(data->httpAuth ? data->httpAuth : "") (data->httpAuth ? data->httpAuth : "")
@ -492,7 +501,8 @@ static int finishHTTPInit(InputStream * inStream) {
return 0; return 0;
} }
static int getHTTPHello(InputStream * inStream) { static int getHTTPHello(InputStream * inStream)
{
InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data; InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
fd_set readSet; fd_set readSet;
struct timeval tv; struct timeval tv;
@ -510,7 +520,8 @@ static int getHTTPHello(InputStream * inStream) {
ret = select(data->sock + 1, &readSet, NULL, NULL, &tv); ret = select(data->sock + 1, &readSet, NULL, NULL, &tv);
if(ret == 0 || (ret < 0 && errno==EINTR)) return 0; if (ret == 0 || (ret < 0 && errno == EINTR))
return 0;
if (ret < 0) { if (ret < 0) {
data->connState = HTTP_CONN_STATE_CLOSED; data->connState = HTTP_CONN_STATE_CLOSED;
@ -528,7 +539,8 @@ static int getHTTPHello(InputStream * inStream) {
readed = recv(data->sock, data->buffer + data->buflen, readed = recv(data->sock, data->buffer + data->buflen,
bufferSize - 1 - data->buflen, 0); bufferSize - 1 - data->buflen, 0);
if(readed < 0 && (errno == EAGAIN || errno == EINTR)) return 0; if (readed < 0 && (errno == EAGAIN || errno == EINTR))
return 0;
if (readed <= 0) { if (readed <= 0) {
data->connState = HTTP_CONN_STATE_CLOSED; data->connState = HTTP_CONN_STATE_CLOSED;
@ -542,22 +554,22 @@ static int getHTTPHello(InputStream * inStream) {
needle = strstr(data->buffer, "\r\n\r\n"); needle = strstr(data->buffer, "\r\n\r\n");
if(!needle) return 0; if (!needle)
return 0;
if (0 == strncmp(cur, "HTTP/1.0 ", 9)) { if (0 == strncmp(cur, "HTTP/1.0 ", 9)) {
inStream->seekable = 0; inStream->seekable = 0;
rc = atoi(cur + 9); rc = atoi(cur + 9);
} } else if (0 == strncmp(cur, "HTTP/1.1 ", 9)) {
else if(0 == strncmp(cur, "HTTP/1.1 ", 9)) {
inStream->seekable = 1; inStream->seekable = 1;
rc = atoi(cur + 9); rc = atoi(cur + 9);
} } else if (0 == strncmp(cur, "ICY 200 OK", 10)) {
else if(0 == strncmp(cur, "ICY 200 OK", 10)) {
inStream->seekable = 0; inStream->seekable = 0;
rc = 200; rc = 200;
} } else if (0 == strncmp(cur, "ICY 400 Server Full", 19))
else if(0 == strncmp(cur, "ICY 400 Server Full", 19)) rc = 400; rc = 400;
else if(0 == strncmp(cur, "ICY 404", 7)) rc = 404; else if (0 == strncmp(cur, "ICY 404", 7))
rc = 404;
else { else {
close(data->sock); close(data->sock);
data->connState = HTTP_CONN_STATE_CLOSED; data->connState = HTTP_CONN_STATE_CLOSED;
@ -575,7 +587,8 @@ static int getHTTPHello(InputStream * inStream) {
char *url; char *url;
int curlen = 0; int curlen = 0;
cur += strlen("Location: "); cur += strlen("Location: ");
while(*(cur+curlen)!='\0' && *(cur+curlen)!='\r') { while (*(cur + curlen) != '\0'
&& *(cur + curlen) != '\r') {
curlen++; curlen++;
} }
url = malloc(curlen + 1); url = malloc(curlen + 1);
@ -584,8 +597,7 @@ static int getHTTPHello(InputStream * inStream) {
ret = parseUrl(data, url); ret = parseUrl(data, url);
free(url); free(url);
if (ret == 0 && data->timesRedirected < if (ret == 0 && data->timesRedirected <
HTTP_REDIRECT_MAX) HTTP_REDIRECT_MAX) {
{
data->timesRedirected++; data->timesRedirected++;
close(data->sock); close(data->sock);
data->connState = HTTP_CONN_STATE_REOPEN; data->connState = HTTP_CONN_STATE_REOPEN;
@ -607,44 +619,49 @@ static int getHTTPHello(InputStream * inStream) {
cur = strstr(data->buffer, "\r\n"); cur = strstr(data->buffer, "\r\n");
while (cur && cur != needle) { while (cur && cur != needle) {
if (0 == strncmp(cur, "\r\nContent-Length: ", 18)) { if (0 == strncmp(cur, "\r\nContent-Length: ", 18)) {
if(!inStream->size) inStream->size = atol(cur+18); if (!inStream->size)
} inStream->size = atol(cur + 18);
else if(0 == strncmp(cur, "\r\nicy-metaint:", 14)) { } else if (0 == strncmp(cur, "\r\nicy-metaint:", 14)) {
data->icyMetaint = atoi(cur + 14); data->icyMetaint = atoi(cur + 14);
} } else if (0 == strncmp(cur, "\r\nicy-name:", 11) ||
else if(0 == strncmp(cur, "\r\nicy-name:", 11) || 0 == strncmp(cur, "\r\nice-name:", 11)) {
0 == strncmp(cur, "\r\nice-name:", 11))
{
int incr = 11; int incr = 11;
char *temp = strstr(cur + incr, "\r\n"); char *temp = strstr(cur + incr, "\r\n");
if(!temp) break; if (!temp)
break;
*temp = '\0'; *temp = '\0';
if(inStream->metaName) free(inStream->metaName); if (inStream->metaName)
while(*(incr+cur) == ' ') incr++; free(inStream->metaName);
while (*(incr + cur) == ' ')
incr++;
inStream->metaName = strdup(cur + incr); inStream->metaName = strdup(cur + incr);
*temp = '\r'; *temp = '\r';
DEBUG("inputStream_http: metaName: %s\n", DEBUG("inputStream_http: metaName: %s\n",
inStream->metaName); inStream->metaName);
} } else if (0 == strncmp(cur, "\r\nx-audiocast-name:", 19)) {
else if(0 == strncmp(cur, "\r\nx-audiocast-name:", 19)) {
int incr = 19; int incr = 19;
char *temp = strstr(cur + incr, "\r\n"); char *temp = strstr(cur + incr, "\r\n");
if(!temp) break; if (!temp)
break;
*temp = '\0'; *temp = '\0';
if(inStream->metaName) free(inStream->metaName); if (inStream->metaName)
while(*(incr+cur) == ' ') incr++; free(inStream->metaName);
while (*(incr + cur) == ' ')
incr++;
inStream->metaName = strdup(cur + incr); inStream->metaName = strdup(cur + incr);
*temp = '\r'; *temp = '\r';
DEBUG("inputStream_http: metaName: %s\n", DEBUG("inputStream_http: metaName: %s\n",
inStream->metaName); inStream->metaName);
} } else if (0 == strncmp(cur, "\r\nContent-Type:", 15)) {
else if(0 == strncmp(cur, "\r\nContent-Type:", 15)) {
int incr = 15; int incr = 15;
char *temp = strstr(cur + incr, "\r\n"); char *temp = strstr(cur + incr, "\r\n");
if(!temp) break; if (!temp)
break;
*temp = '\0'; *temp = '\0';
if(inStream->mime) free(inStream->mime); if (inStream->mime)
while(*(incr+cur) == ' ') incr++; free(inStream->mime);
while (*(incr + cur) == ' ')
incr++;
inStream->mime = strdup(cur + incr); inStream->mime = strdup(cur + incr);
*temp = '\r'; *temp = '\r';
} }
@ -652,7 +669,8 @@ static int getHTTPHello(InputStream * inStream) {
cur = strstr(cur + 2, "\r\n"); cur = strstr(cur + 2, "\r\n");
} }
if(inStream->size <= 0) inStream->seekable = 0; if (inStream->size <= 0)
inStream->seekable = 0;
needle += 4; /* 4 == strlen("\r\n\r\n") */ needle += 4; /* 4 == strlen("\r\n\r\n") */
data->buflen -= (needle - data->buffer); data->buflen -= (needle - data->buffer);
@ -669,7 +687,8 @@ static int getHTTPHello(InputStream * inStream) {
return 0; return 0;
} }
int inputStream_httpOpen(InputStream * inStream, char * url) { int inputStream_httpOpen(InputStream * inStream, char *url)
{
InputStreamHTTPData *data = newInputStreamHTTPData(); InputStreamHTTPData *data = newInputStreamHTTPData();
inStream->data = data; inStream->data = data;
@ -693,7 +712,8 @@ int inputStream_httpOpen(InputStream * inStream, char * url) {
return 0; return 0;
} }
int inputStream_httpSeek(InputStream * inStream, long offset, int whence) { int inputStream_httpSeek(InputStream * inStream, long offset, int whence)
{
/* hack to reopen an HTTP stream if we're trying to seek to /* hack to reopen an HTTP stream if we're trying to seek to
* the beginning */ * the beginning */
if ((whence == SEEK_SET) && (offset == 0)) { if ((whence == SEEK_SET) && (offset == 0)) {
@ -711,8 +731,7 @@ int inputStream_httpSeek(InputStream * inStream, long offset, int whence) {
return -1; return -1;
} }
static void parseIcyMetadata(InputStream * inStream, char * metadata, static void parseIcyMetadata(InputStream * inStream, char *metadata, int size)
int size)
{ {
char *r; char *r;
char *s; char *s;
@ -723,8 +742,10 @@ static void parseIcyMetadata(InputStream * inStream, char * metadata,
while (s) { while (s) {
if (0 == strncmp(s, "StreamTitle=", 12)) { if (0 == strncmp(s, "StreamTitle=", 12)) {
int cur = 12; int cur = 12;
if(inStream->metaTitle) free(inStream->metaTitle); if (inStream->metaTitle)
if(*(s+cur) == '\'') cur++; free(inStream->metaTitle);
if (*(s + cur) == '\'')
cur++;
if (s[strlen(s) - 1] == '\'') { if (s[strlen(s) - 1] == '\'') {
s[strlen(s) - 1] = '\0'; s[strlen(s) - 1] = '\0';
} }
@ -749,11 +770,13 @@ size_t inputStream_httpRead(InputStream * inStream, void * ptr, size_t size,
switch (data->connState) { switch (data->connState) {
case HTTP_CONN_STATE_OPEN: case HTTP_CONN_STATE_OPEN:
if(data->prebuffer || data->buflen < data->icyMetaint) return 0; if (data->prebuffer || data->buflen < data->icyMetaint)
return 0;
break; break;
case HTTP_CONN_STATE_CLOSED: case HTTP_CONN_STATE_CLOSED:
if(data->buflen) break; if (data->buflen)
break;
default: default:
return 0; return 0;
} }
@ -762,7 +785,8 @@ size_t inputStream_httpRead(InputStream * inStream, void * ptr, size_t size,
if (data->icyOffset >= data->icyMetaint) { if (data->icyOffset >= data->icyMetaint) {
int metalen = *(data->buffer); int metalen = *(data->buffer);
metalen <<= 4; metalen <<= 4;
if(metalen < 0) metalen = 0; if (metalen < 0)
metalen = 0;
if (metalen + 1 > data->buflen) { if (metalen + 1 > data->buflen) {
/* damn that's some fucking big metadata! */ /* damn that's some fucking big metadata! */
if (bufferSize < metalen + 1) { if (bufferSize < metalen + 1) {
@ -803,7 +827,8 @@ size_t inputStream_httpRead(InputStream * inStream, void * ptr, size_t size,
return tosend / size; return tosend / size;
} }
int inputStream_httpClose(InputStream * inStream) { int inputStream_httpClose(InputStream * inStream)
{
InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data; InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
switch (data->connState) { switch (data->connState) {
@ -818,30 +843,36 @@ int inputStream_httpClose(InputStream * inStream) {
return 0; return 0;
} }
int inputStream_httpAtEOF(InputStream * inStream) { int inputStream_httpAtEOF(InputStream * inStream)
{
InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data; InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
switch (data->connState) { switch (data->connState) {
case HTTP_CONN_STATE_CLOSED: case HTTP_CONN_STATE_CLOSED:
if(data->buflen == 0) return 1; if (data->buflen == 0)
return 1;
default: default:
return 0; return 0;
} }
} }
int inputStream_httpBuffer(InputStream * inStream) { int inputStream_httpBuffer(InputStream * inStream)
{
InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data; InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
ssize_t readed = 0; ssize_t readed = 0;
if (data->connState == HTTP_CONN_STATE_REOPEN) { if (data->connState == HTTP_CONN_STATE_REOPEN) {
if(initHTTPConnection(inStream) < 0) return -1; if (initHTTPConnection(inStream) < 0)
return -1;
} }
if (data->connState == HTTP_CONN_STATE_INIT) { if (data->connState == HTTP_CONN_STATE_INIT) {
if(finishHTTPInit(inStream) < 0) return -1; if (finishHTTPInit(inStream) < 0)
return -1;
} }
if (data->connState == HTTP_CONN_STATE_HELLO) { if (data->connState == HTTP_CONN_STATE_HELLO) {
if(getHTTPHello(inStream) < 0) return -1; if (getHTTPHello(inStream) < 0)
return -1;
} }
switch (data->connState) { switch (data->connState) {
@ -854,19 +885,17 @@ int inputStream_httpBuffer(InputStream * inStream) {
if (data->buflen == 0 || data->buflen < data->icyMetaint) { if (data->buflen == 0 || data->buflen < data->icyMetaint) {
data->prebuffer = 1; data->prebuffer = 1;
} } else if (data->buflen > prebufferSize)
else if(data->buflen > prebufferSize) data->prebuffer = 0; data->prebuffer = 0;
if (data->connState == HTTP_CONN_STATE_OPEN && if (data->connState == HTTP_CONN_STATE_OPEN &&
data->buflen < bufferSize-1) data->buflen < bufferSize - 1) {
{
readed = read(data->sock, data->buffer + data->buflen, readed = read(data->sock, data->buffer + data->buflen,
(size_t) (bufferSize - 1 - data->buflen)); (size_t) (bufferSize - 1 - data->buflen));
if (readed < 0 && (errno == EAGAIN || errno == EINTR)) { if (readed < 0 && (errno == EAGAIN || errno == EINTR)) {
readed = 0; readed = 0;
} } else if (readed <= 0) {
else if(readed <= 0) {
close(data->sock); close(data->sock);
data->connState = HTTP_CONN_STATE_CLOSED; data->connState = HTTP_CONN_STATE_CLOSED;
readed = 0; readed = 0;
@ -875,7 +904,8 @@ int inputStream_httpBuffer(InputStream * inStream) {
data->buflen += readed; data->buflen += readed;
} }
if(data->buflen > prebufferSize) data->prebuffer = 0; if (data->buflen > prebufferSize)
data->prebuffer = 0;
return (readed ? 1 : 0); return (readed ? 1 : 0);
} }

View File

@ -89,7 +89,8 @@ static void flushInterfaceBuffer(Interface * interface);
static void printInterfaceOutBuffer(Interface * interface); static void printInterfaceOutBuffer(Interface * interface);
static void openInterface(Interface * interface, int fd) { static void openInterface(Interface * interface, int fd)
{
int flags; int flags;
assert(interface->open == 0); assert(interface->open == 0);
@ -119,14 +120,12 @@ static void openInterface(Interface * interface, int fd) {
unsigned int sockOptLen = sizeof(int); unsigned int sockOptLen = sizeof(int);
if (getsockopt(interface->fd, SOL_SOCKET, SO_SNDBUF, if (getsockopt(interface->fd, SOL_SOCKET, SO_SNDBUF,
(char *)&getSize,&sockOptLen) < 0) (char *)&getSize, &sockOptLen) < 0) {
{
DEBUG("problem getting sockets send buffer size\n"); DEBUG("problem getting sockets send buffer size\n");
} } else if (getSize <= 0) {
else if(getSize<=0) {
DEBUG("sockets send buffer size is not positive\n"); DEBUG("sockets send buffer size is not positive\n");
} } else
else interface->outBufSize = getSize; interface->outBufSize = getSize;
} }
#endif #endif
interface->outBuffer = malloc(interface->outBufSize); interface->outBuffer = malloc(interface->outBufSize);
@ -135,22 +134,27 @@ static void openInterface(Interface * interface, int fd) {
printInterfaceOutBuffer(interface); printInterfaceOutBuffer(interface);
} }
static void closeInterface(Interface * interface) { static void closeInterface(Interface * interface)
if (!interface->open) return; {
if (!interface->open)
return;
interface->open = 0; interface->open = 0;
while (fclose(interface->fp) && errno == EINTR) ; while (fclose(interface->fp) && errno == EINTR) ;
if(interface->commandList) freeList(interface->commandList); if (interface->commandList)
if(interface->bufferList) freeList(interface->bufferList); freeList(interface->commandList);
if (interface->bufferList)
freeList(interface->bufferList);
free(interface->outBuffer); free(interface->outBuffer);
SECURE("interface %i: closed\n", interface->num); SECURE("interface %i: closed\n", interface->num);
} }
void openAInterface(int fd, struct sockaddr * addr) { void openAInterface(int fd, struct sockaddr *addr)
{
int i; int i;
for (i = 0; i < interface_max_connections && interfaces[i].open; i++) ; for (i = 0; i < interface_max_connections && interfaces[i].open; i++) ;
@ -158,19 +162,16 @@ void openAInterface(int fd, struct sockaddr * addr) {
if (i == interface_max_connections) { if (i == interface_max_connections) {
ERROR("Max Connections Reached!\n"); ERROR("Max Connections Reached!\n");
while (close(fd) && errno == EINTR) ; while (close(fd) && errno == EINTR) ;
} } else {
else {
SECURE("interface %i: opened from ", i); SECURE("interface %i: opened from ", i);
switch (addr->sa_family) { switch (addr->sa_family) {
case AF_INET: case AF_INET:
{ {
char * host = inet_ntoa( char *host = inet_ntoa(((struct sockaddr_in *)
((struct sockaddr_in *)addr)-> addr)->sin_addr);
sin_addr);
if (host) { if (host) {
SECURE("%s\n", host); SECURE("%s\n", host);
} } else {
else {
SECURE("error getting ipv4 address\n"); SECURE("error getting ipv4 address\n");
} }
} }
@ -182,11 +183,10 @@ void openAInterface(int fd, struct sockaddr * addr) {
memset(host, 0, INET6_ADDRSTRLEN + 1); memset(host, 0, INET6_ADDRSTRLEN + 1);
if (inet_ntop(AF_INET6, (void *) if (inet_ntop(AF_INET6, (void *)
&(((struct sockaddr_in6 *)addr)-> &(((struct sockaddr_in6 *)addr)->
sin6_addr),host,INET6_ADDRSTRLEN)) sin6_addr), host,
{ INET6_ADDRSTRLEN)) {
SECURE("%s\n", host); SECURE("%s\n", host);
} } else {
else {
SECURE("error getting ipv6 address\n"); SECURE("error getting ipv6 address\n");
} }
} }
@ -202,7 +202,8 @@ void openAInterface(int fd, struct sockaddr * addr) {
} }
} }
static int processLineOfInput(Interface * interface) { static int processLineOfInput(Interface * interface)
{
int ret = 1; int ret = 1;
char *line = interface->buffer + interface->bufferPos; char *line = interface->buffer + interface->bufferPos;
@ -216,19 +217,17 @@ static int processLineOfInput(Interface * interface) {
if (strcmp(line, INTERFACE_LIST_MODE_END) == 0) { if (strcmp(line, INTERFACE_LIST_MODE_END) == 0) {
DEBUG("interface %i: process command " DEBUG("interface %i: process command "
"list\n", interface->num); "list\n", interface->num);
ret = processListOfCommands( ret = processListOfCommands(interface->fp,
interface->fp,
&(interface->permission), &(interface->permission),
&(interface->expired), &(interface->expired),
interface->commandListOK, interface->commandListOK,
interface->commandList); interface->commandList);
DEBUG("interface %i: process command " DEBUG("interface %i: process command "
"list returned %i\n", "list returned %i\n", interface->num, ret);
interface->num, if (ret == 0)
ret); commandSuccess(interface->fp);
if(ret==0) commandSuccess(interface->fp); else if (ret == COMMAND_RETURN_CLOSE
else if(ret==COMMAND_RETURN_CLOSE || interface->expired) || interface->expired) {
{
closeInterface(interface); closeInterface(interface);
} }
@ -236,56 +235,48 @@ static int processLineOfInput(Interface * interface) {
freeList(interface->commandList); freeList(interface->commandList);
interface->commandList = NULL; interface->commandList = NULL;
} } else {
else {
interface->commandListSize += sizeof(ListNode); interface->commandListSize += sizeof(ListNode);
interface->commandListSize += strlen(line) + 1; interface->commandListSize += strlen(line) + 1;
if (interface->commandListSize > if (interface->commandListSize >
interface_max_command_list_size) interface_max_command_list_size) {
{
ERROR("interface %i: command " ERROR("interface %i: command "
"list size (%lli) is " "list size (%lli) is "
"larger than the max " "larger than the max "
"(%lli)\n", "(%lli)\n",
interface->num, interface->num,
(long long)interface-> (long long)interface->
commandListSize, commandListSize, (long long)
(long long) interface_max_command_list_size);
interface_max_command_list_size)
;
closeInterface(interface); closeInterface(interface);
ret = COMMAND_RETURN_CLOSE; ret = COMMAND_RETURN_CLOSE;
} } else {
else {
insertInListWithoutKey(interface->commandList, insertInListWithoutKey(interface->commandList,
strdup(line)); strdup(line));
} }
} }
} } else {
else {
if (strcmp(line, INTERFACE_LIST_MODE_BEGIN) == 0) { if (strcmp(line, INTERFACE_LIST_MODE_BEGIN) == 0) {
interface->commandList = makeList(free, 1); interface->commandList = makeList(free, 1);
interface->commandListSize = sizeof(List); interface->commandListSize = sizeof(List);
interface->commandListOK = 0; interface->commandListOK = 0;
ret = 1; ret = 1;
} } else if (strcmp(line, INTERFACE_LIST_OK_MODE_BEGIN) == 0) {
else if(strcmp(line, INTERFACE_LIST_OK_MODE_BEGIN) == 0) {
interface->commandList = makeList(free, 1); interface->commandList = makeList(free, 1);
interface->commandListSize = sizeof(List); interface->commandListSize = sizeof(List);
interface->commandListOK = 1; interface->commandListOK = 1;
ret = 1; ret = 1;
} } else {
else {
DEBUG("interface %i: process command \"%s\"\n", DEBUG("interface %i: process command \"%s\"\n",
interface->num, line); interface->num, line);
ret = processCommand(interface->fp, ret = processCommand(interface->fp,
&(interface->permission), &(interface->permission), line);
line);
DEBUG("interface %i: command returned %i\n", DEBUG("interface %i: command returned %i\n",
interface->num, ret); interface->num, ret);
if(ret==0) commandSuccess(interface->fp); if (ret == 0)
else if(ret==COMMAND_RETURN_CLOSE || interface->expired) commandSuccess(interface->fp);
{ else if (ret == COMMAND_RETURN_CLOSE
|| interface->expired) {
closeInterface(interface); closeInterface(interface);
} }
printInterfaceOutBuffer(interface); printInterfaceOutBuffer(interface);
@ -295,7 +286,8 @@ static int processLineOfInput(Interface * interface) {
return ret; return ret;
} }
static int processBytesRead(Interface * interface, int bytesRead) { static int processBytesRead(Interface * interface, int bytesRead)
{
int ret = 0; int ret = 0;
while (bytesRead > 0) { while (bytesRead > 0) {
@ -306,8 +298,7 @@ static int processBytesRead(Interface * interface, int bytesRead) {
ret = processLineOfInput(interface); ret = processLineOfInput(interface);
interface->bufferPos = interface->bufferLength; interface->bufferPos = interface->bufferLength;
} }
if(interface->bufferLength==INTERFACE_MAX_BUFFER_LENGTH) if (interface->bufferLength == INTERFACE_MAX_BUFFER_LENGTH) {
{
if (interface->bufferPos == 0) { if (interface->bufferPos == 0) {
ERROR("interface %i: buffer overflow\n", ERROR("interface %i: buffer overflow\n",
interface->num); interface->num);
@ -320,60 +311,69 @@ static int processBytesRead(Interface * interface, int bytesRead) {
interface->bufferLength); interface->bufferLength);
interface->bufferPos = 0; interface->bufferPos = 0;
} }
if(ret == COMMAND_RETURN_KILL || ret == COMMAND_RETURN_CLOSE) if (ret == COMMAND_RETURN_KILL || ret == COMMAND_RETURN_CLOSE) {
return ret;
}
}
return ret;
}
static int interfaceReadInput(Interface * interface)
{ {
return ret;
}
}
return ret;
}
static int interfaceReadInput(Interface * interface) {
int bytesRead; int bytesRead;
bytesRead = read(interface->fd, bytesRead = read(interface->fd,
interface->buffer + interface->bufferLength, interface->buffer + interface->bufferLength,
INTERFACE_MAX_BUFFER_LENGTH - interface->bufferLength); INTERFACE_MAX_BUFFER_LENGTH - interface->bufferLength);
if(bytesRead > 0) return processBytesRead(interface, bytesRead); if (bytesRead > 0)
return processBytesRead(interface, bytesRead);
else if (bytesRead == 0 || (bytesRead < 0 && errno != EINTR)) { else if (bytesRead == 0 || (bytesRead < 0 && errno != EINTR)) {
closeInterface(interface); closeInterface(interface);
} } else
else return 0; return 0;
return 1; return 1;
} }
static void addInterfacesReadyToReadAndListenSocketToFdSet(fd_set * fds, int * fdmax) { static void addInterfacesReadyToReadAndListenSocketToFdSet(fd_set * fds,
int *fdmax)
{
int i; int i;
FD_ZERO(fds); FD_ZERO(fds);
addListenSocketsToFdSet(fds, fdmax); addListenSocketsToFdSet(fds, fdmax);
for (i = 0; i < interface_max_connections; i++) { for (i = 0; i < interface_max_connections; i++) {
if(interfaces[i].open && !interfaces[i].expired && !interfaces[i].bufferList) { if (interfaces[i].open && !interfaces[i].expired
&& !interfaces[i].bufferList) {
FD_SET(interfaces[i].fd, fds); FD_SET(interfaces[i].fd, fds);
if(*fdmax<interfaces[i].fd) *fdmax = interfaces[i].fd; if (*fdmax < interfaces[i].fd)
*fdmax = interfaces[i].fd;
} }
} }
} }
static void addInterfacesForBufferFlushToFdSet(fd_set * fds, int * fdmax) { static void addInterfacesForBufferFlushToFdSet(fd_set * fds, int *fdmax)
{
int i; int i;
FD_ZERO(fds); FD_ZERO(fds);
for (i = 0; i < interface_max_connections; i++) { for (i = 0; i < interface_max_connections; i++) {
if(interfaces[i].open && !interfaces[i].expired && interfaces[i].bufferList) { if (interfaces[i].open && !interfaces[i].expired
&& interfaces[i].bufferList) {
FD_SET(interfaces[i].fd, fds); FD_SET(interfaces[i].fd, fds);
if(*fdmax<interfaces[i].fd) *fdmax = interfaces[i].fd; if (*fdmax < interfaces[i].fd)
*fdmax = interfaces[i].fd;
} }
} }
} }
static void closeNextErroredInterface(void) { static void closeNextErroredInterface(void)
{
fd_set fds; fd_set fds;
struct timeval tv; struct timeval tv;
int i; int i;
@ -393,7 +393,8 @@ static void closeNextErroredInterface(void) {
} }
} }
int doIOForInterfaces(void) { int doIOForInterfaces(void)
{
fd_set rfds; fd_set rfds;
fd_set wfds; fd_set wfds;
struct timeval tv; struct timeval tv;
@ -412,7 +413,8 @@ int doIOForInterfaces(void) {
selret = select(fdmax + 1, &rfds, &wfds, NULL, &tv); selret = select(fdmax + 1, &rfds, &wfds, NULL, &tv);
if(selret == 0 || (selret<0 && errno==EINTR)) break; if (selret == 0 || (selret < 0 && errno == EINTR))
break;
if (selret < 0) { if (selret < 0) {
closeNextErroredInterface(); closeNextErroredInterface();
@ -422,13 +424,16 @@ int doIOForInterfaces(void) {
getConnections(&rfds); getConnections(&rfds);
for (i = 0; i < interface_max_connections; i++) { for (i = 0; i < interface_max_connections; i++) {
if(interfaces[i].open && FD_ISSET(interfaces[i].fd,&rfds)) { if (interfaces[i].open
if(COMMAND_RETURN_KILL==interfaceReadInput(&(interfaces[i]))) { && FD_ISSET(interfaces[i].fd, &rfds)) {
if (COMMAND_RETURN_KILL ==
interfaceReadInput(&(interfaces[i]))) {
return COMMAND_RETURN_KILL; return COMMAND_RETURN_KILL;
} }
interfaces[i].lastTime = time(NULL); interfaces[i].lastTime = time(NULL);
} }
if(interfaces[i].open && FD_ISSET(interfaces[i].fd,&wfds)) { if (interfaces[i].open
&& FD_ISSET(interfaces[i].fd, &wfds)) {
flushInterfaceBuffer(&interfaces[i]); flushInterfaceBuffer(&interfaces[i]);
interfaces[i].lastTime = time(NULL); interfaces[i].lastTime = time(NULL);
} }
@ -441,7 +446,8 @@ int doIOForInterfaces(void) {
return 1; return 1;
} }
void initInterfaces(void) { void initInterfaces(void)
{
int i; int i;
char *test; char *test;
ConfigParam *param; ConfigParam *param;
@ -467,8 +473,8 @@ void initInterfaces(void) {
", line %i\n", param->value, param->line); ", line %i\n", param->value, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} } else
else interface_max_connections = INTERFACE_MAX_CONNECTIONS_DEFAULT; interface_max_connections = INTERFACE_MAX_CONNECTIONS_DEFAULT;
param = getConfigParam(CONF_MAX_COMMAND_LIST_SIZE); param = getConfigParam(CONF_MAX_COMMAND_LIST_SIZE);
@ -477,8 +483,7 @@ void initInterfaces(void) {
&test, 10); &test, 10);
if (*test != '\0' || interface_max_command_list_size <= 0) { if (*test != '\0' || interface_max_command_list_size <= 0) {
ERROR("max command list size \"%s\" is not a positive " ERROR("max command list size \"%s\" is not a positive "
"integer, line %i\n", param->value, "integer, line %i\n", param->value, param->line);
param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
interface_max_command_list_size *= 1024; interface_max_command_list_size *= 1024;
@ -491,8 +496,7 @@ void initInterfaces(void) {
10); 10);
if (*test != '\0' || interface_max_output_buffer_size <= 0) { if (*test != '\0' || interface_max_output_buffer_size <= 0) {
ERROR("max output buffer size \"%s\" is not a positive " ERROR("max output buffer size \"%s\" is not a positive "
"integer, line %i\n", param->value, "integer, line %i\n", param->value, param->line);
param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
interface_max_output_buffer_size *= 1024; interface_max_output_buffer_size *= 1024;
@ -506,7 +510,8 @@ void initInterfaces(void) {
} }
} }
static void closeAllInterfaces(void) { static void closeAllInterfaces(void)
{
int i; int i;
fflush(NULL); fflush(NULL);
@ -518,7 +523,8 @@ static void closeAllInterfaces(void) {
} }
} }
void freeAllInterfaces(void) { void freeAllInterfaces(void)
{
closeAllInterfaces(); closeAllInterfaces();
free(interfaces); free(interfaces);
@ -526,7 +532,8 @@ void freeAllInterfaces(void) {
interface_max_connections = 0; interface_max_connections = 0;
} }
void closeOldInterfaces(void) { void closeOldInterfaces(void)
{
int i; int i;
for (i = 0; i < interface_max_connections; i++) { for (i = 0; i < interface_max_connections; i++) {
@ -534,10 +541,8 @@ void closeOldInterfaces(void) {
if (interfaces[i].expired) { if (interfaces[i].expired) {
DEBUG("interface %i: expired\n", i); DEBUG("interface %i: expired\n", i);
closeInterface(&(interfaces[i])); closeInterface(&(interfaces[i]));
} } else if (time(NULL) - interfaces[i].lastTime >
else if(time(NULL)-interfaces[i].lastTime > interface_timeout) {
interface_timeout)
{
DEBUG("interface %i: timeout\n", i); DEBUG("interface %i: timeout\n", i);
closeInterface(&(interfaces[i])); closeInterface(&(interfaces[i]));
} }
@ -545,21 +550,22 @@ void closeOldInterfaces(void) {
} }
} }
static void flushInterfaceBuffer(Interface * interface) { static void flushInterfaceBuffer(Interface * interface)
{
ListNode *node = NULL; ListNode *node = NULL;
char *str; char *str;
int ret = 0; int ret = 0;
while ((node = interface->bufferList->firstNode)) { while ((node = interface->bufferList->firstNode)) {
str = (char *)node->data; str = (char *)node->data;
if((ret = write(interface->fd,str,strlen(str)))<0) break; if ((ret = write(interface->fd, str, strlen(str))) < 0)
break;
else if (ret < strlen(str)) { else if (ret < strlen(str)) {
interface->outputBufferSize -= ret; interface->outputBufferSize -= ret;
str = strdup(&str[ret]); str = strdup(&str[ret]);
free(node->data); free(node->data);
node->data = str; node->data = str;
} } else {
else {
interface->outputBufferSize -= strlen(str) + 1; interface->outputBufferSize -= strlen(str) + 1;
interface->outputBufferSize -= sizeof(ListNode); interface->outputBufferSize -= sizeof(ListNode);
deleteNodeFromList(interface->bufferList, node); deleteNodeFromList(interface->bufferList, node);
@ -571,8 +577,7 @@ static void flushInterfaceBuffer(Interface * interface) {
DEBUG("interface %i: buffer empty\n", interface->num); DEBUG("interface %i: buffer empty\n", interface->num);
freeList(interface->bufferList); freeList(interface->bufferList);
interface->bufferList = NULL; interface->bufferList = NULL;
} } else if (ret < 0 && errno != EAGAIN && errno != EINTR) {
else if(ret<0 && errno!=EAGAIN && errno!=EINTR) {
/* cause interface to close */ /* cause interface to close */
DEBUG("interface %i: problems flushing buffer\n", DEBUG("interface %i: problems flushing buffer\n",
interface->num); interface->num);
@ -582,30 +587,32 @@ static void flushInterfaceBuffer(Interface * interface) {
} }
} }
int interfacePrintWithFD(int fd, char * buffer, int buflen) { int interfacePrintWithFD(int fd, char *buffer, int buflen)
{
static int i = 0; static int i = 0;
int copylen; int copylen;
Interface *interface; Interface *interface;
if (i >= interface_max_connections || if (i >= interface_max_connections ||
!interfaces[i].open || interfaces[i].fd!=fd) !interfaces[i].open || interfaces[i].fd != fd) {
{
for (i = 0; i < interface_max_connections; i++) { for (i = 0; i < interface_max_connections; i++) {
if(interfaces[i].open && interfaces[i].fd==fd) break; if (interfaces[i].open && interfaces[i].fd == fd)
break;
} }
if(i==interface_max_connections) return -1; if (i == interface_max_connections)
return -1;
} }
/* if fd isn't found or interfaces is going to be closed, do nothing */ /* if fd isn't found or interfaces is going to be closed, do nothing */
if(interfaces[i].expired) return 0; if (interfaces[i].expired)
return 0;
interface = interfaces + i; interface = interfaces + i;
while (buflen > 0 && !interface->expired) { while (buflen > 0 && !interface->expired) {
copylen = buflen > copylen = buflen >
interface->outBufSize - interface->outBuflen ? interface->outBufSize - interface->outBuflen ?
interface->outBufSize-interface->outBuflen: interface->outBufSize - interface->outBuflen : buflen;
buflen;
memcpy(interface->outBuffer + interface->outBuflen, buffer, memcpy(interface->outBuffer + interface->outBuflen, buffer,
copylen); copylen);
buflen -= copylen; buflen -= copylen;
@ -619,7 +626,8 @@ int interfacePrintWithFD(int fd, char * buffer, int buflen) {
return 0; return 0;
} }
static void printInterfaceOutBuffer(Interface * interface) { static void printInterfaceOutBuffer(Interface * interface)
{
char *buffer; char *buffer;
int ret; int ret;
@ -631,8 +639,7 @@ static void printInterfaceOutBuffer(Interface * interface) {
interface->outputBufferSize += sizeof(ListNode); interface->outputBufferSize += sizeof(ListNode);
interface->outputBufferSize += interface->outBuflen + 1; interface->outputBufferSize += interface->outBuflen + 1;
if (interface->outputBufferSize > if (interface->outputBufferSize >
interface_max_output_buffer_size) interface_max_output_buffer_size) {
{
ERROR("interface %i: output buffer size (%lli) is " ERROR("interface %i: output buffer size (%lli) is "
"larger than the max (%lli)\n", "larger than the max (%lli)\n",
interface->num, interface->num,
@ -642,19 +649,18 @@ static void printInterfaceOutBuffer(Interface * interface) {
freeList(interface->bufferList); freeList(interface->bufferList);
interface->bufferList = NULL; interface->bufferList = NULL;
interface->expired = 1; interface->expired = 1;
} } else {
else {
buffer = malloc(interface->outBuflen + 1); buffer = malloc(interface->outBuflen + 1);
memcpy(buffer,interface->outBuffer,interface->outBuflen); memcpy(buffer, interface->outBuffer,
interface->outBuflen);
buffer[interface->outBuflen] = '\0'; buffer[interface->outBuflen] = '\0';
insertInListWithoutKey(interface->bufferList,(void *)buffer); insertInListWithoutKey(interface->bufferList,
(void *)buffer);
flushInterfaceBuffer(interface); flushInterfaceBuffer(interface);
} }
} } else {
else {
if ((ret = write(interface->fd, interface->outBuffer, if ((ret = write(interface->fd, interface->outBuffer,
interface->outBuflen))<0) interface->outBuflen)) < 0) {
{
if (errno == EAGAIN || errno == EINTR) { if (errno == EAGAIN || errno == EINTR) {
buffer = malloc(interface->outBuflen + 1); buffer = malloc(interface->outBuflen + 1);
memcpy(buffer, interface->outBuffer, memcpy(buffer, interface->outBuffer,
@ -663,15 +669,13 @@ static void printInterfaceOutBuffer(Interface * interface) {
interface->bufferList = makeList(free, 1); interface->bufferList = makeList(free, 1);
insertInListWithoutKey(interface->bufferList, insertInListWithoutKey(interface->bufferList,
(void *)buffer); (void *)buffer);
} } else {
else {
DEBUG("interface %i: problems writing\n", DEBUG("interface %i: problems writing\n",
interface->num); interface->num);
interface->expired = 1; interface->expired = 1;
return; return;
} }
} } else if (ret < interface->outBuflen) {
else if(ret<interface->outBuflen) {
buffer = malloc(interface->outBuflen - ret + 1); buffer = malloc(interface->outBuflen - ret + 1);
memcpy(buffer, interface->outBuffer + ret, memcpy(buffer, interface->outBuffer + ret,
interface->outBuflen - ret); interface->outBuflen - ret);
@ -684,9 +688,11 @@ static void printInterfaceOutBuffer(Interface * interface) {
DEBUG("interface %i: buffer created\n", interface->num); DEBUG("interface %i: buffer created\n", interface->num);
interface->outputBufferSize = sizeof(List); interface->outputBufferSize = sizeof(List);
interface->outputBufferSize += sizeof(ListNode); interface->outputBufferSize += sizeof(ListNode);
interface->outputBufferSize+=strlen( interface->outputBufferSize += strlen((char *)
(char *)interface->bufferList-> interface->
firstNode->data)+1; bufferList->
firstNode->data) +
1;
} }
} }

View File

@ -16,7 +16,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "list.h" #include "list.h"
#include <stdlib.h> #include <stdlib.h>
@ -25,11 +24,13 @@
#include <time.h> #include <time.h>
#include <stdio.h> #include <stdio.h>
static void makeListNodesArray(List * list) { static void makeListNodesArray(List * list)
{
ListNode *node = list->firstNode; ListNode *node = list->firstNode;
long i; long i;
if(!list->numberOfNodes) return; if (!list->numberOfNodes)
return;
list->nodesArray = realloc(list->nodesArray, list->nodesArray = realloc(list->nodesArray,
sizeof(ListNode *) * list->numberOfNodes); sizeof(ListNode *) * list->numberOfNodes);
@ -40,13 +41,16 @@ static void makeListNodesArray(List * list) {
} }
} }
static void freeListNodesArray(List * list) { static void freeListNodesArray(List * list)
if(!list->nodesArray) return; {
if (!list->nodesArray)
return;
free(list->nodesArray); free(list->nodesArray);
list->nodesArray = NULL; list->nodesArray = NULL;
} }
List * makeList(ListFreeDataFunc * freeDataFunc, int strdupKeys) { List *makeList(ListFreeDataFunc * freeDataFunc, int strdupKeys)
{
List *list = malloc(sizeof(List)); List *list = malloc(sizeof(List));
assert(list != NULL); assert(list != NULL);
@ -62,7 +66,8 @@ List * makeList(ListFreeDataFunc * freeDataFunc, int strdupKeys) {
return list; return list;
} }
ListNode * insertInListBeforeNode(List * list, ListNode * beforeNode, int pos, char * key, void * data) ListNode *insertInListBeforeNode(List * list, ListNode * beforeNode, int pos,
char *key, void *data)
{ {
ListNode *node; ListNode *node;
@ -78,29 +83,28 @@ ListNode * insertInListBeforeNode(List * list, ListNode * beforeNode, int po
if (list->firstNode == NULL) { if (list->firstNode == NULL) {
assert(list->lastNode == NULL); assert(list->lastNode == NULL);
list->lastNode = node; list->lastNode = node;
} } else {
else {
assert(list->lastNode != NULL); assert(list->lastNode != NULL);
assert(list->lastNode->nextNode == NULL); assert(list->lastNode->nextNode == NULL);
list->firstNode->prevNode = node; list->firstNode->prevNode = node;
} }
node->prevNode = NULL; node->prevNode = NULL;
list->firstNode = node; list->firstNode = node;
} } else {
else {
if (beforeNode) { if (beforeNode) {
node->prevNode = beforeNode->prevNode; node->prevNode = beforeNode->prevNode;
beforeNode->prevNode = node; beforeNode->prevNode = node;
} } else {
else {
node->prevNode = list->lastNode; node->prevNode = list->lastNode;
list->lastNode = node; list->lastNode = node;
} }
node->prevNode->nextNode = node; node->prevNode->nextNode = node;
} }
if(list->strdupKeys) node->key = strdup(key); if (list->strdupKeys)
else node->key = key; node->key = strdup(key);
else
node->key = key;
node->data = data; node->data = data;
@ -108,15 +112,17 @@ ListNode * insertInListBeforeNode(List * list, ListNode * beforeNode, int po
if (list->sorted) { if (list->sorted) {
list->nodesArray = realloc(list->nodesArray, list->nodesArray = realloc(list->nodesArray,
list->numberOfNodes*sizeof(ListNode *)); list->numberOfNodes *
sizeof(ListNode *));
if (node == list->lastNode) { if (node == list->lastNode) {
list->nodesArray[list->numberOfNodes - 1] = node; list->nodesArray[list->numberOfNodes - 1] = node;
} } else if (pos < 0)
else if(pos < 0) makeListNodesArray(list); makeListNodesArray(list);
else { else {
memmove(list->nodesArray+pos+1, list->nodesArray+pos, memmove(list->nodesArray + pos + 1,
sizeof(ListNode *)* list->nodesArray + pos,
(list->numberOfNodes-pos-1)); sizeof(ListNode *) * (list->numberOfNodes -
pos - 1));
list->nodesArray[pos] = node; list->nodesArray[pos] = node;
} }
} }
@ -124,7 +130,8 @@ ListNode * insertInListBeforeNode(List * list, ListNode * beforeNode, int po
return node; return node;
} }
ListNode * insertInList(List * list, char * key, void * data) { ListNode *insertInList(List * list, char *key, void *data)
{
ListNode *node; ListNode *node;
assert(list != NULL); assert(list != NULL);
@ -134,20 +141,22 @@ ListNode * insertInList(List * list, char * key, void * data) {
node = malloc(sizeof(ListNode)); node = malloc(sizeof(ListNode));
assert(node != NULL); assert(node != NULL);
if(list->nodesArray) freeListNodesArray(list); if (list->nodesArray)
freeListNodesArray(list);
if (list->firstNode == NULL) { if (list->firstNode == NULL) {
assert(list->lastNode == NULL); assert(list->lastNode == NULL);
list->firstNode = node; list->firstNode = node;
} } else {
else {
assert(list->lastNode != NULL); assert(list->lastNode != NULL);
assert(list->lastNode->nextNode == NULL); assert(list->lastNode->nextNode == NULL);
list->lastNode->nextNode = node; list->lastNode->nextNode = node;
} }
if(list->strdupKeys) node->key = strdup(key); if (list->strdupKeys)
else node->key = key; node->key = strdup(key);
else
node->key = key;
node->data = data; node->data = data;
node->nextNode = NULL; node->nextNode = NULL;
@ -160,7 +169,8 @@ ListNode * insertInList(List * list, char * key, void * data) {
return node; return node;
} }
int insertInListWithoutKey(List * list, void * data) { int insertInListWithoutKey(List * list, void *data)
{
ListNode *node; ListNode *node;
assert(list != NULL); assert(list != NULL);
@ -169,13 +179,13 @@ int insertInListWithoutKey(List * list, void * data) {
node = malloc(sizeof(ListNode)); node = malloc(sizeof(ListNode));
assert(node != NULL); assert(node != NULL);
if(list->nodesArray) freeListNodesArray(list); if (list->nodesArray)
freeListNodesArray(list);
if (list->firstNode == NULL) { if (list->firstNode == NULL) {
assert(list->lastNode == NULL); assert(list->lastNode == NULL);
list->firstNode = node; list->firstNode = node;
} } else {
else {
assert(list->lastNode != NULL); assert(list->lastNode != NULL);
assert(list->lastNode->nextNode == NULL); assert(list->lastNode->nextNode == NULL);
list->lastNode->nextNode = node; list->lastNode->nextNode = node;
@ -195,7 +205,8 @@ int insertInListWithoutKey(List * list, void * data) {
/* if _key_ is not found, *_node_ is assigned to the node before which /* if _key_ is not found, *_node_ is assigned to the node before which
the info would be found */ the info would be found */
int findNodeInList(List * list, char * key, ListNode ** node, int * pos) { int findNodeInList(List * list, char *key, ListNode ** node, int *pos)
{
long high; long high;
long low; long low;
long cur; long cur;
@ -217,10 +228,11 @@ int findNodeInList(List * list, char * key, ListNode ** node, int * pos) {
*node = tmpNode; *node = tmpNode;
*pos = cur; *pos = cur;
return 1; return 1;
} } else if (cmp > 0)
else if(cmp>0) high = cur; high = cur;
else { else {
if(low==cur) break; if (low == cur)
break;
low = cur; low = cur;
} }
} }
@ -231,21 +243,21 @@ int findNodeInList(List * list, char * key, ListNode ** node, int * pos) {
*node = tmpNode; *node = tmpNode;
*pos = high; *pos = high;
cmp = tmpNode ? strcmp(tmpNode->key, key) : -1; cmp = tmpNode ? strcmp(tmpNode->key, key) : -1;
if( 0 == cmp ) return 1; if (0 == cmp)
else if( cmp > 0) return 0; return 1;
else if (cmp > 0)
return 0;
else { else {
*pos = -1; *pos = -1;
*node = NULL; *node = NULL;
return 0; return 0;
} }
} } else {
else {
*pos = 0; *pos = 0;
*node = list->firstNode; *node = list->firstNode;
return 0; return 0;
} }
} } else {
else {
tmpNode = list->firstNode; tmpNode = list->firstNode;
while (tmpNode != NULL && strcmp(tmpNode->key, key) != 0) { while (tmpNode != NULL && strcmp(tmpNode->key, key) != 0) {
@ -253,25 +265,29 @@ int findNodeInList(List * list, char * key, ListNode ** node, int * pos) {
} }
*node = tmpNode; *node = tmpNode;
if(tmpNode) return 1; if (tmpNode)
}
return 0;
}
int findInList(List * list, char * key, void ** data) {
ListNode * node;
int pos;
if(findNodeInList(list, key, &node, &pos)) {
if(data) *data = node->data;
return 1; return 1;
} }
return 0; return 0;
} }
int deleteFromList(List * list,char * key) { int findInList(List * list, char *key, void **data)
{
ListNode *node;
int pos;
if (findNodeInList(list, key, &node, &pos)) {
if (data)
*data = node->data;
return 1;
}
return 0;
}
int deleteFromList(List * list, char *key)
{
ListNode *tmpNode; ListNode *tmpNode;
assert(list != NULL); assert(list != NULL);
@ -290,38 +306,40 @@ int deleteFromList(List * list,char * key) {
return 1; return 1;
} }
void deleteNodeFromList(List * list,ListNode * node) { void deleteNodeFromList(List * list, ListNode * node)
{
assert(list != NULL); assert(list != NULL);
assert(node != NULL); assert(node != NULL);
if (node->prevNode == NULL) { if (node->prevNode == NULL) {
list->firstNode = node->nextNode; list->firstNode = node->nextNode;
} } else {
else {
node->prevNode->nextNode = node->nextNode; node->prevNode->nextNode = node->nextNode;
} }
if (node->nextNode == NULL) { if (node->nextNode == NULL) {
list->lastNode = node->prevNode; list->lastNode = node->prevNode;
} } else {
else {
node->nextNode->prevNode = node->prevNode; node->nextNode->prevNode = node->prevNode;
} }
if (list->freeDataFunc) { if (list->freeDataFunc) {
list->freeDataFunc(node->data); list->freeDataFunc(node->data);
} }
if(list->strdupKeys) free(node->key); if (list->strdupKeys)
free(node->key);
free(node); free(node);
list->numberOfNodes--; list->numberOfNodes--;
if (list->nodesArray) { if (list->nodesArray) {
freeListNodesArray(list); freeListNodesArray(list);
if(list->sorted) makeListNodesArray(list); if (list->sorted)
makeListNodesArray(list);
} }
} }
void freeList(void * list) { void freeList(void *list)
{
ListNode *tmpNode; ListNode *tmpNode;
ListNode *tmpNode2; ListNode *tmpNode2;
@ -329,11 +347,13 @@ void freeList(void * list) {
tmpNode = ((List *) list)->firstNode; tmpNode = ((List *) list)->firstNode;
if(((List *)list)->nodesArray) free(((List *)list)->nodesArray); if (((List *) list)->nodesArray)
free(((List *) list)->nodesArray);
while (tmpNode != NULL) { while (tmpNode != NULL) {
tmpNode2 = tmpNode->nextNode; tmpNode2 = tmpNode->nextNode;
if(((List *)list)->strdupKeys) free(tmpNode->key); if (((List *) list)->strdupKeys)
free(tmpNode->key);
if (((List *) list)->freeDataFunc) { if (((List *) list)->freeDataFunc) {
((List *) list)->freeDataFunc(tmpNode->data); ((List *) list)->freeDataFunc(tmpNode->data);
} }
@ -344,7 +364,8 @@ void freeList(void * list) {
free(list); free(list);
} }
static void swapNodes(ListNode * nodeA, ListNode * nodeB) { static void swapNodes(ListNode * nodeA, ListNode * nodeB)
{
char *key; char *key;
void *data; void *data;
@ -361,12 +382,14 @@ static void swapNodes(ListNode * nodeA, ListNode * nodeB) {
nodeA->data = data; nodeA->data = data;
} }
static void bubbleSort(ListNode ** nodesArray, long start, long end) { static void bubbleSort(ListNode ** nodesArray, long start, long end)
{
long i; long i;
long j; long j;
ListNode *node; ListNode *node;
if(start>=end) return; if (start >= end)
return;
for (j = start; j < end; j++) { for (j = start; j < end; j++) {
for (i = end - 1; i >= start; i--) { for (i = end - 1; i >= start; i--) {
@ -378,9 +401,12 @@ static void bubbleSort(ListNode ** nodesArray, long start, long end) {
} }
} }
static void quickSort(ListNode ** nodesArray, long start, long end) { static void quickSort(ListNode ** nodesArray, long start, long end)
if(start>=end) return; {
else if(end-start<5) bubbleSort(nodesArray,start,end); if (start >= end)
return;
else if (end - start < 5)
bubbleSort(nodesArray, start, end);
else { else {
long i; long i;
ListNode *node; ListNode *node;
@ -403,10 +429,10 @@ static void quickSort(ListNode ** nodesArray, long start, long end) {
if (end - start < 5) { if (end - start < 5) {
bubbleSort(nodesArray, start, end); bubbleSort(nodesArray, start, end);
deleteNodeFromList(startList,startList->lastNode); deleteNodeFromList(startList,
startList->lastNode);
deleteNodeFromList(endList, endList->lastNode); deleteNodeFromList(endList, endList->lastNode);
} } else {
else {
pivot = (start + end) / 2; pivot = (start + end) / 2;
pivotNode = nodesArray[pivot]; pivotNode = nodesArray[pivot];
pivotKey = pivotNode->key; pivotKey = pivotNode->key;
@ -416,9 +442,12 @@ static void quickSort(ListNode ** nodesArray, long start, long end) {
if (strcmp(node->key, pivotKey) > 0) { if (strcmp(node->key, pivotKey) > 0) {
pivot--; pivot--;
if (pivot > i) { if (pivot > i) {
swapNodes(node,nodesArray[pivot]); swapNodes(node,
nodesArray
[pivot]);
} }
swapNodes(pivotNode,nodesArray[pivot]); swapNodes(pivotNode,
nodesArray[pivot]);
pivotNode = nodesArray[pivot]; pivotNode = nodesArray[pivot];
} }
} }
@ -427,14 +456,18 @@ static void quickSort(ListNode ** nodesArray, long start, long end) {
if (strcmp(pivotKey, node->key) > 0) { if (strcmp(pivotKey, node->key) > 0) {
pivot++; pivot++;
if (pivot < i) { if (pivot < i) {
swapNodes(node,nodesArray[pivot]); swapNodes(node,
nodesArray
[pivot]);
} }
swapNodes(pivotNode,nodesArray[pivot]); swapNodes(pivotNode,
nodesArray[pivot]);
pivotNode = nodesArray[pivot]; pivotNode = nodesArray[pivot];
} }
} }
deleteNodeFromList(startList,startList->lastNode); deleteNodeFromList(startList,
startList->lastNode);
deleteNodeFromList(endList, endList->lastNode); deleteNodeFromList(endList, endList->lastNode);
if (pivot - 1 - start > 0) { if (pivot - 1 - start > 0) {
@ -442,8 +475,11 @@ static void quickSort(ListNode ** nodesArray, long start, long end) {
endPtr = malloc(sizeof(long)); endPtr = malloc(sizeof(long));
*startPtr = start; *startPtr = start;
*endPtr = pivot - 1; *endPtr = pivot - 1;
insertInListWithoutKey(startList,(void *)startPtr); insertInListWithoutKey(startList,
insertInListWithoutKey(endList,(void *)endPtr); (void *)
startPtr);
insertInListWithoutKey(endList,
(void *)endPtr);
} }
if (end - pivot - 1 > 0) { if (end - pivot - 1 > 0) {
@ -451,8 +487,11 @@ static void quickSort(ListNode ** nodesArray, long start, long end) {
endPtr = malloc(sizeof(long)); endPtr = malloc(sizeof(long));
*startPtr = pivot + 1; *startPtr = pivot + 1;
*endPtr = end; *endPtr = end;
insertInListWithoutKey(startList,(void *)startPtr); insertInListWithoutKey(startList,
insertInListWithoutKey(endList,(void *)endPtr); (void *)
startPtr);
insertInListWithoutKey(endList,
(void *)endPtr);
} }
} }
} }
@ -462,14 +501,17 @@ static void quickSort(ListNode ** nodesArray, long start, long end) {
} }
} }
void sortList(List * list) { void sortList(List * list)
{
assert(list != NULL); assert(list != NULL);
list->sorted = 1; list->sorted = 1;
if(list->numberOfNodes<2) return; if (list->numberOfNodes < 2)
return;
if(list->nodesArray) freeListNodesArray(list); if (list->nodesArray)
freeListNodesArray(list);
makeListNodesArray(list); makeListNodesArray(list);
quickSort(list->nodesArray, 0, list->numberOfNodes - 1); quickSort(list->nodesArray, 0, list->numberOfNodes - 1);

View File

@ -16,7 +16,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifndef LIST_H #ifndef LIST_H
#define LIST_H #define LIST_H

View File

@ -44,8 +44,7 @@ int * listenSockets = NULL;
int numberOfListenSockets = 0; int numberOfListenSockets = 0;
static void establishListen(unsigned int port, static void establishListen(unsigned int port,
struct sockaddr * addrp, struct sockaddr *addrp, socklen_t addrlen)
socklen_t addrlen)
{ {
int pf; int pf;
int sock; int sock;
@ -80,8 +79,7 @@ static void establishListen(unsigned int port,
} }
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&allowReuse, if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&allowReuse,
sizeof(allowReuse))<0) sizeof(allowReuse)) < 0) {
{
ERROR("problems setsockopt'ing: %s\n", strerror(errno)); ERROR("problems setsockopt'ing: %s\n", strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -105,7 +103,8 @@ static void establishListen(unsigned int port,
listenSockets[numberOfListenSockets - 1] = sock; listenSockets[numberOfListenSockets - 1] = sock;
} }
static void parseListenConfigParam(unsigned int port, ConfigParam * param) { static void parseListenConfigParam(unsigned int port, ConfigParam * param)
{
struct sockaddr *addrp; struct sockaddr *addrp;
socklen_t addrlen; socklen_t addrlen;
struct sockaddr_in sin; struct sockaddr_in sin;
@ -134,8 +133,7 @@ static void parseListenConfigParam(unsigned int port, ConfigParam * param) {
addrp = (struct sockaddr *)&sin; addrp = (struct sockaddr *)&sin;
addrlen = sizeof(struct sockaddr_in); addrlen = sizeof(struct sockaddr_in);
establishListen(port, addrp, addrlen); establishListen(port, addrp, addrlen);
} } else {
else {
struct hostent *he; struct hostent *he;
DEBUG("binding to address for %s\n", param->value); DEBUG("binding to address for %s\n", param->value);
if (!(he = gethostbyname(param->value))) { if (!(he = gethostbyname(param->value))) {
@ -166,8 +164,7 @@ static void parseListenConfigParam(unsigned int port, ConfigParam * param) {
break; break;
default: default:
ERROR("address type for \"%s\" is not IPv4 or IPv6 " ERROR("address type for \"%s\" is not IPv4 or IPv6 "
"at line %i\n", "at line %i\n", param->value, param->line);
param->value, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -175,7 +172,8 @@ static void parseListenConfigParam(unsigned int port, ConfigParam * param) {
} }
} }
void listenOnPort(void) { void listenOnPort(void)
{
int port = DEFAULT_PORT; int port = DEFAULT_PORT;
ConfigParam *param = getNextConfigParam(CONF_BIND_TO_ADDRESS, NULL); ConfigParam *param = getNextConfigParam(CONF_BIND_TO_ADDRESS, NULL);
@ -188,8 +186,7 @@ void listenOnPort(void) {
if (port <= 0 || *test != '\0') { if (port <= 0 || *test != '\0') {
ERROR("%s \"%s\" specified at line %i is not a " ERROR("%s \"%s\" specified at line %i is not a "
"positive integer", CONF_PORT, "positive integer", CONF_PORT,
portParam->value, portParam->value, portParam->line);
portParam->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
@ -200,16 +197,19 @@ void listenOnPort(void) {
} while ((param = getNextConfigParam(CONF_BIND_TO_ADDRESS, param))); } while ((param = getNextConfigParam(CONF_BIND_TO_ADDRESS, param)));
} }
void addListenSocketsToFdSet(fd_set * fds, int * fdmax) { void addListenSocketsToFdSet(fd_set * fds, int *fdmax)
{
int i; int i;
for (i = 0; i < numberOfListenSockets; i++) { for (i = 0; i < numberOfListenSockets; i++) {
FD_SET(listenSockets[i], fds); FD_SET(listenSockets[i], fds);
if(listenSockets[i] > *fdmax) *fdmax = listenSockets[i]; if (listenSockets[i] > *fdmax)
*fdmax = listenSockets[i];
} }
} }
void closeAllListenSockets(void) { void closeAllListenSockets(void)
{
int i; int i;
DEBUG("closeAllListenSockets called\n"); DEBUG("closeAllListenSockets called\n");
@ -221,13 +221,15 @@ void closeAllListenSockets(void) {
freeAllListenSockets(); freeAllListenSockets();
} }
void freeAllListenSockets(void) { void freeAllListenSockets(void)
{
numberOfListenSockets = 0; numberOfListenSockets = 0;
free(listenSockets); free(listenSockets);
listenSockets = NULL; listenSockets = NULL;
} }
void getConnections(fd_set * fds) { void getConnections(fd_set * fds)
{
int i; int i;
int fd = 0; int fd = 0;
struct sockaddr sockAddr; struct sockaddr sockAddr;
@ -236,11 +238,10 @@ void getConnections(fd_set * fds) {
for (i = 0; i < numberOfListenSockets; i++) { for (i = 0; i < numberOfListenSockets; i++) {
if (FD_ISSET(listenSockets[i], fds)) { if (FD_ISSET(listenSockets[i], fds)) {
if ((fd = accept(listenSockets[i], &sockAddr, &socklen)) if ((fd = accept(listenSockets[i], &sockAddr, &socklen))
>= 0) >= 0) {
{
openAInterface(fd, &sockAddr); openAInterface(fd, &sockAddr);
} } else if (fd < 0
else if(fd<0 && (errno!=EAGAIN && errno!=EINTR)) { && (errno != EAGAIN && errno != EINTR)) {
ERROR("Problems accept()'ing\n"); ERROR("Problems accept()'ing\n");
} }
} }

View File

@ -31,21 +31,23 @@ short warningFlushed = 0;
static char *warningBuffer = NULL; static char *warningBuffer = NULL;
void initLog(void) { void initLog(void)
{
ConfigParam *param = getConfigParam(CONF_LOG_LEVEL); ConfigParam *param = getConfigParam(CONF_LOG_LEVEL);
if(!param) return; if (!param)
return;
if (0 == strcmp(param->value, "default")) { if (0 == strcmp(param->value, "default")) {
if(logLevel<LOG_LEVEL_LOW) logLevel = LOG_LEVEL_LOW; if (logLevel < LOG_LEVEL_LOW)
} logLevel = LOG_LEVEL_LOW;
else if(0 == strcmp(param->value, "secure")) { } else if (0 == strcmp(param->value, "secure")) {
if(logLevel<LOG_LEVEL_SECURE) logLevel = LOG_LEVEL_SECURE; if (logLevel < LOG_LEVEL_SECURE)
} logLevel = LOG_LEVEL_SECURE;
else if(0 == strcmp(param->value, "verbose")) { } else if (0 == strcmp(param->value, "verbose")) {
if(logLevel<LOG_LEVEL_DEBUG) logLevel = LOG_LEVEL_DEBUG; if (logLevel < LOG_LEVEL_DEBUG)
} logLevel = LOG_LEVEL_DEBUG;
else { } else {
ERROR("unknown log level \"%s\" at line %i\n", ERROR("unknown log level \"%s\" at line %i\n",
param->value, param->line); param->value, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -54,7 +56,8 @@ void initLog(void) {
#define BUFFER_LENGTH 4096 #define BUFFER_LENGTH 4096
void bufferWarning(char * format, ... ) { void bufferWarning(char *format, ...)
{
va_list arglist; va_list arglist;
char temp[BUFFER_LENGTH + 1]; char temp[BUFFER_LENGTH + 1];
@ -69,12 +72,14 @@ void bufferWarning(char * format, ... ) {
va_end(arglist); va_end(arglist);
} }
void flushWarningLog(void) { void flushWarningLog(void)
{
char *s; char *s;
DEBUG("flushing warning messages\n"); DEBUG("flushing warning messages\n");
if(warningBuffer == NULL) return; if (warningBuffer == NULL)
return;
s = strtok(warningBuffer, "\n"); s = strtok(warningBuffer, "\n");
while (s != NULL) { while (s != NULL) {

View File

@ -37,7 +37,6 @@ extern short warningFlushed;
#define SECURE(...) if(logLevel>=LOG_LEVEL_SECURE) \ #define SECURE(...) if(logLevel>=LOG_LEVEL_SECURE) \
myfprintf(stdout, __VA_ARGS__) myfprintf(stdout, __VA_ARGS__)
#define DEBUG(...) if(logLevel>=LOG_LEVEL_DEBUG) \ #define DEBUG(...) if(logLevel>=LOG_LEVEL_DEBUG) \
myfprintf(stdout, __VA_ARGS__) myfprintf(stdout, __VA_ARGS__)

View File

@ -27,13 +27,13 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
static char * remoteUrlPrefixes[] = static char *remoteUrlPrefixes[] = {
{
"http://", "http://",
NULL NULL
}; };
int printRemoteUrlHandlers(FILE * fp) { int printRemoteUrlHandlers(FILE * fp)
{
char **prefixes = remoteUrlPrefixes; char **prefixes = remoteUrlPrefixes;
while (*prefixes) { while (*prefixes) {
@ -44,7 +44,8 @@ int printRemoteUrlHandlers(FILE * fp) {
return 0; return 0;
} }
int isValidRemoteUtf8Url(char * utf8url) { int isValidRemoteUtf8Url(char *utf8url)
{
int ret = 0; int ret = 0;
char *temp; char *temp;
@ -70,12 +71,8 @@ int isValidRemoteUtf8Url(char * utf8url) {
*temp == '/' || *temp == '/' ||
*temp == ':' || *temp == ':' ||
*temp == '?' || *temp == '?' ||
*temp == ';' || *temp == ';' || *temp == '&' || *temp == '=') {
*temp == '&' || } else {
*temp == '=')
{
}
else {
ret = 1; ret = 1;
break; break;
} }
@ -87,7 +84,8 @@ int isValidRemoteUtf8Url(char * utf8url) {
return ret; return ret;
} }
int isRemoteUrl(char * url) { int isRemoteUrl(char *url)
{
int count = 0; int count = 0;
char **urlPrefixes = remoteUrlPrefixes; char **urlPrefixes = remoteUrlPrefixes;
@ -102,7 +100,8 @@ int isRemoteUrl(char * url) {
return 0; return 0;
} }
int lsPlaylists(FILE * fp, char * utf8path) { int lsPlaylists(FILE * fp, char *utf8path)
{
DIR *dir; DIR *dir;
struct stat st; struct stat st;
struct dirent *ent; struct dirent *ent;
@ -133,12 +132,12 @@ int lsPlaylists(FILE * fp, char * utf8path) {
if (dup[0] != '.' && if (dup[0] != '.' &&
(suff = strlen(dup) - suflen) > 0 && (suff = strlen(dup) - suflen) > 0 &&
dup[suff] == '.' && dup[suff] == '.' &&
strcmp(dup+suff+1,PLAYLIST_FILE_SUFFIX)==0) strcmp(dup + suff + 1, PLAYLIST_FILE_SUFFIX) == 0) {
{
strncpy(s + actlen, ent->d_name, maxlen); strncpy(s + actlen, ent->d_name, maxlen);
if (stat(s, &st) == 0) { if (stat(s, &st) == 0) {
if (S_ISREG(st.st_mode)) { if (S_ISREG(st.st_mode)) {
if(list==NULL) list = makeList(NULL, 1); if (list == NULL)
list = makeList(NULL, 1);
dup[suff] = '\0'; dup[suff] = '\0';
if ((utf8 = fsCharsetToUtf8(dup))) { if ((utf8 = fsCharsetToUtf8(dup))) {
insertInList(list, utf8, NULL); insertInList(list, utf8, NULL);
@ -161,12 +160,14 @@ int lsPlaylists(FILE * fp, char * utf8path) {
for (i = strlen(dup) - 1; i >= 0 && dup[i] == '/'; i--) { for (i = strlen(dup) - 1; i >= 0 && dup[i] == '/'; i--) {
dup[i] = '\0'; dup[i] = '\0';
} }
if(strlen(dup)) strcat(dup,"/"); if (strlen(dup))
strcat(dup, "/");
node = list->firstNode; node = list->firstNode;
while (node != NULL) { while (node != NULL) {
if (!strchr(node->key, '\n')) { if (!strchr(node->key, '\n')) {
myfprintf(fp,"playlist: %s%s\n",dup,node->key); myfprintf(fp, "playlist: %s%s\n", dup,
node->key);
} }
node = node->nextNode; node = node->nextNode;
} }
@ -178,12 +179,14 @@ int lsPlaylists(FILE * fp, char * utf8path) {
return 0; return 0;
} }
int myStat(char * utf8file, struct stat * st) { int myStat(char *utf8file, struct stat *st)
{
char *file = utf8ToFsCharset(utf8file); char *file = utf8ToFsCharset(utf8file);
char *actualFile = file; char *actualFile = file;
int ret; int ret;
if(actualFile[0]!='/') actualFile = rmp2amp(file); if (actualFile[0] != '/')
actualFile = rmp2amp(file);
ret = stat(actualFile, st); ret = stat(actualFile, st);
@ -192,53 +195,59 @@ int myStat(char * utf8file, struct stat * st) {
return ret; return ret;
} }
static int isFile(char * utf8file, time_t * mtime) { static int isFile(char *utf8file, time_t * mtime)
{
struct stat st; struct stat st;
if (myStat(utf8file, &st) == 0) { if (myStat(utf8file, &st) == 0) {
if (S_ISREG(st.st_mode)) { if (S_ISREG(st.st_mode)) {
if(mtime) *mtime = st.st_mtime; if (mtime)
*mtime = st.st_mtime;
return 1; return 1;
} } else {
else
{
DEBUG("isFile: %s is not a regular file\n", utf8file); DEBUG("isFile: %s is not a regular file\n", utf8file);
return 0; return 0;
} }
} } else {
else { DEBUG("isFile: failed to stat: %s: %s\n", utf8file,
DEBUG("isFile: failed to stat: %s: %s\n", utf8file, strerror(errno)); strerror(errno));
} }
return 0; return 0;
} }
/* suffixes should be ascii only characters */ /* suffixes should be ascii only characters */
char * getSuffix(char * utf8file) { char *getSuffix(char *utf8file)
{
char *ret = NULL; char *ret = NULL;
while (*utf8file) { while (*utf8file) {
if(*utf8file == '.') ret = utf8file+1; if (*utf8file == '.')
ret = utf8file + 1;
utf8file++; utf8file++;
} }
return ret; return ret;
} }
int hasSuffix(char * utf8file, char * suffix) { int hasSuffix(char *utf8file, char *suffix)
{
char *s = getSuffix(utf8file); char *s = getSuffix(utf8file);
if(s && 0==strcmp(s,suffix)) return 1; if (s && 0 == strcmp(s, suffix))
return 1;
return 0; return 0;
} }
int isPlaylist(char * utf8file) { int isPlaylist(char *utf8file)
{
if (isFile(utf8file, NULL)) { if (isFile(utf8file, NULL)) {
return hasSuffix(utf8file, PLAYLIST_FILE_SUFFIX); return hasSuffix(utf8file, PLAYLIST_FILE_SUFFIX);
} }
return 0; return 0;
} }
int isDir(char * utf8name) { int isDir(char *utf8name)
{
struct stat st; struct stat st;
if (myStat(utf8name, &st) == 0) { if (myStat(utf8name, &st) == 0) {
@ -250,21 +259,23 @@ int isDir(char * utf8name) {
return 0; return 0;
} }
InputPlugin * hasMusicSuffix(char * utf8file, unsigned int next) { InputPlugin *hasMusicSuffix(char *utf8file, unsigned int next)
{
InputPlugin *ret = NULL; InputPlugin *ret = NULL;
char *s = getSuffix(utf8file); char *s = getSuffix(utf8file);
if (s) { if (s) {
ret = getInputPluginFromSuffix(s, next); ret = getInputPluginFromSuffix(s, next);
} } else {
else { DEBUG("hasMusicSuffix: The file: %s has no valid suffix\n",
DEBUG("hasMusicSuffix: The file: %s has no valid suffix\n",utf8file); utf8file);
} }
return ret; return ret;
} }
InputPlugin * isMusic(char * utf8file, time_t * mtime, unsigned int next) { InputPlugin *isMusic(char *utf8file, time_t * mtime, unsigned int next)
{
if (isFile(utf8file, mtime)) { if (isFile(utf8file, mtime)) {
InputPlugin *plugin = hasMusicSuffix(utf8file, next); InputPlugin *plugin = hasMusicSuffix(utf8file, next);
if (plugin != NULL) if (plugin != NULL)

View File

@ -20,7 +20,8 @@
#include <string.h> #include <string.h>
static void initMetadataChunk(MetadataChunk * chunk) { static void initMetadataChunk(MetadataChunk * chunk)
{
memset(chunk, 0, sizeof(MetadataChunk)); memset(chunk, 0, sizeof(MetadataChunk));
chunk->name = -1; chunk->name = -1;
@ -35,7 +36,8 @@ static void initMetadataChunk(MetadataChunk * chunk) {
} \ } \
} }
MpdTag * metadataChunkToMpdTagDup(MetadataChunk * chunk) { MpdTag *metadataChunkToMpdTagDup(MetadataChunk * chunk)
{
MpdTag *ret = newMpdTag(); MpdTag *ret = newMpdTag();
chunk->buffer[METADATA_BUFFER_LENGTH - 1] = '\0'; chunk->buffer[METADATA_BUFFER_LENGTH - 1] = '\0';
@ -59,14 +61,16 @@ MpdTag * metadataChunkToMpdTagDup(MetadataChunk * chunk) {
} \ } \
} }
void copyMpdTagToMetadataChunk(MpdTag * tag, MetadataChunk * chunk) { void copyMpdTagToMetadataChunk(MpdTag * tag, MetadataChunk * chunk)
{
int pos = 0; int pos = 0;
int slen; int slen;
int i; int i;
initMetadataChunk(chunk); initMetadataChunk(chunk);
if(!tag) return; if (!tag)
return;
for (i = 0; i < tag->numOfItems; i++) { for (i = 0; i < tag->numOfItems; i++) {
switch (tag->items[i].type) { switch (tag->items[i].type) {

View File

@ -38,12 +38,14 @@ static FILE * myfprintf_err;
static char *myfprintf_outFilename; static char *myfprintf_outFilename;
static char *myfprintf_errFilename; static char *myfprintf_errFilename;
static void blockingWrite(int fd, char * string, int len) { static void blockingWrite(int fd, char *string, int len)
{
int ret; int ret;
while (len) { while (len) {
ret = write(fd, string, len); ret = write(fd, string, len);
if(ret==0) return; if (ret == 0)
return;
if (ret < 0) { if (ret < 0) {
switch (errno) { switch (errno) {
case EAGAIN: case EAGAIN:
@ -58,7 +60,8 @@ static void blockingWrite(int fd, char * string, int len) {
} }
} }
void myfprintfStdLogMode(FILE * out, FILE * err) { void myfprintfStdLogMode(FILE * out, FILE * err)
{
myfprintf_stdLogMode = 1; myfprintf_stdLogMode = 1;
myfprintf_out = out; myfprintf_out = out;
myfprintf_err = err; myfprintf_err = err;
@ -66,7 +69,8 @@ void myfprintfStdLogMode(FILE * out, FILE * err) {
myfprintf_errFilename = getConfigParamValue(CONF_ERROR_FILE); myfprintf_errFilename = getConfigParamValue(CONF_ERROR_FILE);
} }
void myfprintf(FILE * fp, char * format, ... ) { void myfprintf(FILE * fp, char *format, ...)
{
static char buffer[BUFFER_LENGTH + 1]; static char buffer[BUFFER_LENGTH + 1];
va_list arglist; va_list arglist;
int fd = fileno(fp); int fd = fileno(fp);
@ -75,16 +79,17 @@ void myfprintf(FILE * fp, char * format, ... ) {
if (fd == 1 || fd == 2) { if (fd == 1 || fd == 2) {
if (myfprintf_stdLogMode) { if (myfprintf_stdLogMode) {
time_t t = time(NULL); time_t t = time(NULL);
if(fd==1) fp = myfprintf_out; if (fd == 1)
else fp = myfprintf_err; fp = myfprintf_out;
else
fp = myfprintf_err;
strftime(buffer, 14, "%b %e %R", localtime(&t)); strftime(buffer, 14, "%b %e %R", localtime(&t));
blockingWrite(fd, buffer, strlen(buffer)); blockingWrite(fd, buffer, strlen(buffer));
blockingWrite(fd, " : ", 3); blockingWrite(fd, " : ", 3);
} }
vsnprintf(buffer, BUFFER_LENGTH, format, arglist); vsnprintf(buffer, BUFFER_LENGTH, format, arglist);
blockingWrite(fd, buffer, strlen(buffer)); blockingWrite(fd, buffer, strlen(buffer));
} } else {
else {
int len; int len;
vsnprintf(buffer, BUFFER_LENGTH, format, arglist); vsnprintf(buffer, BUFFER_LENGTH, format, arglist);
len = strlen(buffer); len = strlen(buffer);
@ -96,22 +101,23 @@ void myfprintf(FILE * fp, char * format, ... ) {
va_end(arglist); va_end(arglist);
} }
int myfprintfCloseAndOpenLogFile(void) { int myfprintfCloseAndOpenLogFile(void)
{
if (myfprintf_stdLogMode) { if (myfprintf_stdLogMode) {
while (fclose(myfprintf_out) < 0 && errno == EINTR) ; while (fclose(myfprintf_out) < 0 && errno == EINTR) ;
while (fclose(myfprintf_err) < 0 && errno == EINTR) ; while (fclose(myfprintf_err) < 0 && errno == EINTR) ;
while((myfprintf_out = fopen(myfprintf_outFilename,"a+"))==NULL while ((myfprintf_out =
fopen(myfprintf_outFilename, "a+")) == NULL
&& errno == EINTR) ; && errno == EINTR) ;
if (!myfprintf_out) { if (!myfprintf_out) {
ERROR("error re-opening log file: %s\n", ERROR("error re-opening log file: %s\n", myfprintf_out);
myfprintf_out);
return -1; return -1;
} }
while((myfprintf_err = fopen(myfprintf_errFilename,"a+"))==NULL while ((myfprintf_err =
fopen(myfprintf_errFilename, "a+")) == NULL
&& errno == EINTR) ; && errno == EINTR) ;
if (!myfprintf_out) { if (!myfprintf_out) {
ERROR("error re-opening log file: %s\n", ERROR("error re-opening log file: %s\n", myfprintf_out);
myfprintf_out);
return -1; return -1;
} }
while (dup2(fileno(myfprintf_out), 1) < 0 && errno == EINTR) ; while (dup2(fileno(myfprintf_out), 1) < 0 && errno == EINTR) ;
@ -121,7 +127,8 @@ int myfprintfCloseAndOpenLogFile(void) {
return 0; return 0;
} }
void myfprintfCloseLogFile(void) { void myfprintfCloseLogFile(void)
{
if (myfprintf_stdLogMode) { if (myfprintf_stdLogMode) {
while (fclose(myfprintf_out) < 0 && errno == EINTR) ; while (fclose(myfprintf_out) < 0 && errno == EINTR) ;
while (fclose(myfprintf_err) < 0 && errno == EINTR) ; while (fclose(myfprintf_err) < 0 && errno == EINTR) ;

View File

@ -30,11 +30,13 @@ static mpd_sint16 currentChunk = -1;
static mpd_sint8 currentMetaChunk = -1; static mpd_sint8 currentMetaChunk = -1;
static mpd_sint8 sendMetaChunk = 0; static mpd_sint8 sendMetaChunk = 0;
void clearAllMetaChunkSets(OutputBuffer * cb) { void clearAllMetaChunkSets(OutputBuffer * cb)
{
memset(cb->metaChunkSet, 0, BUFFERED_METACHUNKS); memset(cb->metaChunkSet, 0, BUFFERED_METACHUNKS);
} }
void clearOutputBuffer(OutputBuffer * cb) { void clearOutputBuffer(OutputBuffer * cb)
{
int currentSet = 1; int currentSet = 1;
currentChunk = -1; currentChunk = -1;
@ -51,7 +53,8 @@ void clearOutputBuffer(OutputBuffer * cb) {
} }
} }
void flushOutputBuffer(OutputBuffer * cb) { void flushOutputBuffer(OutputBuffer * cb)
{
if (currentChunk == cb->end) { if (currentChunk == cb->end) {
int next = cb->end + 1; int next = cb->end + 1;
if (next >= buffered_chunks) { if (next >= buffered_chunks) {
@ -74,15 +77,17 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
static char *convBuffer = NULL; static char *convBuffer = NULL;
static long convBufferLen = 0; static long convBufferLen = 0;
if(cmpAudioFormat(&(cb->audioFormat),&(dc->audioFormat))==0) if (cmpAudioFormat(&(cb->audioFormat), &(dc->audioFormat)) == 0) {
{
data = dataIn; data = dataIn;
datalen = dataInLen; datalen = dataInLen;
} } else {
else { datalen =
datalen = pcm_sizeOfOutputBufferForAudioFormatConversion( pcm_sizeOfOutputBufferForAudioFormatConversion(&
&(dc->audioFormat), dataInLen, (dc->
&(cb->audioFormat)); audioFormat),
dataInLen,
&(cb->
audioFormat));
if (datalen > convBufferLen) { if (datalen > convBufferLen) {
convBuffer = realloc(convBuffer, datalen); convBuffer = realloc(convBuffer, datalen);
convBufferLen = datalen; convBufferLen = datalen;
@ -106,27 +111,26 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
if (dc->seek) { if (dc->seek) {
if (seekable) { if (seekable) {
return OUTPUT_BUFFER_DC_SEEK; return OUTPUT_BUFFER_DC_SEEK;
} } else {
else {
dc->seekError = 1; dc->seekError = 1;
dc->seek = 0; dc->seek = 0;
} }
} }
if (!inStream || if (!inStream ||
bufferInputStream(inStream) <= 0) bufferInputStream(inStream) <= 0) {
{
my_usleep(10000); my_usleep(10000);
} }
} }
if(dc->stop) return OUTPUT_BUFFER_DC_STOP; if (dc->stop)
return OUTPUT_BUFFER_DC_STOP;
currentChunk = cb->end; currentChunk = cb->end;
cb->chunkSize[currentChunk] = 0; cb->chunkSize[currentChunk] = 0;
if (sendMetaChunk) { if (sendMetaChunk) {
cb->metaChunk[currentChunk] = currentMetaChunk; cb->metaChunk[currentChunk] = currentMetaChunk;
} } else
else cb->metaChunk[currentChunk] = -1; cb->metaChunk[currentChunk] = -1;
cb->bitRate[currentChunk] = bitRate; cb->bitRate[currentChunk] = bitRate;
cb->times[currentChunk] = time; cb->times[currentChunk] = time;
} }
@ -135,8 +139,7 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
dataToSend = datalen > chunkLeft ? chunkLeft : datalen; dataToSend = datalen > chunkLeft ? chunkLeft : datalen;
memcpy(cb->chunks + currentChunk * CHUNK_SIZE + memcpy(cb->chunks + currentChunk * CHUNK_SIZE +
cb->chunkSize[currentChunk], cb->chunkSize[currentChunk], data, dataToSend);
data, dataToSend);
cb->chunkSize[currentChunk] += dataToSend; cb->chunkSize[currentChunk] += dataToSend;
datalen -= dataToSend; datalen -= dataToSend;
data += dataToSend; data += dataToSend;
@ -149,13 +152,15 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
return 0; return 0;
} }
int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag) { int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag)
{
int nextChunk; int nextChunk;
static MpdTag *last = NULL; static MpdTag *last = NULL;
if (!cb->acceptMetadata || !tag) { if (!cb->acceptMetadata || !tag) {
sendMetaChunk = 0; sendMetaChunk = 0;
if(last) freeMpdTag(last); if (last)
freeMpdTag(last);
last = NULL; last = NULL;
DEBUG("copyMpdTagToOB: !acceptMetadata || !tag\n"); DEBUG("copyMpdTagToOB: !acceptMetadata || !tag\n");
return 0; return 0;
@ -166,11 +171,13 @@ int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag) {
return 0; return 0;
} }
if(last) freeMpdTag(last); if (last)
freeMpdTag(last);
last = NULL; last = NULL;
nextChunk = currentMetaChunk + 1; nextChunk = currentMetaChunk + 1;
if(nextChunk >= BUFFERED_METACHUNKS) nextChunk = 0; if (nextChunk >= BUFFERED_METACHUNKS)
nextChunk = 0;
if (cb->metaChunkSet[nextChunk]) { if (cb->metaChunkSet[nextChunk]) {
sendMetaChunk = 0; sendMetaChunk = 0;

View File

@ -51,16 +51,14 @@ void flushOutputBuffer(OutputBuffer * cb);
/* we send inStream for buffering the inputStream while waiting to /* we send inStream for buffering the inputStream while waiting to
send the next chunk */ send the next chunk */
int sendDataToOutputBuffer( int sendDataToOutputBuffer(OutputBuffer * cb,
OutputBuffer * cb,
InputStream * inStream, InputStream * inStream,
DecoderControl * dc, DecoderControl * dc,
int seekable, int seekable,
void *data, void *data,
long datalen, long datalen,
float time, float time,
mpd_uint16 bitRate, mpd_uint16 bitRate, ReplayGainInfo * replayGainInfo);
ReplayGainInfo * replayGainInfo);
int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag); int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag);

View File

@ -42,7 +42,8 @@ char * playlistDir;
char *fsCharset = NULL; char *fsCharset = NULL;
static char * pathConvCharset(char * to, char * from, char * str) { static char *pathConvCharset(char *to, char *from, char *str)
{
if (setCharSetConversion(to, from) == 0) { if (setCharSetConversion(to, from) == 0) {
return convStrDup(str); return convStrDup(str);
} }
@ -50,7 +51,8 @@ static char * pathConvCharset(char * to, char * from, char * str) {
return NULL; return NULL;
} }
char * fsCharsetToUtf8(char * str) { char *fsCharsetToUtf8(char *str)
{
char *ret = pathConvCharset("UTF-8", fsCharset, str); char *ret = pathConvCharset("UTF-8", fsCharset, str);
if (ret && !validUtf8String(ret)) { if (ret && !validUtf8String(ret)) {
@ -61,18 +63,22 @@ char * fsCharsetToUtf8(char * str) {
return ret; return ret;
} }
char * utf8ToFsCharset(char * str) { char *utf8ToFsCharset(char *str)
{
char *ret = pathConvCharset(fsCharset, "UTF-8", str); char *ret = pathConvCharset(fsCharset, "UTF-8", str);
if(!ret) ret = strdup(str); if (!ret)
ret = strdup(str);
return ret; return ret;
} }
void setFsCharset(char * charset) { void setFsCharset(char *charset)
{
int error = 0; int error = 0;
if(fsCharset) free(fsCharset); if (fsCharset)
free(fsCharset);
fsCharset = strdup(charset); fsCharset = strdup(charset);
@ -98,11 +104,13 @@ void setFsCharset(char * charset) {
} }
} }
char * getFsCharset(void) { char *getFsCharset(void)
{
return fsCharset; return fsCharset;
} }
static char * appendSlash(char ** path) { static char *appendSlash(char **path)
{
char *temp = *path; char *temp = *path;
int len = strlen(temp); int len = strlen(temp);
@ -118,7 +126,8 @@ static char * appendSlash(char ** path) {
return temp; return temp;
} }
void initPaths(void) { void initPaths(void)
{
ConfigParam *musicParam = parseConfigFilePath(CONF_MUSIC_DIR, 1); ConfigParam *musicParam = parseConfigFilePath(CONF_MUSIC_DIR, 1);
ConfigParam *playlistParam = parseConfigFilePath(CONF_PLAYLIST_DIR, 1); ConfigParam *playlistParam = parseConfigFilePath(CONF_PLAYLIST_DIR, 1);
ConfigParam *fsCharsetParam = getConfigParam(CONF_FS_CHARSET); ConfigParam *fsCharsetParam = getConfigParam(CONF_FS_CHARSET);
@ -159,45 +168,45 @@ void initPaths(void) {
if (!(currentLocale = setlocale(LC_CTYPE, ""))) { if (!(currentLocale = setlocale(LC_CTYPE, ""))) {
WARNING("problems setting current locale with " WARNING("problems setting current locale with "
"setlocale()\n"); "setlocale()\n");
} } else {
else {
if (strcmp(currentLocale, "C") == 0 || if (strcmp(currentLocale, "C") == 0 ||
strcmp(currentLocale,"POSIX")==0) strcmp(currentLocale, "POSIX") == 0) {
{
WARNING("current locale is \"%s\"\n", WARNING("current locale is \"%s\"\n",
currentLocale); currentLocale);
} } else if ((temp = nl_langinfo(CODESET))) {
else if((temp = nl_langinfo(CODESET))) {
charset = strdup(temp); charset = strdup(temp);
} } else
else WARNING("problems getting charset for locale\n"); WARNING
("problems getting charset for locale\n");
if (!setlocale(LC_CTYPE, originalLocale)) { if (!setlocale(LC_CTYPE, originalLocale)) {
WARNING("problems resetting locale with setlocale()\n"); WARNING
("problems resetting locale with setlocale()\n");
} }
} }
free(originalLocale); free(originalLocale);
} } else
else WARNING("problems getting locale with setlocale()\n"); WARNING("problems getting locale with setlocale()\n");
#endif #endif
#endif #endif
if (charset) { if (charset) {
setFsCharset(charset); setFsCharset(charset);
free(charset); free(charset);
} } else {
else {
WARNING("setting filesystem charset to ISO-8859-1\n"); WARNING("setting filesystem charset to ISO-8859-1\n");
setFsCharset("ISO-8859-1"); setFsCharset("ISO-8859-1");
} }
} }
void finishPaths(void) { void finishPaths(void)
{
free(fsCharset); free(fsCharset);
fsCharset = NULL; fsCharset = NULL;
} }
char * rmp2amp(char * relativePath) { char *rmp2amp(char *relativePath)
{
static char absolutePath[MAXPATHLEN + 1]; static char absolutePath[MAXPATHLEN + 1];
memset(absolutePath, 0, MAXPATHLEN + 1); memset(absolutePath, 0, MAXPATHLEN + 1);
@ -208,7 +217,8 @@ char * rmp2amp(char * relativePath) {
return absolutePath; return absolutePath;
} }
char * rpp2app(char * relativePath) { char *rpp2app(char *relativePath)
{
static char absolutePath[MAXPATHLEN + 1]; static char absolutePath[MAXPATHLEN + 1];
memset(absolutePath, 0, MAXPATHLEN + 1); memset(absolutePath, 0, MAXPATHLEN + 1);
@ -219,7 +229,8 @@ char * rpp2app(char * relativePath) {
return absolutePath; return absolutePath;
} }
char * parentPath(char * path) { char *parentPath(char *path)
{
static char parentPath[MAXPATHLEN + 1]; static char parentPath[MAXPATHLEN + 1];
char *c; char *c;
@ -230,14 +241,16 @@ char * parentPath(char * path) {
if (c == NULL) if (c == NULL)
parentPath[0] = '\0'; parentPath[0] = '\0';
else { else {
while ((parentPath <= c) && *(--c) == '/') /* nothing */; while ((parentPath <= c) && *(--c) == '/') /* nothing */
;
c[1] = '\0'; c[1] = '\0';
} }
return parentPath; return parentPath;
} }
char * sanitizePathDup(char * path) { char *sanitizePathDup(char *path)
{
int len = strlen(path) + 1; int len = strlen(path) + 1;
char *ret = malloc(len); char *ret = malloc(len);
char *cp = ret; char *cp = ret;
@ -248,7 +261,8 @@ char * sanitizePathDup(char * path) {
/* illeminate more than one '/' in a row, like "///" */ /* illeminate more than one '/' in a row, like "///" */
while (*path) { while (*path) {
while(*path=='/') path++; while (*path == '/')
path++;
if (*path == '.') { if (*path == '.') {
/* we dont want to have hidden directoires, or '.' or /* we dont want to have hidden directoires, or '.' or
".." in our path */ ".." in our path */
@ -274,4 +288,3 @@ char * sanitizePathDup(char * path) {
return realloc(ret, len + 1); return realloc(ret, len + 1);
} }

View File

@ -16,7 +16,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "pcm_utils.h" #include "pcm_utils.h"
#include "mpd_types.h" #include "mpd_types.h"
@ -33,7 +32,8 @@ void pcm_volumeChange(char * buffer, int bufferSize, AudioFormat * format,
mpd_sint8 *buffer8 = (mpd_sint8 *) buffer; mpd_sint8 *buffer8 = (mpd_sint8 *) buffer;
mpd_sint16 *buffer16 = (mpd_sint16 *) buffer; mpd_sint16 *buffer16 = (mpd_sint16 *) buffer;
if(volume>=1000) return; if (volume >= 1000)
return;
if (volume <= 0) { if (volume <= 0) {
memset(buffer, 0, bufferSize); memset(buffer, 0, bufferSize);
@ -71,7 +71,8 @@ void pcm_volumeChange(char * buffer, int bufferSize, AudioFormat * format,
} }
static void pcm_add(char *buffer1, char *buffer2, size_t bufferSize1, static void pcm_add(char *buffer1, char *buffer2, size_t bufferSize1,
size_t bufferSize2, int vol1, int vol2, AudioFormat * format) size_t bufferSize2, int vol1, int vol2,
AudioFormat * format)
{ {
mpd_sint32 temp32; mpd_sint32 temp32;
mpd_sint8 *buffer8_1 = (mpd_sint8 *) buffer1; mpd_sint8 *buffer8_1 = (mpd_sint8 *) buffer1;
@ -82,27 +83,34 @@ static void pcm_add(char * buffer1, char * buffer2, size_t bufferSize1,
switch (format->bits) { switch (format->bits) {
case 16: case 16:
while (bufferSize1 > 0 && bufferSize2 > 0) { while (bufferSize1 > 0 && bufferSize2 > 0) {
temp32 = (vol1*(*buffer16_1)+vol2*(*buffer16_2))/1000; temp32 =
*buffer16_1 = temp32>32767 ? 32767 : (vol1 * (*buffer16_1) +
(temp32<-32768 ? -32768 : temp32); vol2 * (*buffer16_2)) / 1000;
*buffer16_1 =
temp32 > 32767 ? 32767 : (temp32 <
-32768 ? -32768 : temp32);
buffer16_1++; buffer16_1++;
buffer16_2++; buffer16_2++;
bufferSize1 -= 2; bufferSize1 -= 2;
bufferSize2 -= 2; bufferSize2 -= 2;
} }
if(bufferSize2>0) memcpy(buffer16_1,buffer16_2,bufferSize2); if (bufferSize2 > 0)
memcpy(buffer16_1, buffer16_2, bufferSize2);
break; break;
case 8: case 8:
while (bufferSize1 > 0 && bufferSize2 > 0) { while (bufferSize1 > 0 && bufferSize2 > 0) {
temp32 = (vol1*(*buffer8_1)+vol2*(*buffer8_2))/1000; temp32 =
*buffer8_1 = temp32>127 ? 127 : (vol1 * (*buffer8_1) + vol2 * (*buffer8_2)) / 1000;
(temp32<-128 ? -128 : temp32); *buffer8_1 =
temp32 > 127 ? 127 : (temp32 <
-128 ? -128 : temp32);
buffer8_1++; buffer8_1++;
buffer8_2++; buffer8_2++;
bufferSize1--; bufferSize1--;
bufferSize2--; bufferSize2--;
} }
if(bufferSize2>0) memcpy(buffer8_1,buffer8_2,bufferSize2); if (bufferSize2 > 0)
memcpy(buffer8_1, buffer8_2, bufferSize2);
break; break;
default: default:
ERROR("%i bits not supported by pcm_add!\n", format->bits); ERROR("%i bits not supported by pcm_add!\n", format->bits);
@ -120,10 +128,10 @@ void pcm_mix(char * buffer1, char * buffer2, size_t bufferSize1,
vol1 = s * 1000 + 0.5; vol1 = s * 1000 + 0.5;
vol1 = vol1 > 1000 ? 1000 : (vol1 < 0 ? 0 : vol1); vol1 = vol1 > 1000 ? 1000 : (vol1 < 0 ? 0 : vol1);
pcm_add(buffer1,buffer2,bufferSize1,bufferSize2,vol1,1000-vol1,format); pcm_add(buffer1, buffer2, bufferSize1, bufferSize2, vol1, 1000 - vol1,
format);
} }
/* outFormat bits must be 16 and channels must be 2! */ /* outFormat bits must be 16 and channels must be 2! */
void pcm_convertAudioFormat(AudioFormat * inFormat, char *inBuffer, size_t void pcm_convertAudioFormat(AudioFormat * inFormat, char *inBuffer, size_t
inSize, AudioFormat * outFormat, char *outBuffer) inSize, AudioFormat * outFormat, char *outBuffer)
@ -170,12 +178,10 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t
} }
/* converts only between 16 bit audio between mono and stereo */ /* converts only between 16 bit audio between mono and stereo */
if(inFormat->channels == outFormat->channels) if (inFormat->channels == outFormat->channels) {
{
dataChannelConv = dataBitConv; dataChannelConv = dataBitConv;
dataChannelLen = dataBitLen; dataChannelLen = dataBitLen;
} } else {
else {
switch (inFormat->channels) { switch (inFormat->channels) {
/* convert from 1 -> 2 channels */ /* convert from 1 -> 2 channels */
case 1: case 1:
@ -188,7 +194,8 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t
dataChannelConv = channelConvBuffer; dataChannelConv = channelConvBuffer;
{ {
mpd_sint16 *in = (mpd_sint16 *) dataBitConv; mpd_sint16 *in = (mpd_sint16 *) dataBitConv;
mpd_sint16 * out = (mpd_sint16 *)dataChannelConv; mpd_sint16 *out =
(mpd_sint16 *) dataChannelConv;
int i, inSamples = dataBitLen >> 1; int i, inSamples = dataBitLen >> 1;
for (i = 0; i < inSamples; i++) { for (i = 0; i < inSamples; i++) {
*out++ = *in; *out++ = *in;
@ -207,7 +214,8 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t
dataChannelConv = channelConvBuffer; dataChannelConv = channelConvBuffer;
{ {
mpd_sint16 *in = (mpd_sint16 *) dataBitConv; mpd_sint16 *in = (mpd_sint16 *) dataBitConv;
mpd_sint16 * out = (mpd_sint16 *)dataChannelConv; mpd_sint16 *out =
(mpd_sint16 *) dataChannelConv;
int i, inSamples = dataBitLen >> 2; int i, inSamples = dataBitLen >> 2;
for (i = 0; i < inSamples; i++) { for (i = 0; i < inSamples; i++) {
*out = (*in++) / 2; *out = (*in++) / 2;
@ -216,15 +224,15 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t
} }
break; break;
default: default:
ERROR("only 1 or 2 channels are supported for conversion!\n"); ERROR
("only 1 or 2 channels are supported for conversion!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (inFormat->sampleRate == outFormat->sampleRate) { if (inFormat->sampleRate == outFormat->sampleRate) {
memcpy(outBuffer, dataChannelConv, dataChannelLen); memcpy(outBuffer, dataChannelConv, dataChannelLen);
} } else {
else {
/* only works if outFormat is 16-bit stereo! */ /* only works if outFormat is 16-bit stereo! */
/* resampling code blatantly ripped from ESD */ /* resampling code blatantly ripped from ESD */
mpd_uint32 rd_dat = 0; mpd_uint32 rd_dat = 0;
@ -269,7 +277,8 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t
} }
size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat,
size_t inSize, AudioFormat * outFormat) size_t inSize,
AudioFormat * outFormat)
{ {
const int shift = sizeof(mpd_sint16) * outFormat->channels; const int shift = sizeof(mpd_sint16) * outFormat->channels;
size_t outSize = inSize; size_t outSize = inSize;

View File

@ -35,5 +35,6 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t
inSize, AudioFormat * outFormat, char *outBuffer); inSize, AudioFormat * outFormat, char *outBuffer);
size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat,
size_t inSize, AudioFormat * outFormat); size_t inSize,
AudioFormat * outFormat);
#endif #endif

View File

@ -36,28 +36,26 @@ static List * permission_passwords;
static int permission_default; static int permission_default;
static int parsePermissions(char * string) { static int parsePermissions(char *string)
{
int permission = 0; int permission = 0;
char *temp; char *temp;
char *tok; char *tok;
if(!string) return 0; if (!string)
return 0;
temp = strtok_r(string, PERMISSION_SEPERATOR, &tok); temp = strtok_r(string, PERMISSION_SEPERATOR, &tok);
while (temp) { while (temp) {
if (strcmp(temp, PERMISSION_READ_STRING) == 0) { if (strcmp(temp, PERMISSION_READ_STRING) == 0) {
permission |= PERMISSION_READ; permission |= PERMISSION_READ;
} } else if (strcmp(temp, PERMISSION_ADD_STRING) == 0) {
else if(strcmp(temp,PERMISSION_ADD_STRING)==0) {
permission |= PERMISSION_ADD; permission |= PERMISSION_ADD;
} } else if (strcmp(temp, PERMISSION_CONTROL_STRING) == 0) {
else if(strcmp(temp,PERMISSION_CONTROL_STRING)==0) {
permission |= PERMISSION_CONTROL; permission |= PERMISSION_CONTROL;
} } else if (strcmp(temp, PERMISSION_ADMIN_STRING) == 0) {
else if(strcmp(temp,PERMISSION_ADMIN_STRING)==0) {
permission |= PERMISSION_ADMIN; permission |= PERMISSION_ADMIN;
} } else {
else {
ERROR("unknown permission \"%s\"\n", temp); ERROR("unknown permission \"%s\"\n", temp);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -68,7 +66,8 @@ static int parsePermissions(char * string) {
return permission; return permission;
} }
void initPermissions(void) { void initPermissions(void)
{
char *temp; char *temp;
char *cp2; char *cp2;
char *password; char *password;
@ -90,35 +89,39 @@ void initPermissions(void) {
ERROR("\"%s\" not found in password string " ERROR("\"%s\" not found in password string "
"\"%s\", line %i\n", "\"%s\", line %i\n",
PERMISSION_PASSWORD_CHAR, PERMISSION_PASSWORD_CHAR,
param->value, param->value, param->line);
param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!(temp = strtok_r(param->value, if (!(temp = strtok_r(param->value,
PERMISSION_PASSWORD_CHAR,&cp2))) { PERMISSION_PASSWORD_CHAR,
ERROR("something weird just happened in permission.c\n"); &cp2))) {
ERROR
("something weird just happened in permission.c\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
password = temp; password = temp;
permission = malloc(sizeof(int)); permission = malloc(sizeof(int));
*permission = parsePermissions(strtok_r(NULL,"",&cp2)); *permission =
parsePermissions(strtok_r(NULL, "", &cp2));
insertInList(permission_passwords,password,permission); insertInList(permission_passwords, password,
permission);
} while ((param = getNextConfigParam(CONF_PASSWORD, param))); } while ((param = getNextConfigParam(CONF_PASSWORD, param)));
} }
param = getConfigParam(CONF_DEFAULT_PERMS); param = getConfigParam(CONF_DEFAULT_PERMS);
if(param) permission_default = parsePermissions(param->value); if (param)
permission_default = parsePermissions(param->value);
sortList(permission_passwords); sortList(permission_passwords);
} }
int getPermissionFromPassword(char * password, int * permission) { int getPermissionFromPassword(char *password, int *permission)
{
void *foundPermission; void *foundPermission;
if (findInList(permission_passwords, password, &foundPermission)) { if (findInList(permission_passwords, password, &foundPermission)) {
@ -129,10 +132,12 @@ int getPermissionFromPassword(char * password, int * permission) {
return -1; return -1;
} }
void finishPermissions(void) { void finishPermissions(void)
{
freeList(permission_passwords); freeList(permission_passwords);
} }
int getDefaultPermissions(void) { int getDefaultPermissions(void)
{
return permission_default; return permission_default;
} }

View File

@ -45,7 +45,8 @@
extern int masterPid; extern int masterPid;
static void resetPlayerMetadata() { static void resetPlayerMetadata()
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
if (pc->metadataState == PLAYER_METADATA_STATE_READ) { if (pc->metadataState == PLAYER_METADATA_STATE_READ) {
@ -53,7 +54,8 @@ static void resetPlayerMetadata() {
} }
} }
void resetPlayer() { void resetPlayer()
{
int pid; int pid;
setPlayerPid(0); setPlayerPid(0);
@ -68,41 +70,43 @@ void resetPlayer() {
getPlayerData()->playerControl.metadataState = getPlayerData()->playerControl.metadataState =
PLAYER_METADATA_STATE_WRITE; PLAYER_METADATA_STATE_WRITE;
pid = getPlayerData()->playerControl.decode_pid; pid = getPlayerData()->playerControl.decode_pid;
if(pid>0) kill(pid,SIGTERM); if (pid > 0)
kill(pid, SIGTERM);
getPlayerData()->playerControl.decode_pid = 0; getPlayerData()->playerControl.decode_pid = 0;
} }
void player_sigChldHandler(int pid, int status) { void player_sigChldHandler(int pid, int status)
{
if (getPlayerPid() == pid) { if (getPlayerPid() == pid) {
DEBUG("SIGCHLD caused by player process\n"); DEBUG("SIGCHLD caused by player process\n");
if (WIFSIGNALED(status) && WTERMSIG(status) != SIGTERM && if (WIFSIGNALED(status) && WTERMSIG(status) != SIGTERM &&
WTERMSIG(status)!=SIGINT) WTERMSIG(status) != SIGINT) {
{
ERROR("player process died from signal: %i\n", ERROR("player process died from signal: %i\n",
WTERMSIG(status)); WTERMSIG(status));
} }
resetPlayer(); resetPlayer();
} } else if (pid == getPlayerData()->playerControl.decode_pid
else if(pid==getPlayerData()->playerControl.decode_pid && getPlayerPid()<=0) && getPlayerPid() <= 0) {
{
if (WIFSIGNALED(status) && WTERMSIG(status) != SIGTERM) { if (WIFSIGNALED(status) && WTERMSIG(status) != SIGTERM) {
ERROR("(caught by master parent) " ERROR("(caught by master parent) "
"decode process died from a " "decode process died from a "
"non-TERM signal: %i\n", "non-TERM signal: %i\n", WTERMSIG(status));
WTERMSIG(status));
} }
getPlayerData()->playerControl.decode_pid = 0; getPlayerData()->playerControl.decode_pid = 0;
} }
} }
int playerInit() { int playerInit()
{
kill(masterPid, SIGUSR2); kill(masterPid, SIGUSR2);
/* we need to wait for the signal to take effect: */ /* we need to wait for the signal to take effect: */
while (getPlayerPid()==0) my_usleep(10000); while (getPlayerPid() == 0)
my_usleep(10000);
return 0; return 0;
} }
int playerInitReal() { int playerInitReal()
{
int player_pid; int player_pid;
blockSignals(); blockSignals();
player_pid = fork(); player_pid = fork();
@ -114,39 +118,37 @@ int playerInitReal() {
setSigHandlersForDecoder(); setSigHandlersForDecoder();
while (1) { while (1) {
if(pc->play) decode(); if (pc->play)
else if(pc->stop) pc->stop = 0; decode();
else if(pc->pause) pc->pause = 0; else if (pc->stop)
pc->stop = 0;
else if (pc->pause)
pc->pause = 0;
else if (pc->closeAudio) { else if (pc->closeAudio) {
closeAudioDevice(); closeAudioDevice();
pc->closeAudio = 0; pc->closeAudio = 0;
kill(getppid(), SIGUSR1); kill(getppid(), SIGUSR1);
} } else if (pc->lockQueue) {
else if(pc->lockQueue) {
pc->queueLockState = PLAYER_QUEUE_LOCKED; pc->queueLockState = PLAYER_QUEUE_LOCKED;
pc->lockQueue = 0; pc->lockQueue = 0;
} } else if (pc->unlockQueue) {
else if(pc->unlockQueue) {
pc->queueLockState = PLAYER_QUEUE_UNLOCKED; pc->queueLockState = PLAYER_QUEUE_UNLOCKED;
pc->unlockQueue = 0; pc->unlockQueue = 0;
} } else if (pc->cycleLogFiles) {
else if(pc->cycleLogFiles) {
myfprintfCloseAndOpenLogFile(); myfprintfCloseAndOpenLogFile();
pc->cycleLogFiles = 0; pc->cycleLogFiles = 0;
} } else
else my_usleep(10000); my_usleep(10000);
} }
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} } else if (player_pid < 0) {
else if(player_pid<0) {
unblockSignals(); unblockSignals();
ERROR("player Problems fork()'ing\n"); ERROR("player Problems fork()'ing\n");
setPlayerPid(0); setPlayerPid(0);
player_pid = 0; player_pid = 0;
return -1; return -1;
} } else
else
setPlayerPid(player_pid); setPlayerPid(player_pid);
unblockSignals(); unblockSignals();
@ -154,15 +156,20 @@ int playerInitReal() {
return 0; return 0;
} }
int playerPlay(FILE * fp, Song * song) { int playerPlay(FILE * fp, Song * song)
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
if(fp==NULL) fp = stderr; if (fp == NULL)
fp = stderr;
if(playerStop(fp)<0) return -1; if (playerStop(fp) < 0)
return -1;
if(song->tag) pc->fileTime = song->tag->time; if (song->tag)
else pc->fileTime = 0; pc->fileTime = song->tag->time;
else
pc->fileTime = 0;
copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk)); copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk));
@ -176,17 +183,20 @@ int playerPlay(FILE * fp, Song * song) {
} }
resetPlayerMetadata(); resetPlayerMetadata();
while(getPlayerPid()>0 && pc->play) my_usleep(1000); while (getPlayerPid() > 0 && pc->play)
my_usleep(1000);
return 0; return 0;
} }
int playerStop(FILE * fp) { int playerStop(FILE * fp)
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
if (getPlayerPid() > 0 && pc->state != PLAYER_STATE_STOP) { if (getPlayerPid() > 0 && pc->state != PLAYER_STATE_STOP) {
pc->stop = 1; pc->stop = 1;
while(getPlayerPid()>0 && pc->stop) my_usleep(1000); while (getPlayerPid() > 0 && pc->stop)
my_usleep(1000);
} }
pc->queueState = PLAYER_QUEUE_BLANK; pc->queueState = PLAYER_QUEUE_BLANK;
@ -195,7 +205,8 @@ int playerStop(FILE * fp) {
return 0; return 0;
} }
void playerKill() { void playerKill()
{
int pid; int pid;
/*PlayerControl * pc = &(getPlayerData()->playerControl); /*PlayerControl * pc = &(getPlayerData()->playerControl);
@ -204,62 +215,76 @@ void playerKill() {
if(player_pid>0 && pc->closeAudio) sleep(1); */ if(player_pid>0 && pc->closeAudio) sleep(1); */
pid = getPlayerPid(); pid = getPlayerPid();
if(pid>0) kill(pid,SIGTERM); if (pid > 0)
kill(pid, SIGTERM);
} }
int playerPause(FILE * fp) { int playerPause(FILE * fp)
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
if (getPlayerPid() > 0 && pc->state != PLAYER_STATE_STOP) { if (getPlayerPid() > 0 && pc->state != PLAYER_STATE_STOP) {
pc->pause = 1; pc->pause = 1;
while(getPlayerPid()>0 && pc->pause) my_usleep(1000); while (getPlayerPid() > 0 && pc->pause)
my_usleep(1000);
} }
return 0; return 0;
} }
int playerSetPause(FILE * fp, int pause) { int playerSetPause(FILE * fp, int pause)
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
if(getPlayerPid()<=0) return 0; if (getPlayerPid() <= 0)
return 0;
switch (pc->state) { switch (pc->state) {
case PLAYER_STATE_PLAY: case PLAYER_STATE_PLAY:
if(pause) playerPause(fp); if (pause)
playerPause(fp);
break; break;
case PLAYER_STATE_PAUSE: case PLAYER_STATE_PAUSE:
if(!pause) playerPause(fp); if (!pause)
playerPause(fp);
break; break;
} }
return 0; return 0;
} }
int getPlayerElapsedTime() { int getPlayerElapsedTime()
{
return (int)(getPlayerData()->playerControl.elapsedTime + 0.5); return (int)(getPlayerData()->playerControl.elapsedTime + 0.5);
} }
unsigned long getPlayerBitRate() { unsigned long getPlayerBitRate()
{
return getPlayerData()->playerControl.bitRate; return getPlayerData()->playerControl.bitRate;
} }
int getPlayerTotalTime() { int getPlayerTotalTime()
{
return (int)(getPlayerData()->playerControl.totalTime + 0.5); return (int)(getPlayerData()->playerControl.totalTime + 0.5);
} }
int getPlayerState() { int getPlayerState()
{
return getPlayerData()->playerControl.state; return getPlayerData()->playerControl.state;
} }
void clearPlayerError() { void clearPlayerError()
{
getPlayerData()->playerControl.error = 0; getPlayerData()->playerControl.error = 0;
} }
int getPlayerError() { int getPlayerError()
{
return getPlayerData()->playerControl.error; return getPlayerData()->playerControl.error;
} }
char * getPlayerErrorStr() { char *getPlayerErrorStr()
{
static char *error = NULL; static char *error = NULL;
int errorlen = MAXPATHLEN + 1024; int errorlen = MAXPATHLEN + 1024;
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
@ -293,29 +318,35 @@ char * getPlayerErrorStr() {
errorlen = strlen(error); errorlen = strlen(error);
error = realloc(error, errorlen + 1); error = realloc(error, errorlen + 1);
if(errorlen) return error; if (errorlen)
return error;
return NULL; return NULL;
} }
void playerCloseAudio() { void playerCloseAudio()
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
if (getPlayerPid() > 0) { if (getPlayerPid() > 0) {
if(playerStop(stderr)<0) return; if (playerStop(stderr) < 0)
return;
pc->closeAudio = 1; pc->closeAudio = 1;
} }
} }
int queueSong(Song * song) { int queueSong(Song * song)
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
if (pc->queueState == PLAYER_QUEUE_BLANK) { if (pc->queueState == PLAYER_QUEUE_BLANK) {
strncpy(pc->utf8url, getSongUrl(song), MAXPATHLEN); strncpy(pc->utf8url, getSongUrl(song), MAXPATHLEN);
pc->utf8url[MAXPATHLEN] = '\0'; pc->utf8url[MAXPATHLEN] = '\0';
if(song->tag) pc->fileTime = song->tag->time; if (song->tag)
else pc->fileTime = 0; pc->fileTime = song->tag->time;
else
pc->fileTime = 0;
copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk)); copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk));
@ -326,39 +357,44 @@ int queueSong(Song * song) {
return -1; return -1;
} }
int getPlayerQueueState() { int getPlayerQueueState()
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
return pc->queueState; return pc->queueState;
} }
void setQueueState(int queueState) { void setQueueState(int queueState)
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
pc->queueState = queueState; pc->queueState = queueState;
} }
void playerQueueLock() { void playerQueueLock()
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
if(getPlayerPid()>0 && pc->queueLockState==PLAYER_QUEUE_UNLOCKED) if (getPlayerPid() > 0 && pc->queueLockState == PLAYER_QUEUE_UNLOCKED) {
{
pc->lockQueue = 1; pc->lockQueue = 1;
while(getPlayerPid()>0 && pc->lockQueue) my_usleep(1000); while (getPlayerPid() > 0 && pc->lockQueue)
my_usleep(1000);
} }
} }
void playerQueueUnlock() { void playerQueueUnlock()
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
if(getPlayerPid()>0 && pc->queueLockState==PLAYER_QUEUE_LOCKED) if (getPlayerPid() > 0 && pc->queueLockState == PLAYER_QUEUE_LOCKED) {
{
pc->unlockQueue = 1; pc->unlockQueue = 1;
while(getPlayerPid()>0 && pc->unlockQueue) my_usleep(1000); while (getPlayerPid() > 0 && pc->unlockQueue)
my_usleep(1000);
} }
} }
int playerSeek(FILE * fp, Song * song, float time) { int playerSeek(FILE * fp, Song * song, float time)
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
if (pc->state == PLAYER_STATE_STOP) { if (pc->state == PLAYER_STATE_STOP) {
@ -368,8 +404,10 @@ int playerSeek(FILE * fp, Song * song, float time) {
} }
if (strcmp(pc->utf8url, getSongUrl(song)) != 0) { if (strcmp(pc->utf8url, getSongUrl(song)) != 0) {
if(song->tag) pc->fileTime = song->tag->time; if (song->tag)
else pc->fileTime = 0; pc->fileTime = song->tag->time;
else
pc->fileTime = 0;
copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk)); copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk));
@ -381,28 +419,33 @@ int playerSeek(FILE * fp, Song * song, float time) {
resetPlayerMetadata(); resetPlayerMetadata();
pc->seekWhere = time; pc->seekWhere = time;
pc->seek = 1; pc->seek = 1;
while(getPlayerPid()>0 && pc->seek) my_usleep(1000); while (getPlayerPid() > 0 && pc->seek)
my_usleep(1000);
} }
return 0; return 0;
} }
float getPlayerCrossFade() { float getPlayerCrossFade()
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
return pc->crossFade; return pc->crossFade;
} }
void setPlayerCrossFade(float crossFadeInSeconds) { void setPlayerCrossFade(float crossFadeInSeconds)
{
PlayerControl *pc; PlayerControl *pc;
if(crossFadeInSeconds<0) crossFadeInSeconds = 0; if (crossFadeInSeconds < 0)
crossFadeInSeconds = 0;
pc = &(getPlayerData()->playerControl); pc = &(getPlayerData()->playerControl);
pc->crossFade = crossFadeInSeconds; pc->crossFade = crossFadeInSeconds;
} }
void setPlayerSoftwareVolume(int volume) { void setPlayerSoftwareVolume(int volume)
{
PlayerControl *pc; PlayerControl *pc;
volume = (volume > 1000) ? 1000 : (volume < 0 ? 0 : volume); volume = (volume > 1000) ? 1000 : (volume < 0 ? 0 : volume);
@ -411,31 +454,36 @@ void setPlayerSoftwareVolume(int volume) {
pc->softwareVolume = volume; pc->softwareVolume = volume;
} }
double getPlayerTotalPlayTime() { double getPlayerTotalPlayTime()
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
return pc->totalPlayTime; return pc->totalPlayTime;
} }
unsigned int getPlayerSampleRate() { unsigned int getPlayerSampleRate()
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
return pc->sampleRate; return pc->sampleRate;
} }
int getPlayerBits() { int getPlayerBits()
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
return pc->bits; return pc->bits;
} }
int getPlayerChannels() { int getPlayerChannels()
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
return pc->channels; return pc->channels;
} }
void playerCycleLogFiles() { void playerCycleLogFiles()
{
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
DecoderControl *dc = &(getPlayerData()->decoderControl); DecoderControl *dc = &(getPlayerData()->decoderControl);
@ -444,7 +492,8 @@ void playerCycleLogFiles() {
} }
/* this actually creates a dupe of the current metadata */ /* this actually creates a dupe of the current metadata */
Song * playerCurrentDecodeSong() { Song *playerCurrentDecodeSong()
{
static Song *song = NULL; static Song *song = NULL;
static MetadataChunk *prev = NULL; static MetadataChunk *prev = NULL;
Song *ret = NULL; Song *ret = NULL;
@ -452,10 +501,12 @@ Song * playerCurrentDecodeSong() {
if (pc->metadataState == PLAYER_METADATA_STATE_READ) { if (pc->metadataState == PLAYER_METADATA_STATE_READ) {
DEBUG("playerCurrentDecodeSong: caught new metadata!\n"); DEBUG("playerCurrentDecodeSong: caught new metadata!\n");
if(prev) free(prev); if (prev)
free(prev);
prev = malloc(sizeof(MetadataChunk)); prev = malloc(sizeof(MetadataChunk));
memcpy(prev, &(pc->metadataChunk), sizeof(MetadataChunk)); memcpy(prev, &(pc->metadataChunk), sizeof(MetadataChunk));
if(song) freeJustSong(song); if (song)
freeJustSong(song);
song = newNullSong(); song = newNullSong();
song->url = strdup(pc->currentUrl); song->url = strdup(pc->currentUrl);
song->tag = metadataChunkToMpdTagDup(prev); song->tag = metadataChunkToMpdTagDup(prev);

View File

@ -36,7 +36,8 @@ int buffered_chunks;
static PlayerData *playerData_pd; static PlayerData *playerData_pd;
int *player_pid; int *player_pid;
void initPlayerData(void) { void initPlayerData(void)
{
float perc = DEFAULT_BUFFER_BEFORE_PLAY; float perc = DEFAULT_BUFFER_BEFORE_PLAY;
char *test; char *test;
int shmid; int shmid;
@ -81,8 +82,8 @@ void initPlayerData(void) {
buffered_before_play = (perc / 100) * buffered_chunks; buffered_before_play = (perc / 100) * buffered_chunks;
if (buffered_before_play > buffered_chunks) { if (buffered_before_play > buffered_chunks) {
buffered_before_play = buffered_chunks; buffered_before_play = buffered_chunks;
} } else if (buffered_before_play < 0)
else if(buffered_before_play<0) buffered_before_play = 0; buffered_before_play = 0;
allocationSize = buffered_chunks * CHUNK_SIZE; /*actual buffer */ allocationSize = buffered_chunks * CHUNK_SIZE; /*actual buffer */
allocationSize += buffered_chunks * sizeof(float); /*for times */ allocationSize += buffered_chunks * sizeof(float); /*for times */
@ -128,8 +129,10 @@ void initPlayerData(void) {
buffer->bitRate = (mpd_uint16 *) (((char *)buffer->chunkSize) + buffer->bitRate = (mpd_uint16 *) (((char *)buffer->chunkSize) +
buffered_chunks * sizeof(mpd_sint16)); buffered_chunks * sizeof(mpd_sint16));
buffer->metaChunk = (mpd_sint8 *) (((char *)buffer->bitRate) + buffer->metaChunk = (mpd_sint8 *) (((char *)buffer->bitRate) +
buffered_chunks*sizeof(mpd_sint16)); buffered_chunks *
buffer->times = (float *)(((char *)buffer->metaChunk)+ sizeof(mpd_sint16));
buffer->times =
(float *)(((char *)buffer->metaChunk) +
buffered_chunks * sizeof(mpd_sint8)); buffered_chunks * sizeof(mpd_sint8));
buffer->acceptMetadata = 0; buffer->acceptMetadata = 0;
@ -162,19 +165,23 @@ void initPlayerData(void) {
memset(playerData_pd->decoderControl.utf8url, 0, MAXPATHLEN + 1); memset(playerData_pd->decoderControl.utf8url, 0, MAXPATHLEN + 1);
} }
PlayerData * getPlayerData(void) { PlayerData *getPlayerData(void)
{
return playerData_pd; return playerData_pd;
} }
int getPlayerPid(void) { int getPlayerPid(void)
{
return *player_pid; return *player_pid;
} }
void setPlayerPid(int pid) { void setPlayerPid(int pid)
{
*player_pid = pid; *player_pid = pid;
} }
void freePlayerData(void) { void freePlayerData(void)
{
shmdt(playerData_pd); shmdt(playerData_pd);
shmdt(player_pid); shmdt(player_pid);
} }

File diff suppressed because it is too large Load Diff

View File

@ -31,18 +31,18 @@ static int replayGainState = REPLAYGAIN_OFF;
static float replayGainPreamp = 1.0; static float replayGainPreamp = 1.0;
void initReplayGainState(void) { void initReplayGainState(void)
{
ConfigParam *param = getConfigParam(CONF_REPLAYGAIN); ConfigParam *param = getConfigParam(CONF_REPLAYGAIN);
if(!param) return; if (!param)
return;
if (strcmp(param->value, "track") == 0) { if (strcmp(param->value, "track") == 0) {
replayGainState = REPLAYGAIN_TRACK; replayGainState = REPLAYGAIN_TRACK;
} } else if (strcmp(param->value, "album") == 0) {
else if(strcmp(param->value, "album") == 0) {
replayGainState = REPLAYGAIN_ALBUM; replayGainState = REPLAYGAIN_ALBUM;
} } else {
else {
ERROR("replaygain value \"%s\" at line %i is invalid\n", ERROR("replaygain value \"%s\" at line %i is invalid\n",
param->value, param->line); param->value, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -62,8 +62,7 @@ void initReplayGainState(void) {
if (f < -15 || f > 15) { if (f < -15 || f > 15) {
ERROR("Replaygain preamp \"%s\" is not between -15 and" ERROR("Replaygain preamp \"%s\" is not between -15 and"
"15 at line %i\n", "15 at line %i\n", param->value, param->line);
param->value, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -71,13 +70,16 @@ void initReplayGainState(void) {
} }
} }
static float computeReplayGainScale(float gain, float peak) { static float computeReplayGainScale(float gain, float peak)
{
float scale; float scale;
if(gain == 0.0) return(1); if (gain == 0.0)
return (1);
scale = pow(10.0, gain / 20.0); scale = pow(10.0, gain / 20.0);
scale *= replayGainPreamp; scale *= replayGainPreamp;
if(scale > 15.0) scale = 15.0; if (scale > 15.0)
scale = 15.0;
if (scale * peak > 1.0) { if (scale * peak > 1.0) {
scale = 1.0 / peak; scale = 1.0 / peak;
@ -85,7 +87,8 @@ static float computeReplayGainScale(float gain, float peak) {
return (scale); return (scale);
} }
ReplayGainInfo * newReplayGainInfo(void) { ReplayGainInfo *newReplayGainInfo(void)
{
ReplayGainInfo *ret = malloc(sizeof(ReplayGainInfo)); ReplayGainInfo *ret = malloc(sizeof(ReplayGainInfo));
ret->albumGain = 0.0; ret->albumGain = 0.0;
@ -100,7 +103,8 @@ ReplayGainInfo * newReplayGainInfo(void) {
return ret; return ret;
} }
void freeReplayGainInfo(ReplayGainInfo * info) { void freeReplayGainInfo(ReplayGainInfo * info)
{
free(info); free(info);
} }
@ -112,7 +116,8 @@ void doReplayGain(ReplayGainInfo * info, char * buffer, int bufferSize,
mpd_sint32 temp32; mpd_sint32 temp32;
float scale; float scale;
if(replayGainState == REPLAYGAIN_OFF || !info) return; if (replayGainState == REPLAYGAIN_OFF || !info)
return;
if (info->scale < 0) { if (info->scale < 0) {
switch (replayGainState) { switch (replayGainState) {
@ -127,7 +132,8 @@ void doReplayGain(ReplayGainInfo * info, char * buffer, int bufferSize,
} }
} }
if(info->scale <= 1.01 && info->scale >= 0.99) return; if (info->scale <= 1.01 && info->scale >= 0.99)
return;
buffer16 = (mpd_sint16 *) buffer; buffer16 = (mpd_sint16 *) buffer;
buffer8 = (mpd_sint8 *) buffer; buffer8 = (mpd_sint8 *) buffer;

View File

@ -39,7 +39,8 @@
extern volatile int masterPid; extern volatile int masterPid;
extern volatile int mainPid; extern volatile int mainPid;
int masterHandlePendingSignals() { int masterHandlePendingSignals()
{
if (signal_is_pending(SIGINT) || signal_is_pending(SIGTERM)) { if (signal_is_pending(SIGINT) || signal_is_pending(SIGTERM)) {
DEBUG("master process got SIGINT or SIGTERM, exiting\n"); DEBUG("master process got SIGINT or SIGTERM, exiting\n");
return COMMAND_RETURN_KILL; return COMMAND_RETURN_KILL;
@ -51,11 +52,11 @@ int masterHandlePendingSignals() {
kill(mainPid, SIGHUP); kill(mainPid, SIGHUP);
} }
return 0; return 0;
} }
int handlePendingSignals() { int handlePendingSignals()
{
/* this SIGUSR1 signal comes before the KILL signals, because there if the process is /* this SIGUSR1 signal comes before the KILL signals, because there if the process is
* looping, waiting for this signal, it will not respond to the KILL signal. This might be * looping, waiting for this signal, it will not respond to the KILL signal. This might be
* better implemented by using bit-wise defines and or'ing of the COMMAND_FOO as return. * better implemented by using bit-wise defines and or'ing of the COMMAND_FOO as return.
@ -78,50 +79,60 @@ int handlePendingSignals() {
readDirectoryDB(); readDirectoryDB();
playlistVersionChange(); playlistVersionChange();
} }
if(myfprintfCloseAndOpenLogFile()<0) return COMMAND_RETURN_KILL; if (myfprintfCloseAndOpenLogFile() < 0)
return COMMAND_RETURN_KILL;
playerCycleLogFiles(); playerCycleLogFiles();
} }
return 0; return 0;
} }
void chldSigHandler(int signal) { void chldSigHandler(int signal)
{
int status; int status;
int pid; int pid;
DEBUG("main process got SIGCHLD\n"); DEBUG("main process got SIGCHLD\n");
while (0 != (pid = wait3(&status, WNOHANG, NULL))) { while (0 != (pid = wait3(&status, WNOHANG, NULL))) {
if (pid < 0) { if (pid < 0) {
if(errno==EINTR) continue; if (errno == EINTR)
else break; continue;
else
break;
} }
directory_sigChldHandler(pid, status); directory_sigChldHandler(pid, status);
} }
} }
void masterChldSigHandler(int signal) { void masterChldSigHandler(int signal)
{
int status; int status;
int pid; int pid;
DEBUG("master process got SIGCHLD\n"); DEBUG("master process got SIGCHLD\n");
while (0 != (pid = wait3(&status, WNOHANG, NULL))) { while (0 != (pid = wait3(&status, WNOHANG, NULL))) {
if (pid < 0) { if (pid < 0) {
if(errno==EINTR) continue; if (errno == EINTR)
else break; continue;
else
break;
} }
DEBUG("PID: %d\n", pid); DEBUG("PID: %d\n", pid);
if (pid == mainPid) kill(getpid(), SIGTERM); if (pid == mainPid)
kill(getpid(), SIGTERM);
player_sigChldHandler(pid, status); player_sigChldHandler(pid, status);
} }
} }
int playerInitReal(); int playerInitReal();
void masterSigUsr2Handler(int signal) { void masterSigUsr2Handler(int signal)
{
DEBUG("Master process got SIGUSR2 starting a new player process\n"); DEBUG("Master process got SIGUSR2 starting a new player process\n");
if (getPlayerPid() <= 0) if (getPlayerPid() <= 0)
playerInitReal(); playerInitReal();
} }
void masterInitSigHandlers() { void masterInitSigHandlers()
{
struct sigaction sa; struct sigaction sa;
sa.sa_flags = 0; sa.sa_flags = 0;
@ -138,7 +149,8 @@ void masterInitSigHandlers() {
signal_handle(SIGHUP); signal_handle(SIGHUP);
} }
void initSigHandlers() { void initSigHandlers()
{
struct sigaction sa; struct sigaction sa;
sa.sa_flags = 0; sa.sa_flags = 0;
@ -154,14 +166,16 @@ void initSigHandlers() {
signal_handle(SIGHUP); signal_handle(SIGHUP);
} }
void finishSigHandlers() { void finishSigHandlers()
{
signal_unhandle(SIGINT); signal_unhandle(SIGINT);
signal_unhandle(SIGUSR1); signal_unhandle(SIGUSR1);
signal_unhandle(SIGTERM); signal_unhandle(SIGTERM);
signal_unhandle(SIGHUP); signal_unhandle(SIGHUP);
} }
void setSigHandlersForDecoder() { void setSigHandlersForDecoder()
{
struct sigaction sa; struct sigaction sa;
finishSigHandlers(); finishSigHandlers();
@ -177,7 +191,8 @@ void setSigHandlersForDecoder() {
while (sigaction(SIGTERM, &sa, NULL) < 0 && errno == EINTR) ; while (sigaction(SIGTERM, &sa, NULL) < 0 && errno == EINTR) ;
} }
void ignoreSignals() { void ignoreSignals()
{
struct sigaction sa; struct sigaction sa;
sa.sa_flags = 0; sa.sa_flags = 0;
@ -193,7 +208,8 @@ void ignoreSignals() {
while (sigaction(SIGHUP, &sa, NULL) < 0 && errno == EINTR) ; while (sigaction(SIGHUP, &sa, NULL) < 0 && errno == EINTR) ;
} }
void waitOnSignals() { void waitOnSignals()
{
sigset_t sset; sigset_t sset;
sigfillset(&sset); sigfillset(&sset);
@ -206,7 +222,8 @@ void waitOnSignals() {
sigsuspend(&sset); sigsuspend(&sset);
} }
void blockSignals() { void blockSignals()
{
sigset_t sset; sigset_t sset;
sigemptyset(&sset); sigemptyset(&sset);
@ -219,7 +236,8 @@ void blockSignals() {
while (sigprocmask(SIG_BLOCK, &sset, NULL) < 0 && errno == EINTR) ; while (sigprocmask(SIG_BLOCK, &sset, NULL) < 0 && errno == EINTR) ;
} }
void unblockSignals() { void unblockSignals()
{
sigset_t sset; sigset_t sset;
sigemptyset(&sset); sigemptyset(&sset);

View File

@ -35,7 +35,8 @@
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
Song * newNullSong(void) { Song *newNullSong(void)
{
Song *song = malloc(sizeof(Song)); Song *song = malloc(sizeof(Song));
song->tag = NULL; song->tag = NULL;
@ -46,7 +47,8 @@ Song * newNullSong(void) {
return song; return song;
} }
Song * newSong(char * url, int type, Directory * parentDir) { Song *newSong(char *url, int type, Directory * parentDir)
{
Song *song = NULL; Song *song = NULL;
if (strchr(url, '\n')) { if (strchr(url, '\n')) {
@ -68,7 +70,8 @@ Song * newSong(char * url, int type, Directory * parentDir) {
char *song_url = getSongUrl(song); char *song_url = getSongUrl(song);
char *abs_path = rmp2amp(utf8ToFsCharset(song_url)); char *abs_path = rmp2amp(utf8ToFsCharset(song_url));
while (!song->tag && (plugin = isMusic(song_url, while (!song->tag && (plugin = isMusic(song_url,
&(song->mtime), next++))) { &(song->mtime),
next++))) {
song->tag = plugin->tagDupFunc(abs_path); song->tag = plugin->tagDupFunc(abs_path);
} }
if (!song->tag || song->tag->time < 0) { if (!song->tag || song->tag->time < 0) {
@ -80,19 +83,23 @@ Song * newSong(char * url, int type, Directory * parentDir) {
return song; return song;
} }
void freeSong(Song * song) { void freeSong(Song * song)
{
deleteASongFromPlaylist(song); deleteASongFromPlaylist(song);
freeJustSong(song); freeJustSong(song);
} }
void freeJustSong(Song * song) { void freeJustSong(Song * song)
{
free(song->url); free(song->url);
if(song->tag) freeMpdTag(song->tag); if (song->tag)
freeMpdTag(song->tag);
free(song); free(song);
getSongUrl(NULL); getSongUrl(NULL);
} }
SongList * newSongList(void) { SongList *newSongList(void)
{
return makeList((ListFreeDataFunc *) freeSong, 0); return makeList((ListFreeDataFunc *) freeSong, 0);
} }
@ -114,36 +121,41 @@ Song * addSongToList(SongList * list, char * url, char * utf8path,
DEBUG("addSongToList: Trying to add an invalid song type\n"); DEBUG("addSongToList: Trying to add an invalid song type\n");
} }
if(song==NULL) return NULL; if (song == NULL)
return NULL;
insertInList(list, song->url, (void *)song); insertInList(list, song->url, (void *)song);
return song; return song;
} }
void freeSongList(SongList * list) { void freeSongList(SongList * list)
{
freeList(list); freeList(list);
} }
void printSongUrl(FILE * fp, Song * song) { void printSongUrl(FILE * fp, Song * song)
{
if (song->parentDir && song->parentDir->path) { if (song->parentDir && song->parentDir->path) {
myfprintf(fp, "%s%s/%s\n", SONG_FILE, myfprintf(fp, "%s%s/%s\n", SONG_FILE,
getDirectoryPath(song->parentDir), song->url); getDirectoryPath(song->parentDir), song->url);
} } else {
else {
myfprintf(fp, "%s%s\n", SONG_FILE, song->url); myfprintf(fp, "%s%s\n", SONG_FILE, song->url);
} }
} }
int printSongInfo(FILE * fp, Song * song) { int printSongInfo(FILE * fp, Song * song)
{
printSongUrl(fp, song); printSongUrl(fp, song);
if(song->tag) printMpdTag(fp,song->tag); if (song->tag)
printMpdTag(fp, song->tag);
return 0; return 0;
} }
int printSongInfoFromList(FILE * fp, SongList * list) { int printSongInfoFromList(FILE * fp, SongList * list)
{
ListNode *tempNode = list->firstNode; ListNode *tempNode = list->firstNode;
while (tempNode != NULL) { while (tempNode != NULL) {
@ -154,7 +166,8 @@ int printSongInfoFromList(FILE * fp, SongList * list) {
return 0; return 0;
} }
void writeSongInfoFromList(FILE * fp, SongList * list) { void writeSongInfoFromList(FILE * fp, SongList * list)
{
ListNode *tempNode = list->firstNode; ListNode *tempNode = list->firstNode;
myfprintf(fp, "%s\n", SONG_BEGIN); myfprintf(fp, "%s\n", SONG_BEGIN);
@ -162,21 +175,22 @@ void writeSongInfoFromList(FILE * fp, SongList * list) {
while (tempNode != NULL) { while (tempNode != NULL) {
myfprintf(fp, "%s%s\n", SONG_KEY, tempNode->key); myfprintf(fp, "%s%s\n", SONG_KEY, tempNode->key);
printSongInfo(fp, (Song *) tempNode->data); printSongInfo(fp, (Song *) tempNode->data);
myfprintf(fp,"%s%li\n",SONG_MTIME,(long)((Song *)tempNode->data)->mtime); myfprintf(fp, "%s%li\n", SONG_MTIME,
(long)((Song *) tempNode->data)->mtime);
tempNode = tempNode->nextNode; tempNode = tempNode->nextNode;
} }
myfprintf(fp, "%s\n", SONG_END); myfprintf(fp, "%s\n", SONG_END);
} }
static void insertSongIntoList(SongList * list, ListNode ** nextSongNode, char * key, static void insertSongIntoList(SongList * list, ListNode ** nextSongNode,
Song * song) char *key, Song * song)
{ {
ListNode *nodeTemp; ListNode *nodeTemp;
int cmpRet = 0; int cmpRet = 0;
while(*nextSongNode && (cmpRet = strcmp(key,(*nextSongNode)->key)) > 0) while (*nextSongNode
{ && (cmpRet = strcmp(key, (*nextSongNode)->key)) > 0) {
nodeTemp = (*nextSongNode)->nextNode; nodeTemp = (*nextSongNode)->nextNode;
deleteNodeFromList(list, *nextSongNode); deleteNodeFromList(list, *nextSongNode);
*nextSongNode = nodeTemp; *nextSongNode = nodeTemp;
@ -184,8 +198,7 @@ static void insertSongIntoList(SongList * list, ListNode ** nextSongNode, char *
if (!(*nextSongNode)) { if (!(*nextSongNode)) {
insertInList(list, song->url, (void *)song); insertInList(list, song->url, (void *)song);
} } else if (cmpRet == 0) {
else if(cmpRet == 0) {
Song *tempSong = (Song *) ((*nextSongNode)->data); Song *tempSong = (Song *) ((*nextSongNode)->data);
if (tempSong->mtime != song->mtime) { if (tempSong->mtime != song->mtime) {
freeMpdTag(tempSong->tag); freeMpdTag(tempSong->tag);
@ -195,20 +208,19 @@ static void insertSongIntoList(SongList * list, ListNode ** nextSongNode, char *
} }
freeJustSong(song); freeJustSong(song);
*nextSongNode = (*nextSongNode)->nextNode; *nextSongNode = (*nextSongNode)->nextNode;
} } else {
else {
insertInListBeforeNode(list, *nextSongNode, -1, song->url, insertInListBeforeNode(list, *nextSongNode, -1, song->url,
(void *)song); (void *)song);
} }
} }
static int matchesAnMpdTagItemKey(char * buffer, int * itemType) { static int matchesAnMpdTagItemKey(char *buffer, int *itemType)
{
int i; int i;
for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) { for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) {
if (0 == strncmp(mpdTagItemKeys[i], buffer, if (0 == strncmp(mpdTagItemKeys[i], buffer,
strlen(mpdTagItemKeys[i]))) strlen(mpdTagItemKeys[i]))) {
{
*itemType = i; *itemType = i;
return 1; return 1;
} }
@ -217,7 +229,8 @@ static int matchesAnMpdTagItemKey(char * buffer, int * itemType) {
return 0; return 0;
} }
void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir) { void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir)
{
char buffer[MAXPATHLEN + 1024]; char buffer[MAXPATHLEN + 1024];
int bufferSize = MAXPATHLEN + 1024; int bufferSize = MAXPATHLEN + 1024;
Song *song = NULL; Song *song = NULL;
@ -229,8 +242,7 @@ void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir) {
if (0 == strncmp(SONG_KEY, buffer, strlen(SONG_KEY))) { if (0 == strncmp(SONG_KEY, buffer, strlen(SONG_KEY))) {
if (song) { if (song) {
insertSongIntoList(list, &nextSongNode, insertSongIntoList(list, &nextSongNode,
song->url, song->url, song);
song);
song = NULL; song = NULL;
} }
@ -238,8 +250,7 @@ void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir) {
song->url = strdup(buffer + strlen(SONG_KEY)); song->url = strdup(buffer + strlen(SONG_KEY));
song->type = SONG_TYPE_FILE; song->type = SONG_TYPE_FILE;
song->parentDir = parentDir; song->parentDir = parentDir;
} } else if (0 == strncmp(SONG_FILE, buffer, strlen(SONG_FILE))) {
else if(0==strncmp(SONG_FILE,buffer,strlen(SONG_FILE))) {
if (!song) { if (!song) {
ERROR("Problems reading song info\n"); ERROR("Problems reading song info\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -247,17 +258,18 @@ void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir) {
/* we don't need this info anymore /* we don't need this info anymore
song->url = strdup(&(buffer[strlen(SONG_FILE)])); song->url = strdup(&(buffer[strlen(SONG_FILE)]));
*/ */
} } else if (matchesAnMpdTagItemKey(buffer, &itemType)) {
else if(matchesAnMpdTagItemKey(buffer, &itemType)) { if (!song->tag)
if(!song->tag) song->tag = newMpdTag(); song->tag = newMpdTag();
addItemToMpdTag(song->tag, itemType, addItemToMpdTag(song->tag, itemType,
&(buffer[strlen(mpdTagItemKeys[itemType])+2])); &(buffer
} [strlen(mpdTagItemKeys[itemType]) +
else if(0==strncmp(SONG_TIME,buffer,strlen(SONG_TIME))) { 2]));
if(!song->tag) song->tag = newMpdTag(); } else if (0 == strncmp(SONG_TIME, buffer, strlen(SONG_TIME))) {
if (!song->tag)
song->tag = newMpdTag();
song->tag->time = atoi(&(buffer[strlen(SONG_TIME)])); song->tag->time = atoi(&(buffer[strlen(SONG_TIME)]));
} } else if (0 == strncmp(SONG_MTIME, buffer, strlen(SONG_MTIME))) {
else if(0==strncmp(SONG_MTIME,buffer,strlen(SONG_MTIME))) {
song->mtime = atoi(&(buffer[strlen(SONG_MTIME)])); song->mtime = atoi(&(buffer[strlen(SONG_MTIME)]));
} }
/* ignore empty lines (starting with '\0') */ /* ignore empty lines (starting with '\0') */
@ -279,22 +291,26 @@ void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir) {
} }
} }
int updateSongInfo(Song * song) { int updateSongInfo(Song * song)
{
if (song->type == SONG_TYPE_FILE) { if (song->type == SONG_TYPE_FILE) {
InputPlugin *plugin; InputPlugin *plugin;
unsigned int next = 0; unsigned int next = 0;
char *song_url = getSongUrl(song); char *song_url = getSongUrl(song);
char *abs_path = rmp2amp(song_url); char *abs_path = rmp2amp(song_url);
if(song->tag) freeMpdTag(song->tag); if (song->tag)
freeMpdTag(song->tag);
song->tag = NULL; song->tag = NULL;
while (!song->tag && (plugin = isMusic(song_url, while (!song->tag && (plugin = isMusic(song_url,
&(song->mtime), next++))) { &(song->mtime),
next++))) {
song->tag = plugin->tagDupFunc(abs_path); song->tag = plugin->tagDupFunc(abs_path);
} }
if(!song->tag || song->tag->time<0) return -1; if (!song->tag || song->tag->time < 0)
return -1;
} }
return 0; return 0;
@ -302,7 +318,8 @@ int updateSongInfo(Song * song) {
/* pass song = NULL to reset, we do this freeJustSong(), so that if /* pass song = NULL to reset, we do this freeJustSong(), so that if
* we free and recreate this memory we make sure to print it correctly*/ * we free and recreate this memory we make sure to print it correctly*/
char * getSongUrl(Song * song) { char *getSongUrl(Song * song)
{
static char *buffer = NULL; static char *buffer = NULL;
static int bufferSize = 0; static int bufferSize = 0;
static Song *lastSong = NULL; static Song *lastSong = NULL;
@ -315,10 +332,12 @@ char * getSongUrl(Song * song) {
return NULL; return NULL;
} }
if(!song->parentDir || !song->parentDir->path) return song->url; if (!song->parentDir || !song->parentDir->path)
return song->url;
/* be careful with this! */ /* be careful with this! */
if(song == lastSong) return buffer; if (song == lastSong)
return buffer;
slen = strlen(song->url); slen = strlen(song->url);
dlen = strlen(getDirectoryPath(song->parentDir)); dlen = strlen(getDirectoryPath(song->parentDir));

View File

@ -28,17 +28,20 @@
Stats stats; Stats stats;
void initStats(void) { void initStats(void)
{
stats.daemonStart = time(NULL); stats.daemonStart = time(NULL);
stats.numberOfSongs = 0; stats.numberOfSongs = 0;
} }
int printStats(FILE * fp) { int printStats(FILE * fp)
{
myfprintf(fp, "artists: %li\n", getNumberOfTagItems(TAG_ITEM_ARTIST)); myfprintf(fp, "artists: %li\n", getNumberOfTagItems(TAG_ITEM_ARTIST));
myfprintf(fp, "albums: %li\n", getNumberOfTagItems(TAG_ITEM_ALBUM)); myfprintf(fp, "albums: %li\n", getNumberOfTagItems(TAG_ITEM_ALBUM));
myfprintf(fp, "songs: %i\n", stats.numberOfSongs); myfprintf(fp, "songs: %i\n", stats.numberOfSongs);
myfprintf(fp, "uptime: %li\n", time(NULL) - stats.daemonStart); myfprintf(fp, "uptime: %li\n", time(NULL) - stats.daemonStart);
myfprintf(fp,"playtime: %li\n",(long)(getPlayerTotalPlayTime()+0.5)); myfprintf(fp, "playtime: %li\n",
(long)(getPlayerTotalPlayTime() + 0.5));
myfprintf(fp, "db_playtime: %li\n", stats.dbPlayTime); myfprintf(fp, "db_playtime: %li\n", stats.dbPlayTime);
myfprintf(fp, "db_update: %li\n", getDbModTime()); myfprintf(fp, "db_update: %li\n", getDbModTime());
return 0; return 0;

190
src/tag.c
View File

@ -55,8 +55,7 @@
#endif #endif
#endif #endif
char * mpdTagItemKeys[TAG_NUM_OF_ITEM_TYPES] = char *mpdTagItemKeys[TAG_NUM_OF_ITEM_TYPES] = {
{
"Artist", "Artist",
"Album", "Album",
"Title", "Title",
@ -72,7 +71,8 @@ char * mpdTagItemKeys[TAG_NUM_OF_ITEM_TYPES] =
static mpd_sint8 ignoreTagItems[TAG_NUM_OF_ITEM_TYPES]; static mpd_sint8 ignoreTagItems[TAG_NUM_OF_ITEM_TYPES];
void initTagConfig(void) { void initTagConfig(void)
{
int quit = 0; int quit = 0;
char *temp; char *temp;
char *s; char *s;
@ -87,16 +87,19 @@ void initTagConfig(void) {
param = getConfigParam(CONF_METADATA_TO_USE); param = getConfigParam(CONF_METADATA_TO_USE);
if(!param) return; if (!param)
return;
memset(ignoreTagItems, 1, TAG_NUM_OF_ITEM_TYPES); memset(ignoreTagItems, 1, TAG_NUM_OF_ITEM_TYPES);
if(0 == strcasecmp(param->value, "none")) return; if (0 == strcasecmp(param->value, "none"))
return;
temp = c = s = strdup(param->value); temp = c = s = strdup(param->value);
while (!quit) { while (!quit) {
if (*s == ',' || *s == '\0') { if (*s == ',' || *s == '\0') {
if(*s == '\0') quit = 1; if (*s == '\0')
quit = 1;
*s = '\0'; *s = '\0';
for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) { for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) {
if (strcasecmp(c, mpdTagItemKeys[i]) == 0) { if (strcasecmp(c, mpdTagItemKeys[i]) == 0) {
@ -118,10 +121,12 @@ void initTagConfig(void) {
free(temp); free(temp);
} }
void printMpdTag(FILE * fp, MpdTag * tag) { void printMpdTag(FILE * fp, MpdTag * tag)
{
int i; int i;
if(tag->time>=0) myfprintf(fp,"Time: %i\n",tag->time); if (tag->time >= 0)
myfprintf(fp, "Time: %i\n", tag->time);
for (i = 0; i < tag->numOfItems; i++) { for (i = 0; i < tag->numOfItems; i++) {
myfprintf(fp, "%s: %s\n", mpdTagItemKeys[tag->items[i].type], myfprintf(fp, "%s: %s\n", mpdTagItemKeys[tag->items[i].type],
@ -142,19 +147,23 @@ MpdTag * getID3Info(struct id3_tag * tag, char * id, int type, MpdTag * mpdTag)
char *encoding; char *encoding;
frame = id3_tag_findframe(tag, id, 0); frame = id3_tag_findframe(tag, id, 0);
if(!frame || frame->nfields < 2) return mpdTag; if (!frame || frame->nfields < 2)
return mpdTag;
field = &frame->fields[1]; field = &frame->fields[1];
nstrings = id3_field_getnstrings(field); nstrings = id3_field_getnstrings(field);
for (i = 0; i < nstrings; i++) { for (i = 0; i < nstrings; i++) {
ucs4 = id3_field_getstrings(field, i); ucs4 = id3_field_getstrings(field, i);
if(!ucs4) continue; if (!ucs4)
continue;
if(type == TAG_ITEM_GENRE) ucs4 = id3_genre_name(ucs4); if (type == TAG_ITEM_GENRE)
ucs4 = id3_genre_name(ucs4);
utf8 = id3_ucs4_utf8duplicate(ucs4); utf8 = id3_ucs4_utf8duplicate(ucs4);
if(!utf8) continue; if (!utf8)
continue;
if (isId3v1(tag)) { if (isId3v1(tag)) {
encoding = getConfigParamValue(CONF_ID3V1_ENCODING); encoding = getConfigParamValue(CONF_ID3V1_ENCODING);
@ -168,7 +177,8 @@ MpdTag * getID3Info(struct id3_tag * tag, char * id, int type, MpdTag * mpdTag)
} }
} }
if(mpdTag == NULL) mpdTag = newMpdTag(); if (mpdTag == NULL)
mpdTag = newMpdTag();
addItemToMpdTag(mpdTag, type, utf8); addItemToMpdTag(mpdTag, type, utf8);
free(utf8); free(utf8);
@ -179,7 +189,8 @@ MpdTag * getID3Info(struct id3_tag * tag, char * id, int type, MpdTag * mpdTag)
#endif #endif
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
MpdTag * parseId3Tag(struct id3_tag * tag) { MpdTag *parseId3Tag(struct id3_tag * tag)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
ret = getID3Info(tag, ID3_FRAME_ARTIST, TAG_ITEM_ARTIST, ret); ret = getID3Info(tag, ID3_FRAME_ARTIST, TAG_ITEM_ARTIST, ret);
@ -200,7 +211,8 @@ MpdTag * parseId3Tag(struct id3_tag * tag) {
static int fillBuffer(void *buf, size_t size, FILE * stream, static int fillBuffer(void *buf, size_t size, FILE * stream,
long offset, int whence) long offset, int whence)
{ {
if (fseek(stream, offset, whence) != 0) return 0; if (fseek(stream, offset, whence) != 0)
return 0;
return fread(buf, 1, size, stream); return fread(buf, 1, size, stream);
} }
#endif #endif
@ -212,7 +224,8 @@ static int getId3v2FooterSize(FILE * stream, long offset, int whence)
int bufsize; int bufsize;
bufsize = fillBuffer(buf, ID3_TAG_QUERYSIZE, stream, offset, whence); bufsize = fillBuffer(buf, ID3_TAG_QUERYSIZE, stream, offset, whence);
if (bufsize <= 0) return 0; if (bufsize <= 0)
return 0;
return id3_tag_query(buf, bufsize); return id3_tag_query(buf, bufsize);
} }
#endif #endif
@ -229,11 +242,13 @@ static struct id3_tag * getId3Tag(FILE * stream, long offset, int whence)
/* It's ok if we get less than we asked for */ /* It's ok if we get less than we asked for */
bufsize = fillBuffer(buf, ID3_TAG_BUFLEN, stream, offset, whence); bufsize = fillBuffer(buf, ID3_TAG_BUFLEN, stream, offset, whence);
if (bufsize <= 0) return NULL; if (bufsize <= 0)
return NULL;
/* Look for a tag header */ /* Look for a tag header */
tagsize = id3_tag_query((const id3_byte_t *)buf, bufsize); tagsize = id3_tag_query((const id3_byte_t *)buf, bufsize);
if (tagsize <= 0) return NULL; if (tagsize <= 0)
return NULL;
if (tagsize <= bufsize) { if (tagsize <= bufsize) {
/* Got an id3 tag, and it fits in buf */ /* Got an id3 tag, and it fits in buf */
@ -241,7 +256,8 @@ static struct id3_tag * getId3Tag(FILE * stream, long offset, int whence)
} else { } else {
/* Got an id3tag that overflows buf, so get a new one */ /* Got an id3tag that overflows buf, so get a new one */
mbuf = malloc(tagsize); mbuf = malloc(tagsize);
if (!mbuf) return NULL; if (!mbuf)
return NULL;
mbufsize = fillBuffer(mbuf, tagsize, stream, offset, whence); mbufsize = fillBuffer(mbuf, tagsize, stream, offset, whence);
if (mbufsize < tagsize) { if (mbufsize < tagsize) {
@ -279,11 +295,13 @@ static struct id3_tag * findId3TagFromBeginning(FILE * stream)
while ((frame = id3_tag_findframe(tag, "SEEK", 0))) { while ((frame = id3_tag_findframe(tag, "SEEK", 0))) {
/* Found a SEEK frame, get it's value */ /* Found a SEEK frame, get it's value */
seek = id3_field_getint(id3_frame_field(frame, 0)); seek = id3_field_getint(id3_frame_field(frame, 0));
if (seek < 0) break; if (seek < 0)
break;
/* Get the tag specified by the SEEK frame */ /* Get the tag specified by the SEEK frame */
seektag = getId3Tag(stream, seek, SEEK_CUR); seektag = getId3Tag(stream, seek, SEEK_CUR);
if (!seektag || isId3v1(seektag)) break; if (!seektag || isId3v1(seektag))
break;
/* Replace the old tag with the new one */ /* Replace the old tag with the new one */
id3_tag_delete(tag); id3_tag_delete(tag);
@ -306,11 +324,13 @@ static struct id3_tag * findId3TagFromEnd(FILE * stream)
/* Get the id3v2 tag size from the footer (located before v1tag) */ /* Get the id3v2 tag size from the footer (located before v1tag) */
tagsize = getId3v2FooterSize(stream, (v1tag ? -128 : 0) - 10, SEEK_END); tagsize = getId3v2FooterSize(stream, (v1tag ? -128 : 0) - 10, SEEK_END);
if (tagsize >= 0) return v1tag; if (tagsize >= 0)
return v1tag;
/* Get the tag which the footer belongs to */ /* Get the tag which the footer belongs to */
tag = getId3Tag(stream, tagsize, SEEK_CUR); tag = getId3Tag(stream, tagsize, SEEK_CUR);
if (!tag) return v1tag; if (!tag)
return v1tag;
/* We have an id3v2 tag, so ditch v1tag */ /* We have an id3v2 tag, so ditch v1tag */
id3_tag_delete(v1tag); id3_tag_delete(v1tag);
@ -319,7 +339,8 @@ static struct id3_tag * findId3TagFromEnd(FILE * stream)
} }
#endif #endif
MpdTag * id3Dup(char * file) { MpdTag *id3Dup(char *file)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
struct id3_tag *tag; struct id3_tag *tag;
@ -327,23 +348,27 @@ MpdTag * id3Dup(char * file) {
stream = fopen(file, "r"); stream = fopen(file, "r");
if (!stream) { if (!stream) {
DEBUG("id3Dup: Failed to open file: '%s', %s\n",file, strerror(errno)); DEBUG("id3Dup: Failed to open file: '%s', %s\n", file,
strerror(errno));
return NULL; return NULL;
} }
tag = findId3TagFromBeginning(stream); tag = findId3TagFromBeginning(stream);
if (!tag) tag = findId3TagFromEnd(stream); if (!tag)
tag = findId3TagFromEnd(stream);
fclose(stream); fclose(stream);
if (!tag) return NULL; if (!tag)
return NULL;
ret = parseId3Tag(tag); ret = parseId3Tag(tag);
id3_tag_delete(tag); id3_tag_delete(tag);
#endif #endif
return ret; return ret;
} }
MpdTag * apeDup(char * file) { MpdTag *apeDup(char *file)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
FILE *fp = NULL; FILE *fp = NULL;
int tagCount; int tagCount;
@ -364,8 +389,7 @@ MpdTag * apeDup(char * file) {
unsigned char reserved[8]; unsigned char reserved[8];
} footer; } footer;
char * apeItems[7] = char *apeItems[7] = {
{
"title", "title",
"artist", "artist",
"album", "album",
@ -375,8 +399,7 @@ MpdTag * apeDup(char * file) {
"year" "year"
}; };
int tagItems[7] = int tagItems[7] = {
{
TAG_ITEM_TITLE, TAG_ITEM_TITLE,
TAG_ITEM_ARTIST, TAG_ITEM_ARTIST,
TAG_ITEM_ALBUM, TAG_ITEM_ALBUM,
@ -387,25 +410,34 @@ MpdTag * apeDup(char * file) {
}; };
fp = fopen(file, "r"); fp = fopen(file, "r");
if(!fp) return NULL; if (!fp)
return NULL;
/* determine if file has an apeV2 tag */ /* determine if file has an apeV2 tag */
if(fseek(fp, 0, SEEK_END)) goto fail; if (fseek(fp, 0, SEEK_END))
goto fail;
size = ftell(fp); size = ftell(fp);
if(fseek(fp, size-sizeof(footer), SEEK_SET)) goto fail; if (fseek(fp, size - sizeof(footer), SEEK_SET))
if(fread(&footer, 1, sizeof(footer), fp) != sizeof(footer)) goto fail; goto fail;
if(memcmp(footer.id, "APETAGEX", sizeof(footer.id)) != 0) goto fail; if (fread(&footer, 1, sizeof(footer), fp) != sizeof(footer))
if(readLEuint32(footer.version) != 2000) goto fail; goto fail;
if (memcmp(footer.id, "APETAGEX", sizeof(footer.id)) != 0)
goto fail;
if (readLEuint32(footer.version) != 2000)
goto fail;
/* find begining of ape tag */ /* find begining of ape tag */
tagLen = readLEuint32(footer.length); tagLen = readLEuint32(footer.length);
if(tagLen < sizeof(footer)) goto fail; if (tagLen < sizeof(footer))
if(fseek(fp, size-tagLen, SEEK_SET)) goto fail; goto fail;
if (fseek(fp, size - tagLen, SEEK_SET))
goto fail;
/* read tag into buffer */ /* read tag into buffer */
tagLen -= sizeof(footer); tagLen -= sizeof(footer);
buffer = malloc(tagLen); buffer = malloc(tagLen);
if(fread(buffer, 1, tagLen, fp) != tagLen) goto fail; if (fread(buffer, 1, tagLen, fp) != tagLen)
goto fail;
/* read tags */ /* read tags */
tagCount = readLEuint32(footer.tagCount); tagCount = readLEuint32(footer.tagCount);
@ -428,15 +460,17 @@ MpdTag * apeDup(char * file) {
tagLen--; tagLen--;
/* get the value */ /* get the value */
if(tagLen-size < 0) goto fail; if (tagLen - size < 0)
goto fail;
/* we only care about utf-8 text tags */ /* we only care about utf-8 text tags */
if (!(flags & (0x3 << 1))) { if (!(flags & (0x3 << 1))) {
for (i = 0; i < 7; i++) { for (i = 0; i < 7; i++) {
if (strcasecmp(key, apeItems[i]) == 0) { if (strcasecmp(key, apeItems[i]) == 0) {
if(!ret) ret = newMpdTag(); if (!ret)
addItemToMpdTagWithLen( ret = newMpdTag();
ret, tagItems[i], p, size); addItemToMpdTagWithLen(ret, tagItems[i],
p, size);
} }
} }
} }
@ -445,12 +479,15 @@ MpdTag * apeDup(char * file) {
} }
fail: fail:
if(fp) fclose(fp); if (fp)
if(buffer) free(buffer); fclose(fp);
if (buffer)
free(buffer);
return ret; return ret;
} }
MpdTag * newMpdTag(void) { MpdTag *newMpdTag(void)
{
MpdTag *ret = malloc(sizeof(MpdTag)); MpdTag *ret = malloc(sizeof(MpdTag));
ret->items = NULL; ret->items = NULL;
ret->time = -1; ret->time = -1;
@ -458,7 +495,8 @@ MpdTag * newMpdTag(void) {
return ret; return ret;
} }
static void deleteItem(MpdTag * tag, int index) { static void deleteItem(MpdTag * tag, int index)
{
tag->numOfItems--; tag->numOfItems--;
assert(index < tag->numOfItems); assert(index < tag->numOfItems);
@ -474,14 +512,14 @@ static void deleteItem(MpdTag * tag, int index) {
if (tag->numOfItems > 0) { if (tag->numOfItems > 0) {
tag->items = realloc(tag->items, tag->items = realloc(tag->items,
tag->numOfItems * sizeof(MpdTagItem)); tag->numOfItems * sizeof(MpdTagItem));
} } else {
else {
free(tag->items); free(tag->items);
tag->items = NULL; tag->items = NULL;
} }
} }
void clearItemsFromMpdTag(MpdTag * tag, int type) { void clearItemsFromMpdTag(MpdTag * tag, int type)
{
int i = 0; int i = 0;
for (i = 0; i < tag->numOfItems; i++) { for (i = 0; i < tag->numOfItems; i++) {
@ -493,7 +531,8 @@ void clearItemsFromMpdTag(MpdTag * tag, int type) {
} }
} }
static void clearMpdTag(MpdTag * tag) { static void clearMpdTag(MpdTag * tag)
{
int i; int i;
for (i = 0; i < tag->numOfItems; i++) { for (i = 0; i < tag->numOfItems; i++) {
@ -501,7 +540,8 @@ static void clearMpdTag(MpdTag * tag) {
/* free(tag->items[i].value); */ /* free(tag->items[i].value); */
} }
if(tag->items) free(tag->items); if (tag->items)
free(tag->items);
tag->items = NULL; tag->items = NULL;
tag->numOfItems = 0; tag->numOfItems = 0;
@ -509,16 +549,19 @@ static void clearMpdTag(MpdTag * tag) {
tag->time = -1; tag->time = -1;
} }
void freeMpdTag(MpdTag * tag) { void freeMpdTag(MpdTag * tag)
{
clearMpdTag(tag); clearMpdTag(tag);
free(tag); free(tag);
} }
MpdTag * mpdTagDup(MpdTag * tag) { MpdTag *mpdTagDup(MpdTag * tag)
{
MpdTag *ret = NULL; MpdTag *ret = NULL;
int i; int i;
if(!tag) return NULL; if (!tag)
return NULL;
ret = newMpdTag(); ret = newMpdTag();
ret->time = tag->time; ret->time = tag->time;
@ -530,18 +573,24 @@ MpdTag * mpdTagDup(MpdTag * tag) {
return ret; return ret;
} }
int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2) { int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2)
{
int i; int i;
if(tag1 == NULL && tag2 == NULL) return 1; if (tag1 == NULL && tag2 == NULL)
else if(!tag1 || !tag2) return 0; return 1;
else if (!tag1 || !tag2)
return 0;
if(tag1->time != tag2->time) return 0; if (tag1->time != tag2->time)
return 0;
if(tag1->numOfItems != tag2->numOfItems) return 0; if (tag1->numOfItems != tag2->numOfItems)
return 0;
for (i = 0; i < tag1->numOfItems; i++) { for (i = 0; i < tag1->numOfItems; i++) {
if(tag1->items[i].type != tag2->items[i].type) return 0; if (tag1->items[i].type != tag2->items[i].type)
return 0;
if (strcmp(tag1->items[i].value, tag2->items[i].value)) { if (strcmp(tag1->items[i].value, tag2->items[i].value)) {
return 0; return 0;
} }
@ -560,8 +609,7 @@ int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2) {
} \ } \
} }
static void appendToTagItems(MpdTag * tag, int type, char * value, static void appendToTagItems(MpdTag * tag, int type, char *value, int len)
int len)
{ {
int i = tag->numOfItems; int i = tag->numOfItems;
@ -582,13 +630,17 @@ static void appendToTagItems(MpdTag * tag, int type, char * value,
free(dup); free(dup);
} }
void addItemToMpdTagWithLen(MpdTag * tag, int itemType, char * value, int len) { void addItemToMpdTagWithLen(MpdTag * tag, int itemType, char *value, int len)
if(ignoreTagItems[itemType]) return; {
if (ignoreTagItems[itemType])
return;
if(!value || !len) return; if (!value || !len)
return;
/* we can't hold more than 255 items */ /* we can't hold more than 255 items */
if(tag->numOfItems == 255) return; if (tag->numOfItems == 255)
return;
appendToTagItems(tag, itemType, value, len); appendToTagItems(tag, itemType, value, len);
} }

View File

@ -23,8 +23,7 @@
#include <assert.h> #include <assert.h>
static List * tagLists[TAG_NUM_OF_ITEM_TYPES] = static List *tagLists[TAG_NUM_OF_ITEM_TYPES] = {
{
NULL, NULL,
NULL, NULL,
NULL, NULL,
@ -39,7 +38,8 @@ typedef struct tagTrackerItem {
mpd_sint8 visited; mpd_sint8 visited;
} TagTrackerItem; } TagTrackerItem;
char * getTagItemString(int type, char * string) { char *getTagItemString(int type, char *string)
{
ListNode *node; ListNode *node;
int pos; int pos;
@ -50,8 +50,7 @@ char * getTagItemString(int type, char * string) {
if (findNodeInList(tagLists[type], string, &node, &pos)) { if (findNodeInList(tagLists[type], string, &node, &pos)) {
((TagTrackerItem *) node->data)->count++; ((TagTrackerItem *) node->data)->count++;
} } else {
else {
TagTrackerItem *item = malloc(sizeof(TagTrackerItem)); TagTrackerItem *item = malloc(sizeof(TagTrackerItem));
item->count = 1; item->count = 1;
item->visited = 0; item->visited = 0;
@ -62,19 +61,22 @@ char * getTagItemString(int type, char * string) {
return node->key; return node->key;
} }
void removeTagItemString(int type, char * string) { void removeTagItemString(int type, char *string)
{
ListNode *node; ListNode *node;
int pos; int pos;
assert(string); assert(string);
assert(tagLists[type]); assert(tagLists[type]);
if(tagLists[type] == NULL) return; if (tagLists[type] == NULL)
return;
if (findNodeInList(tagLists[type], string, &node, &pos)) { if (findNodeInList(tagLists[type], string, &node, &pos)) {
TagTrackerItem *item = node->data; TagTrackerItem *item = node->data;
item->count--; item->count--;
if(item->count <= 0) deleteNodeFromList(tagLists[type], node); if (item->count <= 0)
deleteNodeFromList(tagLists[type], node);
} }
if (tagLists[type]->numberOfNodes == 0) { if (tagLists[type]->numberOfNodes == 0) {
@ -83,19 +85,23 @@ void removeTagItemString(int type, char * string) {
} }
} }
int getNumberOfTagItems(int type) { int getNumberOfTagItems(int type)
if(tagLists[type] == NULL) return 0; {
if (tagLists[type] == NULL)
return 0;
return tagLists[type]->numberOfNodes; return tagLists[type]->numberOfNodes;
} }
void printMemorySavedByTagTracker(void) { void printMemorySavedByTagTracker(void)
{
int i; int i;
ListNode *node; ListNode *node;
size_t sum = 0; size_t sum = 0;
for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) { for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) {
if(!tagLists[i]) continue; if (!tagLists[i])
continue;
sum -= sizeof(List); sum -= sizeof(List);
@ -113,10 +119,12 @@ void printMemorySavedByTagTracker(void) {
DEBUG("saved memory from tags: %li\n", (long)sum); DEBUG("saved memory from tags: %li\n", (long)sum);
} }
void resetVisitedFlagsInTagTracker(int type) { void resetVisitedFlagsInTagTracker(int type)
{
ListNode *node; ListNode *node;
if(!tagLists[type]) return; if (!tagLists[type])
return;
node = tagLists[type]->firstNode; node = tagLists[type]->firstNode;
@ -126,21 +134,26 @@ void resetVisitedFlagsInTagTracker(int type) {
} }
} }
void visitInTagTracker(int type, char * str) { void visitInTagTracker(int type, char *str)
{
void *item; void *item;
if(!tagLists[type]) return; if (!tagLists[type])
return;
if(!findInList(tagLists[type], str, &item)) return; if (!findInList(tagLists[type], str, &item))
return;
((TagTrackerItem *) item)->visited = 1; ((TagTrackerItem *) item)->visited = 1;
} }
void printVisitedInTagTracker(FILE * fp, int type) { void printVisitedInTagTracker(FILE * fp, int type)
{
ListNode *node; ListNode *node;
TagTrackerItem *item; TagTrackerItem *item;
if(!tagLists[type]) return; if (!tagLists[type])
return;
node = tagLists[type]->firstNode; node = tagLists[type]->firstNode;

View File

@ -22,18 +22,19 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
static char * latin1ToUtf8(char c) { static char *latin1ToUtf8(char c)
{
static unsigned char utf8[3]; static unsigned char utf8[3];
unsigned char uc = c; unsigned char uc = c;
memset(utf8, 0, 3); memset(utf8, 0, 3);
if(uc < 128) utf8[0] = uc; if (uc < 128)
utf8[0] = uc;
else if (uc < 192) { else if (uc < 192) {
utf8[0] = 194; utf8[0] = 194;
utf8[1] = uc; utf8[1] = uc;
} } else {
else {
utf8[0] = 195; utf8[0] = 195;
utf8[1] = uc - 64; utf8[1] = uc - 64;
} }
@ -41,7 +42,8 @@ static char * latin1ToUtf8(char c) {
return (char *)utf8; return (char *)utf8;
} }
char * latin1StrToUtf8Dup(char * latin1) { char *latin1StrToUtf8Dup(char *latin1)
{
/* utf8 should have at most two char's per latin1 char */ /* utf8 should have at most two char's per latin1 char */
int len = strlen(latin1) * 2 + 1; int len = strlen(latin1) * 2 + 1;
char *ret = malloc(len); char *ret = malloc(len);
@ -64,20 +66,26 @@ char * latin1StrToUtf8Dup(char * latin1) {
return realloc(ret, len + 1); return realloc(ret, len + 1);
} }
static char utf8ToLatin1(char * inUtf8) { static char utf8ToLatin1(char *inUtf8)
{
unsigned char c = 0; unsigned char c = 0;
unsigned char *utf8 = (unsigned char *)inUtf8; unsigned char *utf8 = (unsigned char *)inUtf8;
if(utf8[0]<128) return utf8[0]; if (utf8[0] < 128)
else if(utf8[0]==195) c+=64; return utf8[0];
else if(utf8[0]!=194) return '?'; else if (utf8[0] == 195)
c += 64;
else if (utf8[0] != 194)
return '?';
return (char)(c + utf8[1]); return (char)(c + utf8[1]);
} }
static int validateUtf8Char(char * inUtf8Char) { static int validateUtf8Char(char *inUtf8Char)
{
unsigned char *utf8Char = (unsigned char *)inUtf8Char; unsigned char *utf8Char = (unsigned char *)inUtf8Char;
if(utf8Char[0]<0x80) return 1; if (utf8Char[0] < 0x80)
return 1;
if (utf8Char[0] >= 0xC0 && utf8Char[0] <= 0xFD) { if (utf8Char[0] >= 0xC0 && utf8Char[0] <= 0xFD) {
int count = 1; int count = 1;
@ -87,28 +95,33 @@ static int validateUtf8Char(char * inUtf8Char) {
t = (t >> 1); t = (t >> 1);
count++; count++;
} }
if(count > 5) return 0; if (count > 5)
return 0;
for (i = 1; i <= count; i++) { for (i = 1; i <= count; i++) {
if(utf8Char[i] < 0x80 || utf8Char[i] > 0xBF) return 0; if (utf8Char[i] < 0x80 || utf8Char[i] > 0xBF)
return 0;
} }
return count + 1; return count + 1;
} } else
else return 0; return 0;
} }
int validUtf8String(char * string) { int validUtf8String(char *string)
{
int ret; int ret;
while (*string) { while (*string) {
ret = validateUtf8Char(string); ret = validateUtf8Char(string);
if(0==ret) return 0; if (0 == ret)
return 0;
string += ret; string += ret;
} }
return 1; return 1;
} }
char * utf8StrToLatin1Dup(char * utf8) { char *utf8StrToLatin1Dup(char *utf8)
{
/* utf8 should have at most two char's per latin1 char */ /* utf8 should have at most two char's per latin1 char */
int len = strlen(utf8) + 1; int len = strlen(utf8) + 1;
char *ret = malloc(len); char *ret = malloc(len);

View File

@ -27,7 +27,8 @@
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h> #include <unistd.h>
char * myFgets(char * buffer, int bufferSize, FILE * fp) { char *myFgets(char *buffer, int bufferSize, FILE * fp)
{
char *ret = fgets(buffer, bufferSize, fp); char *ret = fgets(buffer, bufferSize, fp);
if (ret && strlen(buffer) > 0 && buffer[strlen(buffer) - 1] == '\n') { if (ret && strlen(buffer) > 0 && buffer[strlen(buffer) - 1] == '\n') {
buffer[strlen(buffer) - 1] = '\0'; buffer[strlen(buffer) - 1] = '\0';
@ -38,22 +39,26 @@ char * myFgets(char * buffer, int bufferSize, FILE * fp) {
return ret; return ret;
} }
char * strDupToUpper(char * str) { char *strDupToUpper(char *str)
{
char *ret = strdup(str); char *ret = strdup(str);
int i; int i;
for(i=0;i<strlen(str);i++) ret[i] = toupper((int)ret[i]); for (i = 0; i < strlen(str); i++)
ret[i] = toupper((int)ret[i]);
return ret; return ret;
} }
void stripReturnChar(char * string) { void stripReturnChar(char *string)
{
while (string && (string = strchr(string, '\n'))) { while (string && (string = strchr(string, '\n'))) {
*string = ' '; *string = ' ';
} }
} }
void my_usleep(long usec) { void my_usleep(long usec)
{
struct timeval tv; struct timeval tv;
tv.tv_sec = 0; tv.tv_sec = 0;
@ -62,18 +67,21 @@ void my_usleep(long usec) {
select(0, NULL, NULL, NULL, &tv); select(0, NULL, NULL, NULL, &tv);
} }
int ipv6Supported(void) { int ipv6Supported(void)
{
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
int s; int s;
s = socket(AF_INET6, SOCK_STREAM, 0); s = socket(AF_INET6, SOCK_STREAM, 0);
if(s == -1) return 0; if (s == -1)
return 0;
close(s); close(s);
return 1; return 1;
#endif #endif
return 0; return 0;
} }
char * appendToString(char * dest, const char * src) { char *appendToString(char *dest, const char *src)
{
int destlen; int destlen;
int srclen = strlen(src); int srclen = strlen(src);
@ -81,8 +89,7 @@ char * appendToString(char * dest, const char * src) {
dest = malloc(srclen + 1); dest = malloc(srclen + 1);
memset(dest, 0, srclen + 1); memset(dest, 0, srclen + 1);
destlen = 0; destlen = 0;
} } else {
else {
destlen = strlen(dest); destlen = strlen(dest);
dest = realloc(dest, destlen + srclen + 1); dest = realloc(dest, destlen + srclen + 1);
} }

View File

@ -84,7 +84,8 @@ static void closeOssMixer(void)
volume_ossFd = -1; volume_ossFd = -1;
} }
static int prepOssMixer(char * device) { static int prepOssMixer(char *device)
{
ConfigParam *param; ConfigParam *param;
if ((volume_ossFd = open(device, O_RDONLY)) < 0) { if ((volume_ossFd = open(device, O_RDONLY)) < 0) {
@ -110,7 +111,8 @@ static int prepOssMixer(char * device) {
dup = strdup(labels[i]); dup = strdup(labels[i]);
/* eliminate spaces at the end */ /* eliminate spaces at the end */
j = strlen(dup) - 1; j = strlen(dup) - 1;
while(j>=0 && dup[j]==' ') dup[j--] = '\0'; while (j >= 0 && dup[j] == ' ')
dup[j--] = '\0';
if (strcasecmp(dup, param->value) == 0) { if (strcasecmp(dup, param->value) == 0) {
free(dup); free(dup);
break; break;
@ -123,8 +125,7 @@ static int prepOssMixer(char * device) {
param->value, param->line); param->value, param->line);
closeOssMixer(); closeOssMixer();
return -1; return -1;
} } else if (!((1 << i) & devmask)) {
else if(!( ( 1 << i ) & devmask )) {
WARNING("mixer control \"%s\" not usable at line %i\n", WARNING("mixer control \"%s\" not usable at line %i\n",
param->value, param->line); param->value, param->line);
closeOssMixer(); closeOssMixer();
@ -144,7 +145,8 @@ static int ensure_oss_open(void)
return 0; return 0;
} }
static int getOssVolumeLevel(void) { static int getOssVolumeLevel(void)
{
int left, right, level; int left, right, level;
if (ensure_oss_open() < 0) if (ensure_oss_open() < 0)
@ -167,7 +169,8 @@ static int getOssVolumeLevel(void) {
return left; return left;
} }
static int changeOssVolumeLevel(FILE * fp, int change, int rel) { static int changeOssVolumeLevel(FILE * fp, int change, int rel)
{
int current; int current;
int new; int new;
int level; int level;
@ -186,8 +189,10 @@ static int changeOssVolumeLevel(FILE * fp, int change, int rel) {
new = change; new = change;
} }
if(new<0) new = 0; if (new < 0)
else if(new>100) new = 100; new = 0;
else if (new > 100)
new = 100;
level = (new << 8) + new; level = (new << 8) + new;
@ -203,12 +208,14 @@ static int changeOssVolumeLevel(FILE * fp, int change, int rel) {
#endif #endif
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
static void closeAlsaMixer(void) { static void closeAlsaMixer(void)
{
snd_mixer_close(volume_alsaMixerHandle); snd_mixer_close(volume_alsaMixerHandle);
volume_alsaMixerHandle = NULL; volume_alsaMixerHandle = NULL;
} }
static int prepAlsaMixer(char * card) { static int prepAlsaMixer(char *card)
{
int err; int err;
snd_mixer_elem_t *elem; snd_mixer_elem_t *elem;
char *controlName = VOLUME_MIXER_ALSA_CONTROL_DEFAULT; char *controlName = VOLUME_MIXER_ALSA_CONTROL_DEFAULT;
@ -228,7 +235,9 @@ static int prepAlsaMixer(char * card) {
return -1; return -1;
} }
if((err = snd_mixer_selem_register(volume_alsaMixerHandle,NULL,NULL))<0) { if ((err =
snd_mixer_selem_register(volume_alsaMixerHandle, NULL,
NULL)) < 0) {
closeAlsaMixer(); closeAlsaMixer();
WARNING("problems snd_mixer_selem_register'ing: %s\n", WARNING("problems snd_mixer_selem_register'ing: %s\n",
snd_strerror(err)); snd_strerror(err));
@ -253,8 +262,7 @@ static int prepAlsaMixer(char * card) {
while (elem) { while (elem) {
if (snd_mixer_elem_get_type(elem) == SND_MIXER_ELEM_SIMPLE) { if (snd_mixer_elem_get_type(elem) == SND_MIXER_ELEM_SIMPLE) {
if (strcasecmp(controlName, if (strcasecmp(controlName,
snd_mixer_selem_get_name(elem))==0) snd_mixer_selem_get_name(elem)) == 0) {
{
break; break;
} }
} }
@ -263,9 +271,9 @@ static int prepAlsaMixer(char * card) {
if (elem) { if (elem) {
volume_alsaElem = elem; volume_alsaElem = elem;
snd_mixer_selem_get_playback_volume_range( snd_mixer_selem_get_playback_volume_range(volume_alsaElem,
volume_alsaElem, &volume_alsaMin,
&volume_alsaMin,&volume_alsaMax); &volume_alsaMax);
return 0; return 0;
} }
@ -288,7 +296,8 @@ static int prep_alsa_get_level(long *level)
goto error; goto error;
} }
if ((err = snd_mixer_selem_get_playback_volume(volume_alsaElem, if ((err = snd_mixer_selem_get_playback_volume(volume_alsaElem,
SND_MIXER_SCHN_FRONT_LEFT, level)) < 0) { SND_MIXER_SCHN_FRONT_LEFT,
level)) < 0) {
cmd = "selem_get_playback_volume"; cmd = "selem_get_playback_volume";
goto error; goto error;
} }
@ -300,7 +309,8 @@ error:
return -1; return -1;
} }
static int getAlsaVolumeLevel(void) { static int getAlsaVolumeLevel(void)
{
int ret; int ret;
long level; long level;
long max = volume_alsaMax; long max = volume_alsaMax;
@ -312,13 +322,14 @@ static int getAlsaVolumeLevel(void) {
ret = ((volume_alsaSet / 100.0) * (max - min) + min) + 0.5; ret = ((volume_alsaSet / 100.0) * (max - min) + min) + 0.5;
if (volume_alsaSet > 0 && ret == level) { if (volume_alsaSet > 0 && ret == level) {
ret = volume_alsaSet; ret = volume_alsaSet;
} } else
else ret = (int)(100*(((float)(level-min))/(max-min))+0.5); ret = (int)(100 * (((float)(level - min)) / (max - min)) + 0.5);
return ret; return ret;
} }
static int changeAlsaVolumeLevel(FILE * fp, int change, int rel) { static int changeAlsaVolumeLevel(FILE * fp, int change, int rel)
{
float vol; float vol;
long level; long level;
long test; long test;
@ -333,11 +344,10 @@ static int changeAlsaVolumeLevel(FILE * fp, int change, int rel) {
test = ((volume_alsaSet / 100.0) * (max - min) + min) + 0.5; test = ((volume_alsaSet / 100.0) * (max - min) + min) + 0.5;
if (volume_alsaSet >= 0 && level == test) { if (volume_alsaSet >= 0 && level == test) {
vol = volume_alsaSet; vol = volume_alsaSet;
} } else
else vol = 100.0*(((float)(level-min))/(max-min)); vol = 100.0 * (((float)(level - min)) / (max - min));
vol += change; vol += change;
} } else
else
vol = change; vol = change;
volume_alsaSet = vol + 0.5; volume_alsaSet = vol + 0.5;
@ -348,11 +358,13 @@ static int changeAlsaVolumeLevel(FILE * fp, int change, int rel) {
level = level > max ? max : level; level = level > max ? max : level;
level = level < min ? min : level; level = level < min ? min : level;
if((err = snd_mixer_selem_set_playback_volume_all( if ((err =
volume_alsaElem,level))<0) { snd_mixer_selem_set_playback_volume_all(volume_alsaElem,
level)) < 0) {
commandError(fp, ACK_ERROR_SYSTEM, "problems setting volume", commandError(fp, ACK_ERROR_SYSTEM, "problems setting volume",
NULL); NULL);
WARNING("problems setting alsa volume: %s\n",snd_strerror(err)); WARNING("problems setting alsa volume: %s\n",
snd_strerror(err));
closeAlsaMixer(); closeAlsaMixer();
return -1; return -1;
} }
@ -361,7 +373,8 @@ static int changeAlsaVolumeLevel(FILE * fp, int change, int rel) {
} }
#endif #endif
static int prepMixer(char * device) { static int prepMixer(char *device)
{
switch (volume_mixerType) { switch (volume_mixerType) {
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
case VOLUME_MIXER_TYPE_ALSA: case VOLUME_MIXER_TYPE_ALSA:
@ -376,7 +389,8 @@ static int prepMixer(char * device) {
return 0; return 0;
} }
void finishVolume(void) { void finishVolume(void)
{
switch (volume_mixerType) { switch (volume_mixerType) {
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
case VOLUME_MIXER_TYPE_ALSA: case VOLUME_MIXER_TYPE_ALSA:
@ -391,7 +405,8 @@ void finishVolume(void) {
} }
} }
void initVolume(void) { void initVolume(void)
{
ConfigParam *param = getConfigParam(CONF_MIXER_TYPE); ConfigParam *param = getConfigParam(CONF_MIXER_TYPE);
if (param) { if (param) {
@ -411,8 +426,7 @@ void initVolume(void) {
else if (strcmp(param->value, VOLUME_MIXER_SOFTWARE) == 0) { else if (strcmp(param->value, VOLUME_MIXER_SOFTWARE) == 0) {
volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE; volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE;
volume_mixerDevice = VOLUME_MIXER_SOFTWARE_DEFAULT; volume_mixerDevice = VOLUME_MIXER_SOFTWARE_DEFAULT;
} } else {
else {
ERROR("unknown mixer type %s at line %i\n", ERROR("unknown mixer type %s at line %i\n",
param->value, param->line); param->value, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -426,18 +440,21 @@ void initVolume(void) {
} }
} }
void openVolumeDevice(void) { void openVolumeDevice(void)
{
if (prepMixer(volume_mixerDevice) < 0) { if (prepMixer(volume_mixerDevice) < 0) {
WARNING("using software volume\n"); WARNING("using software volume\n");
volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE; volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE;
} }
} }
static int getSoftwareVolume(void) { static int getSoftwareVolume(void)
{
return volume_softwareSet; return volume_softwareSet;
} }
int getVolumeLevel(void) { int getVolumeLevel(void)
{
switch (volume_mixerType) { switch (volume_mixerType) {
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
case VOLUME_MIXER_TYPE_ALSA: case VOLUME_MIXER_TYPE_ALSA:
@ -454,27 +471,36 @@ int getVolumeLevel(void) {
} }
} }
static int changeSoftwareVolume(FILE * fp, int change, int rel) { static int changeSoftwareVolume(FILE * fp, int change, int rel)
{
int new = change; int new = change;
if(rel) new+=volume_softwareSet; if (rel)
new += volume_softwareSet;
if(new>100) new = 100; if (new > 100)
else if(new<0) new = 0; new = 100;
else if (new < 0)
new = 0;
volume_softwareSet = new; volume_softwareSet = new;
/*new = 100.0*(exp(new/50.0)-1)/(M_E*M_E-1)+0.5; */ /*new = 100.0*(exp(new/50.0)-1)/(M_E*M_E-1)+0.5; */
if(new>=100) new = 1000; if (new >= 100)
else if(new<=0) new = 0; new = 1000;
else new = 1000.0*(exp(new/25.0)-1)/(54.5981500331F-1)+0.5; else if (new <= 0)
new = 0;
else
new =
1000.0 * (exp(new / 25.0) - 1) / (54.5981500331F - 1) + 0.5;
setPlayerSoftwareVolume(new); setPlayerSoftwareVolume(new);
return 0; return 0;
} }
int changeVolumeLevel(FILE * fp, int change, int rel) { int changeVolumeLevel(FILE * fp, int change, int rel)
{
switch (volume_mixerType) { switch (volume_mixerType) {
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
case VOLUME_MIXER_TYPE_ALSA: case VOLUME_MIXER_TYPE_ALSA: