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

@ -41,23 +41,25 @@
static AudioFormat audio_format; static AudioFormat audio_format;
static AudioFormat * audio_configFormat = NULL; static AudioFormat *audio_configFormat = NULL;
static AudioOutput ** audioOutputArray = NULL; static AudioOutput **audioOutputArray = NULL;
static mpd_uint8 audioOutputArraySize = 0; static mpd_uint8 audioOutputArraySize = 0;
/* the audioEnabledArray should be stuck into shared memory, and then disable /* the audioEnabledArray should be stuck into shared memory, and then disable
and enable in playAudio() routine */ and enable in playAudio() routine */
static mpd_sint8 * pdAudioDevicesEnabled = NULL; static mpd_sint8 *pdAudioDevicesEnabled = NULL;
static mpd_sint8 myAudioDevicesEnabled[AUDIO_MAX_DEVICES]; static mpd_sint8 myAudioDevicesEnabled[AUDIO_MAX_DEVICES];
static mpd_uint8 audioOpened = 0; static mpd_uint8 audioOpened = 0;
static mpd_sint32 audioBufferSize = 0; 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,15 +93,16 @@ 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;
loadAudioDrivers(); loadAudioDrivers();
pdAudioDevicesEnabled = (getPlayerData())->audioDeviceEnabled; pdAudioDevicesEnabled = (getPlayerData())->audioDeviceEnabled;
for(i = 0; i < AUDIO_MAX_DEVICES; i++) { for (i = 0; i < AUDIO_MAX_DEVICES; i++) {
pdAudioDevicesEnabled[i] = 1; pdAudioDevicesEnabled[i] = 1;
myAudioDevicesEnabled[i] = 1; myAudioDevicesEnabled[i] = 1;
} }
@ -111,7 +113,7 @@ void initAudioDriver(void) {
AudioOutput *output; AudioOutput *output;
int j; int j;
if(audioOutputArraySize == AUDIO_MAX_DEVICES) { if (audioOutputArraySize == AUDIO_MAX_DEVICES) {
ERROR("only up to 255 audio output devices are " ERROR("only up to 255 audio output devices are "
"supported"); "supported");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -120,10 +122,11 @@ 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) {
ERROR("problems configuring output device defined at " ERROR("problems configuring output device defined at "
"line %i\n", param->line); "line %i\n", param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -131,50 +134,51 @@ 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);
} }
} }
audioOutputArray[i] = output; audioOutputArray[i] = output;
} while((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param))); } while ((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param)));
} }
void getOutputAudioFormat(AudioFormat * inAudioFormat, void getOutputAudioFormat(AudioFormat * inAudioFormat,
AudioFormat * outAudioFormat) AudioFormat * outAudioFormat)
{ {
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));
if(0 != parseAudioConfig(audio_configFormat, param->value)) { if (0 != parseAudioConfig(audio_configFormat, param->value)) {
ERROR("error parsing \"%s\" at line %i\n", ERROR("error parsing \"%s\" at line %i\n",
CONF_AUDIO_OUTPUT_FORMAT, param->line); CONF_AUDIO_OUTPUT_FORMAT, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
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));
audioFormat->sampleRate = strtol(conf,&test,10); audioFormat->sampleRate = strtol(conf, &test, 10);
if(*test!=':') { if (*test != ':') {
ERROR("error parsing audio output format: %s\n",conf); ERROR("error parsing audio output format: %s\n", conf);
return -1; return -1;
} }
@ -188,22 +192,22 @@ int parseAudioConfig(AudioFormat * audioFormat, char * conf) {
ERROR("sample rate %i can not be used for audio output\n", ERROR("sample rate %i can not be used for audio output\n",
(int)audioFormat->sampleRate); (int)audioFormat->sampleRate);
return -1 return -1
}*/ } */
if(audioFormat->sampleRate <= 0) { if (audioFormat->sampleRate <= 0) {
ERROR("sample rate %i is not >= 0\n", ERROR("sample rate %i is not >= 0\n",
(int)audioFormat->sampleRate); (int)audioFormat->sampleRate);
return -1; return -1;
} }
audioFormat->bits = strtol(test+1,&test,10); audioFormat->bits = strtol(test + 1, &test, 10);
if(*test!=':') { if (*test != ':') {
ERROR("error parsing audio output format: %s\n",conf); ERROR("error parsing audio output format: %s\n", conf);
return -1; return -1;
} }
switch(audioFormat->bits) { switch (audioFormat->bits) {
case 16: case 16:
break; break;
default: default:
@ -212,14 +216,14 @@ int parseAudioConfig(AudioFormat * audioFormat, char * conf) {
return -1; return -1;
} }
audioFormat->channels = strtol(test+1,&test,10); audioFormat->channels = strtol(test + 1, &test, 10);
if(*test!='\0') { if (*test != '\0') {
ERROR("error parsing audio output format: %s\n",conf); ERROR("error parsing audio output format: %s\n", conf);
return -1; return -1;
} }
switch(audioFormat->channels) { switch (audioFormat->channels) {
case 1: case 1:
case 2: case 2:
break; break;
@ -232,14 +236,17 @@ 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++) {
finishAudioOutput(audioOutputArray[i]); finishAudioOutput(audioOutputArray[i]);
} }
@ -248,44 +255,49 @@ 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);
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,32 +313,36 @@ 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();
copyAudioFormat(&audio_format, audioFormat); copyAudioFormat(&audio_format, audioFormat);
audioBufferSize = (audio_format.bits >> 3)* audioBufferSize = (audio_format.bits >> 3) *
audio_format.channels; audio_format.channels;
audioBufferSize*= audio_format.sampleRate >> 5; audioBufferSize *= audio_format.sampleRate >> 5;
audioBuffer = realloc(audioBuffer, audioBufferSize); audioBuffer = realloc(audioBuffer, audioBufferSize);
} }
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++) {
closeAudioOutput(audioOutputArray[i]); closeAudioOutput(audioOutputArray[i]);
} }
@ -336,48 +352,53 @@ 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) {
send = audioBufferSize-audioBufferPos; send = audioBufferSize - audioBufferPos;
send = send < size ? send : size; send = send < size ? send : size;
memcpy(audioBuffer+audioBufferPos, playChunk, send); memcpy(audioBuffer + audioBufferPos, playChunk, send);
audioBufferPos += send; audioBufferPos += send;
size -= send; size -= send;
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();
@ -386,23 +407,25 @@ void closeAudioDevice(void) {
audioBuffer = NULL; audioBuffer = NULL;
audioBufferSize = 0; audioBufferSize = 0;
for(i = 0; i < audioOutputArraySize; i++) { for (i = 0; i < audioOutputArraySize; i++) {
closeAudioOutput(audioOutputArray[i]); closeAudioOutput(audioOutputArray[i]);
} }
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++) {
sendMetadataToAudioOutput(audioOutputArray[i], tag); sendMetadataToAudioOutput(audioOutputArray[i], 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);
return -1; return -1;
@ -413,8 +436,9 @@ 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);
return -1; return -1;
@ -425,10 +449,11 @@ 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++) {
myfprintf(fp, "outputid: %i\n", i); myfprintf(fp, "outputid: %i\n", i);
myfprintf(fp, "outputname: %s\n", audioOutputArray[i]->name); myfprintf(fp, "outputname: %s\n", audioOutputArray[i]->name);
myfprintf(fp, "outputenabled: %i\n", myfprintf(fp, "outputenabled: %i\n",
@ -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;
@ -444,8 +470,8 @@ void saveAudioDevicesState(void) {
if (!(stateFile = getStateFile())) if (!(stateFile = getStateFile()))
return; return;
while(!(fp = fopen(stateFile,"a")) && errno==EINTR); while (!(fp = fopen(stateFile, "a")) && errno == EINTR) ;
if(!fp) { if (!fp) {
ERROR("problems opening state file \"%s\" for " ERROR("problems opening state file \"%s\" for "
"writing: %s\n", stateFile, strerror(errno)); "writing: %s\n", stateFile, strerror(errno));
return; return;
@ -457,27 +483,27 @@ void saveAudioDevicesState(void) {
(int)pdAudioDevicesEnabled[i], (int)pdAudioDevicesEnabled[i],
audioOutputArray[i]->name); audioOutputArray[i]->name);
} }
while(fclose(fp) && errno==EINTR); while (fclose(fp) && errno == EINTR) ;
} }
static void parse_audio_device_state(FILE *fp) static void parse_audio_device_state(FILE * fp)
{ {
char buffer[AUDIO_BUFFER_SIZE]; char buffer[AUDIO_BUFFER_SIZE];
int i; int i;
assert(audioOutputArraySize != 0); assert(audioOutputArraySize != 0);
while (myFgets(buffer,AUDIO_BUFFER_SIZE,fp)) { while (myFgets(buffer, AUDIO_BUFFER_SIZE, fp)) {
char *c, *name; char *c, *name;
if (strncmp(buffer,AUDIO_DEVICE_STATE,AUDIO_DEVICE_STATE_LEN)) if (strncmp(buffer, AUDIO_DEVICE_STATE, AUDIO_DEVICE_STATE_LEN))
continue; continue;
c = strchr(buffer,':'); c = strchr(buffer, ':');
if (!c || !(++c)) if (!c || !(++c))
goto errline; goto errline;
name = strchr(c,':'); name = strchr(c, ':');
if (!name || !(++name)) if (!name || !(++name))
goto errline; goto errline;
@ -488,37 +514,35 @@ static void parse_audio_device_state(FILE *fp)
} }
} }
continue; continue;
errline: errline:
/* nonfatal */ /* nonfatal */
ERROR("invalid line in state_file: %s\n", buffer); ERROR("invalid line in state_file: %s\n", buffer);
} }
} }
void readAudioDevicesState(void) { void readAudioDevicesState(void)
{
char *stateFile; char *stateFile;
FILE *fp; FILE *fp;
struct stat st; struct stat st;
if (!(stateFile = getStateFile())) if (!(stateFile = getStateFile()))
return; return;
if(stat(stateFile,&st)<0) { if (stat(stateFile, &st) < 0) {
DEBUG("failed to stat state file\n"); DEBUG("failed to stat state file\n");
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

@ -42,7 +42,7 @@ int cmpAudioFormat(AudioFormat * dest, AudioFormat * src);
void getOutputAudioFormat(AudioFormat * inFormat, AudioFormat * outFormat); void getOutputAudioFormat(AudioFormat * inFormat, AudioFormat * outFormat);
int parseAudioConfig(AudioFormat * audioFormat, char * conf); int parseAudioConfig(AudioFormat * audioFormat, char *conf);
/* make sure initPlayerData is called before this function!! */ /* make sure initPlayerData is called before this function!! */
void initAudioConfig(); void initAudioConfig();
@ -55,7 +55,7 @@ void finishAudioDriver();
int openAudioDevice(AudioFormat * audioFormat); int openAudioDevice(AudioFormat * audioFormat);
int playAudio(char * playChunk,int size); int playAudio(char *playChunk, int size);
void dropBufferedAudio(); void dropBufferedAudio();

View File

@ -28,24 +28,30 @@
#define AUDIO_OUTPUT_NAME "name" #define AUDIO_OUTPUT_NAME "name"
#define AUDIO_OUTPUT_FORMAT "format" #define AUDIO_OUTPUT_FORMAT "format"
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,52 +66,50 @@ void finishAudioOutputPlugins(void) {
if(bp) str = bp->value; \ if(bp) str = bp->value; \
} }
AudioOutput * newAudioOutput(ConfigParam * param) { AudioOutput *newAudioOutput(ConfigParam * param)
AudioOutput * ret = NULL; {
void * data = NULL; AudioOutput *ret = NULL;
char * name = NULL; void *data = NULL;
char * format = NULL; char *name = NULL;
char * type = NULL; char *format = NULL;
BlockParam * bp = NULL; char *type = NULL;
AudioOutputPlugin * plugin = NULL; BlockParam *bp = NULL;
AudioOutputPlugin *plugin = NULL;
if(param) { if (param) {
getBlockParam(AUDIO_OUTPUT_NAME, name, 1); getBlockParam(AUDIO_OUTPUT_NAME, name, 1);
getBlockParam(AUDIO_OUTPUT_TYPE, type, 1); getBlockParam(AUDIO_OUTPUT_TYPE, type, 1);
getBlockParam(AUDIO_OUTPUT_FORMAT, format, 0); getBlockParam(AUDIO_OUTPUT_FORMAT, format, 0);
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",
CONF_AUDIO_OUTPUT); CONF_AUDIO_OUTPUT);
WARNING("Attempt to detect audio output device\n"); WARNING("Attempt to detect audio output device\n");
while(node) { while (node) {
plugin = (AudioOutputPlugin *) node->data; plugin = (AudioOutputPlugin *) node->data;
if(plugin->testDefaultDeviceFunc) { if (plugin->testDefaultDeviceFunc) {
WARNING("Attempting to detect a %s audio " WARNING("Attempting to detect a %s audio "
"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;
} }
} }
node = node->nextNode; node = node->nextNode;
} }
if(!node) { if (!node) {
WARNING("Unable to detect an audio device\n"); WARNING("Unable to detect an audio device\n");
return NULL; return NULL;
} }
@ -134,20 +138,18 @@ AudioOutput * newAudioOutput(ConfigParam * param) {
memset(&ret->outAudioFormat, 0, sizeof(AudioFormat)); memset(&ret->outAudioFormat, 0, sizeof(AudioFormat));
memset(&ret->reqAudioFormat, 0, sizeof(AudioFormat)); memset(&ret->reqAudioFormat, 0, sizeof(AudioFormat));
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);
} }
copyAudioFormat(&ret->outAudioFormat, &ret->reqAudioFormat); copyAudioFormat(&ret->outAudioFormat, &ret->reqAudioFormat);
} }
if(plugin->initDriverFunc(ret, param) != 0) { if (plugin->initDriverFunc(ret, param) != 0) {
free(ret); free(ret);
ret = NULL; ret = NULL;
} }
@ -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);
@ -169,35 +171,36 @@ int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat) {
copyAudioFormat(&audioOutput->inAudioFormat, audioFormat); copyAudioFormat(&audioOutput->inAudioFormat, 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);
} }
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;
} }
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->outAudioFormat)); (audioOutput->
inAudioFormat),
*sizeArgPtr,
&(audioOutput->outAudioFormat));
if(size > audioOutput->convBufferLen) { if (size > audioOutput->convBufferLen) {
audioOutput->convBuffer = audioOutput->convBuffer =
realloc(audioOutput->convBuffer, size); realloc(audioOutput->convBuffer, size);
audioOutput->convBufferLen = size; audioOutput->convBufferLen = size;
@ -211,49 +214,59 @@ 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;
while(node) { while (node) {
plugin = (AudioOutputPlugin *)node->data; plugin = (AudioOutputPlugin *) node->data;
myfprintf(fp, "%s ", plugin->name); myfprintf(fp, "%s ", plugin->name);
node = node->nextNode; node = node->nextNode;
} }

View File

@ -40,29 +40,29 @@
typedef struct _AudioOutput AudioOutput; typedef struct _AudioOutput AudioOutput;
typedef int (* AudioOutputTestDefaultDeviceFunc) (); typedef int (*AudioOutputTestDefaultDeviceFunc) ();
typedef int (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput, typedef int (*AudioOutputInitDriverFunc) (AudioOutput * audioOutput,
ConfigParam * param); ConfigParam * param);
typedef void (* AudioOutputFinishDriverFunc) (AudioOutput * audioOutput); typedef void (*AudioOutputFinishDriverFunc) (AudioOutput * audioOutput);
typedef int (* AudioOutputOpenDeviceFunc) (AudioOutput * audioOutput); typedef int (*AudioOutputOpenDeviceFunc) (AudioOutput * audioOutput);
typedef int (* AudioOutputPlayFunc) (AudioOutput * audioOutput, typedef int (*AudioOutputPlayFunc) (AudioOutput * audioOutput,
char * playChunk, int size); char *playChunk, int size);
typedef void (* AudioOutputDropBufferedAudioFunc) (AudioOutput * audioOutput); typedef void (*AudioOutputDropBufferedAudioFunc) (AudioOutput * audioOutput);
typedef void (* AudioOutputCloseDeviceFunc) (AudioOutput * audioOutput); typedef void (*AudioOutputCloseDeviceFunc) (AudioOutput * audioOutput);
typedef void (* AudioOutputSendMetadataFunc) (AudioOutput * audioOutput, typedef void (*AudioOutputSendMetadataFunc) (AudioOutput * audioOutput,
MpdTag * tag); MpdTag * tag);
struct _AudioOutput { struct _AudioOutput {
int open; int open;
char * name; char *name;
char * type; char *type;
AudioOutputFinishDriverFunc finishDriverFunc; AudioOutputFinishDriverFunc finishDriverFunc;
AudioOutputOpenDeviceFunc openDeviceFunc; AudioOutputOpenDeviceFunc openDeviceFunc;
@ -75,15 +75,15 @@ struct _AudioOutput {
AudioFormat inAudioFormat; AudioFormat inAudioFormat;
AudioFormat outAudioFormat; AudioFormat outAudioFormat;
AudioFormat reqAudioFormat; AudioFormat reqAudioFormat;
char * convBuffer; char *convBuffer;
int convBufferLen; int convBufferLen;
int sameInAndOutFormats; int sameInAndOutFormats;
void * data; void *data;
}; };
typedef struct _AudioOutputPlugin { typedef struct _AudioOutputPlugin {
char * name; char *name;
AudioOutputTestDefaultDeviceFunc testDefaultDeviceFunc; AudioOutputTestDefaultDeviceFunc testDefaultDeviceFunc;
AudioOutputInitDriverFunc initDriverFunc; AudioOutputInitDriverFunc initDriverFunc;
@ -101,14 +101,14 @@ void finishAudioOutputPlugins();
void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin); void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin);
void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin); void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin);
AudioOutput * newAudioOutput(ConfigParam * param); AudioOutput *newAudioOutput(ConfigParam * param);
int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat); int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat);
int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size); int playAudioOutput(AudioOutput * audioOutput, char *playChunk, int size);
void dropBufferedAudioOutput(AudioOutput * audioOutput); void dropBufferedAudioOutput(AudioOutput * audioOutput);
void closeAudioOutput(AudioOutput * audioOutput); void closeAudioOutput(AudioOutput * audioOutput);
void finishAudioOutput(AudioOutput * audioOutput); void finishAudioOutput(AudioOutput * audioOutput);
int keepAudioOutputAlive(AudioOutput * audioOutput, int ms); int keepAudioOutputAlive(AudioOutput * audioOutput, int ms);
void sendMetadataToAudioOutput(AudioOutput * audioOutput, MpdTag * tag); void sendMetadataToAudioOutput(AudioOutput * audioOutput, MpdTag * tag);
void printAllOutputPluginTypes(FILE *fp); void printAllOutputPluginTypes(FILE * fp);
#endif #endif

View File

@ -39,13 +39,13 @@
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
typedef snd_pcm_sframes_t alsa_writei_t(snd_pcm_t *pcm, const void *buffer, typedef snd_pcm_sframes_t alsa_writei_t(snd_pcm_t * pcm, const void *buffer,
snd_pcm_uframes_t size); snd_pcm_uframes_t size);
typedef struct _AlsaData { typedef struct _AlsaData {
char * device; char *device;
snd_pcm_t * pcmHandle; snd_pcm_t *pcmHandle;
alsa_writei_t * writei; alsa_writei_t *writei;
unsigned int buffer_time; unsigned int buffer_time;
unsigned int period_time; unsigned int period_time;
int sampleSize; int sampleSize;
@ -54,8 +54,9 @@ 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;
ret->pcmHandle = NULL; ret->pcmHandle = NULL;
@ -67,17 +68,20 @@ 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) {
BlockParam * bp = getBlockParam(param, "device"); BlockParam *bp = getBlockParam(param, "device");
ad->device = bp ? strdup(bp->value) : strdup("default"); ad->device = bp ? strdup(bp->value) : strdup("default");
if ((bp = getBlockParam(param, "use_mmap")) && if ((bp = getBlockParam(param, "use_mmap")) &&
@ -94,45 +98,46 @@ 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);
} }
static int alsa_testDefault(void) static int alsa_testDefault(void)
{ {
snd_pcm_t * handle; snd_pcm_t *handle;
int ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, int ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK,
SND_PCM_NONBLOCK); SND_PCM_NONBLOCK);
snd_config_update_free_global(); snd_config_update_free_global();
if(ret) { if (ret) {
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;
} }
static int alsa_openDevice(AudioOutput * audioOutput) static int alsa_openDevice(AudioOutput * audioOutput)
{ {
AlsaData * ad = audioOutput->data; AlsaData *ad = audioOutput->data;
AudioFormat * audioFormat = &audioOutput->outAudioFormat; AudioFormat *audioFormat = &audioOutput->outAudioFormat;
snd_pcm_format_t bitformat; snd_pcm_format_t bitformat;
snd_pcm_hw_params_t * hwparams; snd_pcm_hw_params_t *hwparams;
snd_pcm_sw_params_t * swparams; snd_pcm_sw_params_t *swparams;
unsigned int sampleRate = audioFormat->sampleRate; unsigned int sampleRate = audioFormat->sampleRate;
unsigned int channels = audioFormat->channels; unsigned int channels = audioFormat->channels;
snd_pcm_uframes_t alsa_buffer_size; snd_pcm_uframes_t alsa_buffer_size;
snd_pcm_uframes_t alsa_period_size; snd_pcm_uframes_t alsa_period_size;
int err; int err;
char * cmd = NULL; char *cmd = NULL;
switch(audioFormat->bits) { switch (audioFormat->bits) {
case 8: case 8:
bitformat = SND_PCM_FORMAT_S8; bitformat = SND_PCM_FORMAT_S8;
break; break;
@ -154,54 +159,55 @@ static int alsa_openDevice(AudioOutput * audioOutput)
err = snd_pcm_open(&ad->pcmHandle, ad->device, err = snd_pcm_open(&ad->pcmHandle, ad->device,
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
snd_config_update_free_global(); snd_config_update_free_global();
if(err < 0) { if (err < 0) {
ad->pcmHandle = NULL; ad->pcmHandle = NULL;
goto error; goto error;
} }
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;
} }
err = snd_pcm_hw_params_set_channels_near(ad->pcmHandle, hwparams, err = snd_pcm_hw_params_set_channels_near(ad->pcmHandle, hwparams,
&channels); &channels);
if(err < 0) { if (err < 0) {
ERROR("Alsa device \"%s\" does not support %i channels: " ERROR("Alsa device \"%s\" does not support %i channels: "
"%s\n", ad->device, (int)audioFormat->channels, "%s\n", ad->device, (int)audioFormat->channels,
snd_strerror(-err)); snd_strerror(-err));
@ -211,7 +217,7 @@ static int alsa_openDevice(AudioOutput * audioOutput)
err = snd_pcm_hw_params_set_rate_near(ad->pcmHandle, hwparams, err = snd_pcm_hw_params_set_rate_near(ad->pcmHandle, hwparams,
&sampleRate, NULL); &sampleRate, NULL);
if(err < 0 || sampleRate == 0) { if (err < 0 || sampleRate == 0) {
ERROR("Alsa device \"%s\" does not support %i Hz audio\n", ERROR("Alsa device \"%s\" does not support %i Hz audio\n",
ad->device, (int)audioFormat->sampleRate); ad->device, (int)audioFormat->sampleRate);
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,27 +262,33 @@ 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;
audioOutput->open = 1; audioOutput->open = 1;
@ -281,31 +298,31 @@ static int alsa_openDevice(AudioOutput * audioOutput)
return 0; return 0;
error: 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);
} }
switch(snd_pcm_state(ad->pcmHandle)) { switch (snd_pcm_state(ad->pcmHandle)) {
case SND_PCM_STATE_PAUSED: case SND_PCM_STATE_PAUSED:
err = snd_pcm_pause(ad->pcmHandle, /* disable */ 0); err = snd_pcm_pause(ad->pcmHandle, /* disable */ 0);
break; break;
@ -331,16 +348,18 @@ 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) {
snd_pcm_drain(ad->pcmHandle); snd_pcm_drain(ad->pcmHandle);
snd_pcm_close(ad->pcmHandle); snd_pcm_close(ad->pcmHandle);
ad->pcmHandle = NULL; ad->pcmHandle = NULL;
@ -349,10 +368,9 @@ 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;
size /= ad->sampleSize; size /= ad->sampleSize;
@ -360,10 +378,11 @@ 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) {
ERROR("closing alsa device \"%s\" due to write " ERROR("closing alsa device \"%s\" due to write "
"error: %s\n", ad->device, "error: %s\n", ad->device,
snd_strerror(-errno)); snd_strerror(-errno));
@ -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

@ -34,26 +34,26 @@ static int driverInitCount = 0;
typedef struct _AoData { typedef struct _AoData {
int writeSize; int writeSize;
int driverId; int driverId;
ao_option * options; ao_option *options;
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;
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");
} }
} }
@ -61,47 +61,45 @@ static void audioOutputAo_error() {
static int audioOutputAo_initDriver(AudioOutput * audioOutput, static int audioOutputAo_initDriver(AudioOutput * audioOutput,
ConfigParam * param) ConfigParam * param)
{ {
ao_info * ai; ao_info *ai;
char * dup; char *dup;
char * stk1; char *stk1;
char * stk2; char *stk2;
char * n1; char *n1;
char * key; char *key;
char * value; char *value;
char * test; char *test;
AoData * ad = newAoData(); AoData *ad = newAoData();
BlockParam * blockParam; BlockParam *blockParam;
audioOutput->data = ad; audioOutput->data = ad;
if((blockParam = getBlockParam(param, "write_size"))) { if ((blockParam = getBlockParam(param, "write_size"))) {
ad->writeSize = strtol(blockParam->value, &test, 10); ad->writeSize = strtol(blockParam->value, &test, 10);
if (*test!='\0') { if (*test != '\0') {
ERROR("\"%s\" is not a valid write size at line %i\n", ERROR("\"%s\" is not a valid write size at line %i\n",
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();
} }
driverInitCount++; driverInitCount++;
blockParam = getBlockParam(param, "driver"); blockParam = getBlockParam(param, "driver");
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);
} }
if((ai = ao_driver_info(ad->driverId))==NULL) { if ((ai = ao_driver_info(ad->driverId)) == NULL) {
ERROR("problems getting driver info for device defined at " ERROR("problems getting driver info for device defined at "
"line %i\n", param->line); "line %i\n", param->line);
ERROR("you may not have permission to the audio device\n"); ERROR("you may not have permission to the audio device\n");
@ -113,18 +111,18 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput,
blockParam = getBlockParam(param, "options"); blockParam = getBlockParam(param, "options");
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;
n1 = strtok_r(dup,";",&stk1); n1 = strtok_r(dup, ";", &stk1);
while(n1) { while (n1) {
stk2 = NULL; stk2 = NULL;
key = strtok_r(n1,"=",&stk2); key = strtok_r(n1, "=", &stk2);
if(!key) { if (!key) {
ERROR("problems parsing " ERROR("problems parsing "
"ao_driver_options \"%s\"\n", n1); "ao_driver_options \"%s\"\n", n1);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -141,15 +139,15 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput,
"\"%s\" ao driver\n",key, "\"%s\" ao driver\n",key,
ai->short_name); ai->short_name);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
}*/ } */
value = strtok_r(NULL,"",&stk2); value = strtok_r(NULL, "", &stk2);
if(!value) { if (!value) {
ERROR("problems parsing " ERROR("problems parsing "
"ao_driver_options \"%s\"\n", n1); "ao_driver_options \"%s\"\n", n1);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
ao_append_option(&ad->options,key,value); ao_append_option(&ad->options, key, value);
n1 = strtok_r(NULL,";",&stk1); n1 = strtok_r(NULL, ";", &stk1);
} }
} }
free(dup); free(dup);
@ -157,28 +155,33 @@ 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) {
ao_close(ad->device); ao_close(ad->device);
ad->device = NULL; ad->device = NULL;
} }
@ -186,11 +189,12 @@ 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;
if(ad->device) { if (ad->device) {
audioOutputAo_closeDevice(audioOutput); audioOutputAo_closeDevice(audioOutput);
} }
@ -201,41 +205,41 @@ 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;
if(ao_play(ad->device, playChunk, send)==0) { if (ao_play(ad->device, playChunk, send) == 0) {
audioOutputAo_error(); audioOutputAo_error();
ERROR("closing audio device due to write error\n"); ERROR("closing audio device due to write error\n");
audioOutputAo_closeDevice(audioOutput); audioOutputAo_closeDevice(audioOutput);
return -1; return -1;
} }
playChunk+=send; playChunk += send;
size-=send; size -= send;
} }
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

@ -54,14 +54,14 @@
typedef struct _OssData { typedef struct _OssData {
int fd; int fd;
char * device; char *device;
int channels; int channels;
int sampleRate; int sampleRate;
int bitFormat; int bitFormat;
int bits; int bits;
int * supported[3]; int *supported[3];
int numSupported[3]; int numSupported[3];
int * unsupported[3]; int *unsupported[3];
int numUnsupported[3]; int numUnsupported[3];
} OssData; } OssData;
@ -73,10 +73,11 @@ 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) {
case SNDCTL_DSP_SPEED: case SNDCTL_DSP_SPEED:
index = OSS_RATE; index = OSS_RATE;
break; break;
@ -91,42 +92,49 @@ 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;
int least = val; int least = val;
int diff; int diff;
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)
if(diff < least) { diff = -diff;
if(!canConvert(index, od->supported[index][i])) { if (diff < least) {
if (!canConvert(index, od->supported[index][i])) {
continue; continue;
} }
least = diff; least = diff;
@ -137,97 +145,115 @@ 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]++;
od->supported[index] = realloc(od->supported[index], od->supported[index] = realloc(od->supported[index],
od->numSupported[index]*sizeof(int)); od->numSupported[index] * sizeof(int));
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] *
od->unsupported[index][od->numUnsupported[index]-1] = val; sizeof(int));
od->unsupported[index][od->numUnsupported[index] - 1] = val;
} }
static void removeSupportedParam(OssData * od, int param, int val) { static void removeSupportedParam(OssData * od, int param, int val)
{
int i = 0; int 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)
od->supported[index][i] = od->supported[index][i+j]; j = 1;
od->supported[index][i] = od->supported[index][i + j];
} }
od->numSupported[index]--; od->numSupported[index]--;
od->supported[index] = realloc(od->supported[index], od->supported[index] = realloc(od->supported[index],
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)
od->unsupported[index][i] = od->unsupported[index][i+j]; j = 1;
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);
} }
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);
} }
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;
ret->fd = -1; ret->fd = -1;
@ -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,18 +307,18 @@ 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) {
case ENOENT: case ENOENT:
case ENOTDIR: case ENOTDIR:
return OSS_STAT_DOESN_T_EXIST; return OSS_STAT_DOESN_T_EXIST;
@ -298,12 +332,13 @@ 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);
if(fd >= 0) { if (fd >= 0) {
close(fd); close(fd);
return 0; return 0;
} }
@ -313,108 +348,106 @@ static int oss_testDefault(void) {
fd = open("/dev/dsp", O_WRONLY); fd = open("/dev/dsp", O_WRONLY);
if(fd >= 0) { if (fd >= 0) {
close(fd); close(fd);
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; {
OssData * od; BlockParam *bp = NULL;
OssData *od;
if(param) bp = getBlockParam(param, "device"); if (param)
bp = getBlockParam(param, "device");
od = newOssData(); od = newOssData();
audioOutput->data = od; audioOutput->data = od;
if(!bp) { if (!bp) {
int err[2]; int err[2];
int ret[2]; int ret[2];
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");
} }
if((ret[0] == OSS_STAT_DOESN_T_EXIST) && if ((ret[0] == OSS_STAT_DOESN_T_EXIST) &&
(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);
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;
} }
val = copy; val = copy;
} }
} while( supported == OSS_UNSUPPORTED ); } while (supported == OSS_UNSUPPORTED);
*value = val; *value = val;
@ -423,37 +456,35 @@ 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;
if((od->fd = open(od->device, O_WRONLY)) < 0) { if ((od->fd = open(od->device, O_WRONLY)) < 0) {
ERROR("Error opening OSS device \"%s\": %s\n", od->device, ERROR("Error opening OSS device \"%s\": %s\n", od->device,
strerror(errno)); strerror(errno));
goto fail; goto fail;
} }
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;
} }
switch(od->bits) { switch (od->bits) {
case 8: case 8:
tmp = AFMT_S8; tmp = AFMT_S8;
break; break;
@ -461,11 +492,9 @@ static int oss_open(AudioOutput * audioOutput) {
tmp = AFMT_S16_MPD; tmp = AFMT_S16_MPD;
} }
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;
} }
@ -473,7 +502,7 @@ static int oss_open(AudioOutput * audioOutput) {
return 0; return 0;
fail: fail:
oss_close(od); oss_close(od);
audioOutput->open = 0; audioOutput->open = 0;
return -1; return -1;
@ -482,8 +511,8 @@ fail:
static int oss_openDevice(AudioOutput * audioOutput) static int oss_openDevice(AudioOutput * audioOutput)
{ {
int ret = -1; int ret = -1;
OssData * od = audioOutput->data; OssData *od = audioOutput->data;
AudioFormat * audioFormat = &audioOutput->outAudioFormat; AudioFormat *audioFormat = &audioOutput->outAudioFormat;
od->channels = audioFormat->channels; od->channels = audioFormat->channels;
od->sampleRate = audioFormat->sampleRate; od->sampleRate = audioFormat->sampleRate;
@ -497,43 +526,44 @@ 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);
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) {
ioctl(od->fd, SNDCTL_DSP_RESET, 0); ioctl(od->fd, SNDCTL_DSP_RESET, 0);
oss_close(od); oss_close(od);
} }
} }
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;
/* reopen the device since it was closed by dropBufferedAudio */ /* reopen the device since it was closed by dropBufferedAudio */
if(od->fd < 0 && oss_open(audioOutput) < 0) if (od->fd < 0 && oss_open(audioOutput) < 0)
return -1; return -1;
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

@ -31,15 +31,16 @@ typedef struct _OsxData {
AudioUnit au; AudioUnit au;
pthread_mutex_t mutex; pthread_mutex_t mutex;
pthread_cond_t condition; pthread_cond_t condition;
char * buffer; char *buffer;
int bufferSize; int bufferSize;
int pos; int pos;
int len; int len;
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);
pthread_cond_init(&ret->condition, NULL); pthread_cond_init(&ret->condition, 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;
@ -75,49 +77,55 @@ static int osx_testDefault() {
return -1; return -1;
} }
CloseComponent(au);*/ CloseComponent(au); */
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;
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);
od->len = 0; od->len = 0;
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);
while(od->len) { while (od->len) {
pthread_cond_wait(&od->condition, &od->mutex); pthread_cond_wait(&od->condition, &od->mutex);
} }
pthread_mutex_unlock(&od->mutex); pthread_mutex_unlock(&od->mutex);
if(od->started) { if (od->started) {
AudioOutputUnitStop(od->au); AudioOutputUnitStop(od->au);
od->started = 0; od->started = 0;
} }
@ -128,14 +136,14 @@ static void osx_closeDevice(AudioOutput * audioOutput) {
audioOutput->open = 0; audioOutput->open = 0;
} }
static OSStatus osx_render(void * vdata, static OSStatus osx_render(void *vdata,
AudioUnitRenderActionFlags *ioActionFlags, AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp, const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber, UInt32 inNumberFrames, UInt32 inBusNumber, UInt32 inNumberFrames,
AudioBufferList *bufferList) AudioBufferList * bufferList)
{ {
OsxData * od = (OsxData *)vdata; OsxData *od = (OsxData *) vdata;
AudioBuffer * buffer = &bufferList->mBuffers[0]; AudioBuffer *buffer = &bufferList->mBuffers[0];
int bufferSize = buffer->mDataByteSize; int bufferSize = buffer->mDataByteSize;
int bytesToCopy; int bytesToCopy;
int curpos = 0; int curpos = 0;
@ -161,7 +169,7 @@ static OSStatus osx_render(void * vdata,
if(*ioActionFlags & kAudioOfflineUnitRenderAction_Complete) { if(*ioActionFlags & kAudioOfflineUnitRenderAction_Complete) {
DEBUG("complete\n"); DEBUG("complete\n");
} }
}*/ } */
/* while(bufferSize) { /* while(bufferSize) {
DEBUG("osx_render: lock\n"); */ DEBUG("osx_render: lock\n"); */
@ -180,19 +188,20 @@ static OSStatus osx_render(void * vdata,
bufferSize = bytesToCopy; bufferSize = bytesToCopy;
od->len -= bytesToCopy; od->len -= bytesToCopy;
if(od->pos+bytesToCopy > od->bufferSize) { if (od->pos + bytesToCopy > od->bufferSize) {
int bytes = od->bufferSize-od->pos; int bytes = od->bufferSize - od->pos;
memcpy(buffer->mData+curpos, od->buffer+od->pos, bytes); memcpy(buffer->mData + curpos, od->buffer + od->pos, bytes);
od->pos = 0; od->pos = 0;
curpos += bytes; curpos += bytes;
bytesToCopy -= bytes; bytesToCopy -= bytes;
} }
memcpy(buffer->mData+curpos, od->buffer+od->pos, bytesToCopy); memcpy(buffer->mData + curpos, od->buffer + od->pos, bytesToCopy);
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);
@ -200,7 +209,7 @@ static OSStatus osx_render(void * vdata,
buffer->mDataByteSize = bufferSize; buffer->mDataByteSize = bufferSize;
if(!bufferSize) { if (!bufferSize) {
my_usleep(1000); my_usleep(1000);
} }
@ -208,12 +217,13 @@ 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;
AURenderCallbackStruct callback; AURenderCallbackStruct callback;
AudioFormat * audioFormat = &audioOutput->outAudioFormat; AudioFormat *audioFormat = &audioOutput->outAudioFormat;
AudioStreamBasicDescription streamDesc; AudioStreamBasicDescription streamDesc;
desc.componentType = kAudioUnitType_Output; desc.componentType = kAudioUnitType_Output;
@ -223,17 +233,17 @@ static int osx_openDevice(AudioOutput * audioOutput) {
desc.componentFlagsMask = 0; desc.componentFlagsMask = 0;
comp = FindNextComponent(NULL, &desc); comp = FindNextComponent(NULL, &desc);
if(comp == 0) { if (comp == 0) {
ERROR("Error finding OS X component\n"); ERROR("Error finding OS X component\n");
return -1; return -1;
} }
if(OpenAComponent(comp, &od->au) != noErr) { if (OpenAComponent(comp, &od->au) != noErr) {
ERROR("Unable to open OS X component\n"); ERROR("Unable to open OS X component\n");
return -1; return -1;
} }
if(AudioUnitInitialize(od->au) != 0) { if (AudioUnitInitialize(od->au) != 0) {
CloseComponent(od->au); CloseComponent(od->au);
ERROR("Unable to initialuze OS X audio unit\n"); ERROR("Unable to initialuze OS X audio unit\n");
return -1; return -1;
@ -242,10 +252,9 @@ static int osx_openDevice(AudioOutput * audioOutput) {
callback.inputProc = osx_render; callback.inputProc = osx_render;
callback.inputProcRefCon = od; callback.inputProcRefCon = od;
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,16 +265,16 @@ 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;
streamDesc.mBitsPerChannel = audioFormat->bits; streamDesc.mBitsPerChannel = audioFormat->bits;
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,18 +294,19 @@ 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;
/* DEBUG("osx_play: enter\n"); */ /* DEBUG("osx_play: enter\n"); */
if(!od->started) { if (!od->started) {
int err; int err;
od->started = 1; od->started = 1;
err = AudioOutputUnitStart(od->au); err = AudioOutputUnitStart(od->au);
if(err) { if (err) {
ERROR("unable to start audio output: %i\n", err); ERROR("unable to start audio output: %i\n", err);
return -1; return -1;
} }
@ -304,14 +314,15 @@ static int osx_play(AudioOutput * audioOutput, char * playChunk, int size) {
pthread_mutex_lock(&od->mutex); pthread_mutex_lock(&od->mutex);
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;
while(od->len > od->bufferSize-bytesToCopy) { while (od->len > od->bufferSize - bytesToCopy) {
/* DEBUG("osx_play: wait\n"); */ /* DEBUG("osx_play: wait\n"); */
pthread_cond_wait(&od->condition, &od->mutex); pthread_cond_wait(&od->condition, &od->mutex);
} }
@ -321,15 +332,15 @@ static int osx_play(AudioOutput * audioOutput, char * playChunk, int size) {
size -= bytesToCopy; size -= bytesToCopy;
od->len += bytesToCopy; od->len += bytesToCopy;
if(curpos+bytesToCopy > od->bufferSize) { if (curpos + bytesToCopy > od->bufferSize) {
int bytes = od->bufferSize-curpos; int bytes = od->bufferSize - curpos;
memcpy(od->buffer+curpos, playChunk, bytes); memcpy(od->buffer + curpos, playChunk, bytes);
curpos = 0; curpos = 0;
playChunk += bytes; playChunk += bytes;
bytesToCopy -= bytes; bytesToCopy -= bytes;
} }
memcpy(od->buffer+curpos, playChunk, bytesToCopy); memcpy(od->buffer + curpos, playChunk, bytesToCopy);
curpos += bytesToCopy; curpos += bytesToCopy;
playChunk += bytesToCopy; playChunk += bytesToCopy;
@ -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

@ -34,16 +34,16 @@
#define CONN_ATTEMPT_INTERVAL 60 #define CONN_ATTEMPT_INTERVAL 60
typedef struct _PulseData { typedef struct _PulseData {
pa_simple * s; pa_simple *s;
char * server; char *server;
char * sink; char *sink;
int connAttempts; int connAttempts;
time_t lastAttempt; time_t lastAttempt;
} PulseData; } PulseData;
static PulseData * newPulseData() static PulseData *newPulseData()
{ {
PulseData * ret; PulseData *ret;
ret = malloc(sizeof(PulseData)); ret = malloc(sizeof(PulseData));
@ -58,16 +58,18 @@ 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);
} }
static int pulse_initDriver(AudioOutput * audioOutput, ConfigParam * param) static int pulse_initDriver(AudioOutput * audioOutput, ConfigParam * param)
{ {
BlockParam * server = NULL; BlockParam *server = NULL;
BlockParam * sink = NULL; BlockParam *sink = NULL;
PulseData * pd; PulseData *pd;
if (param) { if (param) {
server = getBlockParam(param, "server"); server = getBlockParam(param, "server");
@ -89,7 +91,7 @@ static void pulse_finishDriver(AudioOutput * audioOutput)
static int pulse_testDefault() static int pulse_testDefault()
{ {
pa_simple * s; pa_simple *s;
pa_sample_spec ss; pa_sample_spec ss;
int error; int error;
@ -112,8 +114,8 @@ static int pulse_testDefault()
static int pulse_openDevice(AudioOutput * audioOutput) static int pulse_openDevice(AudioOutput * audioOutput)
{ {
PulseData * pd; PulseData *pd;
AudioFormat * audioFormat; AudioFormat *audioFormat;
pa_sample_spec ss; pa_sample_spec ss;
time_t t; time_t t;
int error; int error;
@ -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);
@ -160,7 +163,7 @@ static int pulse_openDevice(AudioOutput * audioOutput)
static void pulse_dropBufferedAudio(AudioOutput * audioOutput) static void pulse_dropBufferedAudio(AudioOutput * audioOutput)
{ {
PulseData * pd; PulseData *pd;
int error; int error;
pd = audioOutput->data; pd = audioOutput->data;
@ -171,7 +174,7 @@ static void pulse_dropBufferedAudio(AudioOutput * audioOutput)
static void pulse_closeDevice(AudioOutput * audioOutput) static void pulse_closeDevice(AudioOutput * audioOutput)
{ {
PulseData * pd; PulseData *pd;
pd = audioOutput->data; pd = audioOutput->data;
if (pd->s) { if (pd->s) {
@ -182,16 +185,15 @@ 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;
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

@ -42,7 +42,7 @@ static int shoutInitCount = 0;
/* lots of this code blatantly stolent from bossogg/bossao2 */ /* lots of this code blatantly stolent from bossogg/bossao2 */
typedef struct _ShoutData { typedef struct _ShoutData {
shout_t * shoutConn; shout_t *shoutConn;
int shoutError; int shoutError;
ogg_stream_state os; ogg_stream_state os;
@ -62,18 +62,19 @@ typedef struct _ShoutData {
int opened; int opened;
MpdTag * tag; MpdTag *tag;
int tagToSend; int tagToSend;
int connAttempts; int connAttempts;
time_t lastAttempt; time_t lastAttempt;
/* just a pointer to audioOutput->outAudioFormat */ /* just a pointer to audioOutput->outAudioFormat */
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();
ret->opened = 0; ret->opened = 0;
@ -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,21 +108,23 @@ static void freeShoutData(ShoutData * sd) {
} \ } \
} }
static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) { static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param)
ShoutData * sd; {
char * test; ShoutData *sd;
char *test;
int port; int port;
char * host; char *host;
char * mount; char *mount;
char * passwd; char *passwd;
char * user; char *user;
char * name; char *name;
BlockParam * blockParam; BlockParam *blockParam;
unsigned int public; unsigned int public;
sd = newShoutData(); sd = newShoutData();
if(shoutInitCount == 0) shout_init(); if (shoutInitCount == 0)
shout_init();
shoutInitCount++; shoutInitCount++;
@ -132,7 +138,7 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
port = strtol(blockParam->value, &test, 10); port = strtol(blockParam->value, &test, 10);
if(*test != '\0' || port <= 0) { if (*test != '\0' || port <= 0) {
ERROR("shout port \"%s\" is not a positive integer, line %i\n", ERROR("shout port \"%s\" is not a positive integer, line %i\n",
blockParam->value, blockParam->line); blockParam->value, blockParam->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -145,29 +151,33 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
name = blockParam->value; name = blockParam->value;
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");
if(blockParam) { if (blockParam) {
int line = blockParam->line; int line = blockParam->line;
sd->quality = strtod(blockParam->value, &test); sd->quality = strtod(blockParam->value, &test);
if(*test != '\0' || sd->quality < 0.0 || sd->quality > 10.0) { if (*test != '\0' || sd->quality < 0.0 || sd->quality > 10.0) {
ERROR("shout quality \"%s\" is not a number in the " ERROR("shout quality \"%s\" is not a number in the "
"range 0-10, line %i\n", blockParam->value, "range 0-10, line %i\n", blockParam->value,
blockParam->line); blockParam->line);
@ -176,17 +186,16 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
blockParam = getBlockParam(param, "bitrate"); blockParam = getBlockParam(param, "bitrate");
if(blockParam) { if (blockParam) {
ERROR("quality (line %i) and bitrate (line %i) are " ERROR("quality (line %i) and bitrate (line %i) are "
"both defined for shout output\n", line, "both defined for shout output\n", line,
blockParam->line); blockParam->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} } else {
else {
blockParam = getBlockParam(param, "bitrate"); blockParam = getBlockParam(param, "bitrate");
if(!blockParam) { if (!blockParam) {
ERROR("neither bitrate nor quality defined for shout " ERROR("neither bitrate nor quality defined for shout "
"output at line %i\n", param->line); "output at line %i\n", param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -194,7 +203,7 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
sd->bitrate = strtol(blockParam->value, &test, 10); sd->bitrate = strtol(blockParam->value, &test, 10);
if(*test != '\0' || sd->bitrate <= 0) { if (*test != '\0' || sd->bitrate <= 0) {
ERROR("bitrate at line %i should be a positive integer " ERROR("bitrate at line %i should be a positive integer "
"\n", blockParam->line); "\n", blockParam->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -204,7 +213,7 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
checkBlockParam("format"); checkBlockParam("format");
sd->audioFormat = &audioOutput->outAudioFormat; sd->audioFormat = &audioOutput->outAudioFormat;
if(shout_set_host(sd->shoutConn, host) != SHOUTERR_SUCCESS || if (shout_set_host(sd->shoutConn, host) != SHOUTERR_SUCCESS ||
shout_set_port(sd->shoutConn, port) != SHOUTERR_SUCCESS || shout_set_port(sd->shoutConn, port) != SHOUTERR_SUCCESS ||
shout_set_password(sd->shoutConn, passwd) != SHOUTERR_SUCCESS || shout_set_password(sd->shoutConn, passwd) != SHOUTERR_SUCCESS ||
shout_set_mount(sd->shoutConn, mount) != SHOUTERR_SUCCESS || shout_set_mount(sd->shoutConn, mount) != SHOUTERR_SUCCESS ||
@ -215,30 +224,25 @@ 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);
} }
/* optional paramters */ /* optional paramters */
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);
} }
@ -253,12 +257,11 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
shout_set_audio_info(sd->shoutConn, SHOUT_AI_SAMPLERATE, temp); shout_set_audio_info(sd->shoutConn, SHOUT_AI_SAMPLERATE, temp);
if(sd->quality >= 0) { if (sd->quality >= 0) {
snprintf(temp, sizeof(temp), "%2.2f", sd->quality); 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,8 +273,9 @@ 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;
case SHOUTERR_UNCONNECTED: case SHOUTERR_UNCONNECTED:
@ -294,39 +298,46 @@ 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) {
vorbis_analysis(&sd->vb, NULL); vorbis_analysis(&sd->vb, NULL);
vorbis_bitrate_addblock(&sd->vb); vorbis_bitrate_addblock(&sd->vb);
while(vorbis_bitrate_flushpacket(&sd->vd, &sd->op)) { while (vorbis_bitrate_flushpacket(&sd->vd, &sd->op)) {
ogg_stream_packetin(&sd->os, &sd->op); ogg_stream_packetin(&sd->os, &sd->op);
} }
} }
} }
static int flushEncoder(ShoutData * sd) { static int flushEncoder(ShoutData * sd)
{
return (ogg_stream_pageout(&sd->os, &sd->og) > 0); 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,11 +347,12 @@ 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);
if(shout_close(sd->shoutConn) != SHOUTERR_SUCCESS) { if (shout_close(sd->shoutConn) != SHOUTERR_SUCCESS) {
ERROR("problem closing connection to shout server: " ERROR("problem closing connection to shout server: "
"%s\n", shout_get_error(sd->shoutConn)); "%s\n", shout_get_error(sd->shoutConn));
} }
@ -349,8 +361,9 @@ 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,15 +371,18 @@ 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,12 +393,13 @@ 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;
for(i = 0; i < sd->tag->numOfItems; i++) { for (i = 0; i < sd->tag->numOfItems; i++) {
switch(sd->tag->items[i].type) { switch (sd->tag->items[i].type) {
case TAG_ITEM_ARTIST: case TAG_ITEM_ARTIST:
addTag("ARTIST", sd->tag->items[i].value); addTag("ARTIST", sd->tag->items[i].value);
break; break;
@ -397,25 +414,24 @@ static void copyTagToVorbisComment(ShoutData * sd) {
} }
} }
static int initEncoder(ShoutData * sd) { static int initEncoder(ShoutData * sd)
{
vorbis_info_init(&(sd->vi)); 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;
@ -423,7 +439,7 @@ static int initEncoder(ShoutData * sd) {
} }
vorbis_analysis_init(&(sd->vd), &(sd->vi)); vorbis_analysis_init(&(sd->vd), &(sd->vi));
vorbis_block_init (&(sd->vd), &(sd->vb)); vorbis_block_init(&(sd->vd), &(sd->vb));
ogg_stream_init(&(sd->os), rand()); ogg_stream_init(&(sd->os), rand());
@ -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;
} }
@ -446,17 +462,16 @@ static int myShout_openShoutConn(AudioOutput * audioOutput) {
sd->lastAttempt = t; sd->lastAttempt = t;
if(shout_open(sd->shoutConn) != SHOUTERR_SUCCESS) { if (shout_open(sd->shoutConn) != SHOUTERR_SUCCESS) {
ERROR("problem opening connection to shout server %s:%i " ERROR("problem opening connection to shout server %s:%i "
"(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;
} }
if(initEncoder(sd) < 0) { if (initEncoder(sd) < 0) {
shout_close(sd->shoutConn); shout_close(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,9 +491,8 @@ 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,14 +503,16 @@ 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;
return -1; return -1;
} }
@ -503,76 +520,80 @@ 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;
} }
} }
/*if(sd->tag) freeMpdTag(sd->tag); /*if(sd->tag) freeMpdTag(sd->tag);
sd->tag = NULL;*/ sd->tag = NULL; */
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; {
ShoutData * sd = (ShoutData *)audioOutput->data; int i, j;
float ** vorbbuf; ShoutData *sd = (ShoutData *) audioOutput->data;
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) {
return -1; return -1;
} }
} }
samples = size/(bytes*sd->audioFormat->channels); samples = size / (bytes * sd->audioFormat->channels);
/* this is for only 16-bit audio */ /* this is for only 16-bit audio */
vorbbuf = vorbis_analysis_buffer(&(sd->vd), samples); vorbbuf = vorbis_analysis_buffer(&(sd->vd), samples);
for(i=0; i<samples; i++) { for (i = 0; i < samples; i++) {
for(j=0; j<sd->audioFormat->channels; j++) { for (j = 0; j < sd->audioFormat->channels; j++) {
vorbbuf[j][i] = (*((mpd_sint16 *)playChunk)) / 32768.0; vorbbuf[j][i] = (*((mpd_sint16 *) playChunk)) / 32768.0;
playChunk += bytes; playChunk += bytes;
} }
} }
vorbis_analysis_wrote(&(sd->vd), samples); vorbis_analysis_wrote(&(sd->vd), samples);
while(1 == vorbis_analysis_blockout(&(sd->vd), &(sd->vb))) { while (1 == vorbis_analysis_blockout(&(sd->vd), &(sd->vb))) {
vorbis_analysis(&(sd->vb), NULL); vorbis_analysis(&(sd->vb), NULL);
vorbis_bitrate_addblock(&(sd->vb)); vorbis_bitrate_addblock(&(sd->vb));
while(vorbis_bitrate_flushpacket(&(sd->vd), &(sd->op))) { while (vorbis_bitrate_flushpacket(&(sd->vd), &(sd->op))) {
ogg_stream_packetin(&(sd->os), &(sd->op)); ogg_stream_packetin(&(sd->os), &(sd->op));
} }
} }
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);
return -1; return -1;
} }
@ -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,79 +22,74 @@
#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;
int curr; int curr;
int * beginArray; int *beginArray;
char * buffer = strdup(origBuffer); char *buffer = strdup(origBuffer);
int bufferLength = strlen(buffer); int bufferLength = strlen(buffer);
char * markArray = malloc(sizeof(char)*(bufferLength+1)); char *markArray = malloc(sizeof(char) * (bufferLength + 1));
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') {
if(curr>0) { if (curr > 0) {
if(markArray[curr-1]=='0') { if (markArray[curr - 1] == '0') {
count++; count++;
} }
} } else {
else {
count++; count++;
} }
} }
} }
markArray[bufferLength] = '\0'; markArray[bufferLength] = '\0';
if(!count) { if (!count) {
free(buffer); free(buffer);
free(markArray); free(markArray);
return count; return count;
} }
beginArray = malloc(sizeof(int)*count); beginArray = malloc(sizeof(int) * count);
(*array) = malloc(sizeof(char *)*count); (*array) = malloc(sizeof(char *) * count);
count = 0; count = 0;
for(curr=0;curr<bufferLength;curr++) { for (curr = 0; curr < bufferLength; curr++) {
if(markArray[curr]=='1') { if (markArray[curr] == '1') {
if(curr>0) { if (curr > 0) {
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';
} }
} }
for(i=0;i<count;i++) { for (i = 0; i < count; i++) {
int len = strlen(buffer+beginArray[i])+1; int len = strlen(buffer + beginArray[i]) + 1;
int arrayCurr = 0; int arrayCurr = 0;
(*array)[i] = malloc(sizeof(char)*len); (*array)[i] = malloc(sizeof(char) * len);
for(curr=beginArray[i];buffer[curr]!='\0';curr++) { for (curr = beginArray[i]; buffer[curr] != '\0'; curr++) {
if(buffer[curr]=='\\') { if (buffer[curr] == '\\') {
if(buffer[curr+1]!='\0') { if (buffer[curr + 1] != '\0') {
curr++; curr++;
} }
} }
@ -110,12 +105,14 @@ 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]);
} }
free(array); free(array);

View File

@ -21,8 +21,8 @@
#include "../config.h" #include "../config.h"
int buffer2array(char * buffer, char *** array); int buffer2array(char *buffer, char ***array);
void freeArgArray(char ** array, int argArrayLength); void freeArgArray(char **array, int argArrayLength);
#endif #endif

View File

@ -29,8 +29,8 @@
iconv_t char_conv_iconv; iconv_t char_conv_iconv;
#endif #endif
char * char_conv_to = NULL; char *char_conv_to = NULL;
char * char_conv_from = NULL; char *char_conv_from = NULL;
mpd_sint8 char_conv_same = 0; mpd_sint8 char_conv_same = 0;
mpd_sint8 char_conv_use_iconv = 0; mpd_sint8 char_conv_use_iconv = 0;
@ -43,37 +43,37 @@ 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 && {
strcmp(to,char_conv_to)==0 && strcmp(from,char_conv_from)==0) if (char_conv_to && char_conv_from &&
strcmp(to, char_conv_to) == 0 && strcmp(from, char_conv_from) == 0)
{ {
return 0; return 0;
} }
closeCharSetConversion(); closeCharSetConversion();
if(0==strcmp(to,from)) { if (0 == strcmp(to, from)) {
char_conv_same = 1; char_conv_same = 1;
char_conv_to = strdup(to); char_conv_to = strdup(to);
char_conv_from = strdup(from); char_conv_from = strdup(from);
return 0; return 0;
} }
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;
} }
if(char_conv_latin1ToUtf8!=0) { if (char_conv_latin1ToUtf8 != 0) {
char_conv_to = strdup(to); char_conv_to = strdup(to);
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,37 +85,42 @@ 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) {
char buffer[BUFFER_SIZE]; char buffer[BUFFER_SIZE];
size_t inleft = strlen(string); size_t inleft = strlen(string);
char * ret; char *ret;
size_t outleft; size_t outleft;
size_t retlen = 0; size_t retlen = 0;
size_t err; size_t err;
char * bufferPtr; char *bufferPtr;
ret = malloc(1); ret = malloc(1);
ret[0] = '\0'; ret[0] = '\0';
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;
} }
ret = realloc(ret,retlen+BUFFER_SIZE-outleft+1); ret = realloc(ret, retlen + BUFFER_SIZE - outleft + 1);
memcpy(ret+retlen,buffer,BUFFER_SIZE-outleft); memcpy(ret + retlen, buffer, BUFFER_SIZE - outleft);
retlen+=BUFFER_SIZE-outleft; retlen += BUFFER_SIZE - outleft;
ret[retlen] = '\0'; ret[retlen] = '\0';
} }
@ -123,7 +128,7 @@ char * convStrDup(char * string) {
} }
#endif #endif
switch(char_conv_latin1ToUtf8) { switch (char_conv_latin1ToUtf8) {
case 1: case 1:
return latin1StrToUtf8Dup(string); return latin1StrToUtf8Dup(string);
break; break;
@ -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

@ -21,8 +21,8 @@
#include "../config.h" #include "../config.h"
int setCharSetConversion(char * to, char * from); int setCharSetConversion(char *to, char *from);
char * convStrDup(char * string); char *convStrDup(char *string);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -32,13 +32,13 @@
#define COMMAND_RETURN_CLOSE 20 #define COMMAND_RETURN_CLOSE 20
#define COMMAND_MASTER_READY 30 #define COMMAND_MASTER_READY 30
extern char * current_command; extern char *current_command;
extern int command_listNum; extern int command_listNum;
int processListOfCommands(FILE * fp, int * permission, int * expired, int processListOfCommands(FILE * fp, int *permission, int *expired,
int listOK, List * list); int listOK, List * list);
int processCommand(FILE * fp, int * permission, char * commandString); int processCommand(FILE * fp, int *permission, char *commandString);
void initCommands(); void initCommands();

View File

@ -44,16 +44,19 @@
typedef struct _configEntry { typedef struct _configEntry {
unsigned char mask; unsigned char mask;
List * configParamList; List *configParamList;
} ConfigEntry; } 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,46 +66,55 @@ 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) {
free(param->blockParams[i].name); free(param->blockParams[i].name);
} }
if(param->blockParams[i].value) { if (param->blockParams[i].value) {
free(param->blockParams[i].value); free(param->blockParams[i].value);
} }
} }
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)) {
ERROR("config parameter \"%s\" already registered\n", name); ERROR("config parameter \"%s\" already registered\n", name);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -112,12 +124,14 @@ 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); */
registerConfigParam(CONF_PORT, 0, 0); registerConfigParam(CONF_PORT, 0, 0);
@ -159,61 +173,63 @@ void initConf(void) {
registerConfigParam(CONF_ID3V1_ENCODING, 0, 0); registerConfigParam(CONF_ID3V1_ENCODING, 0, 0);
} }
static void addBlockParam(ConfigParam * param, char * name, char * value, static void addBlockParam(ConfigParam * param, char *name, char *value,
int line) int line)
{ {
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 =
param->blockParams[param->numberOfBlockParams-1].line = line; strdup(value);
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;
int i; int i;
int numberOfArgs; int numberOfArgs;
int argsMinusComment; int argsMinusComment;
while(myFgets(string, MAX_STRING_SIZE ,fp)) { while (myFgets(string, MAX_STRING_SIZE, fp)) {
(*count)++; (*count)++;
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;
if(0 == argsMinusComment) { if (0 == argsMinusComment) {
freeArgArray(array, numberOfArgs); freeArgArray(array, numberOfArgs);
continue; continue;
} }
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;
} }
if(2 != argsMinusComment) { if (2 != argsMinusComment) {
ERROR("improperly formatted config file at line %i:" ERROR("improperly formatted config file at line %i:"
" %s\n", *count, string); " %s\n", *count, string);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
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,47 +244,49 @@ static ConfigParam * readConfigBlock(FILE * fp, int * count, char * string) {
return ret; return ret;
} }
void readConf(char * file) { void readConf(char *file)
FILE * fp; {
char string[MAX_STRING_SIZE+1]; FILE *fp;
char ** array; char string[MAX_STRING_SIZE + 1];
char **array;
int i; int i;
int numberOfArgs; int numberOfArgs;
int argsMinusComment; int argsMinusComment;
int count = 0; int count = 0;
ConfigEntry * entry; ConfigEntry *entry;
void * voidPtr; void *voidPtr;
ConfigParam * param; ConfigParam *param;
if(!(fp=fopen(file,"r"))) { if (!(fp = fopen(file, "r"))) {
ERROR("problems opening file %s for reading: %s\n", file, ERROR("problems opening file %s for reading: %s\n", file,
strerror(errno)); strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
while(myFgets(string, MAX_STRING_SIZE, fp)) { while (myFgets(string, MAX_STRING_SIZE, fp)) {
count++; count++;
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;
if(0 == argsMinusComment) { if (0 == argsMinusComment) {
freeArgArray(array, numberOfArgs); freeArgArray(array, numberOfArgs);
continue; continue;
} }
if(2 != argsMinusComment) { if (2 != argsMinusComment) {
ERROR("improperly formatted config file at line %i:" ERROR("improperly formatted config file at line %i:"
" %s\n", count, string); " %s\n", count, string);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(!findInList(configEntriesList, array[0], &voidPtr)) { if (!findInList(configEntriesList, array[0], &voidPtr)) {
ERROR("unrecognized parameter in config file at line " ERROR("unrecognized parameter in config file at line "
"%i: %s\n", count, string); "%i: %s\n", count, string);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -276,25 +294,25 @@ 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);
} }
if(entry->mask & CONF_BLOCK_MASK) { if (entry->mask & CONF_BLOCK_MASK) {
if(0 != strcmp(array[1], CONF_BLOCK_BEGIN)) { if (0 != strcmp(array[1], CONF_BLOCK_BEGIN)) {
ERROR("improperly formatted config file at " ERROR("improperly formatted config file at "
"line %i: %s\n", count, string); "line %i: %s\n", count, string);
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,120 +321,129 @@ void readConf(char * file) {
fclose(fp); fclose(fp);
} }
ConfigParam * getNextConfigParam(char * name, ConfigParam * last) { ConfigParam *getNextConfigParam(char *name, ConfigParam * last)
void * voidPtr; {
ConfigEntry * entry; void *voidPtr;
ListNode * node; ConfigEntry *entry;
ConfigParam * param; ListNode *node;
ConfigParam *param;
if(!findInList(configEntriesList, name, &voidPtr)) return NULL; if (!findInList(configEntriesList, name, &voidPtr))
return NULL;
entry = voidPtr; entry = voidPtr;
node = entry->configParamList->firstNode; node = entry->configParamList->firstNode;
if(last) { if (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;
for(i = 0; i < param->numberOfBlockParams; i++) { for (i = 0; i < param->numberOfBlockParams; i++) {
if(0 == strcmp(name, param->blockParams[i].name)) { if (0 == strcmp(name, param->blockParams[i].name)) {
if(ret) { if (ret) {
ERROR("\"%s\" first defined on line %i, and " ERROR("\"%s\" first defined on line %i, and "
"redefined on line %i\n", name, "redefined on line %i\n", name,
ret->line, param->blockParams[i].line); ret->line, param->blockParams[i].line);
} }
ret = param->blockParams+i; ret = param->blockParams + i;
} }
} }
return ret; return ret;
} }
ConfigParam * parseConfigFilePath(char * name, int force) { ConfigParam *parseConfigFilePath(char *name, int force)
ConfigParam * param = getConfigParam(name); {
char * path; ConfigParam *param = getConfigParam(name);
char *path;
if(!param && force) { if (!param && force) {
ERROR("config parameter \"%s\" not found\n", name); ERROR("config parameter \"%s\" not found\n", name);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(!param) return NULL; if (!param)
return NULL;
path = param->value; path = param->value;
if(path[0] != '/' && path[0] != '~') { if (path[0] != '/' && path[0] != '~') {
ERROR("\"%s\" is not an absolute path at line %i\n", ERROR("\"%s\" is not an absolute path at line %i\n",
param->value, param->line); param->value, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* Parse ~ in path */ /* Parse ~ in path */
else if(path[0] == '~') { else if (path[0] == '~') {
struct passwd * pwd = NULL; struct passwd *pwd = NULL;
char * newPath; char *newPath;
int pos = 1; int pos = 1;
if(path[1]=='/' || path[1] == '\0') { if (path[1] == '/' || path[1] == '\0') {
ConfigParam * userParam = getConfigParam(CONF_USER); ConfigParam *userParam = getConfigParam(CONF_USER);
if(userParam) { if (userParam) {
pwd = getpwnam(userParam->value); pwd = getpwnam(userParam->value);
if(!pwd) { if (!pwd) {
ERROR("no such user %s at line %i\n", ERROR("no such user %s at line %i\n",
userParam->value, userParam->value,
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 "
"for current user\n"); "for current user\n");
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 == '/')
* ch = '\0'; foundSlash = 1;
pos+= ch-path-1; *ch = '\0';
if((pwd = getpwnam(path+1)) == NULL) { pos += ch - path - 1;
if ((pwd = getpwnam(path + 1)) == NULL) {
ERROR("user \"%s\" not found at line %i\n", ERROR("user \"%s\" not found at line %i\n",
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);
strcat(newPath, path+pos); strcat(newPath, path + pos);
free(param->value); free(param->value);
param->value = newPath; param->value = newPath;
} }

View File

@ -60,33 +60,33 @@
#define CONF_ID3V1_ENCODING "id3v1_encoding" #define CONF_ID3V1_ENCODING "id3v1_encoding"
typedef struct _BlockParam { typedef struct _BlockParam {
char * name; char *name;
char * value; char *value;
int line; int line;
} BlockParam; } BlockParam;
typedef struct _ConfigParam { typedef struct _ConfigParam {
char * value; char *value;
unsigned int line; unsigned int line;
BlockParam * blockParams; BlockParam *blockParams;
int numberOfBlockParams; int numberOfBlockParams;
} ConfigParam; } ConfigParam;
void initConf(); void initConf();
void finishConf(); void finishConf();
void readConf(char * file); void readConf(char *file);
/* don't free the returned value /* don't free the returned value
set _last_ to NULL to get first entry */ set _last_ to NULL to get first entry */
ConfigParam * getNextConfigParam(char * name, ConfigParam * last); ConfigParam *getNextConfigParam(char *name, ConfigParam * last);
#define getConfigParam(name) getNextConfigParam(name, NULL) #define getConfigParam(name) getNextConfigParam(name, NULL)
char * getConfigParamValue(char * name); char *getConfigParamValue(char *name);
BlockParam * getBlockParam(ConfigParam * param, char * name); BlockParam *getBlockParam(ConfigParam * param, char *name);
ConfigParam * parseConfigFilePath(char * name, int force); ConfigParam *parseConfigFilePath(char *name, int force);
#endif #endif

View File

@ -31,52 +31,54 @@
#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;
LocateTagItem * conditionals; LocateTagItem *conditionals;
} ListCommandItem; } ListCommandItem;
typedef struct _LocateTagItemArray { typedef struct _LocateTagItemArray {
int numItems; int numItems;
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)) {
return LOCATE_TAG_FILE_TYPE; return LOCATE_TAG_FILE_TYPE;
} }
if(0 == strcasecmp(str, LOCATE_TAG_ANY_KEY)) { if (0 == strcasecmp(str, LOCATE_TAG_ANY_KEY)) {
return LOCATE_TAG_ANY_TYPE; return LOCATE_TAG_ANY_TYPE;
} }
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) {
free(ret); free(ret);
ret = NULL; ret = NULL;
} }
@ -84,36 +86,40 @@ 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;
} }
return numArgs/2; return numArgs / 2;
fail: fail:
for(j = 0; j < i; j++) { for (j = 0; j < i; j++) {
free((*arrayRet)[j].needle); free((*arrayRet)[j].needle);
} }
@ -122,70 +128,78 @@ 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;
return 0; return 0;
} }
static int printDirectoryInDirectory(FILE * fp, Directory * directory, void * data) { static int printDirectoryInDirectory(FILE * fp, Directory * directory,
if(directory->path) { void *data)
myfprintf(fp,"directory: %s\n", getDirectoryPath(directory)); {
if (directory->path) {
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,16 +209,15 @@ 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;
char ** originalNeedles = malloc(numItems*sizeof(char *)); char **originalNeedles = malloc(numItems * sizeof(char *));
LocateTagItemArray array; LocateTagItemArray array;
for(i = 0; i < numItems; i++) { for (i = 0; i < numItems; i++) {
originalNeedles[i] = items[i].needle; originalNeedles[i] = items[i].needle;
items[i].needle = strDupToUpper(originalNeedles[i]); items[i].needle = strDupToUpper(originalNeedles[i]);
} }
@ -212,9 +225,9 @@ int searchForSongsIn(FILE * fp, char * name, int numItems,
array.numItems = numItems; array.numItems = numItems;
array.items = items; array.items = items;
ret = traverseAllIn(fp,name,searchInDirectory, NULL, &array); ret = traverseAllIn(fp, name, searchInDirectory, NULL, &array);
for(i = 0; i < numItems; i++) { for (i = 0; i < numItems; i++) {
free(items[i].needle); free(items[i].needle);
items[i].needle = originalNeedles[i]; items[i].needle = originalNeedles[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,67 +277,77 @@ 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, {
printDirectoryInDirectory,NULL); return traverseAllIn(fp, name, printSongInDirectory,
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;
traverseAllIn(fp,name,NULL,countSongsInDirectory,ptr); traverseAllIn(fp, name, NULL, countSongsInDirectory, ptr);
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;
traverseAllIn(fp,name,sumSongTime,NULL,ptr); traverseAllIn(fp, name, sumSongTime, NULL, ptr);
return dbPlayTime; return dbPlayTime;
} }
static ListCommandItem * newListCommandItem(int tagType, int numConditionals, static ListCommandItem *newListCommandItem(int tagType, int numConditionals,
LocateTagItem * conditionals) LocateTagItem * conditionals)
{ {
ListCommandItem * item = malloc(sizeof(ListCommandItem)); ListCommandItem *item = malloc(sizeof(ListCommandItem));
item->tagType = tagType; item->tagType = tagType;
item->numConditionals = numConditionals; item->numConditionals = numConditionals;
@ -328,36 +356,39 @@ 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;
if(tagType == LOCATE_TAG_FILE_TYPE) { if (tagType == LOCATE_TAG_FILE_TYPE) {
printSongUrl(fp, song); printSongUrl(fp, song);
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) {
visitInTagTracker(tagType, tag->items[i].value); visitInTagTracker(tagType, tag->items[i].value);
} }
} }
} }
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;
} }
} }
@ -371,17 +402,17 @@ int listAllUniqueTags(FILE * fp, int type, int numConditionals,
LocateTagItem * conditionals) LocateTagItem * conditionals)
{ {
int ret; int ret;
ListCommandItem * item = newListCommandItem(type, numConditionals, ListCommandItem *item = newListCommandItem(type, numConditionals,
conditionals); conditionals);
if(type >= 0 && type <= TAG_NUM_OF_ITEM_TYPES) { if (type >= 0 && type <= TAG_NUM_OF_ITEM_TYPES) {
resetVisitedFlagsInTagTracker(type); resetVisitedFlagsInTagTracker(type);
} }
ret = traverseAllIn(fp, NULL, listUniqueTagsInDirectory, NULL, ret = traverseAllIn(fp, NULL, listUniqueTagsInDirectory, NULL,
(void *)item); (void *)item);
if(type >= 0 && type <= TAG_NUM_OF_ITEM_TYPES) { if (type >= 0 && type <= TAG_NUM_OF_ITEM_TYPES) {
printVisitedInTagTracker(fp, type); printVisitedInTagTracker(fp, type);
} }
@ -390,26 +421,31 @@ 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,
int * sum = data; void *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;
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;
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

@ -27,38 +27,36 @@
typedef struct _LocateTagItem { typedef struct _LocateTagItem {
mpd_sint8 tagType; mpd_sint8 tagType;
/* what we are looking for */ /* what we are looking for */
char * needle; char *needle;
} LocateTagItem; } LocateTagItem;
int getLocateTagItemType(char * str); int getLocateTagItemType(char *str);
/* returns NULL if not a known type */ /* returns NULL if not a known type */
LocateTagItem * newLocateTagItem(char * typeString, char * needle); LocateTagItem *newLocateTagItem(char *typeString, char *needle);
/* return number of items or -1 on error */ /* return number of items or -1 on error */
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);
int printAllIn(FILE * fp, char * name); int printAllIn(FILE * fp, char *name);
int addAllIn(FILE * fp, char * name); int addAllIn(FILE * fp, char *name);
int printInfoForAllIn(FILE * fp, char * name); 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);
unsigned long sumSongTimesIn(FILE * fp, char * name); unsigned long sumSongTimesIn(FILE * fp, char *name);
int listAllUniqueTags(FILE * fp, int type, int numConditiionals, int listAllUniqueTags(FILE * fp, int type, int numConditiionals,
LocateTagItem * conditionals); LocateTagItem * conditionals);

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;
@ -80,22 +82,25 @@ static void quitDecode(PlayerControl * pc, DecoderControl * dc) {
pc->play = 0; pc->play = 0;
pc->stop = 0; pc->stop = 0;
pc->pause = 0; pc->pause = 0;
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);
if(chunks>(buffered_chunks-buffered_before_play)) { if (chunks > (buffered_chunks - buffered_before_play)) {
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,24 +141,25 @@ 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);
pc->erroredUrl[MAXPATHLEN] = '\0'; pc->erroredUrl[MAXPATHLEN] = '\0';
pc->error = PLAYER_ERROR_FILE; pc->error = PLAYER_ERROR_FILE;
quitDecode(pc,dc); quitDecode(pc, dc);
return -1; return -1;
} }
if((tag = metadataChunkToMpdTagDup(&(pc->fileMetadataChunk)))) { if ((tag = metadataChunkToMpdTagDup(&(pc->fileMetadataChunk)))) {
sendMetadataToAudioDevice(tag); sendMetadataToAudioDevice(tag);
freeMpdTag(tag); freeMpdTag(tag);
} }
@ -168,35 +174,33 @@ 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;
cb->end = 0; cb->end = 0;
dc->error = 0; dc->error = 0;
dc->start = 1; dc->start = 1;
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)
if(!dc->seekError) { my_usleep(10000);
if (!dc->seekError) {
pc->elapsedTime = dc->seekWhere; pc->elapsedTime = dc->seekWhere;
ret = 0; ret = 0;
} }
@ -256,23 +260,24 @@ 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;
char * path; char *path;
char * relativePath; char *relativePath;
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);
} }
if(!path) { if (!path) {
dc->error = DECODE_ERROR_FILE; dc->error = DECODE_ERROR_FILE;
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->start = 0; dc->start = 0;
@ -284,7 +289,7 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl *
strncpy(dc->utf8url, pc->utf8url, MAXPATHLEN); strncpy(dc->utf8url, pc->utf8url, MAXPATHLEN);
dc->utf8url[MAXPATHLEN] = '\0'; dc->utf8url[MAXPATHLEN] = '\0';
if(openInputStream(&inStream, path) < 0) { if (openInputStream(&inStream, path) < 0) {
dc->error = DECODE_ERROR_FILE; dc->error = DECODE_ERROR_FILE;
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->start = 0; dc->start = 0;
@ -296,14 +301,13 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl *
dc->state = DECODE_STATE_START; dc->state = DECODE_STATE_START;
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);
} }
if(dc->stop) { if (dc->stop) {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
free(path); free(path);
@ -315,88 +319,87 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl *
tag->name = strdup(inStream.metaName); tag->name = strdup(inStream.metaName);
copyMpdTagToOutputBuffer(cb, tag); copyMpdTagToOutputBuffer(cb, tag);
freeMpdTag(tag); freeMpdTag(tag);
}*/ } */
/* reset Metadata in OutputBuffer */ /* reset Metadata in OutputBuffer */
ret = DECODE_ERROR_UNKTYPE; ret = DECODE_ERROR_UNKTYPE;
if(isRemoteUrl(dc->utf8url)) { if (isRemoteUrl(dc->utf8url)) {
unsigned int next = 0; unsigned int next = 0;
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;
} }
/* if that fails, try suffix matching the URL: */ /* if that fails, try suffix matching the URL: */
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;
} }
} }
/* fallback to mp3: */ /* fallback to mp3: */
/* this is needed for bastard streams that don't have a suffix /* this is needed for bastard streams that don't have a suffix
or set the mimeType */ or set the mimeType */
if(plugin == NULL) { if (plugin == NULL) {
/* we already know our mp3Plugin supports streams, no /* we already know our mp3Plugin supports streams, no
* need to check for stream{Types,DecodeFunc} */ * need to check for stream{Types,DecodeFunc} */
if ((plugin = getInputPluginFromName("mp3"))) if ((plugin = getInputPluginFromName("mp3")))
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);
} }
} }
} }
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,32 +411,33 @@ 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();
if(decode_pid==0) { if (decode_pid == 0) {
/* CHILD */ /* CHILD */
unblockSignals(); unblockSignals();
while(1) { while (1) {
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';
@ -447,17 +451,17 @@ static int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * d
return 0; return 0;
} }
static void handleMetadata(OutputBuffer * cb, PlayerControl * pc, int * previous, static void handleMetadata(OutputBuffer * cb, PlayerControl * pc, int *previous,
int * currentChunkSent, MetadataChunk * currentChunk) int *currentChunkSent, MetadataChunk * currentChunk)
{ {
if(cb->begin!=cb->end) { if (cb->begin != cb->end) {
int meta = cb->metaChunk[cb->begin]; int meta = cb->metaChunk[cb->begin];
if( meta != *previous ) { if (meta != *previous) {
DEBUG("player: metadata change\n"); DEBUG("player: metadata change\n");
if( meta >= 0 && cb->metaChunkSet[meta]) { if (meta >= 0 && cb->metaChunkSet[meta]) {
DEBUG("player: new metadata from decoder!\n"); DEBUG("player: new metadata from decoder!\n");
memcpy(currentChunk, memcpy(currentChunk,
cb->metadataChunks+meta, cb->metadataChunks + meta,
sizeof(MetadataChunk)); sizeof(MetadataChunk));
*currentChunkSent = 0; *currentChunkSent = 0;
cb->metaChunkSet[meta] = 0; cb->metaChunkSet[meta] = 0;
@ -465,14 +469,13 @@ 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;
if((tag = metadataChunkToMpdTagDup(currentChunk))) { if ((tag = metadataChunkToMpdTagDup(currentChunk))) {
sendMetadataToAudioDevice(tag); sendMetadataToAudioDevice(tag);
freeMpdTag(tag); freeMpdTag(tag);
} }
@ -485,20 +488,21 @@ 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,
currentChunk); currentChunk);
cb->begin++; cb->begin++;
if(cb->begin>=buffered_chunks) { if (cb->begin >= buffered_chunks) {
cb->begin = 0; cb->begin = 0;
} }
} }
} }
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;
@ -516,133 +520,125 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
int end; int end;
int next = -1; int next = -1;
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;
pc->play = 0; pc->play = 0;
kill(getppid(),SIGUSR1); kill(getppid(), SIGUSR1);
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);
} }
while(!quit) { while (!quit) {
processDecodeInput(); processDecodeInput();
handleDecodeStart(); handleDecodeStart();
handleMetadata(cb, pc, &previousMetadataChunk, handleMetadata(cb, pc, &previousMetadataChunk,
&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)
else if(cb->begin!=end && cb->begin!=next) { my_usleep(10000);
if(doCrossFade==1 && next>=0 && else if (cb->begin != end && cb->begin != next) {
((next>cb->begin && if (doCrossFade == 1 && next >= 0 &&
(fadePosition=next-cb->begin) ((next > cb->begin &&
<=crossFadeChunks) || (fadePosition = next - cb->begin)
(cb->begin>next && <= crossFadeChunks) ||
(fadePosition=next-cb->begin+ (cb->begin > next &&
buffered_chunks)<=crossFadeChunks))) (fadePosition = next - cb->begin +
{ 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)
nextChunk = cb->begin+crossFadeChunks; test += buffered_chunks;
if(nextChunk<test) { nextChunk = cb->begin + crossFadeChunks;
if(nextChunk>=buffered_chunks) if (nextChunk < test) {
{ 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];
pc->bitRate = cb->bitRate[cb->begin]; pc->bitRate = cb->bitRate[cb->begin];
pcm_volumeChange(cb->chunks+cb->begin* pcm_volumeChange(cb->chunks + cb->begin *
CHUNK_SIZE, CHUNK_SIZE,
cb->chunkSize[cb->begin], cb->chunkSize[cb->begin],
&(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 +=
if( cb->begin+1 >= buffered_chunks ) { sizeToTime * cb->chunkSize[cb->begin];
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)
if(nextChunk<test) { test += buffered_chunks;
if(nextChunk>=buffered_chunks) if (nextChunk < test) {
{ if (nextChunk >= buffered_chunks) {
nextChunk -= buffered_chunks; nextChunk -= buffered_chunks;
} }
advanceOutputBufferTo(cb, pc, advanceOutputBufferTo(cb, pc,
@ -652,44 +648,41 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
nextChunk); nextChunk);
} }
} }
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);
return; return;
} }
my_usleep(10000); my_usleep(10000);
} }
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;
doCrossFade = 0; doCrossFade = 0;
crossFadeChunks = 0; crossFadeChunks = 0;
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;
} }
} }
quitDecode(pc,dc); quitDecode(pc, dc);
} }
/* decode w/ buffering /* decode w/ buffering
@ -697,10 +690,11 @@ 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; {
PlayerControl * pc; OutputBuffer *cb;
DecoderControl * dc; PlayerControl *pc;
DecoderControl *dc;
cb = &(getPlayerData()->buffer); cb = &(getPlayerData()->buffer);
@ -714,8 +708,9 @@ void decode() {
dc->stop = 0; dc->stop = 0;
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);

View File

@ -58,11 +58,11 @@ typedef struct _DecoderControl {
volatile mpd_sint8 cycleLogFiles; volatile mpd_sint8 cycleLogFiles;
volatile double seekWhere; volatile double seekWhere;
AudioFormat audioFormat; AudioFormat audioFormat;
char utf8url[MAXPATHLEN+1]; char utf8url[MAXPATHLEN + 1];
volatile float totalTime; volatile float totalTime;
} DecoderControl; } DecoderControl;
void decodeSigHandler(int sig, siginfo_t * siginfo, void * v); void decodeSigHandler(int sig, siginfo_t * siginfo, void *v);
void decode(); void decode();

File diff suppressed because it is too large Load Diff

View File

@ -32,11 +32,11 @@ typedef struct _DirectoryStat {
} DirectoryStat; } DirectoryStat;
typedef struct _Directory { typedef struct _Directory {
char * path; char *path;
DirectoryList * subDirectories; DirectoryList *subDirectories;
SongList * songs; SongList *songs;
struct _Directory * parent; struct _Directory *parent;
DirectoryStat * stat; DirectoryStat *stat;
} Directory; } Directory;
void readDirectoryDBIfUpdateIsFinished(); void readDirectoryDBIfUpdateIsFinished();
@ -51,7 +51,7 @@ void initMp3Directory();
void closeMp3Directory(); void closeMp3Directory();
int printDirectoryInfo(FILE * fp, char * dirname); int printDirectoryInfo(FILE * fp, char *dirname);
int checkDirectoryDB(); int checkDirectoryDB();
@ -61,14 +61,13 @@ int readDirectoryDB();
void updateMp3Directory(); void updateMp3Directory();
Song * getSongFromDB(char * file); Song *getSongFromDB(char *file);
time_t getDbModTime(); 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

@ -24,47 +24,59 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
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) { {
if(strcasecmp(*array, suffix) == 0) return 1; while (array && *array) {
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; {
ListNode * node; static ListNode *pos = NULL;
InputPlugin * plugin; ListNode *node;
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;
while(node != NULL) { while (node != NULL) {
plugin = node->data; plugin = node->data;
if(stringFoundInStringArray(plugin->suffixes, suffix)) { if (stringFoundInStringArray(plugin->suffixes, suffix)) {
pos = node->nextNode; pos = node->nextNode;
return plugin; return plugin;
} }
@ -74,18 +86,20 @@ 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; {
ListNode * node; static ListNode *pos = NULL;
InputPlugin * plugin; ListNode *node;
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;
while(node != NULL) { while (node != NULL) {
plugin = node->data; plugin = node->data;
if(stringFoundInStringArray(plugin->mimeTypes, mimeType)) { if (stringFoundInStringArray(plugin->mimeTypes, mimeType)) {
pos = node->nextNode; pos = node->nextNode;
return plugin; return plugin;
} }
@ -95,23 +109,25 @@ 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);
return (InputPlugin *)plugin; return (InputPlugin *) plugin;
} }
void printAllInputPluginSuffixes(FILE * fp) { void printAllInputPluginSuffixes(FILE * fp)
ListNode * node = inputPlugin_list->firstNode; {
InputPlugin * plugin; ListNode *node = inputPlugin_list->firstNode;
char ** suffixes; InputPlugin *plugin;
char **suffixes;
while(node) { while (node) {
plugin = (InputPlugin *)node->data; plugin = (InputPlugin *) node->data;
suffixes = plugin->suffixes; suffixes = plugin->suffixes;
while(suffixes && *suffixes) { while (suffixes && *suffixes) {
myfprintf(fp, "%s ", *suffixes); myfprintf(fp, "%s ", *suffixes);
suffixes++; 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

@ -31,20 +31,20 @@
/* optional, set this to NULL if the InputPlugin doesn't have/need one /* optional, set this to NULL if the InputPlugin doesn't have/need one
* this must return < 0 if there is an error and >= 0 otherwise */ * this must return < 0 if there is an error and >= 0 otherwise */
typedef int (* InputPlugin_initFunc) (); typedef int (*InputPlugin_initFunc) ();
/* optional, set this to NULL if the InputPlugin doesn't have/need one */ /* optional, set this to NULL if the InputPlugin doesn't have/need one */
typedef void (* InputPlugin_finishFunc) (); typedef void (*InputPlugin_finishFunc) ();
/* boolean return value, returns 1 if the InputStream is decodable by /* boolean return value, returns 1 if the InputStream is decodable by
* the InputPlugin, 0 if not */ * the InputPlugin, 0 if not */
typedef unsigned int (* InputPlugin_tryDecodeFunc) (InputStream *); typedef unsigned int (*InputPlugin_tryDecodeFunc) (InputStream *);
/* this will be used to decode InputStreams, and is recommended for files /* this will be used to decode InputStreams, and is recommended for files
* and networked (HTTP) connections. * and networked (HTTP) connections.
* *
* returns -1 on error, 0 on success */ * returns -1 on error, 0 on success */
typedef int (* InputPlugin_streamDecodeFunc) (OutputBuffer *, DecoderControl *, typedef int (*InputPlugin_streamDecodeFunc) (OutputBuffer *, DecoderControl *,
InputStream *); InputStream *);
/* use this if and only if your InputPlugin can only be passed a filename or /* use this if and only if your InputPlugin can only be passed a filename or
@ -52,15 +52,15 @@ typedef int (* InputPlugin_streamDecodeFunc) (OutputBuffer *, DecoderControl *,
* and FLAC libraries allow) * and FLAC libraries allow)
* *
* returns -1 on error, 0 on success */ * returns -1 on error, 0 on success */
typedef int (* InputPlugin_fileDecodeFunc) (OutputBuffer *, DecoderControl *, typedef int (*InputPlugin_fileDecodeFunc) (OutputBuffer *, DecoderControl *,
char * path); char *path);
/* file should be the full path! Returns NULL if a tag cannot be found /* file should be the full path! Returns NULL if a tag cannot be found
* or read */ * or read */
typedef MpdTag * (* InputPlugin_tagDupFunc) (char * file); typedef MpdTag *(*InputPlugin_tagDupFunc) (char *file);
typedef struct _InputPlugin { typedef struct _InputPlugin {
char * name; char *name;
InputPlugin_initFunc initFunc; InputPlugin_initFunc initFunc;
InputPlugin_finishFunc finishFunc; InputPlugin_finishFunc finishFunc;
InputPlugin_tryDecodeFunc tryDecodeFunc; InputPlugin_tryDecodeFunc tryDecodeFunc;
@ -72,8 +72,8 @@ typedef struct _InputPlugin {
unsigned char streamTypes; unsigned char streamTypes;
/* last element in these arrays must always be a NULL: */ /* last element in these arrays must always be a NULL: */
char ** suffixes; char **suffixes;
char ** mimeTypes; char **mimeTypes;
} InputPlugin; } InputPlugin;
/* individual functions to load/unload plugins */ /* individual functions to load/unload plugins */
@ -82,11 +82,11 @@ void unloadInputPlugin(InputPlugin * inputPlugin);
/* interface for using plugins */ /* interface for using plugins */
InputPlugin * getInputPluginFromSuffix(char * suffix, unsigned int next); InputPlugin *getInputPluginFromSuffix(char *suffix, unsigned int next);
InputPlugin * getInputPluginFromMimeType(char * mimeType, unsigned int next); InputPlugin *getInputPluginFromMimeType(char *mimeType, unsigned int next);
InputPlugin * getInputPluginFromName(char * name); InputPlugin *getInputPluginFromName(char *name);
void printAllInputPluginSuffixes(FILE * fp); void printAllInputPluginSuffixes(FILE * fp);

View File

@ -38,7 +38,7 @@
#include <FLAC/format.h> #include <FLAC/format.h>
#include <FLAC/metadata.h> #include <FLAC/metadata.h>
void init_FlacData (FlacData * data, OutputBuffer * cb, void init_FlacData(FlacData * data, OutputBuffer * cb,
DecoderControl * dc, InputStream * inStream) DecoderControl * dc, InputStream * inStream)
{ {
data->chunk_length = 0; data->chunk_length = 0;
@ -53,18 +53,18 @@ 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 '=' */
int len = block->data.vorbis_comment.comments[offset].length int len = block->data.vorbis_comment.comments[offset].length
-pos; - pos;
if(len > 0) { if (len > 0) {
unsigned char tmp; unsigned char tmp;
unsigned char * dup = &(block->data.vorbis_comment. unsigned char *dup = &(block->data.vorbis_comment.
comments[offset].entry[pos]); comments[offset].entry[pos]);
tmp = dup[len]; tmp = dup[len];
dup[len] = '\0'; dup[len] = '\0';
@ -79,8 +79,9 @@ 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)
@ -88,13 +89,13 @@ static void flacParseReplayGain(const FLAC__StreamMetadata *block,
data->replayGainInfo = newReplayGainInfo(); data->replayGainInfo = newReplayGainInfo();
found &= flacFindVorbisCommentFloat(block,"replaygain_album_gain", found &= flacFindVorbisCommentFloat(block, "replaygain_album_gain",
&data->replayGainInfo->albumGain); &data->replayGainInfo->albumGain);
found &= flacFindVorbisCommentFloat(block,"replaygain_album_peak", found &= flacFindVorbisCommentFloat(block, "replaygain_album_peak",
&data->replayGainInfo->albumPeak); &data->replayGainInfo->albumPeak);
found &= flacFindVorbisCommentFloat(block,"replaygain_track_gain", found &= flacFindVorbisCommentFloat(block, "replaygain_track_gain",
&data->replayGainInfo->trackGain); &data->replayGainInfo->trackGain);
found &= flacFindVorbisCommentFloat(block,"replaygain_track_peak", found &= flacFindVorbisCommentFloat(block, "replaygain_track_peak",
&data->replayGainInfo->trackPeak); &data->replayGainInfo->trackPeak);
if (!found) { if (!found) {
@ -105,33 +106,38 @@ static void flacParseReplayGain(const FLAC__StreamMetadata *block,
/* tracknumber is used in VCs, MPD uses "track" ..., all the other /* tracknumber is used in VCs, MPD uses "track" ..., all the other
* tag names match */ * tag names match */
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;
size_t slen; size_t slen;
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;
if ((vlen > 0) && (0 == strncasecmp(str,(char *)entry->entry, slen)) if ((vlen > 0) && (0 == strncasecmp(str, (char *)entry->entry, slen))
&& (*(entry->entry + slen) == '=')) { && (*(entry->entry + slen) == '=')) {
if (!*tag) if (!*tag)
*tag = newMpdTag(); *tag = newMpdTag();
addItemToMpdTagWithLen(*tag, itemType, addItemToMpdTagWithLen(*tag, itemType,
(char *)(entry->entry+slen + 1), vlen); (char *)(entry->entry + slen + 1), vlen);
return 1; return 1;
} }
@ -139,7 +145,7 @@ static unsigned int commentMatchesAddToTag(
return 0; return 0;
} }
MpdTag * copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block, MpdTag *copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
MpdTag * tag) MpdTag * tag)
{ {
unsigned int i, j; unsigned int i, j;
@ -148,7 +154,7 @@ MpdTag * copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
comments = block->data.vorbis_comment.comments; comments = block->data.vorbis_comment.comments;
for (i = block->data.vorbis_comment.num_comments; i != 0; --i) { for (i = block->data.vorbis_comment.num_comments; i != 0; --i) {
for (j = TAG_NUM_OF_ITEM_TYPES; j--; ) { for (j = TAG_NUM_OF_ITEM_TYPES; j--;) {
if (commentMatchesAddToTag(comments, j, &tag)) if (commentMatchesAddToTag(comments, j, &tag))
break; break;
} }
@ -158,12 +164,13 @@ 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);
switch(block->type) { switch (block->type) {
case FLAC__METADATA_TYPE_STREAMINFO: case FLAC__METADATA_TYPE_STREAMINFO:
dc->audioFormat.bits = si->bits_per_sample; dc->audioFormat.bits = si->bits_per_sample;
dc->audioFormat.sampleRate = si->sample_rate; dc->audioFormat.sampleRate = si->sample_rate;
@ -173,19 +180,20 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata *block, FlacData *data)
&(data->cb->audioFormat)); &(data->cb->audioFormat));
break; break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT: case FLAC__METADATA_TYPE_VORBIS_COMMENT:
flacParseReplayGain(block,data); flacParseReplayGain(block, data);
default: default:
break; break;
} }
} }
void flac_error_common_cb( const char * plugin, 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:
ERROR("%s lost sync\n", plugin); ERROR("%s lost sync\n", plugin);
break; break;
@ -196,7 +204,7 @@ void flac_error_common_cb( const char * plugin,
ERROR("%s crc mismatch\n", plugin); ERROR("%s crc mismatch\n", plugin);
break; break;
default: default:
ERROR("unknown %s error\n",plugin); ERROR("unknown %s error\n", plugin);
} }
} }

View File

@ -41,38 +41,38 @@ typedef struct {
float time; float time;
int bitRate; int bitRate;
FLAC__uint64 position; FLAC__uint64 position;
OutputBuffer * cb; OutputBuffer *cb;
DecoderControl * dc; DecoderControl *dc;
InputStream * inStream; InputStream *inStream;
ReplayGainInfo * replayGainInfo; ReplayGainInfo *replayGainInfo;
MpdTag * tag; MpdTag *tag;
} FlacData; } FlacData;
/* initializes a given FlacData struct */ /* initializes a given FlacData struct */
void init_FlacData (FlacData * data, OutputBuffer * cb, void init_FlacData(FlacData * data, OutputBuffer * cb,
DecoderControl * dc, InputStream * inStream); DecoderControl * dc, InputStream * inStream);
void flac_metadata_common_cb( const FLAC__StreamMetadata *block, void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
FlacData *data); FlacData * data);
void flac_error_common_cb( const char * plugin, void flac_error_common_cb(const char *plugin,
FLAC__StreamDecoderErrorStatus status, FLAC__StreamDecoderErrorStatus status,
FlacData *data); FlacData * data);
MpdTag * copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block, MpdTag *copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
MpdTag * tag); MpdTag * tag);
/* keep this inlined, this is just macro but prettier :) */ /* keep this inlined, this is just macro but prettier :) */
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

@ -36,7 +36,7 @@
/* 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 */
typedef struct { typedef struct {
InputStream * inStream; InputStream *inStream;
long bytesIntoBuffer; long bytesIntoBuffer;
long bytesConsumed; long bytesConsumed;
long fileOffset; long fileOffset;
@ -44,163 +44,193 @@ 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 +
1,b->bytesConsumed); b->
if(bread!=b->bytesConsumed) b->atEof = 1; bytesIntoBuffer),
b->bytesIntoBuffer+=bread; 1, b->bytesConsumed);
if (bread != b->bytesConsumed)
b->atEof = 1;
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) {
b->bytesIntoBuffer = 0; b->bytesIntoBuffer = 0;
} }
} }
if(b->bytesIntoBuffer > 8) { if (b->bytesIntoBuffer > 8) {
if(memcmp(b->buffer,"APETAGEX",8)==0) { if (memcmp(b->buffer, "APETAGEX", 8) == 0) {
b->bytesIntoBuffer = 0; b->bytesIntoBuffer = 0;
} }
} }
} }
} }
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;
float framesPerSec, bytesPerFrame; float framesPerSec, bytesPerFrame;
/* Read all frames to ensure correct time and bitrate */ /* Read all frames to ensure correct time and bitrate */
for(frames = 0; ;frames++) { for (frames = 0;; frames++) {
fillAacBuffer(b); fillAacBuffer(b);
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))
<< 11) | (((unsigned int)b->buffer[4]) << 11) | (((unsigned int)b->buffer[4])
<< 3) | (b->buffer[5] >> 5); << 3) | (b->buffer[5] >> 5);
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;
} }
static void initAacBuffer(InputStream * inStream, AacBuffer * b, float * length, static void initAacBuffer(InputStream * inStream, AacBuffer * b, float *length,
size_t * retFileread, size_t * retTagsize) size_t * retFileread, size_t * retTagsize)
{ {
size_t fileread; size_t fileread;
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));
b->inStream = inStream; b->inStream = inStream;
fileread = inStream->size; fileread = inStream->size;
b->buffer = malloc(FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); b->buffer = malloc(FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
memset(b->buffer,0,FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); memset(b->buffer, 0, FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
bread = readFromInputStream(inStream,b->buffer,1, bread = readFromInputStream(inStream, b->buffer, 1,
FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
b->bytesIntoBuffer = bread; b->bytesIntoBuffer = bread;
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)) {
tagsize = (b->buffer[6] << 21) | (b->buffer[7] << 14) | tagsize = (b->buffer[6] << 21) | (b->buffer[7] << 14) |
(b->buffer[8] << 7) | (b->buffer[9] << 0); (b->buffer[8] << 7) | (b->buffer[9] << 0);
tagsize+=10; tagsize += 10;
advanceAacBuffer(b,tagsize); advanceAacBuffer(b, tagsize);
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,46 +241,51 @@ 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);
if(length < 0) { if (length < 0) {
decoder = faacDecOpen(); decoder = faacDecOpen();
config = faacDecGetCurrentConfiguration(decoder); config = faacDecGetCurrentConfiguration(decoder);
config->outputFormat = FAAD_FMT_16BIT; config->outputFormat = FAAD_FMT_16BIT;
faacDecSetConfiguration(decoder,config); faacDecSetConfiguration(decoder, config);
fillAacBuffer(&b); fillAacBuffer(&b);
#ifdef HAVE_FAAD_BUFLEN_FUNCS #ifdef HAVE_FAAD_BUFLEN_FUNCS
bread = faacDecInit(decoder,b.buffer,b.bytesIntoBuffer, bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer,
&sampleRate,&channels); &sampleRate, &channels);
#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;
@ -261,20 +296,22 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
unsigned char channels; unsigned char channels;
int eof = 0; int eof = 0;
unsigned int sampleCount; unsigned int sampleCount;
char * sampleBuffer; char *sampleBuffer;
size_t sampleBufferLen; size_t sampleBufferLen;
/*float * seekTable; /*float * seekTable;
long seekTableEnd = -1; long seekTableEnd = -1;
int seekPositionFound = 0;*/ int seekPositionFound = 0; */
mpd_uint16 bitRate = 0; mpd_uint16 bitRate = 0;
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);
decoder = faacDecOpen(); decoder = faacDecOpen();
@ -286,21 +323,22 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR #ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR
config->dontUpSampleImplicitSBR = 0; config->dontUpSampleImplicitSBR = 0;
#endif #endif
faacDecSetConfiguration(decoder,config); faacDecSetConfiguration(decoder, config);
fillAacBuffer(&b); fillAacBuffer(&b);
#ifdef HAVE_FAAD_BUFLEN_FUNCS #ifdef HAVE_FAAD_BUFLEN_FUNCS
bread = faacDecInit(decoder,b.buffer,b.bytesIntoBuffer, bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer,
&sampleRate,&channels); &sampleRate, &channels);
#else #else
bread = faacDecInit(decoder,b.buffer,&sampleRate,&channels); bread = faacDecInit(decoder, b.buffer, &sampleRate, &channels);
#endif #endif
if(bread < 0) { if (bread < 0) {
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;
} }
@ -310,36 +348,34 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
time = 0.0; time = 0.0;
advanceAacBuffer(&b,bread); advanceAacBuffer(&b, bread);
while(!eof) { while (!eof) {
fillAacBuffer(&b); fillAacBuffer(&b);
if(b.bytesIntoBuffer==0) { if (b.bytesIntoBuffer == 0) {
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);
#else #else
sampleBuffer = faacDecDecode(decoder,&frameInfo,b.buffer); sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer);
#endif #endif
if(frameInfo.error > 0) { if (frameInfo.error > 0) {
ERROR("error decoding AAC file: %s\n", path); ERROR("error decoding AAC file: %s\n", path);
ERROR("faad2 error: %s\n", ERROR("faad2 error: %s\n",
faacDecGetErrorMessage(frameInfo.error)); faacDecGetErrorMessage(frameInfo.error));
eof = 1; eof = 1;
break; break;
} }
#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE #ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
sampleRate = frameInfo.samplerate; sampleRate = frameInfo.samplerate;
#endif #endif
if(dc->state != DECODE_STATE_DECODE) { if (dc->state != DECODE_STATE_DECODE) {
dc->audioFormat.channels = frameInfo.channels; dc->audioFormat.channels = frameInfo.channels;
dc->audioFormat.sampleRate = sampleRate; dc->audioFormat.sampleRate = sampleRate;
getOutputAudioFormat(&(dc->audioFormat), getOutputAudioFormat(&(dc->audioFormat),
@ -347,27 +383,27 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
dc->state = DECODE_STATE_DECODE; dc->state = DECODE_STATE_DECODE;
} }
advanceAacBuffer(&b,frameInfo.bytesconsumed); advanceAacBuffer(&b, frameInfo.bytesconsumed);
sampleCount = (unsigned long)(frameInfo.samples); sampleCount = (unsigned long)(frameInfo.samples);
if(sampleCount>0) { if (sampleCount > 0) {
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;
} }
sampleBufferLen = sampleCount*2; sampleBufferLen = sampleCount * 2;
sendDataToOutputBuffer(cb, NULL, dc, 0, sampleBuffer, sendDataToOutputBuffer(cb, NULL, dc, 0, sampleBuffer,
sampleBufferLen, time, bitRate, NULL); sampleBufferLen, time, bitRate, NULL);
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,45 +413,48 @@ 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;
dc->seek = 0; dc->seek = 0;
} }
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;
} }
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

@ -37,34 +37,35 @@
#include <unistd.h> #include <unistd.h>
#include <audiofile.h> #include <audiofile.h>
static int getAudiofileTotalTime(char * file) static int getAudiofileTotalTime(char *file)
{ {
int time; int time;
AFfilehandle af_fp = afOpenFile(file, "r", NULL); AFfilehandle af_fp = afOpenFile(file, "r", NULL);
if(af_fp == AF_NULL_FILEHANDLE) { if (af_fp == AF_NULL_FILEHANDLE) {
return -1; return -1;
} }
time = (int) time = (int)
((double)afGetFrameCount(af_fp,AF_DEFAULT_TRACK) ((double)afGetFrameCount(af_fp, AF_DEFAULT_TRACK)
/afGetRate(af_fp,AF_DEFAULT_TRACK)); / afGetRate(af_fp, AF_DEFAULT_TRACK));
afCloseFile(af_fp); afCloseFile(af_fp);
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;
mpd_uint16 bitRate; mpd_uint16 bitRate;
struct stat st; struct stat st;
if(stat(path, &st) < 0) { if (stat(path, &st) < 0) {
ERROR("failed to stat: %s\n", path); ERROR("failed to stat: %s\n", path);
return -1; return -1;
} }
af_fp = afOpenFile(path, "r", NULL); af_fp = afOpenFile(path, "r", NULL);
if(af_fp == AF_NULL_FILEHANDLE) { if (af_fp == AF_NULL_FILEHANDLE) {
ERROR("failed to open: %s\n", path); ERROR("failed to open: %s\n", path);
return -1; return -1;
} }
@ -72,14 +73,15 @@ static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char * path)
afGetSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits); afGetSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits);
dc->audioFormat.bits = bits; dc->audioFormat.bits = bits;
dc->audioFormat.sampleRate = afGetRate(af_fp, AF_DEFAULT_TRACK); dc->audioFormat.sampleRate = afGetRate(af_fp, AF_DEFAULT_TRACK);
dc->audioFormat.channels = afGetChannels(af_fp,AF_DEFAULT_TRACK); dc->audioFormat.channels = afGetChannels(af_fp, AF_DEFAULT_TRACK);
getOutputAudioFormat(&(dc->audioFormat),&(cb->audioFormat)); getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat));
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;
if (dc->audioFormat.bits != 8 && dc->audioFormat.bits != 16) { if (dc->audioFormat.bits != 8 && dc->audioFormat.bits != 16) {
ERROR("Only 8 and 16-bit files are supported. %s is %i-bit\n", ERROR("Only 8 and 16-bit files are supported. %s is %i-bit\n",
@ -88,24 +90,27 @@ static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char * path)
return -1; return -1;
} }
fs = (int)afGetFrameSize(af_fp, AF_DEFAULT_TRACK,1); fs = (int)afGetFrameSize(af_fp, AF_DEFAULT_TRACK, 1);
dc->state = DECODE_STATE_DECODE; dc->state = DECODE_STATE_DECODE;
{ {
int ret, eof = 0, current = 0; int ret, eof = 0, current = 0;
char chunk[CHUNK_SIZE]; char chunk[CHUNK_SIZE];
while(!eof) { while (!eof) {
if(dc->seek) { if (dc->seek) {
clearOutputBuffer(cb); clearOutputBuffer(cb);
current = dc->seekWhere * current = dc->seekWhere *
dc->audioFormat.sampleRate; dc->audioFormat.sampleRate;
afSeekFrame(af_fp, AF_DEFAULT_TRACK,current); afSeekFrame(af_fp, AF_DEFAULT_TRACK, current);
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,
@ -113,12 +118,13 @@ static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char * path)
dc, dc,
1, 1,
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;
} }
} }
@ -127,38 +133,40 @@ static int audiofile_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;
}*/ } */
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;
} }
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,111 +43,126 @@ 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;
int status = 1; int status = 1;
int ret =0; int ret = 0;
init_FlacData(&data, cb, dc, inStream); init_FlacData(&data, cb, dc, inStream);
if(!(flacDec = FLAC__seekable_stream_decoder_new())) { if (!(flacDec = FLAC__seekable_stream_decoder_new())) {
ret = -1; ret = -1;
goto fail; goto fail;
} }
/*status&=FLAC__file_decoder_set_md5_checking(flacDec,1);*/ /*status&=FLAC__file_decoder_set_md5_checking(flacDec,1); */
status&=FLAC__seekable_stream_decoder_set_read_callback(flacDec, status &= FLAC__seekable_stream_decoder_set_read_callback(flacDec,
flacRead); flacRead);
status&=FLAC__seekable_stream_decoder_set_seek_callback(flacDec, status &= FLAC__seekable_stream_decoder_set_seek_callback(flacDec,
flacSeek); flacSeek);
status&=FLAC__seekable_stream_decoder_set_tell_callback(flacDec, status &= FLAC__seekable_stream_decoder_set_tell_callback(flacDec,
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;
} }
dc->state = DECODE_STATE_DECODE; dc->state = DECODE_STATE_DECODE;
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) {
FLAC__uint64 sampleToSeek = dc->seekWhere* FLAC__uint64 sampleToSeek = dc->seekWhere *
dc->audioFormat.sampleRate+0.5; dc->audioFormat.sampleRate + 0.5;
if(FLAC__seekable_stream_decoder_seek_absolute(flacDec, if (FLAC__seekable_stream_decoder_seek_absolute(flacDec,
sampleToSeek)) 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;
} }
} }
/* 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 */
if(data.chunk_length>0 && !dc->stop) { if (data.chunk_length > 0 && !dc->stop) {
flacSendChunk(&data); flacSendChunk(&data);
flushOutputBuffer(data.cb); flushOutputBuffer(data.cb);
} }
@ -160,24 +175,30 @@ static int flac_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inS
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
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,
FlacData * data = (FlacData *) fdata; FLAC__byte buf[],
unsigned *bytes,
void *fdata)
{
FlacData *data = (FlacData *) fdata;
size_t r; size_t r;
while (1) { while (1) {
r = readFromInputStream(data->inStream,(void *)buf,1,*bytes); r = readFromInputStream(data->inStream, (void *)buf, 1, *bytes);
if (r == 0 && !inputStreamAtEOF(data->inStream) && if (r == 0 && !inputStreamAtEOF(data->inStream) &&
!data->dc->stop) !data->dc->stop)
my_usleep(10000); my_usleep(10000);
@ -186,64 +207,72 @@ static FLAC__SeekableStreamDecoderReadStatus flacRead(
} }
*bytes = r; *bytes = r;
if (*bytes==0 && !inputStreamAtEOF(data->inStream) && !data->dc->stop) if (*bytes == 0 && !inputStreamAtEOF(data->inStream) && !data->dc->stop)
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
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;
if(seekInputStream(data->inStream,offset,SEEK_SET)<0) { if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) {
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
} }
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;
*offset = (long)(data->inStream->offset); *offset = (long)(data->inStream->offset);
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;
*length = (size_t)(data->inStream->size); *length = (size_t) (data->inStream->size);
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,
FlacData * data = (FlacData *) fdata; void *fdata)
{
FlacData *data = (FlacData *) fdata;
if (inputStreamAtEOF(data->inStream) == 1) if (inputStreamAtEOF(data->inStream) == 1)
return true; return true;
return false; return false;
} }
static void flacError(const FLAC__SeekableStreamDecoder *dec, static void flacError(const FLAC__SeekableStreamDecoder * dec,
FLAC__StreamDecoderErrorStatus status, void *fdata) FLAC__StreamDecoderErrorStatus status, void *fdata)
{ {
flac_error_common_cb("flac",status,(FlacData *) fdata); flac_error_common_cb("flac", status, (FlacData *) fdata);
} }
static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state) static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
{ {
switch(state) { switch (state) {
case FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR: case FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
ERROR("flac allocation error\n"); ERROR("flac allocation error\n");
break; break;
@ -272,48 +301,53 @@ static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
} }
} }
static void flacMetadata(const FLAC__SeekableStreamDecoder *dec, static void flacMetadata(const FLAC__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 FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *dec, static FLAC__StreamDecoderWriteStatus flacWrite(const
const FLAC__Frame *frame, const FLAC__int32 * const buf[], FLAC__SeekableStreamDecoder *
void * vdata) dec, 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;
FLAC__uint16 u16; FLAC__uint16 u16;
unsigned char * uc; unsigned char *uc;
int c_samp, c_chan, d_samp; int c_samp, c_chan, d_samp;
int i; int i;
float timeChange; float timeChange;
FLAC__uint64 newPosition = 0; FLAC__uint64 newPosition = 0;
timeChange = ((float)samples)/frame->header.sample_rate; timeChange = ((float)samples) / frame->header.sample_rate;
data->time+= timeChange; data->time += timeChange;
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 =
/1000+0.5; ((newPosition - data->position) * 8.0 / timeChange)
/ 1000 + 0.5;
} }
data->position = newPosition; data->position = newPosition;
for(c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) { for (c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) {
for(c_chan = 0; c_chan < frame->header.channels; for (c_chan = 0; c_chan < frame->header.channels;
c_chan++, d_samp++) { c_chan++, d_samp++) {
u16 = buf[c_chan][c_samp]; u16 = buf[c_chan][c_samp];
uc = (unsigned char *)&u16; uc = (unsigned char *)&u16;
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,27 +358,35 @@ 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; {
FLAC__Metadata_SimpleIterator * it; MpdTag *ret = NULL;
FLAC__StreamMetadata * block = NULL; FLAC__Metadata_SimpleIterator *it;
FLAC__StreamMetadata *block = NULL;
*vorbisCommentFound = 0; *vorbisCommentFound = 0;
it = FLAC__metadata_simple_iterator_new(); it = FLAC__metadata_simple_iterator_new();
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,38 +394,41 @@ 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)
if(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { break;
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));
FLAC__metadata_simple_iterator_delete(it); FLAC__metadata_simple_iterator_delete(it);
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) {
MpdTag * temp = id3Dup(file); MpdTag *temp = id3Dup(file);
if(temp) { if (temp) {
temp->time = ret->time; temp->time = ret->time;
freeMpdTag(ret); freeMpdTag(ret);
ret = temp; ret = temp;
@ -393,11 +438,10 @@ static MpdTag * flacTagDup(char * file) {
return ret; return ret;
} }
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,10 +95,12 @@ 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;
md_device = 0; md_device = 0;
@ -110,7 +115,7 @@ static int mod_initMikMod(void) {
md_mode = (DMODE_SOFT_MUSIC | DMODE_INTERP | DMODE_STEREO | md_mode = (DMODE_SOFT_MUSIC | DMODE_INTERP | DMODE_STEREO |
DMODE_16BITS); DMODE_16BITS);
if(MikMod_Init("")) { if (MikMod_Init("")) {
ERROR("Could not init MikMod: %s\n", ERROR("Could not init MikMod: %s\n",
MikMod_strerror(MikMod_errno)); MikMod_strerror(MikMod_errno));
mod_mikModInitError = 1; mod_mikModInitError = 1;
@ -120,20 +125,23 @@ static int mod_initMikMod(void) {
return 0; return 0;
} }
static void mod_finishMikMod(void) { static void mod_finishMikMod(void)
{
MikMod_Exit(); MikMod_Exit();
} }
typedef struct _mod_Data { typedef struct _mod_Data {
MODULE * moduleHandle; MODULE *moduleHandle;
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; {
mod_Data * data; MODULE *moduleHandle;
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,22 +153,25 @@ 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);
MikMod_Exit(); MikMod_Exit();
return -1; return -1;
@ -169,24 +180,27 @@ static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
dc->audioFormat.bits = 16; dc->audioFormat.bits = 16;
dc->audioFormat.sampleRate = 44100; dc->audioFormat.sampleRate = 44100;
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;
while(1) { while (1) {
if(dc->seek) { if (dc->seek) {
dc->seekError = 1; dc->seekError = 1;
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;
sendDataToOutputBuffer(cb, NULL, dc, 0, sendDataToOutputBuffer(cb, NULL, dc, 0,
(char *)data->audio_buffer, ret, time, (char *)data->audio_buffer, ret, time,
0, NULL); 0, NULL);
@ -198,27 +212,28 @@ static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
MikMod_Exit(); MikMod_Exit();
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; {
MODULE * moduleHandle; MpdTag *ret = NULL;
char * title; MODULE *moduleHandle;
char *title;
if(mod_initMikMod() < 0) { if (mod_initMikMod() < 0) {
DEBUG("modTagDup: Failed to initialize MikMod\n"); DEBUG("modTagDup: Failed to initialize MikMod\n");
return NULL; return NULL;
} }
if(!(moduleHandle = Player_Load(file, 128, 0))) { if (!(moduleHandle = Player_Load(file, 128, 0))) {
DEBUG("modTagDup: Failed to open file: %s\n",file); DEBUG("modTagDup: Failed to open file: %s\n", file);
MikMod_Exit(); MikMod_Exit();
return NULL; return NULL;
@ -229,14 +244,15 @@ 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();
return ret; return ret;
} }
static char * modSuffixes[] = {"amf", static char *modSuffixes[] = { "amf",
"dsm", "dsm",
"far", "far",
"gdm", "gdm",
@ -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,

File diff suppressed because it is too large Load Diff

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;
} }
} }
@ -76,14 +79,16 @@ static int mp4_getAACTrack(mp4ff_t *infile) {
static uint32_t mp4_inputStreamReadCallback(void *inStream, void *buffer, static uint32_t mp4_inputStreamReadCallback(void *inStream, void *buffer,
uint32_t length) uint32_t length)
{ {
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();
@ -95,20 +100,21 @@ static faacDecHandle * openConfigureFaad() {
#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR #ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR
config->dontUpSampleImplicitSBR = 0; config->dontUpSampleImplicitSBR = 0;
#endif #endif
faacDecSetConfiguration(decoder,config); faacDecSetConfiguration(decoder, config);
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_callback_t * mp4cb; mp4ff_t *mp4fh;
mp4ff_callback_t *mp4cb;
int32_t track; int32_t track;
float time; float time;
int32_t scale; int32_t scale;
faacDecHandle * decoder; faacDecHandle *decoder;
faacDecFrameInfo frameInfo; faacDecFrameInfo frameInfo;
unsigned char * mp4Buffer; unsigned char *mp4Buffer;
unsigned int mp4BufferSize; unsigned int mp4BufferSize;
uint32_t sampleRate; uint32_t sampleRate;
unsigned char channels; unsigned char channels;
@ -117,10 +123,10 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
int eof = 0; int eof = 0;
long dur; long dur;
unsigned int sampleCount; unsigned int sampleCount;
char * sampleBuffer; char *sampleBuffer;
size_t sampleBufferLen; size_t sampleBufferLen;
unsigned int initial = 1; unsigned int initial = 1;
float * seekTable; float *seekTable;
long seekTableEnd = -1; long seekTableEnd = -1;
int seekPositionFound = 0; int seekPositionFound = 0;
long offset; long offset;
@ -128,7 +134,7 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
InputStream inStream; InputStream inStream;
int seeking = 0; int seeking = 0;
if(openInputStream(&inStream, path) < 0) { if (openInputStream(&inStream, path) < 0) {
ERROR("failed to open %s\n", path); ERROR("failed to open %s\n", path);
return -1; return -1;
} }
@ -139,7 +145,7 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
mp4cb->user_data = &inStream; mp4cb->user_data = &inStream;
mp4fh = mp4ff_open_read(mp4cb); mp4fh = mp4ff_open_read(mp4cb);
if(!mp4fh) { if (!mp4fh) {
ERROR("Input does not appear to be a mp4 stream.\n"); ERROR("Input does not appear to be a mp4 stream.\n");
free(mp4cb); free(mp4cb);
closeInputStream(&inStream); closeInputStream(&inStream);
@ -147,7 +153,7 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
} }
track = mp4_getAACTrack(mp4fh); track = mp4_getAACTrack(mp4fh);
if(track < 0) { if (track < 0) {
ERROR("No AAC track found in mp4 stream.\n"); ERROR("No AAC track found in mp4 stream.\n");
mp4ff_close(mp4fh); mp4ff_close(mp4fh);
closeInputStream(&inStream); closeInputStream(&inStream);
@ -161,11 +167,11 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
mp4Buffer = NULL; mp4Buffer = NULL;
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);
@ -176,12 +182,13 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
dc->audioFormat.sampleRate = sampleRate; dc->audioFormat.sampleRate = sampleRate;
dc->audioFormat.channels = channels; dc->audioFormat.channels = channels;
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");
faacDecClose(decoder); faacDecClose(decoder);
mp4ff_close(mp4fh); mp4ff_close(mp4fh);
@ -189,66 +196,71 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
free(mp4cb); free(mp4cb);
return -1; return -1;
} }
dc->totalTime = ((float)time)/scale; dc->totalTime = ((float)time) / scale;
numSamples = mp4ff_num_samples(mp4fh,track); numSamples = mp4ff_num_samples(mp4fh, track);
time = 0.0; time = 0.0;
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)
sampleId = i-1; i++;
sampleId = i - 1;
time = seekTable[sampleId]; time = seekTable[sampleId];
} }
dur = mp4ff_get_sample_duration(mp4fh,track,sampleId); dur = mp4ff_get_sample_duration(mp4fh, track, sampleId);
offset = mp4ff_get_sample_offset(mp4fh,track,sampleId); offset = mp4ff_get_sample_offset(mp4fh, track, sampleId);
if(sampleId>seekTableEnd) { if (sampleId > seekTableEnd) {
seekTable[sampleId] = time; seekTable[sampleId] = time;
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)
time+=((float)dur)/scale; dur = 0;
else
dur -= offset;
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;
clearOutputBuffer(cb); clearOutputBuffer(cb);
seeking = 0; seeking = 0;
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);
#else #else
sampleBuffer = faacDecDecode(decoder,&frameInfo,mp4Buffer); sampleBuffer = faacDecDecode(decoder, &frameInfo, mp4Buffer);
#endif #endif
if(mp4Buffer) free(mp4Buffer); if (mp4Buffer)
if(frameInfo.error > 0) { free(mp4Buffer);
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",
faacDecGetErrorMessage(frameInfo.error)); faacDecGetErrorMessage(frameInfo.error));
@ -256,7 +268,7 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
break; break;
} }
if(dc->state != DECODE_STATE_DECODE) { if (dc->state != DECODE_STATE_DECODE) {
channels = frameInfo.channels; channels = frameInfo.channels;
#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE #ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
scale = frameInfo.samplerate; scale = frameInfo.samplerate;
@ -268,28 +280,27 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
dc->state = DECODE_STATE_DECODE; dc->state = DECODE_STATE_DECODE;
} }
if(channels*(dur+offset) > frameInfo.samples) { if (channels * (dur + offset) > frameInfo.samples) {
dur = frameInfo.samples/channels; dur = frameInfo.samples / channels;
offset = 0; offset = 0;
} }
sampleCount = (unsigned long)(dur*channels); sampleCount = (unsigned long)(dur * channels);
if(sampleCount>0) { if (sampleCount > 0) {
initial =0; initial = 0;
bitRate = frameInfo.bytesconsumed*8.0* bitRate = frameInfo.bytesconsumed * 8.0 *
frameInfo.channels*scale/ frameInfo.channels * scale /
frameInfo.samples/1000+0.5; frameInfo.samples / 1000 + 0.5;
} }
sampleBufferLen = sampleCount * 2;
sampleBufferLen = sampleCount*2; sampleBuffer += offset * channels * 2;
sampleBuffer+=offset*channels*2;
sendDataToOutputBuffer(cb, NULL, dc, 1, sampleBuffer, sendDataToOutputBuffer(cb, NULL, dc, 1, sampleBuffer,
sampleBufferLen, time, bitRate, NULL); sampleBufferLen, time, bitRate, NULL);
if(dc->stop) { if (dc->stop) {
eof = 1; eof = 1;
break; break;
} }
@ -301,25 +312,28 @@ 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);
dc->seek = 0; dc->seek = 0;
} }
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;
mp4ff_callback_t * cb; mp4ff_callback_t *cb;
int32_t track; int32_t track;
int32_t time; int32_t time;
int32_t scale; int32_t scale;
@ -327,7 +341,7 @@ static MpdTag * mp4DataDup(char * file, int * mp4MetadataFound) {
*mp4MetadataFound = 0; *mp4MetadataFound = 0;
if(openInputStream(&inStream, file) < 0) { if (openInputStream(&inStream, file) < 0) {
DEBUG("mp4DataDup: Failed to open file: %s\n", file); DEBUG("mp4DataDup: Failed to open file: %s\n", file);
return NULL; return NULL;
} }
@ -338,14 +352,14 @@ static MpdTag * mp4DataDup(char * file, int * mp4MetadataFound) {
cb->user_data = &inStream; cb->user_data = &inStream;
mp4fh = mp4ff_open_read(cb); mp4fh = mp4ff_open_read(cb);
if(!mp4fh) { if (!mp4fh) {
free(cb); free(cb);
closeInputStream(&inStream); closeInputStream(&inStream);
return NULL; return NULL;
} }
track = mp4_getAACTrack(mp4fh); track = mp4_getAACTrack(mp4fh);
if(track < 0) { if (track < 0) {
mp4ff_close(mp4fh); mp4ff_close(mp4fh);
closeInputStream(&inStream); closeInputStream(&inStream);
free(cb); free(cb);
@ -353,48 +367,42 @@ static MpdTag * mp4DataDup(char * file, int * mp4MetadataFound) {
} }
ret = newMpdTag(); ret = newMpdTag();
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(scale < 0) { if (scale < 0) {
mp4ff_close(mp4fh); mp4ff_close(mp4fh);
closeInputStream(&inStream); closeInputStream(&inStream);
free(cb); free(cb);
freeMpdTag(ret); freeMpdTag(ret);
return NULL; return NULL;
} }
ret->time = ((float)time)/scale+0.5; ret->time = ((float)time) / scale + 0.5;
for(i = 0; i < mp4ff_meta_get_num_items(mp4fh); i++) { for (i = 0; i < mp4ff_meta_get_num_items(mp4fh); i++) {
char * item; char *item;
char * value; char *value;
mp4ff_meta_get_by_index(mp4fh, i, &item, &value); mp4ff_meta_get_by_index(mp4fh, i, &item, &value);
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,15 +418,17 @@ 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)
if(!mp4MetadataFound) { return NULL;
MpdTag * temp = id3Dup(file); if (!mp4MetadataFound) {
if(temp) { MpdTag *temp = id3Dup(file);
if (temp) {
temp->time = ret->time; temp->time = ret->time;
freeMpdTag(ret); freeMpdTag(ret);
ret = temp; ret = temp;
@ -428,10 +438,9 @@ static MpdTag * mp4TagDup(char * file) {
return ret; return ret;
} }
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

@ -37,53 +37,58 @@
#include <math.h> #include <math.h>
typedef struct _MpcCallbackData { typedef struct _MpcCallbackData {
InputStream * inStream; InputStream *inStream;
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;
@ -93,10 +98,9 @@ static inline mpd_sint16 convertSample(MPC_SAMPLE_FORMAT sample) {
#ifdef MPC_FIXED_POINT #ifdef MPC_FIXED_POINT
const int shift = 16 - MPC_FIXED_POINT_SCALE_SHIFT; const int shift = 16 - MPC_FIXED_POINT_SCALE_SHIFT;
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;
} }
@ -129,13 +135,13 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
char chunk[MPC_CHUNK_SIZE]; char chunk[MPC_CHUNK_SIZE];
int chunkpos = 0; int chunkpos = 0;
long bitRate = 0; long bitRate = 0;
mpd_sint16 * s16 = (mpd_sint16 *) chunk; mpd_sint16 *s16 = (mpd_sint16 *) chunk;
unsigned long samplePos = 0; unsigned long samplePos = 0;
mpc_uint32_t vbrUpdateAcc; mpc_uint32_t vbrUpdateAcc;
mpc_uint32_t vbrUpdateBits; mpc_uint32_t vbrUpdateBits;
float time; float time;
int i; int i;
ReplayGainInfo * replayGainInfo = NULL; ReplayGainInfo *replayGainInfo = NULL;
data.inStream = inStream; data.inStream = inStream;
data.dc = dc; data.dc = dc;
@ -149,13 +155,12 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
mpc_streaminfo_init(&info); mpc_streaminfo_init(&info);
if((ret = mpc_streaminfo_read(&info, &reader)) != ERROR_CODE_OK) { if ((ret = mpc_streaminfo_read(&info, &reader)) != ERROR_CODE_OK) {
closeInputStream(inStream); closeInputStream(inStream);
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;
} }
@ -164,12 +169,11 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
mpc_decoder_setup(&decoder, &reader); mpc_decoder_setup(&decoder, &reader);
if(!mpc_decoder_initialize(&decoder, &info)) { if (!mpc_decoder_initialize(&decoder, &info)) {
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;
} }
@ -191,14 +195,14 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
dc->state = DECODE_STATE_DECODE; dc->state = DECODE_STATE_DECODE;
while(!eof) { while (!eof) {
if(dc->seek) { if (dc->seek) {
samplePos = dc->seekWhere * dc->audioFormat.sampleRate; samplePos = dc->seekWhere * dc->audioFormat.sampleRate;
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;
} }
@ -207,7 +211,7 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
ret = mpc_decoder_decode(&decoder, sample_buffer, ret = mpc_decoder_decode(&decoder, sample_buffer,
&vbrUpdateAcc, &vbrUpdateBits); &vbrUpdateAcc, &vbrUpdateBits);
if(ret <= 0 || dc->stop ) { if (ret <= 0 || dc->stop) {
eof = 1; eof = 1;
break; break;
} }
@ -217,30 +221,28 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
/* ret is in samples, and we have stereo */ /* ret is in samples, and we have stereo */
ret *= 2; ret *= 2;
for(i = 0; i < ret; i++) { for (i = 0; i < ret; i++) {
/* 16 bit audio again */ /* 16 bit audio again */
*s16 = convertSample(sample_buffer[i]); *s16 = convertSample(sample_buffer[i]);
chunkpos += 2; chunkpos += 2;
s16++; s16++;
if(chunkpos >= MPC_CHUNK_SIZE) { if (chunkpos >= MPC_CHUNK_SIZE) {
time = ((float)samplePos) / time = ((float)samplePos) /
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;
if(dc->stop) { if (dc->stop) {
eof = 1; eof = 1;
break; break;
} }
@ -248,10 +250,11 @@ 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,
@ -264,18 +267,18 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
freeReplayGainInfo(replayGainInfo); freeReplayGainInfo(replayGainInfo);
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;
@ -295,12 +298,12 @@ static float mpcGetTime(char * file) {
mpc_streaminfo_init(&info); mpc_streaminfo_init(&info);
if(openInputStream(&inStream, file) < 0) { if (openInputStream(&inStream, file) < 0) {
DEBUG("mpcGetTime: Failed to open file: %s\n", file); DEBUG("mpcGetTime: Failed to open file: %s\n", file);
return -1; return -1;
} }
if(mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) { if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) {
closeInputStream(&inStream); closeInputStream(&inStream);
return -1; return -1;
} }
@ -312,28 +315,31 @@ 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;
} }
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,14 +51,18 @@ 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,
FlacData * data = (FlacData *) fdata; FLAC__byte buf[],
unsigned *bytes,
void *fdata)
{
FlacData *data = (FlacData *) fdata;
size_t r; size_t r;
while (1) { while (1) {
r = readFromInputStream(data->inStream,(void *)buf,1,*bytes); r = readFromInputStream(data->inStream, (void *)buf, 1, *bytes);
if (r == 0 && !inputStreamAtEOF(data->inStream) && if (r == 0 && !inputStreamAtEOF(data->inStream) &&
!data->dc->stop) !data->dc->stop)
my_usleep(10000); my_usleep(10000);
@ -73,44 +77,52 @@ 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;
if(seekInputStream(data->inStream,offset,SEEK_SET)<0) { if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) {
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
} }
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;
*offset = (long)(data->inStream->offset); *offset = (long)(data->inStream->offset);
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;
*length = (size_t)(data->inStream->size); *length = (size_t) (data->inStream->size);
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
} }
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)
return true; return true;
@ -120,12 +132,12 @@ static FLAC__bool of_EOF_cb(const OggFLAC__SeekableStreamDecoder * decoder,
static void of_error_cb(const OggFLAC__SeekableStreamDecoder * decoder, static void of_error_cb(const OggFLAC__SeekableStreamDecoder * decoder,
FLAC__StreamDecoderErrorStatus status, void *fdata) FLAC__StreamDecoderErrorStatus status, void *fdata)
{ {
flac_error_common_cb("oggflac",status,(FlacData *) fdata); flac_error_common_cb("oggflac", status, (FlacData *) fdata);
} }
static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state) static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state)
{ {
switch(state) { switch (state) {
case OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR: case OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
ERROR("oggflac allocation error\n"); ERROR("oggflac allocation error\n");
break; break;
@ -154,21 +166,23 @@ 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;
FLAC__uint16 u16; FLAC__uint16 u16;
unsigned char * uc; unsigned char *uc;
int c_samp, c_chan, d_samp; int c_samp, c_chan, d_samp;
int i; int i;
float timeChange; float timeChange;
timeChange = ((float)samples)/frame->header.sample_rate; timeChange = ((float)samples) / frame->header.sample_rate;
data->time+= timeChange; data->time += timeChange;
/* ogg123 uses a complicated method of calculating bitrate /* ogg123 uses a complicated method of calculating bitrate
* with averaging which I'm not too fond of. * with averaging which I'm not too fond of.
@ -182,19 +196,21 @@ static FLAC__StreamDecoderWriteStatus oggflacWrite(
/((float)samples * 1000)) + 0.5; /((float)samples * 1000)) + 0.5;
*/ */
for(c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) { for (c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) {
for(c_chan = 0; c_chan < frame->header.channels; for (c_chan = 0; c_chan < frame->header.channels;
c_chan++, d_samp++) { c_chan++, d_samp++) {
u16 = buf[c_chan][c_samp]; u16 = buf[c_chan][c_samp];
uc = (unsigned char *)&u16; uc = (unsigned char *)&u16;
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,22 +222,21 @@ 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);
default: default:
break; break;
} }
@ -229,30 +244,30 @@ 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;
unsigned int s = 1; unsigned int s = 1;
if (!(decoder = OggFLAC__seekable_stream_decoder_new())) if (!(decoder = OggFLAC__seekable_stream_decoder_new()))
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,31 +294,30 @@ 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;
} }
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;
} }
/* public functions: */ /* public functions: */
static MpdTag * oggflac_TagDup(char * file) static MpdTag *oggflac_TagDup(char *file)
{ {
InputStream inStream; InputStream inStream;
OggFLAC__SeekableStreamDecoder * decoder; OggFLAC__SeekableStreamDecoder *decoder;
FlacData data; FlacData data;
if (openInputStream(&inStream, file) < 0) if (openInputStream(&inStream, file) < 0)
@ -317,7 +331,7 @@ static MpdTag * oggflac_TagDup(char * file)
/* errors here won't matter, /* errors here won't matter,
* data.tag will be set or unset, that's all we care about */ * data.tag will be set or unset, that's all we care about */
decoder = full_decoder_init_and_read_metadata(&data,1); decoder = full_decoder_init_and_read_metadata(&data, 1);
oggflac_cleanup(&inStream, &data, decoder); oggflac_cleanup(&inStream, &data, decoder);
@ -332,49 +346,47 @@ static unsigned int oggflac_try_decode(InputStream * inStream)
static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc, static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc,
InputStream * inStream) InputStream * inStream)
{ {
OggFLAC__SeekableStreamDecoder * decoder = NULL; OggFLAC__SeekableStreamDecoder *decoder = NULL;
FlacData data; FlacData data;
int ret = 0; int ret = 0;
init_FlacData(&data, cb, dc, inStream); init_FlacData(&data, cb, dc, inStream);
if(!(decoder = full_decoder_init_and_read_metadata(&data,0))){ if (!(decoder = full_decoder_init_and_read_metadata(&data, 0))) {
ret = -1; ret = -1;
goto fail; goto fail;
} }
dc->state = DECODE_STATE_DECODE; dc->state = DECODE_STATE_DECODE;
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 */
if(data.chunk_length>0 && !dc->stop) { if (data.chunk_length > 0 && !dc->stop) {
flacSendChunk(&data); flacSendChunk(&data);
flushOutputBuffer(data.cb); flushOutputBuffer(data.cb);
} }
@ -382,17 +394,16 @@ static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc,
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
fail: fail:
oggflac_cleanup(inStream, &data, decoder); oggflac_cleanup(inStream, &data, decoder);
return ret; return ret;
} }
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

@ -61,86 +61,85 @@
#endif #endif
typedef struct _OggCallbackData { typedef struct _OggCallbackData {
InputStream * inStream; InputStream *inStream;
DecoderControl * dc; DecoderControl *dc;
} OggCallbackData; } OggCallbackData;
static size_t ogg_read_cb(void * ptr, size_t size, size_t nmemb, void * vdata) static size_t ogg_read_cb(void *ptr, size_t size, size_t nmemb, void *vdata)
{ {
size_t ret = 0; size_t ret = 0;
OggCallbackData * data = (OggCallbackData *)vdata; OggCallbackData *data = (OggCallbackData *) 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; */
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) == '=') {
return comment+len+1; return comment + len + 1;
} }
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;
} }
@ -148,32 +147,38 @@ static void ogg_getReplayGainInfo(char ** comments, ReplayGainInfo ** infoPtr) {
comments++; comments++;
} }
if(!found) { if (!found) {
freeReplayGainInfo(*infoPtr); freeReplayGainInfo(*infoPtr);
*infoPtr = NULL; *infoPtr = NULL;
} }
} }
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 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);
if(strncasecmp(comment, needle, len) == 0 && *(comment+len) == '=') { if (strncasecmp(comment, needle, len) == 0 && *(comment + len) == '=') {
if (!*tag) if (!*tag)
*tag = newMpdTag(); *tag = newMpdTag();
addItemToMpdTag(*tag, itemType, comment+len+1); addItemToMpdTag(*tag, itemType, comment + len + 1);
return 1; return 1;
} }
@ -181,12 +186,13 @@ 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) {
int j; int j;
for (j = TAG_NUM_OF_ITEM_TYPES; --j >= 0; ) { for (j = TAG_NUM_OF_ITEM_TYPES; --j >= 0;) {
if (ogg_parseCommentAddToTag(*comments, j, &tag)) if (ogg_parseCommentAddToTag(*comments, j, &tag))
break; break;
} }
@ -196,23 +202,24 @@ static MpdTag * oggCommentsParse(char ** comments) {
return tag; return tag;
} }
static void putOggCommentsIntoOutputBuffer(OutputBuffer * cb, char * streamName, static void putOggCommentsIntoOutputBuffer(OutputBuffer * cb, char *streamName,
char ** comments) char **comments)
{ {
MpdTag * tag; MpdTag *tag;
tag = oggCommentsParse(comments); tag = oggCommentsParse(comments);
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);
if(tag->track) printf("Track: %s\n", tag->track); if(tag->track) printf("Track: %s\n", tag->track);
if(tag->title) printf("Title: %s\n", tag->title);*/ if(tag->title) printf("Title: %s\n", tag->title); */
if(streamName) { if (streamName) {
clearItemsFromMpdTag(tag, TAG_ITEM_NAME); clearItemsFromMpdTag(tag, TAG_ITEM_NAME);
addItemToMpdTag(tag, TAG_ITEM_NAME, streamName); addItemToMpdTag(tag, TAG_ITEM_NAME, streamName);
} }
@ -238,9 +245,9 @@ static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
int chunkpos = 0; int chunkpos = 0;
long bitRate = 0; long bitRate = 0;
long test; long test;
ReplayGainInfo * replayGainInfo = NULL; ReplayGainInfo *replayGainInfo = NULL;
char ** comments; char **comments;
char * errorStr; char *errorStr;
data.inStream = inStream; data.inStream = inStream;
data.dc = dc; data.dc = dc;
@ -250,10 +257,10 @@ static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
callbacks.close_func = ogg_close_cb; callbacks.close_func = ogg_close_cb;
callbacks.tell_func = ogg_tell_cb; callbacks.tell_func = ogg_tell_cb;
if((ret = ov_open_callbacks(&data, &vf, NULL, 0, callbacks)) < 0) { if ((ret = ov_open_callbacks(&data, &vf, NULL, 0, callbacks)) < 0) {
closeInputStream(inStream); closeInputStream(inStream);
if(!dc->stop) { if (!dc->stop) {
switch(ret) { switch (ret) {
case OV_EREAD: case OV_EREAD:
errorStr = "read error"; errorStr = "read error";
break; break;
@ -276,39 +283,38 @@ 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;
} }
return 0; return 0;
} }
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;
while(!eof) { while (!eof) {
if(dc->seek) { if (dc->seek) {
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"); */
vorbis_info *vi=ov_info(&vf,-1); vorbis_info *vi = ov_info(&vf, -1);
dc->audioFormat.channels = vi->channels; dc->audioFormat.channels = vi->channels;
dc->audioFormat.sampleRate = vi->rate; dc->audioFormat.sampleRate = vi->rate;
if(dc->state == DECODE_STATE_START) { if (dc->state == DECODE_STATE_START) {
getOutputAudioFormat(&(dc->audioFormat), getOutputAudioFormat(&(dc->audioFormat),
&(cb->audioFormat)); &(cb->audioFormat));
dc->state = DECODE_STATE_DECODE; dc->state = DECODE_STATE_DECODE;
@ -321,71 +327,76 @@ static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
prev_section = current_section; prev_section = current_section;
if(ret <= 0 && ret != OV_HOLE) { if (ret <= 0 && ret != OV_HOLE) {
eof = 1; eof = 1;
break; break;
} }
if(ret == OV_HOLE) ret = 0; if (ret == OV_HOLE)
ret = 0;
chunkpos+=ret; chunkpos += ret;
if(chunkpos >= OGG_CHUNK_SIZE) { if (chunkpos >= OGG_CHUNK_SIZE) {
if((test = ov_bitrate_instant(&vf))>0) { if ((test = ov_bitrate_instant(&vf)) > 0) {
bitRate = test/1000; bitRate = test / 1000;
} }
sendDataToOutputBuffer(cb, inStream, dc, sendDataToOutputBuffer(cb, inStream, dc,
inStream->seekable, inStream->seekable,
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);
flushOutputBuffer(cb); flushOutputBuffer(cb);
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; {
FILE * fp; MpdTag *ret = NULL;
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) {
fclose(fp); fclose(fp);
return NULL; return NULL;
} }
ret = oggCommentsParse(ov_comment(&vf,-1)->user_comments); ret = oggCommentsParse(ov_comment(&vf, -1)->user_comments);
if(!ret) ret = newMpdTag(); if (!ret)
ret->time = (int)(ov_time_total(&vf,-1)+0.5); ret = newMpdTag();
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_MimeTypes[] = { "application/ogg", NULL };
static char * oggvorbis_Suffixes[] = {"ogg", NULL}; InputPlugin oggvorbisPlugin = {
static char * oggvorbis_MimeTypes[] = {"application/ogg", NULL};
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,34 +41,43 @@ 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);
} }
size_t readFromInputStream(InputStream * inStream, void * ptr, size_t size, size_t readFromInputStream(InputStream * inStream, void *ptr, size_t size,
size_t nmemb) size_t nmemb)
{ {
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

@ -23,19 +23,19 @@
typedef struct _InputStream InputStream; 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);
struct _InputStream { struct _InputStream {
int error; int error;
long offset; long offset;
size_t size; size_t size;
char * mime; char *mime;
int seekable; int seekable;
/* don't touc this stuff */ /* don't touc this stuff */
@ -44,18 +44,18 @@ struct _InputStream {
InputStreamCloseFunc closeFunc; InputStreamCloseFunc closeFunc;
InputStreamAtEOFFunc atEOFFunc; InputStreamAtEOFFunc atEOFFunc;
InputStreamBufferFunc bufferFunc; InputStreamBufferFunc bufferFunc;
void * data; void *data;
char * metaName; char *metaName;
char * metaTitle; char *metaTitle;
}; };
void initInputStream(); void initInputStream();
int isUrlSaneForInputStream(char * url); int isUrlSaneForInputStream(char *url);
/* if an error occurs for these 3 functions, then -1 is returned and errno /* if an error occurs for these 3 functions, then -1 is returned and errno
for the input stream is set */ for the input stream is set */
int openInputStream(InputStream * inStream, char * url); int openInputStream(InputStream * inStream, char *url);
int seekInputStream(InputStream * inStream, long offset, int whence); int seekInputStream(InputStream * inStream, long offset, int whence);
int closeInputStream(InputStream * inStream); int closeInputStream(InputStream * inStream);
int inputStreamAtEOF(InputStream * inStream); int inputStreamAtEOF(InputStream * inStream);
@ -64,7 +64,7 @@ int inputStreamAtEOF(InputStream * inStream);
was buffered */ was buffered */
int bufferInputStream(InputStream * inStream); int bufferInputStream(InputStream * inStream);
size_t readFromInputStream(InputStream * inStream, void * ptr, size_t size, size_t readFromInputStream(InputStream * inStream, void *ptr, size_t size,
size_t nmemb); size_t nmemb);
#endif #endif

View File

@ -26,23 +26,25 @@
#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");
if(!fp) { if (!fp) {
inStream->error = errno; inStream->error = errno;
return -1; return -1;
} }
inStream->seekable = 1; inStream->seekable = 1;
fseek(fp,0,SEEK_END); fseek(fp, 0, SEEK_END);
inStream->size = ftell(fp); inStream->size = ftell(fp);
fseek(fp,0,SEEK_SET); fseek(fp, 0, SEEK_SET);
inStream->data = fp; inStream->data = fp;
inStream->seekFunc = inputStream_fileSeek; inStream->seekFunc = inputStream_fileSeek;
@ -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) { {
inStream->offset = ftell((FILE *)inStream->data); if (fseek((FILE *) inStream->data, offset, whence) == 0) {
} inStream->offset = ftell((FILE *) inStream->data);
else { } else {
inStream->error = errno; inStream->error = errno;
return -1; return -1;
} }
@ -66,25 +68,26 @@ int inputStream_fileSeek(InputStream * inStream, long offset, int whence) {
return 0; return 0;
} }
size_t inputStream_fileRead(InputStream * inStream, void * ptr, size_t size, size_t inputStream_fileRead(InputStream * inStream, void *ptr, size_t size,
size_t nmemb) size_t nmemb)
{ {
size_t readSize; size_t readSize;
readSize = fread(ptr,size,nmemb,(FILE *)inStream->data); readSize = fread(ptr, size, nmemb, (FILE *) inStream->data);
if(readSize <=0 && ferror((FILE *)inStream->data)) { if (readSize <= 0 && ferror((FILE *) inStream->data)) {
inStream->error = errno; inStream->error = errno;
DEBUG("inputStream_fileRead: error reading: %s\n", DEBUG("inputStream_fileRead: error reading: %s\n",
strerror(inStream->error)); strerror(inStream->error));
} }
inStream->offset = ftell((FILE *)inStream->data); inStream->offset = ftell((FILE *) inStream->data);
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,16 +95,19 @@ 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;
} }
return 0; return 0;
} }
int inputStream_fileBuffer(InputStream * inStream) { int inputStream_fileBuffer(InputStream * inStream)
{
return 0; return 0;
} }

View File

@ -23,11 +23,11 @@
void inputStream_initFile(); void inputStream_initFile();
int inputStream_fileOpen(InputStream * inStream, char * filename); int inputStream_fileOpen(InputStream * inStream, char *filename);
int inputStream_fileSeek(InputStream * inStream, long offset, int whence); int inputStream_fileSeek(InputStream * inStream, long offset, int whence);
size_t inputStream_fileRead(InputStream * inStream, void * ptr, size_t size, size_t inputStream_fileRead(InputStream * inStream, void *ptr, size_t size,
size_t nmemb); size_t nmemb);
int inputStream_fileClose(InputStream * inStream); int inputStream_fileClose(InputStream * inStream);

File diff suppressed because it is too large Load Diff

View File

@ -23,11 +23,11 @@
void inputStream_initHttp(); void inputStream_initHttp();
int inputStream_httpOpen(InputStream * inStream, char * filename); int inputStream_httpOpen(InputStream * inStream, char *filename);
int inputStream_httpSeek(InputStream * inStream, long offset, int whence); int inputStream_httpSeek(InputStream * inStream, long offset, int whence);
size_t inputStream_httpRead(InputStream * inStream, void * ptr, size_t size, size_t inputStream_httpRead(InputStream * inStream, void *ptr, size_t size,
size_t nmemb); size_t nmemb);
int inputStream_httpClose(InputStream * inStream); int inputStream_httpClose(InputStream * inStream);

View File

@ -54,7 +54,7 @@
#define INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT (8192*1024) #define INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT (8192*1024)
/* set this to zero to indicate we have no possible interfaces */ /* set this to zero to indicate we have no possible interfaces */
static int interface_max_connections = 0; /*INTERFACE_MAX_CONNECTIONS_DEFAULT;*/ static int interface_max_connections = 0; /*INTERFACE_MAX_CONNECTIONS_DEFAULT; */
static int interface_timeout = INTERFACE_TIMEOUT_DEFAULT; static int interface_timeout = INTERFACE_TIMEOUT_DEFAULT;
static size_t interface_max_command_list_size = static size_t interface_max_command_list_size =
INTERFACE_MAX_COMMAND_LIST_DEFAULT; INTERFACE_MAX_COMMAND_LIST_DEFAULT;
@ -66,42 +66,43 @@ typedef struct _Interface {
int bufferLength; int bufferLength;
int bufferPos; int bufferPos;
int fd; /* file descriptor */ int fd; /* file descriptor */
FILE * fp; /* file pointer */ FILE *fp; /* file pointer */
int open; /* open/used */ int open; /* open/used */
int permission; int permission;
time_t lastTime; time_t lastTime;
List * commandList; /* for when in list mode */ List *commandList; /* for when in list mode */
int commandListOK; /* print OK after each command execution */ int commandListOK; /* print OK after each command execution */
size_t commandListSize; /* mem commandList consumes */ size_t commandListSize; /* mem commandList consumes */
List * bufferList; /* for output if client is slow */ List *bufferList; /* for output if client is slow */
size_t outputBufferSize; /* mem bufferList consumes */ size_t outputBufferSize; /* mem bufferList consumes */
int expired; /* set whether this interface should be closed on next int expired; /* set whether this interface should be closed on next
check of old interfaces */ check of old interfaces */
int num; /* interface number */ int num; /* interface number */
char * outBuffer; char *outBuffer;
int outBuflen; int outBuflen;
int outBufSize; int outBufSize;
} Interface; } Interface;
static Interface * interfaces = NULL; static Interface *interfaces = NULL;
static void flushInterfaceBuffer(Interface * interface); 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);
interface->bufferLength = 0; interface->bufferLength = 0;
interface->bufferPos = 0; interface->bufferPos = 0;
interface->fd = fd; interface->fd = fd;
/* fcntl(interface->fd,F_SETOWN,(int)getpid()); */ /* fcntl(interface->fd,F_SETOWN,(int)getpid()); */
while((flags = fcntl(fd,F_GETFL))<0 && errno==EINTR); while ((flags = fcntl(fd, F_GETFL)) < 0 && errno == EINTR) ;
flags|=O_NONBLOCK; flags |= O_NONBLOCK;
while(fcntl(interface->fd,F_SETFL,flags)<0 && errno==EINTR); while (fcntl(interface->fd, F_SETFL, flags) < 0 && errno == EINTR) ;
while((interface->fp = fdopen(fd,"rw"))==NULL && errno==EINTR); while ((interface->fp = fdopen(fd, "rw")) == NULL && errno == EINTR) ;
interface->open = 1; interface->open = 1;
interface->lastTime = time(NULL); interface->lastTime = time(NULL);
interface->commandList = NULL; interface->commandList = NULL;
@ -118,15 +119,13 @@ static void openInterface(Interface * interface, int fd) {
int getSize; int getSize;
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,42 +134,44 @@ 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++) ;
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");
} }
} }
@ -178,15 +179,14 @@ void openAInterface(int fd, struct sockaddr * addr) {
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
case AF_INET6: case AF_INET6:
{ {
char host[INET6_ADDRSTRLEN+1]; char host[INET6_ADDRSTRLEN + 1];
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");
} }
} }
@ -198,37 +198,36 @@ void openAInterface(int fd, struct sockaddr * addr) {
default: default:
SECURE("unknown\n"); SECURE("unknown\n");
} }
openInterface(&(interfaces[i]),fd); openInterface(&(interfaces[i]), fd);
} }
} }
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;
if(interface->bufferLength - interface->bufferPos > 1) { if (interface->bufferLength - interface->bufferPos > 1) {
if(interface->buffer[interface->bufferLength-2] == '\r') { if (interface->buffer[interface->bufferLength - 2] == '\r') {
interface->buffer[interface->bufferLength-2] = '\0'; interface->buffer[interface->bufferLength - 2] = '\0';
} }
} }
if(interface->commandList) { if (interface->commandList) {
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,33 +286,32 @@ 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) {
interface->bufferLength++; interface->bufferLength++;
bytesRead--; bytesRead--;
if(interface->buffer[interface->bufferLength-1]=='\n') { if (interface->buffer[interface->bufferLength - 1] == '\n') {
interface->buffer[interface->bufferLength-1] = '\0'; interface->buffer[interface->bufferLength - 1] = '\0';
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);
closeInterface(interface); closeInterface(interface);
return 1; return 1;
} }
interface->bufferLength-= interface->bufferPos; interface->bufferLength -= interface->bufferPos;
memmove(interface->buffer, memmove(interface->buffer,
interface->buffer+interface->bufferPos, interface->buffer + interface->bufferPos,
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;
} }
@ -330,50 +320,60 @@ static int processBytesRead(Interface * interface, int bytesRead) {
return ret; return ret;
} }
static int interfaceReadInput(Interface * interface) { 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)
else if(bytesRead == 0 || (bytesRead < 0 && errno != EINTR)) { return processBytesRead(interface, bytesRead);
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
FD_SET(interfaces[i].fd,fds); && !interfaces[i].bufferList) {
if(*fdmax<interfaces[i].fd) *fdmax = interfaces[i].fd; FD_SET(interfaces[i].fd, fds);
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
FD_SET(interfaces[i].fd,fds); && interfaces[i].bufferList) {
if(*fdmax<interfaces[i].fd) *fdmax = interfaces[i].fd; FD_SET(interfaces[i].fd, fds);
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;
@ -381,11 +381,11 @@ static void closeNextErroredInterface(void) {
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
for(i=0;i<interface_max_connections;i++) { for (i = 0; i < interface_max_connections; i++) {
if(interfaces[i].open) { if (interfaces[i].open) {
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(interfaces[i].fd,&fds); FD_SET(interfaces[i].fd, &fds);
if(select(FD_SETSIZE,&fds,NULL,NULL,&tv)<0) { if (select(FD_SETSIZE, &fds, NULL, NULL, &tv) < 0) {
closeInterface(&interfaces[i]); closeInterface(&interfaces[i]);
return; return;
} }
@ -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;
@ -404,31 +405,35 @@ int doIOForInterfaces(void) {
tv.tv_sec = 1; tv.tv_sec = 1;
tv.tv_usec = 0; tv.tv_usec = 0;
while(1) { while (1) {
fdmax = 0; fdmax = 0;
addInterfacesReadyToReadAndListenSocketToFdSet(&rfds,&fdmax); addInterfacesReadyToReadAndListenSocketToFdSet(&rfds, &fdmax);
addInterfacesForBufferFlushToFdSet(&wfds,&fdmax); addInterfacesForBufferFlushToFdSet(&wfds, &fdmax);
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();
continue; continue;
} }
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,16 +446,17 @@ 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;
param = getConfigParam(CONF_CONN_TIMEOUT); param = getConfigParam(CONF_CONN_TIMEOUT);
if(param) { if (param) {
interface_timeout = strtol(param->value,&test,10); interface_timeout = strtol(param->value, &test, 10);
if(*test!='\0' || interface_timeout<=0) { if (*test != '\0' || interface_timeout <= 0) {
ERROR("connection timeout \"%s\" is not a positive " ERROR("connection timeout \"%s\" is not a positive "
"integer, line %i\n", CONF_CONN_TIMEOUT, "integer, line %i\n", CONF_CONN_TIMEOUT,
param->line); param->line);
@ -460,65 +466,65 @@ void initInterfaces(void) {
param = getConfigParam(CONF_MAX_CONN); param = getConfigParam(CONF_MAX_CONN);
if(param) { if (param) {
interface_max_connections = strtol(param->value, &test, 10); interface_max_connections = strtol(param->value, &test, 10);
if(*test!='\0' || interface_max_connections<=0) { if (*test != '\0' || interface_max_connections <= 0) {
ERROR("max connections \"%s\" is not a positive integer" ERROR("max connections \"%s\" is not a positive integer"
", 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);
if(param) { if (param) {
interface_max_command_list_size = strtoll(param->value, interface_max_command_list_size = strtoll(param->value,
&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;
} }
param = getConfigParam(CONF_MAX_OUTPUT_BUFFER_SIZE); param = getConfigParam(CONF_MAX_OUTPUT_BUFFER_SIZE);
if(param) { if (param) {
interface_max_output_buffer_size = strtoll(param->value, &test, interface_max_output_buffer_size = strtoll(param->value, &test,
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;
} }
interfaces = malloc(sizeof(Interface)*interface_max_connections); interfaces = malloc(sizeof(Interface) * interface_max_connections);
for(i=0;i<interface_max_connections;i++) { for (i = 0; i < interface_max_connections; i++) {
interfaces[i].open = 0; interfaces[i].open = 0;
interfaces[i].num = i; interfaces[i].num = i;
} }
} }
static void closeAllInterfaces(void) { static void closeAllInterfaces(void)
{
int i; int i;
fflush(NULL); fflush(NULL);
for(i=0;i<interface_max_connections;i++) { for (i = 0; i < interface_max_connections; i++) {
if(interfaces[i].open) { if (interfaces[i].open) {
closeInterface(&(interfaces[i])); closeInterface(&(interfaces[i]));
} }
} }
} }
void freeAllInterfaces(void) { void freeAllInterfaces(void)
{
closeAllInterfaces(); closeAllInterfaces();
free(interfaces); free(interfaces);
@ -526,53 +532,52 @@ 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++) {
if(interfaces[i].open) { if (interfaces[i].open) {
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]));
} }
} }
} }
} }
static void flushInterfaceBuffer(Interface * interface) { static void flushInterfaceBuffer(Interface * interface)
ListNode * node = NULL; {
char * str; ListNode *node = NULL;
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)
else if(ret<strlen(str)) { break;
interface->outputBufferSize-=ret; else if (ret < strlen(str)) {
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);
} }
interface->lastTime = time(NULL); interface->lastTime = time(NULL);
} }
if(!interface->bufferList->firstNode) { if (!interface->bufferList->firstNode) {
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,36 +587,38 @@ 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)
if(interfaces[i].open && interfaces[i].fd==fd) break; 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;
interface->outBuflen+=copylen; interface->outBuflen += copylen;
buffer+=copylen; buffer += copylen;
if(interface->outBuflen>=interface->outBufSize) { if (interface->outBuflen >= interface->outBufSize) {
printInterfaceOutBuffer(interface); printInterfaceOutBuffer(interface);
} }
} }
@ -619,20 +626,20 @@ 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;
if(!interface->open || interface->expired || !interface->outBuflen) { if (!interface->open || interface->expired || !interface->outBuflen) {
return; return;
} }
if(interface->bufferList) { if (interface->bufferList) {
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,51 +649,50 @@ 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,
memcpy(buffer,interface->outBuffer,interface->outBuflen); 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) {
{ buffer = malloc(interface->outBuflen + 1);
if(errno==EAGAIN || errno==EINTR) { memcpy(buffer, interface->outBuffer,
buffer = malloc(interface->outBuflen+1);
memcpy(buffer,interface->outBuffer,
interface->outBuflen); interface->outBuflen);
buffer[interface->outBuflen] = '\0'; buffer[interface->outBuflen] = '\0';
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); buffer[interface->outBuflen - ret] = '\0';
buffer[interface->outBuflen-ret] = '\0';
interface->bufferList = makeList(free, 1); interface->bufferList = makeList(free, 1);
insertInListWithoutKey(interface->bufferList,buffer); insertInListWithoutKey(interface->bufferList, buffer);
} }
/* if we needed to create buffer, initialize bufferSize info */ /* if we needed to create buffer, initialize bufferSize info */
if(interface->bufferList) { if (interface->bufferList) {
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

@ -27,10 +27,10 @@
#include <sys/socket.h> #include <sys/socket.h>
void initInterfaces(); void initInterfaces();
void openAInterface(int fd, struct sockaddr * addr); void openAInterface(int fd, struct sockaddr *addr);
void freeAllInterfaces(); void freeAllInterfaces();
void closeOldInterfaces(); void closeOldInterfaces();
int interfacePrintWithFD(int fd, char * buffer, int len); int interfacePrintWithFD(int fd, char *buffer, int len);
int doIOForInterfaces(); int doIOForInterfaces();

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,31 +24,36 @@
#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);
for(i=0;i<list->numberOfNodes;i++) { for (i = 0; i < list->numberOfNodes; i++) {
list->nodesArray[i] = node; list->nodesArray[i] = node;
node = node->nextNode; node = node->nextNode;
} }
} }
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);
list->sorted = 0; list->sorted = 0;
list->firstNode = NULL; list->firstNode = NULL;
@ -62,61 +66,63 @@ 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;
assert(list!=NULL); assert(list != NULL);
assert(key!=NULL); assert(key != NULL);
/*assert(data!=NULL);*/ /*assert(data!=NULL); */
node = malloc(sizeof(ListNode)); node = malloc(sizeof(ListNode));
assert(node!=NULL); assert(node != NULL);
node->nextNode = beforeNode; node->nextNode = beforeNode;
if(beforeNode==list->firstNode) { if (beforeNode == list->firstNode) {
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;
list->numberOfNodes++; list->numberOfNodes++;
if(list->sorted) { if (list->sorted) {
list->nodesArray = realloc(list->nodesArray, list->nodesArray = realloc(list->nodesArray,
list->numberOfNodes*sizeof(ListNode *)); list->numberOfNodes *
if(node == list->lastNode) { sizeof(ListNode *));
list->nodesArray[list->numberOfNodes-1] = node; if (node == list->lastNode) {
} list->nodesArray[list->numberOfNodes - 1] = node;
else if(pos < 0) makeListNodesArray(list); } else if (pos < 0)
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,30 +130,33 @@ 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);
assert(key!=NULL); assert(key != NULL);
/*assert(data!=NULL);*/ /*assert(data!=NULL); */
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,24 +169,25 @@ 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);
assert(data!=NULL); assert(data != NULL);
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,147 +205,157 @@ 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;
ListNode * tmpNode; ListNode *tmpNode;
int cmp; int cmp;
assert(list!=NULL); assert(list != NULL);
if(list->sorted && list->nodesArray) { if (list->sorted && list->nodesArray) {
high = list->numberOfNodes-1; high = list->numberOfNodes - 1;
low = 0; low = 0;
cur = high; cur = high;
while(high>low) { while (high > low) {
cur = (high+low)/2; cur = (high + low) / 2;
tmpNode = list->nodesArray[cur]; tmpNode = list->nodesArray[cur];
cmp = strcmp(tmpNode->key,key); cmp = strcmp(tmpNode->key, key);
if(cmp==0) { if (cmp == 0) {
*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;
} }
} }
cur = high; cur = high;
if(cur>=0) { if (cur >= 0) {
tmpNode = list->nodesArray[cur]; tmpNode = list->nodesArray[cur];
*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) {
tmpNode = tmpNode->nextNode; tmpNode = tmpNode->nextNode;
} }
*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 * tmpNode; {
ListNode *node;
int pos;
assert(list!=NULL); if (findNodeInList(list, key, &node, &pos)) {
if (data)
*data = node->data;
return 1;
}
return 0;
}
int deleteFromList(List * list, char *key)
{
ListNode *tmpNode;
assert(list != NULL);
tmpNode = list->firstNode; tmpNode = list->firstNode;
while(tmpNode!=NULL && strcmp(tmpNode->key,key)!=0) { while (tmpNode != NULL && strcmp(tmpNode->key, key) != 0) {
tmpNode = tmpNode->nextNode; tmpNode = tmpNode->nextNode;
} }
if(tmpNode!=NULL) if (tmpNode != NULL)
deleteNodeFromList(list,tmpNode); deleteNodeFromList(list, tmpNode);
else else
return 0; return 0;
return 1; return 1;
} }
void deleteNodeFromList(List * list,ListNode * node) { void deleteNodeFromList(List * list, ListNode * node)
assert(list!=NULL); {
assert(node!=NULL); assert(list != 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 * tmpNode2; ListNode *tmpNode;
ListNode *tmpNode2;
assert(list!=NULL); assert(list != NULL);
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)
if(((List *)list)->freeDataFunc) { free(tmpNode->key);
((List *)list)->freeDataFunc(tmpNode->data); if (((List *) list)->freeDataFunc) {
((List *) list)->freeDataFunc(tmpNode->data);
} }
free(tmpNode); free(tmpNode);
tmpNode = tmpNode2; tmpNode = tmpNode2;
@ -344,12 +364,13 @@ void freeList(void * list) {
free(list); free(list);
} }
static void swapNodes(ListNode * nodeA, ListNode * nodeB) { static void swapNodes(ListNode * nodeA, ListNode * nodeB)
char * key; {
void * data; char *key;
void *data;
assert(nodeA!=NULL); assert(nodeA != NULL);
assert(nodeB!=NULL); assert(nodeB != NULL);
key = nodeB->key; key = nodeB->key;
data = nodeB->data; data = nodeB->data;
@ -361,98 +382,116 @@ 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--) {
node = nodesArray[i]; node = nodesArray[i];
if(strcmp(node->key,node->nextNode->key)>0) { if (strcmp(node->key, node->nextNode->key) > 0) {
swapNodes(node,node->nextNode); swapNodes(node, node->nextNode);
} }
} }
} }
} }
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;
long pivot; long pivot;
ListNode * pivotNode; ListNode *pivotNode;
char * pivotKey; char *pivotKey;
List * startList = makeList(free, 0); List *startList = makeList(free, 0);
List * endList = makeList(free, 0); List *endList = makeList(free, 0);
long * startPtr = malloc(sizeof(long)); long *startPtr = malloc(sizeof(long));
long * endPtr = malloc(sizeof(long)); long *endPtr = malloc(sizeof(long));
*startPtr = start; *startPtr = start;
*endPtr = end; *endPtr = end;
insertInListWithoutKey(startList,(void *)startPtr); insertInListWithoutKey(startList, (void *)startPtr);
insertInListWithoutKey(endList,(void *)endPtr); insertInListWithoutKey(endList, (void *)endPtr);
while(startList->numberOfNodes) { while (startList->numberOfNodes) {
start = *((long *)startList->lastNode->data); start = *((long *)startList->lastNode->data);
end = *((long *)endList->lastNode->data); end = *((long *)endList->lastNode->data);
if(end-start<5) { if (end - start < 5) {
bubbleSort(nodesArray,start,end); bubbleSort(nodesArray, start, end);
deleteNodeFromList(startList,startList->lastNode); deleteNodeFromList(startList,
deleteNodeFromList(endList,endList->lastNode); startList->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;
for(i=pivot-1;i>=start;i--) { for (i = pivot - 1; i >= start; i--) {
node = nodesArray[i]; node = nodesArray[i];
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];
} }
} }
for(i=pivot+1;i<=end;i++) { for (i = pivot + 1; i <= end; i++) {
node = nodesArray[i]; node = nodesArray[i];
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,
deleteNodeFromList(endList,endList->lastNode); startList->lastNode);
deleteNodeFromList(endList, endList->lastNode);
if(pivot-1-start>0) { if (pivot - 1 - start > 0) {
startPtr = malloc(sizeof(long)); startPtr = malloc(sizeof(long));
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) {
startPtr = malloc(sizeof(long)); startPtr = malloc(sizeof(long));
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,15 +501,18 @@ 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
@ -32,26 +31,26 @@ typedef void ListFreeDataFunc(void *);
typedef struct _ListNode { typedef struct _ListNode {
/* used to identify node (ie. when using findInList) */ /* used to identify node (ie. when using findInList) */
char * key; char *key;
/* data store in node */ /* data store in node */
void * data; void *data;
/* next node in list */ /* next node in list */
struct _ListNode * nextNode; struct _ListNode *nextNode;
/* previous node in list */ /* previous node in list */
struct _ListNode * prevNode; struct _ListNode *prevNode;
} ListNode; } ListNode;
typedef struct _List { typedef struct _List {
/* first node in list */ /* first node in list */
ListNode * firstNode; ListNode *firstNode;
/* last node in list */ /* last node in list */
ListNode * lastNode; ListNode *lastNode;
/* function used to free data stored in nodes of the list */ /* function used to free data stored in nodes of the list */
ListFreeDataFunc * freeDataFunc; ListFreeDataFunc *freeDataFunc;
/* number of nodes */ /* number of nodes */
long numberOfNodes; long numberOfNodes;
/* array for searching when list is sorted */ /* array for searching when list is sorted */
ListNode ** nodesArray; ListNode **nodesArray;
/* sorted */ /* sorted */
int sorted; int sorted;
/* weather to strdup() key's on insertion */ /* weather to strdup() key's on insertion */
@ -63,7 +62,7 @@ typedef struct _List {
* DEFAULT_FREE_DATAFUNC to use free() * DEFAULT_FREE_DATAFUNC to use free()
* returns pointer to new list if successful, NULL otherwise * returns pointer to new list if successful, NULL otherwise
*/ */
List * makeList(ListFreeDataFunc * freeDataFunc, int strdupKeys); List *makeList(ListFreeDataFunc * freeDataFunc, int strdupKeys);
/* inserts a node into _list_ with _key_ and _data_ /* inserts a node into _list_ with _key_ and _data_
* _list_ -> list the data will be inserted in * _list_ -> list the data will be inserted in
@ -71,21 +70,21 @@ List * makeList(ListFreeDataFunc * freeDataFunc, int strdupKeys);
* _data_ -> data to be inserted in list * _data_ -> data to be inserted in list
* returns 1 if successful, 0 otherwise * returns 1 if successful, 0 otherwise
*/ */
ListNode * insertInList(List * list,char * key,void * data); ListNode *insertInList(List * list, char *key, void *data);
ListNode * insertInListBeforeNode(List * list, ListNode * beforeNode, ListNode *insertInListBeforeNode(List * list, ListNode * beforeNode,
int pos, char * key, void * data); int pos, char *key, void *data);
int insertInListWithoutKey(List * list,void * data); int insertInListWithoutKey(List * list, void *data);
/* deletes the first node in the list with the key _key_ /* deletes the first node in the list with the key _key_
* _list_ -> list the node will be deleted from * _list_ -> list the node will be deleted from
* _key_ -> key used to identify node to delete * _key_ -> key used to identify node to delete
* returns 1 if node is found and deleted, 0 otherwise * returns 1 if node is found and deleted, 0 otherwise
*/ */
int deleteFromList(List * list,char * key); int deleteFromList(List * list, char *key);
void deleteNodeFromList(List * list,ListNode * node); void deleteNodeFromList(List * list, ListNode * node);
/* finds data in a list based on key /* finds data in a list based on key
* _list_ -> list to search for _key_ in * _list_ -> list to search for _key_ in
@ -95,16 +94,16 @@ void deleteNodeFromList(List * list,ListNode * node);
* _data_ can be NULL * _data_ can be NULL
* returns 1 if successful, 0 otherwise * returns 1 if successful, 0 otherwise
*/ */
int findInList(List * list, char * key, void ** data); int findInList(List * list, char *key, 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);
/* frees memory malloc'd for list and its nodes /* frees memory malloc'd for list and its nodes
* _list_ -> List to be free'd * _list_ -> List to be free'd
*/ */
void freeList(void * list); void freeList(void *list);
void sortList(List * list); void sortList(List * list);

View File

@ -40,18 +40,17 @@
#define DEFAULT_PORT 6600 #define DEFAULT_PORT 6600
int * listenSockets = NULL; 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;
int allowReuse = ALLOW_REUSE; int allowReuse = ALLOW_REUSE;
switch(addrp->sa_family) { switch (addrp->sa_family) {
case AF_INET: case AF_INET:
pf = PF_INET; pf = PF_INET;
break; break;
@ -64,49 +63,49 @@ static void establishListen(unsigned int port,
pf = PF_UNIX; pf = PF_UNIX;
break; break;
default: default:
ERROR("unknown address family: %i\n",addrp->sa_family); ERROR("unknown address family: %i\n", addrp->sa_family);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if((sock = socket(pf,SOCK_STREAM,0)) < 0) { if ((sock = socket(pf, SOCK_STREAM, 0)) < 0) {
ERROR("socket < 0\n"); ERROR("socket < 0\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(fcntl(sock, F_SETFL ,fcntl(sock, F_GETFL) | O_NONBLOCK) < 0) { if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) < 0) {
ERROR("problems setting nonblocking on listen socket: %s\n", ERROR("problems setting nonblocking on listen socket: %s\n",
strerror(errno)); strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
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);
} }
if(bind(sock,addrp,addrlen)<0) { if (bind(sock, addrp, addrlen) < 0) {
ERROR("unable to bind port %u", port); ERROR("unable to bind port %u", port);
ERROR(": %s\n", strerror(errno)); ERROR(": %s\n", strerror(errno));
ERROR("maybe MPD is still running?\n"); ERROR("maybe MPD is still running?\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(listen(sock,5)<0) { if (listen(sock, 5) < 0) {
ERROR("problems listen'ing: %s\n", strerror(errno)); ERROR("problems listen'ing: %s\n", strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
numberOfListenSockets++; numberOfListenSockets++;
listenSockets = listenSockets =
realloc(listenSockets,sizeof(int)*numberOfListenSockets); realloc(listenSockets, sizeof(int) * numberOfListenSockets);
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;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
@ -120,54 +119,52 @@ static void parseListenConfigParam(unsigned int port, ConfigParam * param) {
sin.sin_port = htons(port); sin.sin_port = htons(port);
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
if(!param || 0==strcmp(param->value, "any")) { if (!param || 0 == strcmp(param->value, "any")) {
DEBUG("binding to any address\n"); DEBUG("binding to any address\n");
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if(ipv6Supported()) { if (ipv6Supported()) {
sin6.sin6_addr = in6addr_any; sin6.sin6_addr = in6addr_any;
addrp = (struct sockaddr *) &sin6; addrp = (struct sockaddr *)&sin6;
addrlen = sizeof(struct sockaddr_in6); addrlen = sizeof(struct sockaddr_in6);
establishListen(port, addrp, addrlen); establishListen(port, addrp, addrlen);
} }
#endif #endif
sin.sin_addr.s_addr = INADDR_ANY; sin.sin_addr.s_addr = INADDR_ANY;
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))) {
ERROR("can't lookup host \"%s\" at line %i\n", ERROR("can't lookup host \"%s\" at line %i\n",
param->value, param->line); param->value, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
switch(he->h_addrtype) { switch (he->h_addrtype) {
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
case AF_INET6: case AF_INET6:
if(!ipv6Supported()) { if (!ipv6Supported()) {
ERROR("no IPv6 support, but a IPv6 address " ERROR("no IPv6 support, but a IPv6 address "
"found for \"%s\" at line %i\n", "found for \"%s\" at line %i\n",
param->value, param->line); param->value, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
bcopy((char *)he->h_addr,(char *) bcopy((char *)he->h_addr, (char *)
&sin6.sin6_addr.s6_addr,he->h_length); &sin6.sin6_addr.s6_addr, he->h_length);
addrp = (struct sockaddr *) &sin6; addrp = (struct sockaddr *)&sin6;
addrlen = sizeof(struct sockaddr_in6); addrlen = sizeof(struct sockaddr_in6);
break; break;
#endif #endif
case AF_INET: case AF_INET:
bcopy((char *)he->h_addr,(char *)&sin.sin_addr.s_addr, bcopy((char *)he->h_addr, (char *)&sin.sin_addr.s_addr,
he->h_length); he->h_length);
addrp = (struct sockaddr *) &sin; addrp = (struct sockaddr *)&sin;
addrlen = sizeof(struct sockaddr_in); addrlen = sizeof(struct sockaddr_in);
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,21 +172,21 @@ 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);
{ {
ConfigParam * portParam = getConfigParam(CONF_PORT); ConfigParam *portParam = getConfigParam(CONF_PORT);
if(portParam) { if (portParam) {
char * test; char *test;
port = strtol(portParam->value, &test, 10); port = strtol(portParam->value, &test, 10);
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,47 +197,51 @@ 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");
for(i=0; i<numberOfListenSockets; i++) { for (i = 0; i < numberOfListenSockets; i++) {
DEBUG("closing listen socket %i\n", i); DEBUG("closing listen socket %i\n", i);
while(close(listenSockets[i]) < 0 && errno==EINTR); while (close(listenSockets[i]) < 0 && errno == EINTR) ;
} }
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;
socklen_t socklen = sizeof(sockAddr); socklen_t socklen = sizeof(sockAddr);
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
} && (errno != EAGAIN && errno != EINTR)) {
else if(fd<0 && (errno!=EAGAIN && errno!=EINTR)) {
ERROR("Problems accept()'ing\n"); ERROR("Problems accept()'ing\n");
} }
} }

View File

@ -34,6 +34,6 @@ void closeAllListenSockets();
void freeAllListenSockets(); void freeAllListenSockets();
/* fdmax should be initialized to something */ /* fdmax should be initialized to something */
void addListenSocketsToFdSet(fd_set * fds, int * fdmax); void addListenSocketsToFdSet(fd_set * fds, int *fdmax);
#endif #endif

View File

@ -29,23 +29,25 @@
int logLevel = LOG_LEVEL_LOW; int logLevel = LOG_LEVEL_LOW;
short warningFlushed = 0; 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,11 +56,12 @@ 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];
memset(temp, 0, BUFFER_LENGTH+1); memset(temp, 0, BUFFER_LENGTH + 1);
va_start(arglist, format); va_start(arglist, format);
@ -69,15 +72,17 @@ 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) {
myfprintf(stderr, "%s\n", s); myfprintf(stderr, "%s\n", s);
s = strtok(NULL, "\n"); s = strtok(NULL, "\n");

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__)
@ -48,7 +47,7 @@ extern short warningFlushed;
void initLog(); void initLog();
void bufferWarning(char * format, ... ); void bufferWarning(char *format, ...);
void flushWarningLog(); void flushWarningLog();

203
src/ls.c
View File

@ -27,33 +27,34 @@
#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) {
myfprintf(fp,"handler: %s\n", *prefixes); myfprintf(fp, "handler: %s\n", *prefixes);
prefixes++; prefixes++;
} }
return 0; return 0;
} }
int isValidRemoteUtf8Url(char * utf8url) { int isValidRemoteUtf8Url(char *utf8url)
{
int ret = 0; int ret = 0;
char * temp; char *temp;
switch(isRemoteUrl(utf8url)) { switch (isRemoteUrl(utf8url)) {
case 1: case 1:
ret = 1; ret = 1;
temp = utf8url; temp = utf8url;
while(*temp) { while (*temp) {
if((*temp >= 'a' && *temp <= 'z') || if ((*temp >= 'a' && *temp <= 'z') ||
(*temp >= 'A' && *temp <= 'Z') || (*temp >= 'A' && *temp <= 'Z') ||
(*temp >= '0' && *temp <= '9') || (*temp >= '0' && *temp <= '9') ||
*temp == '$' || *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,13 +84,14 @@ 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;
while(*urlPrefixes) { while (*urlPrefixes) {
count++; count++;
if(strncmp(*urlPrefixes,url,strlen(*urlPrefixes)) == 0) { if (strncmp(*urlPrefixes, url, strlen(*urlPrefixes)) == 0) {
return count; return count;
} }
urlPrefixes++; urlPrefixes++;
@ -102,46 +100,47 @@ 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;
char * dup; char *dup;
char * utf8; char *utf8;
char s[MAXPATHLEN+1]; char s[MAXPATHLEN + 1];
List * list = NULL; List *list = NULL;
ListNode * node = NULL; ListNode *node = NULL;
char * path = utf8ToFsCharset(utf8path); char *path = utf8ToFsCharset(utf8path);
char * actualPath = rpp2app(path); char *actualPath = rpp2app(path);
int actlen = strlen(actualPath)+1; int actlen = strlen(actualPath) + 1;
int maxlen = MAXPATHLEN-actlen; int maxlen = MAXPATHLEN - actlen;
int suflen = strlen(PLAYLIST_FILE_SUFFIX)+1; int suflen = strlen(PLAYLIST_FILE_SUFFIX) + 1;
int suff; int suff;
if(actlen>MAXPATHLEN-1 || (dir = opendir(actualPath))==NULL) { if (actlen > MAXPATHLEN - 1 || (dir = opendir(actualPath)) == NULL) {
free(path); free(path);
return 0; return 0;
} }
s[MAXPATHLEN] = '\0'; s[MAXPATHLEN] = '\0';
/* this is safe, notice actlen > MAXPATHLEN-1 above */ /* this is safe, notice actlen > MAXPATHLEN-1 above */
strcpy(s,actualPath); strcpy(s, actualPath);
strcat(s,"/"); strcat(s, "/");
while((ent = readdir(dir))) { while ((ent = readdir(dir))) {
dup = ent->d_name; dup = ent->d_name;
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)
if(list==NULL) list = makeList(NULL, 1); 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);
free(utf8); free(utf8);
} }
} }
@ -152,21 +151,23 @@ int lsPlaylists(FILE * fp, char * utf8path) {
closedir(dir); closedir(dir);
free(path); free(path);
if(list) { if (list) {
int i; int i;
sortList(list); sortList(list);
dup = malloc(strlen(utf8path)+2); dup = malloc(strlen(utf8path) + 2);
strcpy(dup,utf8path); strcpy(dup, 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,71 +179,79 @@ 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 * actualFile = file; char *file = utf8ToFsCharset(utf8file);
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);
free(file); free(file);
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); {
if(s && 0==strcmp(s,suffix)) return 1; char *s = getSuffix(utf8file);
if (s && 0 == strcmp(s, suffix))
return 1;
return 0; return 0;
} }
int isPlaylist(char * utf8file) { int isPlaylist(char *utf8file)
if(isFile(utf8file,NULL)) { {
return hasSuffix(utf8file,PLAYLIST_FILE_SUFFIX); if (isFile(utf8file, NULL)) {
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) {
if(S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
return 1; return 1;
} }
} }
@ -250,26 +259,28 @@ 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)) { {
InputPlugin * plugin = hasMusicSuffix(utf8file, next); if (isFile(utf8file, mtime)) {
InputPlugin *plugin = hasMusicSuffix(utf8file, next);
if (plugin != NULL) if (plugin != NULL)
return plugin; return plugin;
} }
DEBUG("isMusic: %s is not a valid file\n",utf8file); DEBUG("isMusic: %s is not a valid file\n", utf8file);
return NULL; return NULL;
} }

View File

@ -29,23 +29,23 @@
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
int lsPlaylists(FILE * fp, char * utf8path); int lsPlaylists(FILE * fp, char *utf8path);
char * getSuffix(char * utf8file); char *getSuffix(char *utf8file);
int isValidRemoteUtf8Url(char * utf8url); int isValidRemoteUtf8Url(char *utf8url);
int isRemoteUrl(char * url); int isRemoteUrl(char *url);
int myStat(char * utf8file, struct stat * st); int myStat(char *utf8file, struct stat *st);
int isDir(char * utf8name); int isDir(char *utf8name);
int isPlaylist(char * utf8file); int isPlaylist(char *utf8file);
InputPlugin * hasMusicSuffix(char * utf8file, unsigned int next); InputPlugin *hasMusicSuffix(char *utf8file, unsigned int next);
InputPlugin * isMusic(char * utf8file, time_t * mtime, unsigned int next); InputPlugin *isMusic(char *utf8file, time_t * mtime, unsigned int next);
int printRemoteUrlHandlers(FILE * fp); int printRemoteUrlHandlers(FILE * fp);

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,10 +36,11 @@ 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';
dupElementToTag(TAG_ITEM_NAME, chunk->name); dupElementToTag(TAG_ITEM_NAME, chunk->name);
dupElementToTag(TAG_ITEM_TITLE, chunk->title); dupElementToTag(TAG_ITEM_TITLE, chunk->title);
@ -59,17 +61,19 @@ 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) {
case TAG_ITEM_NAME: case TAG_ITEM_NAME:
copyStringToChunk(tag->items[i].value, chunk->name); copyStringToChunk(tag->items[i].value, chunk->name);
break; break;

View File

@ -31,7 +31,7 @@ typedef struct _MetadataChunk {
char buffer[METADATA_BUFFER_LENGTH]; char buffer[METADATA_BUFFER_LENGTH];
} MetadataChunk; } MetadataChunk;
MpdTag * metadataChunkToMpdTagDup(MetadataChunk * chunk); MpdTag *metadataChunkToMpdTagDup(MetadataChunk * chunk);
void copyMpdTagToMetadataChunk(MpdTag * tag, MetadataChunk * chunk); void copyMpdTagToMetadataChunk(MpdTag * tag, MetadataChunk * chunk);

View File

@ -33,19 +33,21 @@
#define BUFFER_LENGTH MAXPATHLEN+1024 #define BUFFER_LENGTH MAXPATHLEN+1024
static int myfprintf_stdLogMode = 0; static int myfprintf_stdLogMode = 0;
static FILE * myfprintf_out; static FILE *myfprintf_out;
static FILE * myfprintf_err; 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)
if(ret<0) { return;
switch(errno) { if (ret < 0) {
switch (errno) {
case EAGAIN: case EAGAIN:
case EINTR: case EINTR:
continue; continue;
@ -53,12 +55,13 @@ static void blockingWrite(int fd, char * string, int len) {
return; return;
} }
} }
len-= ret; len -= ret;
string+= ret; string += ret;
} }
} }
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,64 +69,68 @@ 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);
va_start(arglist,format); va_start(arglist, 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;
strftime(buffer,14,"%b %e %R",localtime(&t)); else
blockingWrite(fd,buffer,strlen(buffer)); fp = myfprintf_err;
blockingWrite(fd," : ",3); strftime(buffer, 14, "%b %e %R", localtime(&t));
blockingWrite(fd, buffer, strlen(buffer));
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);
if(interfacePrintWithFD(fd,buffer,len)<0) { if (interfacePrintWithFD(fd, buffer, len) < 0) {
blockingWrite(fd,buffer,len); blockingWrite(fd, buffer, len);
} }
} }
va_end(arglist); va_end(arglist);
} }
int myfprintfCloseAndOpenLogFile(void) { int myfprintfCloseAndOpenLogFile(void)
if(myfprintf_stdLogMode) { {
while(fclose(myfprintf_out)<0 && errno==EINTR); if (myfprintf_stdLogMode) {
while(fclose(myfprintf_err)<0 && errno==EINTR); while (fclose(myfprintf_out) < 0 && errno == EINTR) ;
while((myfprintf_out = fopen(myfprintf_outFilename,"a+"))==NULL while (fclose(myfprintf_err) < 0 && errno == EINTR) ;
&& errno==EINTR); while ((myfprintf_out =
if(!myfprintf_out) { fopen(myfprintf_outFilename, "a+")) == NULL
ERROR("error re-opening log file: %s\n", && errno == EINTR) ;
myfprintf_out); if (!myfprintf_out) {
ERROR("error re-opening log file: %s\n", myfprintf_out);
return -1; return -1;
} }
while((myfprintf_err = fopen(myfprintf_errFilename,"a+"))==NULL while ((myfprintf_err =
&& errno==EINTR); fopen(myfprintf_errFilename, "a+")) == NULL
if(!myfprintf_out) { && errno == EINTR) ;
ERROR("error re-opening log file: %s\n", if (!myfprintf_out) {
myfprintf_out); ERROR("error re-opening log file: %s\n", myfprintf_out);
return -1; return -1;
} }
while(dup2(fileno(myfprintf_out),1)<0 && errno==EINTR); while (dup2(fileno(myfprintf_out), 1) < 0 && errno == EINTR) ;
while(dup2(fileno(myfprintf_err),2)<0 && errno==EINTR); while (dup2(fileno(myfprintf_err), 2) < 0 && errno == EINTR) ;
} }
return 0; return 0;
} }
void myfprintfCloseLogFile(void) { void myfprintfCloseLogFile(void)
if(myfprintf_stdLogMode) { {
while(fclose(myfprintf_out)<0 && errno==EINTR); if (myfprintf_stdLogMode) {
while(fclose(myfprintf_err)<0 && errno==EINTR); while (fclose(myfprintf_out) < 0 && errno == EINTR) ;
while (fclose(myfprintf_err) < 0 && errno == EINTR) ;
} }
} }

View File

@ -25,7 +25,7 @@
void myfprintfStdLogMode(FILE * out, FILE * err); void myfprintfStdLogMode(FILE * out, FILE * err);
void myfprintf(FILE * fp, char * format, ... ); void myfprintf(FILE * fp, char *format, ...);
int myfprintfCloseAndOpenLogFile(); int myfprintfCloseAndOpenLogFile();

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;
@ -42,19 +44,20 @@ void clearOutputBuffer(OutputBuffer * cb) {
/* be sure to reset metaChunkSets cause we are skipping over audio /* be sure to reset metaChunkSets cause we are skipping over audio
* audio chunks, and thus skipping over metadata */ * audio chunks, and thus skipping over metadata */
if(sendMetaChunk == 0 && currentMetaChunk >= 0) { if (sendMetaChunk == 0 && currentMetaChunk >= 0) {
currentSet = cb->metaChunkSet[currentChunk]; currentSet = cb->metaChunkSet[currentChunk];
} }
clearAllMetaChunkSets(cb); clearAllMetaChunkSets(cb);
if(sendMetaChunk == 0 && currentMetaChunk >= 0) { if (sendMetaChunk == 0 && currentMetaChunk >= 0) {
cb->metaChunkSet[currentChunk] = currentSet; cb->metaChunkSet[currentChunk] = currentSet;
} }
} }
void flushOutputBuffer(OutputBuffer * cb) { void flushOutputBuffer(OutputBuffer * cb)
if(currentChunk == cb->end) { {
int next = cb->end+1; if (currentChunk == cb->end) {
if(next>=buffered_chunks) { int next = cb->end + 1;
if (next >= buffered_chunks) {
next = 0; next = 0;
} }
cb->end = next; cb->end = next;
@ -63,85 +66,85 @@ void flushOutputBuffer(OutputBuffer * cb) {
} }
int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream, int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
DecoderControl * dc, int seekable, void * dataIn, DecoderControl * dc, int seekable, void *dataIn,
long dataInLen, float time, mpd_uint16 bitRate, long dataInLen, float time, mpd_uint16 bitRate,
ReplayGainInfo * replayGainInfo) ReplayGainInfo * replayGainInfo)
{ {
mpd_uint16 dataToSend; mpd_uint16 dataToSend;
mpd_uint16 chunkLeft; mpd_uint16 chunkLeft;
char * data; char *data;
size_t datalen; size_t datalen;
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),
if(datalen > convBufferLen) { dataInLen,
convBuffer = realloc(convBuffer,datalen); &(cb->
audioFormat));
if (datalen > convBufferLen) {
convBuffer = realloc(convBuffer, datalen);
convBufferLen = datalen; convBufferLen = datalen;
} }
data = convBuffer; data = convBuffer;
pcm_convertAudioFormat(&(dc->audioFormat), dataIn, dataInLen, pcm_convertAudioFormat(&(dc->audioFormat), dataIn, dataInLen,
&(cb->audioFormat),data); &(cb->audioFormat), data);
} }
if(replayGainInfo) { if (replayGainInfo) {
doReplayGain(replayGainInfo, data, datalen, &cb->audioFormat); doReplayGain(replayGainInfo, data, datalen, &cb->audioFormat);
} }
while(datalen) { while (datalen) {
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) {
next = 0; next = 0;
} }
while(cb->begin==next && !dc->stop) { while (cb->begin == next && !dc->stop) {
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;
} }
chunkLeft = CHUNK_SIZE-cb->chunkSize[currentChunk]; chunkLeft = CHUNK_SIZE - cb->chunkSize[currentChunk];
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;
if(cb->chunkSize[currentChunk] == CHUNK_SIZE) { if (cb->chunkSize[currentChunk] == CHUNK_SIZE) {
flushOutputBuffer(cb); flushOutputBuffer(cb);
} }
} }
@ -149,30 +152,34 @@ 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;
} }
if(last && mpdTagsAreEqual(last, tag)) { if (last && mpdTagsAreEqual(last, tag)) {
DEBUG("copyMpdTagToOB: same as last\n"); DEBUG("copyMpdTagToOB: same as last\n");
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;
DEBUG("copyMpdTagToOB: metachunk in use!\n"); DEBUG("copyMpdTagToOB: metachunk in use!\n");
return -1; return -1;

View File

@ -32,16 +32,16 @@
#define BUFFERED_METACHUNKS 25 #define BUFFERED_METACHUNKS 25
typedef struct _OutputBuffer { typedef struct _OutputBuffer {
char * volatile chunks; char *volatile chunks;
mpd_uint16 * volatile chunkSize; mpd_uint16 *volatile chunkSize;
mpd_uint16 * volatile bitRate; mpd_uint16 *volatile bitRate;
float * volatile times; float *volatile times;
mpd_sint16 volatile begin; mpd_sint16 volatile begin;
mpd_sint16 volatile end; mpd_sint16 volatile end;
AudioFormat audioFormat; AudioFormat audioFormat;
MetadataChunk metadataChunks[BUFFERED_METACHUNKS]; MetadataChunk metadataChunks[BUFFERED_METACHUNKS];
mpd_sint8 metaChunkSet[BUFFERED_METACHUNKS]; mpd_sint8 metaChunkSet[BUFFERED_METACHUNKS];
mpd_sint8 * volatile metaChunk; mpd_sint8 *volatile metaChunk;
volatile mpd_sint8 acceptMetadata; volatile mpd_sint8 acceptMetadata;
} OutputBuffer; } OutputBuffer;
@ -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

@ -37,23 +37,25 @@
#endif #endif
#endif #endif
char * musicDir; char *musicDir;
char * playlistDir; 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);
} }
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)) {
free(ret); free(ret);
ret = NULL; ret = NULL;
} }
@ -61,54 +63,60 @@ 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);
DEBUG("setFsCharset: fs charset is: %s\n",fsCharset); DEBUG("setFsCharset: fs charset is: %s\n", fsCharset);
if(setCharSetConversion("UTF-8",fsCharset)!=0) { if (setCharSetConversion("UTF-8", fsCharset) != 0) {
WARNING("fs charset conversion problem: " WARNING("fs charset conversion problem: "
"not able to convert from \"%s\" to \"%s\"\n", "not able to convert from \"%s\" to \"%s\"\n",
fsCharset,"UTF-8"); fsCharset, "UTF-8");
error = 1; error = 1;
} }
if(setCharSetConversion(fsCharset,"UTF-8")!=0) { if (setCharSetConversion(fsCharset, "UTF-8") != 0) {
WARNING("fs charset conversion problem: " WARNING("fs charset conversion problem: "
"not able to convert from \"%s\" to \"%s\"\n", "not able to convert from \"%s\" to \"%s\"\n",
"UTF-8",fsCharset); "UTF-8", fsCharset);
error = 1; error = 1;
} }
if(error) { if (error) {
free(fsCharset); free(fsCharset);
WARNING("setting fs charset to ISO-8859-1!\n"); WARNING("setting fs charset to ISO-8859-1!\n");
fsCharset = strdup("ISO-8859-1"); fsCharset = strdup("ISO-8859-1");
} }
} }
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);
if(temp[len-1] != '/') { if (temp[len - 1] != '/') {
temp = malloc(len+2); temp = malloc(len + 2);
memset(temp, 0, len+2); memset(temp, 0, len + 2);
memcpy(temp, *path, len); memcpy(temp, *path, len);
temp[len] = '/'; temp[len] = '/';
free(*path); free(*path);
@ -118,19 +126,20 @@ static char * appendSlash(char ** path) {
return temp; return temp;
} }
void initPaths(void) { void initPaths(void)
ConfigParam * musicParam = parseConfigFilePath(CONF_MUSIC_DIR, 1); {
ConfigParam * playlistParam = parseConfigFilePath(CONF_PLAYLIST_DIR, 1); ConfigParam *musicParam = parseConfigFilePath(CONF_MUSIC_DIR, 1);
ConfigParam * fsCharsetParam = getConfigParam(CONF_FS_CHARSET); ConfigParam *playlistParam = parseConfigFilePath(CONF_PLAYLIST_DIR, 1);
ConfigParam *fsCharsetParam = getConfigParam(CONF_FS_CHARSET);
char * charset = NULL; char *charset = NULL;
char * originalLocale; char *originalLocale;
DIR * dir; DIR *dir;
musicDir = appendSlash(&(musicParam->value)); musicDir = appendSlash(&(musicParam->value));
playlistDir = appendSlash(&(playlistParam->value)); playlistDir = appendSlash(&(playlistParam->value));
if((dir = opendir(playlistDir)) == NULL) { if ((dir = opendir(playlistDir)) == NULL) {
ERROR("cannot open %s \"%s\" (config line %i): %s\n", ERROR("cannot open %s \"%s\" (config line %i): %s\n",
CONF_PLAYLIST_DIR, playlistParam->value, CONF_PLAYLIST_DIR, playlistParam->value,
playlistParam->line, strerror(errno)); playlistParam->line, strerror(errno));
@ -138,7 +147,7 @@ void initPaths(void) {
} }
closedir(dir); closedir(dir);
if((dir = opendir(musicDir)) == NULL) { if ((dir = opendir(musicDir)) == NULL) {
ERROR("cannot open %s \"%s\" (config line %i): %s\n", ERROR("cannot open %s \"%s\" (config line %i): %s\n",
CONF_MUSIC_DIR, musicParam->value, CONF_MUSIC_DIR, musicParam->value,
musicParam->line, strerror(errno)); musicParam->line, strerror(errno));
@ -146,132 +155,136 @@ void initPaths(void) {
} }
closedir(dir); closedir(dir);
if(fsCharsetParam) { if (fsCharsetParam) {
charset = strdup(fsCharsetParam->value); charset = strdup(fsCharsetParam->value);
} }
#ifdef HAVE_LOCALE #ifdef HAVE_LOCALE
#ifdef HAVE_LANGINFO_CODESET #ifdef HAVE_LANGINFO_CODESET
else if((originalLocale = setlocale(LC_CTYPE,NULL))) { else if ((originalLocale = setlocale(LC_CTYPE, NULL))) {
char * temp; char *temp;
char * currentLocale; char *currentLocale;
originalLocale = strdup(originalLocale); originalLocale = strdup(originalLocale);
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
if(!setlocale(LC_CTYPE,originalLocale)) { ("problems getting charset for locale\n");
WARNING("problems resetting locale with setlocale()\n"); if (!setlocale(LC_CTYPE, originalLocale)) {
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);
strncpy(absolutePath,musicDir,MAXPATHLEN); strncpy(absolutePath, musicDir, MAXPATHLEN);
strncat(absolutePath,relativePath,MAXPATHLEN-strlen(musicDir)); strncat(absolutePath, relativePath, MAXPATHLEN - strlen(musicDir));
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);
strncpy(absolutePath,playlistDir,MAXPATHLEN); strncpy(absolutePath, playlistDir, MAXPATHLEN);
strncat(absolutePath,relativePath,MAXPATHLEN-strlen(musicDir)); strncat(absolutePath, relativePath, MAXPATHLEN - strlen(musicDir));
return absolutePath; return absolutePath;
} }
char * parentPath(char * path) { char *parentPath(char *path)
static char parentPath[MAXPATHLEN+1]; {
char * c; static char parentPath[MAXPATHLEN + 1];
char *c;
memset(parentPath,0,MAXPATHLEN+1); memset(parentPath, 0, MAXPATHLEN + 1);
strncpy(parentPath,path,MAXPATHLEN); strncpy(parentPath, path, MAXPATHLEN);
c = strrchr(parentPath,'/'); c = strrchr(parentPath, '/');
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; {
char * ret = malloc(len); int len = strlen(path) + 1;
char * cp = ret; char *ret = malloc(len);
char *cp = ret;
memset(ret,0,len); memset(ret, 0, len);
len = 0; len = 0;
/* 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 == '/')
if(*path=='.') { 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 */
free(ret); free(ret);
return NULL; return NULL;
} }
while(*path && *path!='/') { while (*path && *path != '/') {
*(cp++) = *(path++); *(cp++) = *(path++);
len++; len++;
} }
if(*path=='/') { if (*path == '/') {
*(cp++) = *(path++); *(cp++) = *(path++);
len++; len++;
} }
} }
if(len && ret[len-1]=='/') { if (len && ret[len - 1] == '/') {
len--; len--;
ret[len] = '\0'; ret[len] = '\0';
} }
DEBUG("sanitized: %s\n", ret); DEBUG("sanitized: %s\n", ret);
return realloc(ret,len+1); return realloc(ret, len + 1);
} }

View File

@ -23,32 +23,32 @@
#include <sys/param.h> #include <sys/param.h>
extern char * musicDir; extern char *musicDir;
void initPaths(); void initPaths();
void finishPaths(); void finishPaths();
char * utf8ToFsCharset(char * str); char *utf8ToFsCharset(char *str);
char * fsCharsetToUtf8(char * str); char *fsCharsetToUtf8(char *str);
void setFsCharset(char * charset); void setFsCharset(char *charset);
char * getFsCharset(); char *getFsCharset();
/* relative music path to absolute music path /* relative music path to absolute music path
* char * passed is a static variable, so don't free it * char * passed is a static variable, so don't free it
*/ */
char * rmp2amp(char * file); char *rmp2amp(char *file);
/* static char * returned */ /* static char * returned */
char * rpp2app(char * file); char *rpp2app(char *file);
/* static char * returned */ /* static char * returned */
char * parentPath(char * path); char *parentPath(char *path);
/* strips extra "///" and leading "/" and trailing "/" */ /* strips extra "///" and leading "/" and trailing "/" */
char * sanitizePathDup(char * path); char *sanitizePathDup(char *path);
#endif #endif

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"
@ -26,39 +25,40 @@
#include <math.h> #include <math.h>
#include <assert.h> #include <assert.h>
void pcm_volumeChange(char * buffer, int bufferSize, AudioFormat * format, void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format,
int volume) int volume)
{ {
mpd_sint32 temp32; mpd_sint32 temp32;
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);
return; return;
} }
switch(format->bits) { switch (format->bits) {
case 16: case 16:
while(bufferSize>0) { while (bufferSize > 0) {
temp32 = *buffer16; temp32 = *buffer16;
temp32*= volume; temp32 *= volume;
temp32/=1000; temp32 /= 1000;
*buffer16 = temp32>32767 ? 32767 : *buffer16 = temp32 > 32767 ? 32767 :
(temp32<-32768 ? -32768 : temp32); (temp32 < -32768 ? -32768 : temp32);
buffer16++; buffer16++;
bufferSize-=2; bufferSize -= 2;
} }
break; break;
case 8: case 8:
while(bufferSize>0) { while (bufferSize > 0) {
temp32 = *buffer8; temp32 = *buffer8;
temp32*= volume; temp32 *= volume;
temp32/=1000; temp32 /= 1000;
*buffer8 = temp32>127 ? 127 : *buffer8 = temp32 > 127 ? 127 :
(temp32<-128 ? -128 : temp32); (temp32 < -128 ? -128 : temp32);
buffer8++; buffer8++;
bufferSize--; bufferSize--;
} }
@ -70,90 +70,98 @@ 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;
mpd_sint8 * buffer8_2 = (mpd_sint8 *)buffer2; mpd_sint8 *buffer8_2 = (mpd_sint8 *) buffer2;
mpd_sint16 * buffer16_1 = (mpd_sint16 *)buffer1; mpd_sint16 *buffer16_1 = (mpd_sint16 *) buffer1;
mpd_sint16 * buffer16_2 = (mpd_sint16 *)buffer2; mpd_sint16 *buffer16_2 = (mpd_sint16 *) buffer2;
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);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
void pcm_mix(char * buffer1, char * buffer2, size_t bufferSize1, void pcm_mix(char *buffer1, char *buffer2, size_t bufferSize1,
size_t bufferSize2, AudioFormat * format, float portion1) size_t bufferSize2, AudioFormat * format, float portion1)
{ {
int vol1; int vol1;
float s = sin(M_PI_2*portion1); float s = sin(M_PI_2 * portion1);
s*=s; s *= s;
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)
{ {
static char * bitConvBuffer = NULL; static char *bitConvBuffer = NULL;
static int bitConvBufferLength = 0; static int bitConvBufferLength = 0;
static char * channelConvBuffer = NULL; static char *channelConvBuffer = NULL;
static int channelConvBufferLength = 0; static int channelConvBufferLength = 0;
char * dataChannelConv; char *dataChannelConv;
int dataChannelLen; int dataChannelLen;
char * dataBitConv; char *dataBitConv;
int dataBitLen; int dataBitLen;
assert(outFormat->bits==16); assert(outFormat->bits == 16);
assert(outFormat->channels==2 || outFormat->channels==1); assert(outFormat->channels == 2 || outFormat->channels == 1);
/* converts */ /* converts */
switch(inFormat->bits) { switch (inFormat->bits) {
case 8: case 8:
dataBitLen = inSize << 1; dataBitLen = inSize << 1;
if(dataBitLen > bitConvBufferLength) { if (dataBitLen > bitConvBufferLength) {
bitConvBuffer = realloc(bitConvBuffer, dataBitLen); bitConvBuffer = realloc(bitConvBuffer, dataBitLen);
bitConvBufferLength = dataBitLen; bitConvBufferLength = dataBitLen;
} }
dataBitConv = bitConvBuffer; dataBitConv = bitConvBuffer;
{ {
mpd_sint8 * in = (mpd_sint8 *)inBuffer; mpd_sint8 *in = (mpd_sint8 *) inBuffer;
mpd_sint16 * out = (mpd_sint16 *)dataBitConv; mpd_sint16 *out = (mpd_sint16 *) dataBitConv;
int i; int i;
for(i=0; i<inSize; i++) { for (i = 0; i < inSize; i++) {
*out++ = (*in++) << 8; *out++ = (*in++) << 8;
} }
} }
@ -170,27 +178,26 @@ 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:
dataChannelLen = (dataBitLen >> 1) << 2; dataChannelLen = (dataBitLen >> 1) << 2;
if(dataChannelLen > channelConvBufferLength) { if (dataChannelLen > channelConvBufferLength) {
channelConvBuffer = realloc(channelConvBuffer, channelConvBuffer = realloc(channelConvBuffer,
dataChannelLen); dataChannelLen);
channelConvBufferLength = dataChannelLen; channelConvBufferLength = dataChannelLen;
} }
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;
*out++ = *in++; *out++ = *in++;
} }
@ -199,67 +206,68 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t
/* convert from 2 -> 1 channels */ /* convert from 2 -> 1 channels */
case 2: case 2:
dataChannelLen = dataBitLen >> 1; dataChannelLen = dataBitLen >> 1;
if(dataChannelLen > channelConvBufferLength) { if (dataChannelLen > channelConvBufferLength) {
channelConvBuffer = realloc(channelConvBuffer, channelConvBuffer = realloc(channelConvBuffer,
dataChannelLen); dataChannelLen);
channelConvBufferLength = dataChannelLen; channelConvBufferLength = dataChannelLen;
} }
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;
*out++ += (*in++)/2; *out++ += (*in++) / 2;
} }
} }
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;
mpd_uint32 wr_dat = 0; mpd_uint32 wr_dat = 0;
mpd_sint16 lsample, rsample; mpd_sint16 lsample, rsample;
mpd_sint16 * out = (mpd_sint16 *)outBuffer; mpd_sint16 *out = (mpd_sint16 *) outBuffer;
mpd_sint16 * in = (mpd_sint16 *)dataChannelConv; mpd_sint16 *in = (mpd_sint16 *) dataChannelConv;
const int shift = sizeof(mpd_sint16)*outFormat->channels; const int shift = sizeof(mpd_sint16) * outFormat->channels;
mpd_uint32 nlen = ((( dataChannelLen / shift) * mpd_uint32 nlen = (((dataChannelLen / shift) *
(mpd_uint32)(outFormat->sampleRate)) / (mpd_uint32) (outFormat->sampleRate)) /
inFormat->sampleRate); inFormat->sampleRate);
nlen *= outFormat->channels; nlen *= outFormat->channels;
switch(outFormat->channels) { switch (outFormat->channels) {
case 1: case 1:
while( wr_dat < nlen) { while (wr_dat < nlen) {
rd_dat = wr_dat * inFormat->sampleRate / rd_dat = wr_dat * inFormat->sampleRate /
outFormat->sampleRate; outFormat->sampleRate;
lsample = in[ rd_dat++ ]; lsample = in[rd_dat++];
out[ wr_dat++ ] = lsample; out[wr_dat++] = lsample;
} }
break; break;
case 2: case 2:
while( wr_dat < nlen) { while (wr_dat < nlen) {
rd_dat = wr_dat * inFormat->sampleRate / rd_dat = wr_dat * inFormat->sampleRate /
outFormat->sampleRate; outFormat->sampleRate;
rd_dat &= ~1; rd_dat &= ~1;
lsample = in[ rd_dat++ ]; lsample = in[rd_dat++];
rsample = in[ rd_dat++ ]; rsample = in[rd_dat++];
out[ wr_dat++ ] = lsample; out[wr_dat++] = lsample;
out[ wr_dat++ ] = rsample; out[wr_dat++] = rsample;
} }
break; break;
} }
@ -269,12 +277,13 @@ 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;
switch(inFormat->bits) { switch (inFormat->bits) {
case 8: case 8:
outSize = outSize << 1; outSize = outSize << 1;
break; break;
@ -285,8 +294,8 @@ size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat,
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(inFormat->channels != outFormat->channels) { if (inFormat->channels != outFormat->channels) {
switch(inFormat->channels) { switch (inFormat->channels) {
case 1: case 1:
outSize = (outSize >> 1) << 2; outSize = (outSize >> 1) << 2;
break; break;
@ -296,7 +305,7 @@ size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat,
} }
} }
outSize = (((outSize / shift) * (mpd_uint32)(outFormat->sampleRate)) / outSize = (((outSize / shift) * (mpd_uint32) (outFormat->sampleRate)) /
inFormat->sampleRate); inFormat->sampleRate);
outSize *= shift; outSize *= shift;

View File

@ -25,15 +25,16 @@
#include <stdlib.h> #include <stdlib.h>
void pcm_volumeChange(char * buffer, int bufferSize, AudioFormat * format, void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format,
int volume); int volume);
void pcm_mix(char * buffer1, char * buffer2, size_t bufferSize1, void pcm_mix(char *buffer1, char *buffer2, size_t bufferSize1,
size_t bufferSize2, AudioFormat * format, float portion1); size_t bufferSize2, AudioFormat * format, float portion1);
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);
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

@ -32,48 +32,47 @@
#define PERMISSION_CONTROL_STRING "control" #define PERMISSION_CONTROL_STRING "control"
#define PERMISSION_ADMIN_STRING "admin" #define PERMISSION_ADMIN_STRING "admin"
static List * permission_passwords; 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);
} }
temp = strtok_r(NULL,PERMISSION_SEPERATOR,&tok); temp = strtok_r(NULL, PERMISSION_SEPERATOR, &tok);
} }
return permission; return permission;
} }
void initPermissions(void) { void initPermissions(void)
char * temp; {
char * cp2; char *temp;
char * password; char *cp2;
int * permission; char *password;
ConfigParam * param; int *permission;
ConfigParam *param;
permission_passwords = makeList(free, 1); permission_passwords = makeList(free, 1);
@ -82,46 +81,50 @@ void initPermissions(void) {
param = getNextConfigParam(CONF_PASSWORD, NULL); param = getNextConfigParam(CONF_PASSWORD, NULL);
if(param) { if (param) {
permission_default = 0; permission_default = 0;
do { do {
if(!strstr(param->value, PERMISSION_PASSWORD_CHAR)) { if (!strstr(param->value, PERMISSION_PASSWORD_CHAR)) {
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,
} while((param = getNextConfigParam(CONF_PASSWORD, param))); permission);
} 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)) {
*permission = *((int *)foundPermission); *permission = *((int *)foundPermission);
return 0; return 0;
} }
@ -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

@ -28,7 +28,7 @@
void initPermissions(); void initPermissions();
int getPermissionFromPassword(char * password, int * permission); int getPermissionFromPassword(char *password, int *permission);
void finishPermissions(); void finishPermissions();

View File

@ -45,15 +45,17 @@
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) {
pc->metadataState = PLAYER_METADATA_STATE_WRITE; pc->metadataState = PLAYER_METADATA_STATE_WRITE;
} }
} }
void resetPlayer() { void resetPlayer()
{
int pid; int pid;
setPlayerPid(0); setPlayerPid(0);
@ -68,85 +70,85 @@ 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();
if(player_pid==0) { if (player_pid == 0) {
PlayerControl * pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
unblockSignals(); unblockSignals();
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)
else if(pc->closeAudio) { pc->stop = 0;
else if (pc->pause)
pc->pause = 0;
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));
@ -170,23 +177,26 @@ int playerPlay(FILE * fp, Song * song) {
pc->utf8url[MAXPATHLEN] = '\0'; pc->utf8url[MAXPATHLEN] = '\0';
pc->play = 1; pc->play = 1;
if(getPlayerPid()==0 && playerInit()<0) { if (getPlayerPid() == 0 && playerInit() < 0) {
pc->play = 0; pc->play = 0;
return -1; return -1;
} }
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,127 +205,148 @@ int playerStop(FILE * fp) {
return 0; return 0;
} }
void playerKill() { void playerKill()
{
int pid; int pid;
/*PlayerControl * pc = &(getPlayerData()->playerControl); /*PlayerControl * pc = &(getPlayerData()->playerControl);
playerStop(stderr); playerStop(stderr);
playerCloseAudio(stderr); playerCloseAudio(stderr);
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; {
int errorlen = MAXPATHLEN+1024; static char *error = NULL;
PlayerControl * pc = &(getPlayerData()->playerControl); int errorlen = MAXPATHLEN + 1024;
PlayerControl *pc = &(getPlayerData()->playerControl);
error = realloc(error,errorlen+1); error = realloc(error, errorlen + 1);
memset(error,0,errorlen+1); memset(error, 0, errorlen + 1);
switch(pc->error) { switch (pc->error) {
case PLAYER_ERROR_FILENOTFOUND: case PLAYER_ERROR_FILENOTFOUND:
snprintf(error,errorlen, snprintf(error, errorlen,
"file \"%s\" does not exist or is inaccesible", "file \"%s\" does not exist or is inaccesible",
pc->erroredUrl); pc->erroredUrl);
break; break;
case PLAYER_ERROR_FILE: case PLAYER_ERROR_FILE:
snprintf(error,errorlen,"problems decoding \"%s\"", snprintf(error, errorlen, "problems decoding \"%s\"",
pc->erroredUrl); pc->erroredUrl);
break; break;
case PLAYER_ERROR_AUDIO: case PLAYER_ERROR_AUDIO:
snprintf(error,errorlen,"problems opening audio device"); snprintf(error, errorlen, "problems opening audio device");
break; break;
case PLAYER_ERROR_SYSTEM: case PLAYER_ERROR_SYSTEM:
snprintf(error,errorlen,"system error occured"); snprintf(error, errorlen, "system error occured");
break; break;
case PLAYER_ERROR_UNKTYPE: case PLAYER_ERROR_UNKTYPE:
snprintf(error,errorlen,"file type of \"%s\" is unknown", snprintf(error, errorlen, "file type of \"%s\" is unknown",
pc->erroredUrl); pc->erroredUrl);
default: default:
break; break;
} }
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,50 +357,57 @@ 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) {
commandError(fp, ACK_ERROR_PLAYER_SYNC, commandError(fp, ACK_ERROR_PLAYER_SYNC,
"player not currently playing", NULL); "player not currently playing", NULL);
return -1; return -1;
} }
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));
@ -377,85 +415,98 @@ int playerSeek(FILE * fp, Song * song, float time) {
pc->utf8url[MAXPATHLEN] = '\0'; pc->utf8url[MAXPATHLEN] = '\0';
} }
if(pc->error==PLAYER_ERROR_NOERROR) { if (pc->error == PLAYER_ERROR_NOERROR) {
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; {
if(crossFadeInSeconds<0) crossFadeInSeconds = 0; PlayerControl *pc;
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; {
volume = (volume>1000) ? 1000 : (volume<0 ? 0 : volume); PlayerControl *pc;
volume = (volume > 1000) ? 1000 : (volume < 0 ? 0 : volume);
pc = &(getPlayerData()->playerControl); pc = &(getPlayerData()->playerControl);
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); {
DecoderControl * dc = &(getPlayerData()->decoderControl); PlayerControl *pc = &(getPlayerData()->playerControl);
DecoderControl *dc = &(getPlayerData()->decoderControl);
pc->cycleLogFiles = 1; pc->cycleLogFiles = 1;
dc->cycleLogFiles = 1; dc->cycleLogFiles = 1;
} }
/* 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 MetadataChunk * prev = NULL; static Song *song = NULL;
Song * ret = NULL; static MetadataChunk *prev = NULL;
PlayerControl * pc = &(getPlayerData()->playerControl); Song *ret = NULL;
PlayerControl *pc = &(getPlayerData()->playerControl);
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

@ -70,9 +70,9 @@ typedef struct _PlayerControl {
volatile float totalTime; volatile float totalTime;
volatile float elapsedTime; volatile float elapsedTime;
volatile float fileTime; volatile float fileTime;
char utf8url[MAXPATHLEN+1]; char utf8url[MAXPATHLEN + 1];
char currentUrl[MAXPATHLEN+1]; char currentUrl[MAXPATHLEN + 1];
char erroredUrl[MAXPATHLEN+1]; char erroredUrl[MAXPATHLEN + 1];
volatile mpd_sint8 queueState; volatile mpd_sint8 queueState;
volatile mpd_sint8 queueLockState; volatile mpd_sint8 queueLockState;
volatile mpd_sint8 lockQueue; volatile mpd_sint8 lockQueue;
@ -115,7 +115,7 @@ int getPlayerState();
void clearPlayerError(); void clearPlayerError();
char * getPlayerErrorStr(); char *getPlayerErrorStr();
int getPlayerError(); int getPlayerError();
@ -149,6 +149,6 @@ int getPlayerChannels();
void playerCycleLogFiles(); void playerCycleLogFiles();
Song * playerCurrentDecodeSong(); Song *playerCurrentDecodeSong();
#endif #endif

View File

@ -33,44 +33,45 @@ int buffered_chunks;
#define DEFAULT_BUFFER_SIZE 2048 #define DEFAULT_BUFFER_SIZE 2048
#define DEFAULT_BUFFER_BEFORE_PLAY 0 #define DEFAULT_BUFFER_BEFORE_PLAY 0
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;
int crossfade = 0; int crossfade = 0;
size_t bufferSize = DEFAULT_BUFFER_SIZE; size_t bufferSize = DEFAULT_BUFFER_SIZE;
size_t allocationSize; size_t allocationSize;
OutputBuffer * buffer; OutputBuffer *buffer;
ConfigParam * param; ConfigParam *param;
param = getConfigParam(CONF_AUDIO_BUFFER_SIZE); param = getConfigParam(CONF_AUDIO_BUFFER_SIZE);
if(param) { if (param) {
bufferSize = strtol(param->value, &test, 10); bufferSize = strtol(param->value, &test, 10);
if(*test!='\0' || bufferSize<=0) { if (*test != '\0' || bufferSize <= 0) {
ERROR("buffer size \"%s\" is not a positive integer, " ERROR("buffer size \"%s\" is not a positive integer, "
"line %i\n", param->value, param->line); "line %i\n", param->value, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
bufferSize*=1024; bufferSize *= 1024;
buffered_chunks = bufferSize/CHUNK_SIZE; buffered_chunks = bufferSize / CHUNK_SIZE;
if(buffered_chunks >= 1<<15) { if (buffered_chunks >= 1 << 15) {
ERROR("buffer size \"%i\" is too big\n",bufferSize); ERROR("buffer size \"%i\" is too big\n", bufferSize);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
param = getConfigParam(CONF_BUFFER_BEFORE_PLAY); param = getConfigParam(CONF_BUFFER_BEFORE_PLAY);
if(param) { if (param) {
perc = strtod(param->value, &test); perc = strtod(param->value, &test);
if(*test!='%' || perc<0 || perc>100) { if (*test != '%' || perc < 0 || perc > 100) {
ERROR("buffered before play \"%s\" is not a positive " ERROR("buffered before play \"%s\" is not a positive "
"percentage and less than 100 percent, line %i" "percentage and less than 100 percent, line %i"
"\n", param->value, param->line); "\n", param->value, param->line);
@ -78,28 +79,28 @@ 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 */
allocationSize+= buffered_chunks*sizeof(mpd_sint16); /*for chunkSize*/ allocationSize += buffered_chunks * sizeof(mpd_sint16); /*for chunkSize */
allocationSize+= buffered_chunks*sizeof(mpd_sint16); /*for bitRate*/ allocationSize += buffered_chunks * sizeof(mpd_sint16); /*for bitRate */
allocationSize+= buffered_chunks*sizeof(mpd_sint8); /*for metaChunk*/ allocationSize += buffered_chunks * sizeof(mpd_sint8); /*for metaChunk */
allocationSize+= sizeof(PlayerData); /*for playerData struct*/ allocationSize += sizeof(PlayerData); /*for playerData struct */
if((shmid = shmget(IPC_PRIVATE,allocationSize,IPC_CREAT|0600))<0) { if ((shmid = shmget(IPC_PRIVATE, allocationSize, IPC_CREAT | 0600)) < 0) {
ERROR("problems shmget'ing\n"); ERROR("problems shmget'ing\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if((playerData_pd = shmat(shmid,NULL,0))<0) { if ((playerData_pd = shmat(shmid, NULL, 0)) < 0) {
ERROR("problems shmat'ing\n"); ERROR("problems shmat'ing\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (shmctl(shmid, IPC_RMID, NULL)<0) { if (shmctl(shmid, IPC_RMID, NULL) < 0) {
ERROR("problems shmctl'ing\n"); ERROR("problems shmctl'ing\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -107,30 +108,32 @@ void initPlayerData(void) {
* or maybe even made a part of the playerData struct * or maybe even made a part of the playerData struct
*/ */
allocationSize = sizeof(int); allocationSize = sizeof(int);
if((shmid = shmget(IPC_PRIVATE,allocationSize,IPC_CREAT|0600))<0) { if ((shmid = shmget(IPC_PRIVATE, allocationSize, IPC_CREAT | 0600)) < 0) {
ERROR("problems shmget'ing\n"); ERROR("problems shmget'ing\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if((player_pid = shmat(shmid,NULL,0))<0) { if ((player_pid = shmat(shmid, NULL, 0)) < 0) {
ERROR("problems shmat'ing\n"); ERROR("problems shmat'ing\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (shmctl(shmid, IPC_RMID, NULL)<0) { if (shmctl(shmid, IPC_RMID, NULL) < 0) {
ERROR("problems shmctl'ing\n"); ERROR("problems shmctl'ing\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
buffer = &(playerData_pd->buffer); buffer = &(playerData_pd->buffer);
buffer->chunks = ((char *)playerData_pd)+sizeof(PlayerData); buffer->chunks = ((char *)playerData_pd) + sizeof(PlayerData);
buffer->chunkSize = (mpd_uint16 *)(((char *)buffer->chunks)+ buffer->chunkSize = (mpd_uint16 *) (((char *)buffer->chunks) +
buffered_chunks*CHUNK_SIZE); buffered_chunks * CHUNK_SIZE);
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));
buffered_chunks*sizeof(mpd_sint8)); buffer->times =
(float *)(((char *)buffer->metaChunk) +
buffered_chunks * sizeof(mpd_sint8));
buffer->acceptMetadata = 0; buffer->acceptMetadata = 0;
playerData_pd->playerControl.stop = 0; playerData_pd->playerControl.stop = 0;
@ -144,9 +147,9 @@ void initPlayerData(void) {
playerData_pd->playerControl.queueLockState = PLAYER_QUEUE_UNLOCKED; playerData_pd->playerControl.queueLockState = PLAYER_QUEUE_UNLOCKED;
playerData_pd->playerControl.seek = 0; playerData_pd->playerControl.seek = 0;
playerData_pd->playerControl.closeAudio = 0; playerData_pd->playerControl.closeAudio = 0;
memset(playerData_pd->playerControl.utf8url, 0, MAXPATHLEN+1); memset(playerData_pd->playerControl.utf8url, 0, MAXPATHLEN + 1);
memset(playerData_pd->playerControl.erroredUrl, 0, MAXPATHLEN+1); memset(playerData_pd->playerControl.erroredUrl, 0, MAXPATHLEN + 1);
memset(playerData_pd->playerControl.currentUrl, 0, MAXPATHLEN+1); memset(playerData_pd->playerControl.currentUrl, 0, MAXPATHLEN + 1);
playerData_pd->playerControl.crossFade = crossfade; playerData_pd->playerControl.crossFade = crossfade;
playerData_pd->playerControl.softwareVolume = 1000; playerData_pd->playerControl.softwareVolume = 1000;
playerData_pd->playerControl.totalPlayTime = 0; playerData_pd->playerControl.totalPlayTime = 0;
@ -159,22 +162,26 @@ void initPlayerData(void) {
playerData_pd->decoderControl.state = DECODE_STATE_STOP; playerData_pd->decoderControl.state = DECODE_STATE_STOP;
playerData_pd->decoderControl.seek = 0; playerData_pd->decoderControl.seek = 0;
playerData_pd->decoderControl.error = DECODE_ERROR_NOERROR; playerData_pd->decoderControl.error = DECODE_ERROR_NOERROR;
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);
} }

View File

@ -42,7 +42,7 @@ typedef struct _PlayerData {
void initPlayerData(); void initPlayerData();
PlayerData * getPlayerData(); PlayerData *getPlayerData();
int getPlayerPid(); int getPlayerPid();
void setPlayerPid(int pid); void setPlayerPid(int pid);

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@ void savePlaylistState();
int clearPlaylist(FILE * fp); int clearPlaylist(FILE * fp);
int addToPlaylist(FILE * fp, char * file, int printId); int addToPlaylist(FILE * fp, char *file, int printId);
int addSongToPlaylist(FILE * fp, Song * song, int printId); int addSongToPlaylist(FILE * fp, Song * song, int printId);
@ -68,11 +68,11 @@ int previousSongInPlaylist(FILE * fp);
int shufflePlaylist(FILE * fp); int shufflePlaylist(FILE * fp);
int savePlaylist(FILE * fp, char * utf8file); int savePlaylist(FILE * fp, char *utf8file);
int deletePlaylist(FILE * fp, char * utf8file); int deletePlaylist(FILE * fp, char *utf8file);
int deletePlaylistById(FILE * fp, char * utf8file); int deletePlaylistById(FILE * fp, char *utf8file);
void deleteASongFromPlaylist(Song * song); void deleteASongFromPlaylist(Song * song);
@ -84,7 +84,7 @@ int swapSongsInPlaylist(FILE * fp, int song1, int song2);
int swapSongsInPlaylistById(FILE * fp, int id1, int id2); int swapSongsInPlaylistById(FILE * fp, int id1, int id2);
int loadPlaylist(FILE * fp, char * utf8file); int loadPlaylist(FILE * fp, char *utf8file);
int getPlaylistRepeatStatus(); int getPlaylistRepeatStatus();
@ -114,8 +114,8 @@ int playlistChanges(FILE * fp, mpd_uint32 version);
int playlistChangesPosId(FILE * fp, mpd_uint32 version); int playlistChangesPosId(FILE * fp, mpd_uint32 version);
int PlaylistInfo(FILE * fp, char * utf8file, int detail); int PlaylistInfo(FILE * fp, char *utf8file, int detail);
char * getStateFile(); char *getStateFile();
#endif #endif

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);
@ -50,43 +50,46 @@ void initReplayGainState(void) {
param = getConfigParam(CONF_REPLAYGAIN_PREAMP); param = getConfigParam(CONF_REPLAYGAIN_PREAMP);
if(param) { if (param) {
char * test; char *test;
float f = strtod(param->value, &test); float f = strtod(param->value, &test);
if(*test != '\0') { if (*test != '\0') {
ERROR("Replaygain preamp \"%s\" is not a number at " ERROR("Replaygain preamp \"%s\" is not a number at "
"line %i\n", param->value, param->line); "line %i\n", param->value, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
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);
} }
replayGainPreamp = pow(10, f/20.0); replayGainPreamp = pow(10, f / 20.0);
} }
} }
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)
scale = pow(10.0, gain/20.0); return (1);
scale*= replayGainPreamp; scale = pow(10.0, gain / 20.0);
if(scale > 15.0) scale = 15.0; scale *= replayGainPreamp;
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;
} }
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;
ret->albumPeak = 0.0; ret->albumPeak = 0.0;
@ -100,22 +103,24 @@ ReplayGainInfo * newReplayGainInfo(void) {
return ret; return ret;
} }
void freeReplayGainInfo(ReplayGainInfo * info) { void freeReplayGainInfo(ReplayGainInfo * info)
{
free(info); free(info);
} }
void doReplayGain(ReplayGainInfo * info, char * buffer, int bufferSize, void doReplayGain(ReplayGainInfo * info, char *buffer, int bufferSize,
AudioFormat * format) AudioFormat * format)
{ {
mpd_sint16 * buffer16; mpd_sint16 *buffer16;
mpd_sint8 * buffer8; mpd_sint8 *buffer8;
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) {
case REPLAYGAIN_TRACK: case REPLAYGAIN_TRACK:
info->scale = computeReplayGainScale(info->trackGain, info->scale = computeReplayGainScale(info->trackGain,
info->trackPeak); info->trackPeak);
@ -127,30 +132,31 @@ 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;
scale = info->scale; scale = info->scale;
switch(format->bits) { switch (format->bits) {
case 16: case 16:
while(bufferSize > 0){ while (bufferSize > 0) {
temp32 = *buffer16; temp32 = *buffer16;
temp32 *= scale; temp32 *= scale;
*buffer16 = temp32>32767 ? 32767 : *buffer16 = temp32 > 32767 ? 32767 :
(temp32<-32768 ? -32768 : temp32); (temp32 < -32768 ? -32768 : temp32);
buffer16++; buffer16++;
bufferSize-=2; bufferSize -= 2;
} }
break; break;
case 8: case 8:
while(bufferSize>0){ while (bufferSize > 0) {
temp32 = *buffer8; temp32 = *buffer8;
temp32 *= scale; temp32 *= scale;
*buffer8 = temp32>127 ? 127 : *buffer8 = temp32 > 127 ? 127 :
(temp32<-128 ? -128 : temp32); (temp32 < -128 ? -128 : temp32);
buffer8++; buffer8++;
bufferSize--; bufferSize--;
} }

View File

@ -32,17 +32,17 @@ typedef struct _ReplayGainInfo {
float trackGain; float trackGain;
float trackPeak; float trackPeak;
/* used internally by mpd, to mess with it*/ /* used internally by mpd, to mess with it */
float scale; float scale;
} ReplayGainInfo; } ReplayGainInfo;
ReplayGainInfo * newReplayGainInfo(); ReplayGainInfo *newReplayGainInfo();
void freeReplayGainInfo(ReplayGainInfo * info); void freeReplayGainInfo(ReplayGainInfo * info);
void initReplayGainState(); void initReplayGainState();
void doReplayGain(ReplayGainInfo * info, char * buffer, int bufferSize, void doReplayGain(ReplayGainInfo * info, char *buffer, int bufferSize,
AudioFormat * format); AudioFormat * format);
#endif #endif

View File

@ -39,23 +39,24 @@
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;
} }
if(signal_is_pending(SIGHUP)) { if (signal_is_pending(SIGHUP)) {
signal_clear(SIGHUP); signal_clear(SIGHUP);
/* Forward it to the main process, which will update the DB */ /* Forward it to the main process, which will update the DB */
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.
@ -66,87 +67,98 @@ int handlePendingSignals() {
return COMMAND_MASTER_READY; return COMMAND_MASTER_READY;
} }
if(signal_is_pending(SIGINT) || signal_is_pending(SIGTERM)) { if (signal_is_pending(SIGINT) || signal_is_pending(SIGTERM)) {
DEBUG("main process got SIGINT or SIGTERM, exiting\n"); DEBUG("main process got SIGINT or SIGTERM, exiting\n");
return COMMAND_RETURN_KILL; return COMMAND_RETURN_KILL;
} }
if(signal_is_pending(SIGHUP)) { if (signal_is_pending(SIGHUP)) {
DEBUG("got SIGHUP, rereading DB\n"); DEBUG("got SIGHUP, rereading DB\n");
signal_clear(SIGHUP); signal_clear(SIGHUP);
if(!isUpdatingDB()) { if (!isUpdatingDB()) {
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)
player_sigChldHandler(pid,status); kill(getpid(), SIGTERM);
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;
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN; sa.sa_handler = SIG_IGN;
while(sigaction(SIGPIPE,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGPIPE, &sa, NULL) < 0 && errno == EINTR) ;
sa.sa_handler = masterChldSigHandler; sa.sa_handler = masterChldSigHandler;
while(sigaction(SIGCHLD,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGCHLD, &sa, NULL) < 0 && errno == EINTR) ;
sa.sa_handler = masterSigUsr2Handler; sa.sa_handler = masterSigUsr2Handler;
while(sigaction(SIGUSR2,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGUSR2, &sa, NULL) < 0 && errno == EINTR) ;
signal_handle(SIGUSR1); signal_handle(SIGUSR1);
signal_handle(SIGINT); signal_handle(SIGINT);
signal_handle(SIGTERM); signal_handle(SIGTERM);
signal_handle(SIGHUP); signal_handle(SIGHUP);
} }
void initSigHandlers() { void initSigHandlers()
{
struct sigaction sa; struct sigaction sa;
sa.sa_flags = 0; sa.sa_flags = 0;
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN; sa.sa_handler = SIG_IGN;
while(sigaction(SIGPIPE,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGPIPE, &sa, NULL) < 0 && errno == EINTR) ;
sa.sa_handler = chldSigHandler; sa.sa_handler = chldSigHandler;
while(sigaction(SIGCHLD,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGCHLD, &sa, NULL) < 0 && errno == EINTR) ;
signal_handle(SIGUSR2); signal_handle(SIGUSR2);
signal_handle(SIGUSR1); signal_handle(SIGUSR1);
signal_handle(SIGINT); signal_handle(SIGINT);
@ -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();
@ -169,65 +183,69 @@ void setSigHandlersForDecoder() {
sa.sa_flags = 0; sa.sa_flags = 0;
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN; sa.sa_handler = SIG_IGN;
while(sigaction(SIGHUP,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGHUP, &sa, NULL) < 0 && errno == EINTR) ;
while(sigaction(SIGINT,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGINT, &sa, NULL) < 0 && errno == EINTR) ;
sa.sa_flags = SA_SIGINFO; sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = decodeSigHandler; sa.sa_sigaction = decodeSigHandler;
while(sigaction(SIGCHLD,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGCHLD, &sa, NULL) < 0 && errno == EINTR) ;
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;
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN; sa.sa_handler = SIG_IGN;
sa.sa_sigaction = NULL; sa.sa_sigaction = NULL;
while(sigaction(SIGPIPE,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGPIPE, &sa, NULL) < 0 && errno == EINTR) ;
while(sigaction(SIGCHLD,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGCHLD, &sa, NULL) < 0 && errno == EINTR) ;
while(sigaction(SIGUSR1,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGUSR1, &sa, NULL) < 0 && errno == EINTR) ;
while(sigaction(SIGUSR2,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGUSR2, &sa, NULL) < 0 && errno == EINTR) ;
while(sigaction(SIGINT,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGINT, &sa, NULL) < 0 && errno == EINTR) ;
while(sigaction(SIGTERM,&sa,NULL)<0 && errno==EINTR); while (sigaction(SIGTERM, &sa, NULL) < 0 && errno == EINTR) ;
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);
sigdelset(&sset,SIGCHLD); sigdelset(&sset, SIGCHLD);
sigdelset(&sset,SIGUSR1); sigdelset(&sset, SIGUSR1);
sigdelset(&sset,SIGUSR2); sigdelset(&sset, SIGUSR2);
sigdelset(&sset,SIGHUP); sigdelset(&sset, SIGHUP);
sigdelset(&sset,SIGINT); sigdelset(&sset, SIGINT);
sigdelset(&sset,SIGTERM); sigdelset(&sset, SIGTERM);
sigsuspend(&sset); sigsuspend(&sset);
} }
void blockSignals() { void blockSignals()
{
sigset_t sset; sigset_t sset;
sigemptyset(&sset); sigemptyset(&sset);
sigaddset(&sset,SIGCHLD); sigaddset(&sset, SIGCHLD);
sigaddset(&sset,SIGUSR1); sigaddset(&sset, SIGUSR1);
sigaddset(&sset,SIGUSR2); sigaddset(&sset, SIGUSR2);
sigaddset(&sset,SIGHUP); sigaddset(&sset, SIGHUP);
sigaddset(&sset,SIGINT); sigaddset(&sset, SIGINT);
sigaddset(&sset,SIGTERM); sigaddset(&sset, SIGTERM);
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);
sigaddset(&sset,SIGCHLD); sigaddset(&sset, SIGCHLD);
sigaddset(&sset,SIGUSR1); sigaddset(&sset, SIGUSR1);
sigaddset(&sset,SIGUSR2); sigaddset(&sset, SIGUSR2);
sigaddset(&sset,SIGHUP); sigaddset(&sset, SIGHUP);
sigaddset(&sset,SIGINT); sigaddset(&sset, SIGINT);
sigaddset(&sset,SIGTERM); sigaddset(&sset, SIGTERM);
while(sigprocmask(SIG_UNBLOCK,&sset,NULL)<0 && errno==EINTR); while (sigprocmask(SIG_UNBLOCK, &sset, NULL) < 0 && errno == EINTR) ;
} }

View File

@ -29,13 +29,13 @@ static void __signal_handler(int sig)
__caught_signals[sig] = 1; __caught_signals[sig] = 1;
} }
static void __set_signal_handler(int sig, void (* handler)(int)) static void __set_signal_handler(int sig, void (*handler) (int))
{ {
struct sigaction act; struct sigaction act;
act.sa_flags = 0; act.sa_flags = 0;
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
act.sa_handler = handler; act.sa_handler = handler;
while(sigaction(sig, &act, NULL) && errno==EINTR); while (sigaction(sig, &act, NULL) && errno == EINTR) ;
} }
void signal_handle(int sig) void signal_handle(int sig)

View File

@ -35,8 +35,9 @@
#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;
song->url = NULL; song->url = NULL;
@ -46,11 +47,12 @@ 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')) {
DEBUG("newSong: '%s' is not a valid uri\n",url); DEBUG("newSong: '%s' is not a valid uri\n", url);
return NULL; return NULL;
} }
@ -62,16 +64,17 @@ Song * newSong(char * url, int type, Directory * parentDir) {
assert(type == SONG_TYPE_URL || parentDir); assert(type == SONG_TYPE_URL || parentDir);
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(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) {
freeSong(song); freeSong(song);
song = NULL; song = NULL;
} }
@ -80,30 +83,34 @@ 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);
} }
Song * addSongToList(SongList * list, char * url, char * utf8path, Song *addSongToList(SongList * list, char *url, char *utf8path,
int songType, Directory * parentDirectory) int songType, Directory * parentDirectory)
{ {
Song * song = NULL; Song *song = NULL;
switch(songType) { switch (songType) {
case SONG_TYPE_FILE: case SONG_TYPE_FILE:
if(isMusic(utf8path, NULL, 0)) { if (isMusic(utf8path, NULL, 0)) {
song = newSong(url, songType, parentDirectory); song = newSong(url, songType, parentDirectory);
} }
break; break;
@ -114,80 +121,86 @@ 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;
while(tempNode!=NULL) {
printSongInfo(fp,(Song *)tempNode->data);
tempNode = tempNode->nextNode;
}
return 0;
}
void writeSongInfoFromList(FILE * fp, SongList * list) {
ListNode * tempNode = list->firstNode;
myfprintf(fp,"%s\n",SONG_BEGIN);
while(tempNode!=NULL) {
myfprintf(fp,"%s%s\n",SONG_KEY,tempNode->key);
printSongInfo(fp,(Song *)tempNode->data);
myfprintf(fp,"%s%li\n",SONG_MTIME,(long)((Song *)tempNode->data)->mtime);
tempNode = tempNode->nextNode;
}
myfprintf(fp,"%s\n",SONG_END);
}
static void insertSongIntoList(SongList * list, ListNode ** nextSongNode, char * key,
Song * song)
{ {
ListNode * nodeTemp; ListNode *tempNode = list->firstNode;
int cmpRet= 0;
while(*nextSongNode && (cmpRet = strcmp(key,(*nextSongNode)->key)) > 0) while (tempNode != NULL) {
{ printSongInfo(fp, (Song *) tempNode->data);
tempNode = tempNode->nextNode;
}
return 0;
}
void writeSongInfoFromList(FILE * fp, SongList * list)
{
ListNode *tempNode = list->firstNode;
myfprintf(fp, "%s\n", SONG_BEGIN);
while (tempNode != NULL) {
myfprintf(fp, "%s%s\n", SONG_KEY, tempNode->key);
printSongInfo(fp, (Song *) tempNode->data);
myfprintf(fp, "%s%li\n", SONG_MTIME,
(long)((Song *) tempNode->data)->mtime);
tempNode = tempNode->nextNode;
}
myfprintf(fp, "%s\n", SONG_END);
}
static void insertSongIntoList(SongList * list, ListNode ** nextSongNode,
char *key, Song * song)
{
ListNode *nodeTemp;
int cmpRet = 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;
} }
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);
tempSong->tag = song->tag; tempSong->tag = song->tag;
tempSong->mtime = song->mtime; tempSong->mtime = song->mtime;
@ -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,84 +229,88 @@ 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]; {
int bufferSize = MAXPATHLEN+1024; char buffer[MAXPATHLEN + 1024];
Song * song = NULL; int bufferSize = MAXPATHLEN + 1024;
ListNode * nextSongNode = list->firstNode; Song *song = NULL;
ListNode * nodeTemp; ListNode *nextSongNode = list->firstNode;
ListNode *nodeTemp;
int itemType; int itemType;
while(myFgets(buffer,bufferSize,fp) && 0!=strcmp(SONG_END,buffer)) { while (myFgets(buffer, bufferSize, fp) && 0 != strcmp(SONG_END, buffer)) {
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;
} }
song = newNullSong(); song = newNullSong();
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);
} }
/* 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') */
else if(*buffer){ else if (*buffer) {
ERROR("songinfo: unknown line in db: %s\n",buffer); ERROR("songinfo: unknown line in db: %s\n", buffer);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if(song) { if (song) {
insertSongIntoList(list, &nextSongNode, song->url, song); insertSongIntoList(list, &nextSongNode, song->url, song);
song = NULL; song = NULL;
} }
while(nextSongNode) { while (nextSongNode) {
nodeTemp = nextSongNode->nextNode; nodeTemp = nextSongNode->nextNode;
deleteNodeFromList(list,nextSongNode); deleteNodeFromList(list, nextSongNode);
nextSongNode = nodeTemp; nextSongNode = nodeTemp;
} }
} }
int updateSongInfo(Song * song) { int updateSongInfo(Song * song)
if(song->type == SONG_TYPE_FILE) { {
InputPlugin * plugin; if (song->type == SONG_TYPE_FILE) {
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,37 +318,40 @@ 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;
int slen; int slen;
int dlen; int dlen;
int size; int size;
if(!song) { if (!song) {
lastSong = song; lastSong = 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));
size = slen+dlen+2; size = slen + dlen + 2;
if(size > bufferSize) { if (size > bufferSize) {
buffer = realloc(buffer, size); buffer = realloc(buffer, size);
bufferSize = size; bufferSize = size;
} }
strcpy(buffer, getDirectoryPath(song->parentDir)); strcpy(buffer, getDirectoryPath(song->parentDir));
buffer[dlen] = '/'; buffer[dlen] = '/';
strcpy(buffer+dlen+1, song->url); strcpy(buffer + dlen + 1, song->url);
return buffer; return buffer;
} }

View File

@ -34,29 +34,29 @@
#define SONG_TYPE_URL 2 #define SONG_TYPE_URL 2
typedef struct _Song { typedef struct _Song {
char * url; char *url;
mpd_sint8 type; mpd_sint8 type;
MpdTag * tag; MpdTag *tag;
struct _Directory * parentDir; struct _Directory *parentDir;
time_t mtime; time_t mtime;
} Song; } Song;
typedef List SongList; typedef List SongList;
Song * newNullSong(); Song *newNullSong();
Song * newSong(char * url, int songType, struct _Directory * parentDir); Song *newSong(char *url, int songType, struct _Directory *parentDir);
void freeSong(Song *); void freeSong(Song *);
void freeJustSong(Song *); void freeJustSong(Song *);
SongList * newSongList(); SongList *newSongList();
void freeSongList(SongList * list); void freeSongList(SongList * list);
Song * addSongToList(SongList * list, char * url, char * utf8path, Song *addSongToList(SongList * list, char *url, char *utf8path,
int songType, struct _Directory * parentDir); int songType, struct _Directory *parentDir);
int printSongInfo(FILE * fp, Song * song); int printSongInfo(FILE * fp, Song * song);
@ -65,12 +65,12 @@ int printSongInfoFromList(FILE * fp, SongList * list);
void writeSongInfoFromList(FILE * fp, SongList * list); void writeSongInfoFromList(FILE * fp, SongList * list);
void readSongInfoIntoList(FILE * fp, SongList * list, void readSongInfoIntoList(FILE * fp, SongList * list,
struct _Directory * parent); struct _Directory *parent);
int updateSongInfo(Song * song); int updateSongInfo(Song * song);
void printSongUrl(FILE * fp, Song * song); void printSongUrl(FILE * fp, Song * song);
char * getSongUrl(Song * song); char *getSongUrl(Song * song);
#endif #endif

View File

@ -28,18 +28,21 @@
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,"albums: %li\n", getNumberOfTagItems(TAG_ITEM_ALBUM)); myfprintf(fp, "artists: %li\n", getNumberOfTagItems(TAG_ITEM_ARTIST));
myfprintf(fp,"songs: %i\n",stats.numberOfSongs); myfprintf(fp, "albums: %li\n", getNumberOfTagItems(TAG_ITEM_ALBUM));
myfprintf(fp,"uptime: %li\n",time(NULL)-stats.daemonStart); myfprintf(fp, "songs: %i\n", stats.numberOfSongs);
myfprintf(fp,"playtime: %li\n",(long)(getPlayerTotalPlayTime()+0.5)); myfprintf(fp, "uptime: %li\n", time(NULL) - stats.daemonStart);
myfprintf(fp,"db_playtime: %li\n",stats.dbPlayTime); myfprintf(fp, "playtime: %li\n",
myfprintf(fp,"db_update: %li\n",getDbModTime()); (long)(getPlayerTotalPlayTime() + 0.5));
myfprintf(fp, "db_playtime: %li\n", stats.dbPlayTime);
myfprintf(fp, "db_update: %li\n", getDbModTime());
return 0; return 0;
} }

View File

@ -28,7 +28,7 @@ typedef struct _Stats {
int numberOfSongs; int numberOfSongs;
unsigned long dbPlayTime; unsigned long dbPlayTime;
/*unsigned long playTime; /*unsigned long playTime;
unsigned long songsPlayed;*/ unsigned long songsPlayed; */
} Stats; } Stats;
extern Stats stats; extern Stats stats;

316
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,12 +71,13 @@ 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;
char * c; char *c;
ConfigParam * param; ConfigParam *param;
int i; int i;
/* parse the "metadata_to_use" config parameter below */ /* parse the "metadata_to_use" config parameter below */
@ -87,24 +87,27 @@ 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) {
ignoreTagItems[i] = 0; ignoreTagItems[i] = 0;
break; break;
} }
} }
if(strlen(c) && i == TAG_NUM_OF_ITEM_TYPES) { if (strlen(c) && i == TAG_NUM_OF_ITEM_TYPES) {
ERROR("error parsing metadata item \"%s\" at " ERROR("error parsing metadata item \"%s\" at "
"line %i\n", c, param->line); "line %i\n", c, param->line);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -118,47 +121,53 @@ 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],
tag->items[i].value); tag->items[i].value);
} }
} }
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
MpdTag * getID3Info(struct id3_tag * tag, char * id, int type, MpdTag * mpdTag) MpdTag *getID3Info(struct id3_tag *tag, char *id, int type, MpdTag * mpdTag)
{ {
struct id3_frame const * frame; struct id3_frame const *frame;
id3_ucs4_t const * ucs4; id3_ucs4_t const *ucs4;
id3_utf8_t * utf8; id3_utf8_t *utf8;
union id3_field const * field; union id3_field const *field;
unsigned int nstrings; unsigned int nstrings;
int i; int i;
char * isostr; char *isostr;
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);
if(encoding) { if (encoding) {
setCharSetConversion("ISO-8859-1", "UTF-8"); setCharSetConversion("ISO-8859-1", "UTF-8");
isostr = convStrDup(utf8); isostr = convStrDup(utf8);
free(utf8); free(utf8);
@ -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,8 +189,9 @@ 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);
ret = getID3Info(tag, ID3_FRAME_TITLE, TAG_ITEM_TITLE, ret); ret = getID3Info(tag, ID3_FRAME_TITLE, TAG_ITEM_TITLE, ret);
@ -197,10 +208,11 @@ MpdTag * parseId3Tag(struct id3_tag * tag) {
#endif #endif
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
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,28 +224,31 @@ 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
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
static struct id3_tag * getId3Tag(FILE * stream, long offset, int whence) static struct id3_tag *getId3Tag(FILE * stream, long offset, int whence)
{ {
struct id3_tag * tag; struct id3_tag *tag;
id3_byte_t * buf[ID3_TAG_BUFLEN]; id3_byte_t *buf[ID3_TAG_BUFLEN];
id3_byte_t * mbuf; id3_byte_t *mbuf;
int tagsize; int tagsize;
int bufsize; int bufsize;
int mbufsize; int mbufsize;
/* 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) {
@ -259,11 +275,11 @@ static struct id3_tag * getId3Tag(FILE * stream, long offset, int whence)
#endif #endif
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
static struct id3_tag * findId3TagFromBeginning(FILE * stream) static struct id3_tag *findId3TagFromBeginning(FILE * stream)
{ {
struct id3_tag * tag; struct id3_tag *tag;
struct id3_tag * seektag; struct id3_tag *seektag;
struct id3_frame * frame; struct id3_frame *frame;
int seek; int seek;
tag = getId3Tag(stream, 0, SEEK_SET); tag = getId3Tag(stream, 0, SEEK_SET);
@ -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);
@ -295,10 +313,10 @@ static struct id3_tag * findId3TagFromBeginning(FILE * stream)
#endif #endif
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
static struct id3_tag * findId3TagFromEnd(FILE * stream) static struct id3_tag *findId3TagFromEnd(FILE * stream)
{ {
struct id3_tag * tag; struct id3_tag *tag;
struct id3_tag * v1tag; struct id3_tag *v1tag;
int tagsize; int tagsize;
/* Get an id3v1 tag from the end of file for later use */ /* Get an id3v1 tag from the end of file for later use */
@ -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,41 +339,46 @@ 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;
FILE * stream; FILE *stream;
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; {
FILE * fp = NULL; MpdTag *ret = NULL;
FILE *fp = NULL;
int tagCount; int tagCount;
char * buffer = NULL; char *buffer = NULL;
char * p; char *p;
int tagLen; int tagLen;
int size; int size;
unsigned long flags; unsigned long flags;
int i; int i;
char * key; char *key;
struct { struct {
unsigned char id[8]; unsigned char id[8];
@ -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,30 +410,39 @@ 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);
p = buffer; p = buffer;
while(tagCount-- && tagLen > 10) { while (tagCount-- && tagLen > 10) {
size = readLEuint32((unsigned char *)p); size = readLEuint32((unsigned char *)p);
p += 4; p += 4;
tagLen -= 4; tagLen -= 4;
@ -420,7 +452,7 @@ MpdTag * apeDup(char * file) {
/* get the key */ /* get the key */
key = p; key = p;
while(tagLen-size > 0 && *p != '\0') { while (tagLen - size > 0 && *p != '\0') {
p++; p++;
tagLen--; tagLen--;
} }
@ -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);
} }
} }
} }
@ -444,21 +478,25 @@ MpdTag * apeDup(char * file) {
tagLen -= size; tagLen -= size;
} }
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;
ret->numOfItems = 0; ret->numOfItems = 0;
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);
@ -466,26 +504,26 @@ static void deleteItem(MpdTag * tag, int index) {
removeTagItemString(tag->items[index].type, tag->items[index].value); removeTagItemString(tag->items[index].type, tag->items[index].value);
/* free(tag->items[index].value); */ /* free(tag->items[index].value); */
if(tag->numOfItems-index > 0) { if (tag->numOfItems - index > 0) {
memmove(tag->items+index, tag->items+index+1, memmove(tag->items + index, tag->items + index + 1,
tag->numOfItems-index); tag->numOfItems - 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++) {
if(tag->items[i].type == type) { if (tag->items[i].type == type) {
deleteItem(tag, i); deleteItem(tag, i);
/* decrement since when just deleted this node */ /* decrement since when just deleted this node */
i--; i--;
@ -493,15 +531,17 @@ 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++) {
removeTagItemString(tag->items[i].type, tag->items[i].value); removeTagItemString(tag->items[i].type, tag->items[i].value);
/* 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,40 +549,49 @@ 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;
for(i = 0; i < tag->numOfItems; i++) { for (i = 0; i < tag->numOfItems; i++) {
addItemToMpdTag(ret, tag->items[i].type, tag->items[i].value); addItemToMpdTag(ret, tag->items[i].type, tag->items[i].value);
} }
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)
if(strcmp(tag1->items[i].value, tag2->items[i].value)) { return 0;
if (strcmp(tag1->items[i].value, tag2->items[i].value)) {
return 0; return 0;
} }
} }
@ -560,13 +609,12 @@ 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;
char * dup; char *dup;
dup = malloc(len+1); dup = malloc(len + 1);
strncpy(dup, value, len); strncpy(dup, value, len);
dup[len] = '\0'; dup[len] = '\0';
@ -574,7 +622,7 @@ static void appendToTagItems(MpdTag * tag, int type, char * value,
stripReturnChar(dup); stripReturnChar(dup);
tag->numOfItems++; tag->numOfItems++;
tag->items = realloc(tag->items, tag->numOfItems*sizeof(MpdTagItem)); tag->items = realloc(tag->items, tag->numOfItems * sizeof(MpdTagItem));
tag->items[i].type = type; tag->items[i].type = type;
tag->items[i].value = getTagItemString(type, dup); tag->items[i].value = getTagItemString(type, dup);
@ -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

@ -44,28 +44,28 @@
#define TAG_NUM_OF_ITEM_TYPES 11 #define TAG_NUM_OF_ITEM_TYPES 11
extern char * mpdTagItemKeys[]; extern char *mpdTagItemKeys[];
typedef struct _MpdTagItem { typedef struct _MpdTagItem {
mpd_sint8 type; mpd_sint8 type;
char * value; char *value;
} MpdTagItem; } MpdTagItem;
typedef struct _MpdTag { typedef struct _MpdTag {
int time; int time;
MpdTagItem * items; MpdTagItem *items;
mpd_uint8 numOfItems; mpd_uint8 numOfItems;
} MpdTag; } MpdTag;
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
MpdTag * parseId3Tag(struct id3_tag *); MpdTag *parseId3Tag(struct id3_tag *);
#endif #endif
MpdTag * apeDup(char * file); MpdTag *apeDup(char *file);
MpdTag * id3Dup(char * file); MpdTag *id3Dup(char *file);
MpdTag * newMpdTag(); MpdTag *newMpdTag();
void initTagConfig(); void initTagConfig();
@ -73,14 +73,14 @@ void clearItemsFromMpdTag(MpdTag * tag, int itemType);
void freeMpdTag(MpdTag * tag); void freeMpdTag(MpdTag * tag);
void addItemToMpdTagWithLen(MpdTag * tag, int itemType, char * value, int len); void addItemToMpdTagWithLen(MpdTag * tag, int itemType, char *value, int len);
#define addItemToMpdTag(tag, itemType, value) \ #define addItemToMpdTag(tag, itemType, value) \
addItemToMpdTagWithLen(tag, itemType, value, strlen(value)) addItemToMpdTagWithLen(tag, itemType, value, strlen(value))
void printMpdTag(FILE * fp, MpdTag * tag); void printMpdTag(FILE * fp, MpdTag * tag);
MpdTag * mpdTagDup(MpdTag * tag); MpdTag *mpdTagDup(MpdTag * tag);
int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2); int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2);

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,20 +38,20 @@ 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;
if(tagLists[type] == NULL) { if (tagLists[type] == NULL) {
tagLists[type] = makeList(free, 1); tagLists[type] = makeList(free, 1);
sortList(tagLists[type]); sortList(tagLists[type]);
} }
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;
node = insertInListBeforeNode(tagLists[type], node, pos, node = insertInListBeforeNode(tagLists[type], node, pos,
@ -62,50 +61,57 @@ 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) {
freeList(tagLists[type]); freeList(tagLists[type]);
tagLists[type] = NULL; tagLists[type] = NULL;
} }
} }
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);
node = tagLists[i]->firstNode; node = tagLists[i]->firstNode;
while(node != NULL) { while (node != NULL) {
sum -= sizeof(ListNode); sum -= sizeof(ListNode);
sum -= sizeof(TagTrackerItem); sum -= sizeof(TagTrackerItem);
sum -= sizeof(node->key); sum -= sizeof(node->key);
sum += (strlen(node->key)+1)*(*((int *)node->data)); sum += (strlen(node->key) + 1) * (*((int *)node->data));
node = node->nextNode; node = node->nextNode;
} }
} }
@ -113,40 +119,47 @@ 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;
while(node) { while (node) {
((TagTrackerItem *)node->data)->visited = 0; ((TagTrackerItem *) node->data)->visited = 0;
node = node->nextNode; node = node->nextNode;
} }
} }
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; {
TagTrackerItem * item; ListNode *node;
TagTrackerItem *item;
if(!tagLists[type]) return; if (!tagLists[type])
return;
node = tagLists[type]->firstNode; node = tagLists[type]->firstNode;
while(node) { while (node) {
item = node->data; item = node->data;
if(item->visited) { if (item->visited) {
myfprintf(fp, "%s: %s\n", mpdTagItemKeys[type], myfprintf(fp, "%s: %s\n", mpdTagItemKeys[type],
node->key); node->key);
} }

View File

@ -21,9 +21,9 @@
#include "tag.h" #include "tag.h"
char * getTagItemString(int type, char * string); char *getTagItemString(int type, char *string);
void removeTagItemString(int type, char * string); void removeTagItemString(int type, char *string);
int getNumberOfTagItems(int type); int getNumberOfTagItems(int type);
@ -31,7 +31,7 @@ void printMemorySavedByTagTracker();
void resetVisitedFlagsInTagTracker(int type); void resetVisitedFlagsInTagTracker(int type);
void visitInTagTracker(int type, char * str); void visitInTagTracker(int type, char *str);
void printVisitedInTagTracker(FILE * fp, int type); void printVisitedInTagTracker(FILE * fp, int type);

View File

@ -22,113 +22,126 @@
#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)
else if(uc<192) { utf8[0] = uc;
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;
} }
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);
char * cp = ret; char *cp = ret;
char * utf8; char *utf8;
memset(ret,0,len); memset(ret, 0, len);
len = 0; len = 0;
while(*latin1) { while (*latin1) {
utf8 = latin1ToUtf8(*latin1); utf8 = latin1ToUtf8(*latin1);
while(*utf8) { while (*utf8) {
*(cp++) = *(utf8++); *(cp++) = *(utf8++);
len++; len++;
} }
latin1++; 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)
return (char)(c+utf8[1]); c += 64;
else if (utf8[0] != 194)
return '?';
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;
char t = 1 << 5; char t = 1 << 5;
int i; int i;
while(count < 6 && (t & utf8Char[0])) { while (count < 6 && (t & utf8Char[0])) {
t = (t >> 1); t = (t >> 1);
count++; count++;
} }
if(count > 5) return 0; if (count > 5)
for(i=1;i<=count;i++) { return 0;
if(utf8Char[i] < 0x80 || utf8Char[i] > 0xBF) return 0; for (i = 1; i <= count; i++) {
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)
string+= ret; return 0;
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);
char * cp = ret; char *cp = ret;
int count; int count;
memset(ret,0,len); memset(ret, 0, len);
len = 0; len = 0;
while(*utf8) { while (*utf8) {
count = validateUtf8Char(utf8); count = validateUtf8Char(utf8);
if(!count) { if (!count) {
free(ret); free(ret);
return NULL; return NULL;
} }
*(cp++) = utf8ToLatin1(utf8); *(cp++) = utf8ToLatin1(utf8);
utf8+= count; utf8 += count;
len++; len++;
} }
return realloc(ret,len+1); return realloc(ret, len + 1);
} }

View File

@ -19,10 +19,10 @@
#ifndef UTF_8_H #ifndef UTF_8_H
#define UTF_8_H #define UTF_8_H
char * latin1StrToUtf8Dup(char * latin1); char *latin1StrToUtf8Dup(char *latin1);
char * utf8StrToLatin1Dup(char * utf8); char *utf8StrToLatin1Dup(char *utf8);
int validUtf8String(char * string); int validUtf8String(char *string);
#endif #endif

View File

@ -27,75 +27,82 @@
#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); {
if(ret && strlen(buffer)>0 && buffer[strlen(buffer)-1]=='\n') { char *ret = fgets(buffer, bufferSize, fp);
buffer[strlen(buffer)-1] = '\0'; if (ret && strlen(buffer) > 0 && buffer[strlen(buffer) - 1] == '\n') {
buffer[strlen(buffer) - 1] = '\0';
} }
if(ret && strlen(buffer)>0 && buffer[strlen(buffer)-1]=='\r') { if (ret && strlen(buffer) > 0 && buffer[strlen(buffer) - 1] == '\r') {
buffer[strlen(buffer)-1] = '\0'; buffer[strlen(buffer) - 1] = '\0';
} }
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;
tv.tv_usec = usec; tv.tv_usec = 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);
if(dest == NULL) { if (dest == NULL) {
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);
} }
memcpy(dest+destlen, src, srclen); memcpy(dest + destlen, src, srclen);
dest[destlen+srclen] = '\0'; dest[destlen + srclen] = '\0';
return dest; return dest;
} }
unsigned long readLEuint32(const unsigned char *p) unsigned long readLEuint32(const unsigned char *p)
{ {
return ((unsigned long) p[0] << 0) | return ((unsigned long)p[0] << 0) |
((unsigned long) p[1] << 8) | ((unsigned long)p[1] << 8) |
((unsigned long) p[2] << 16) | ((unsigned long) p[3] << 24); ((unsigned long)p[2] << 16) | ((unsigned long)p[3] << 24);
} }

View File

@ -23,18 +23,18 @@
#include <stdio.h> #include <stdio.h>
char * myFgets(char * buffer, int bufferSize, FILE * fp); char *myFgets(char *buffer, int bufferSize, FILE * fp);
char * strDupToUpper(char * str); char *strDupToUpper(char *str);
void stripReturnChar(char * string); void stripReturnChar(char *string);
void my_usleep(long usec); void my_usleep(long usec);
int ipv6Supported(); int ipv6Supported();
char * appendToString(char * dest, const char * src); char *appendToString(char *dest, const char *src);
unsigned long readLEuint32(const unsigned char * p); unsigned long readLEuint32(const unsigned char *p);
#endif #endif

View File

@ -59,7 +59,7 @@
#endif #endif
static int volume_mixerType = VOLUME_MIXER_TYPE_DEFAULT; static int volume_mixerType = VOLUME_MIXER_TYPE_DEFAULT;
static char * volume_mixerDevice = VOLUME_MIXER_DEVICE_DEFAULT; static char *volume_mixerDevice = VOLUME_MIXER_DEVICE_DEFAULT;
static int volume_softwareSet = 100; static int volume_softwareSet = 100;
@ -69,8 +69,8 @@ static int volume_ossControl = SOUND_MIXER_PCM;
#endif #endif
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
static snd_mixer_t * volume_alsaMixerHandle = NULL; static snd_mixer_t *volume_alsaMixerHandle = NULL;
static snd_mixer_elem_t * volume_alsaElem; static snd_mixer_elem_t *volume_alsaElem;
static long volume_alsaMin; static long volume_alsaMin;
static long volume_alsaMax; static long volume_alsaMax;
static int volume_alsaSet = -1; static int volume_alsaSet = -1;
@ -80,51 +80,52 @@ static int volume_alsaSet = -1;
static void closeOssMixer(void) static void closeOssMixer(void)
{ {
while (close(volume_ossFd) && errno == EINTR); while (close(volume_ossFd) && errno == EINTR) ;
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) {
WARNING("unable to open oss mixer \"%s\"\n",device); WARNING("unable to open oss mixer \"%s\"\n", device);
return -1; return -1;
} }
param = getConfigParam(CONF_MIXER_CONTROL); param = getConfigParam(CONF_MIXER_CONTROL);
if(param) { if (param) {
char * labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS; char *labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
char * dup; char *dup;
int i,j; int i, j;
int devmask = 0; int devmask = 0;
if(ioctl(volume_ossFd,SOUND_MIXER_READ_DEVMASK,&devmask)<0) { if (ioctl(volume_ossFd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) {
WARNING("errors getting read_devmask for oss mixer\n"); WARNING("errors getting read_devmask for oss mixer\n");
closeOssMixer(); closeOssMixer();
return -1; return -1;
} }
for(i=0;i<SOUND_MIXER_NRDEVICES;i++) { for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
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] == ' ')
if(strcasecmp(dup, param->value)==0) { dup[j--] = '\0';
if (strcasecmp(dup, param->value) == 0) {
free(dup); free(dup);
break; break;
} }
free(dup); free(dup);
} }
if(i>=SOUND_MIXER_NRDEVICES) { if (i >= SOUND_MIXER_NRDEVICES) {
WARNING("mixer control \"%s\" not found at line %i\n", WARNING("mixer control \"%s\" not found at line %i\n",
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,13 +145,14 @@ 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)
return -1; return -1;
if(ioctl(volume_ossFd,MIXER_READ(volume_ossControl),&level) < 0) { if (ioctl(volume_ossFd, MIXER_READ(volume_ossControl), &level) < 0) {
closeOssMixer(); closeOssMixer();
WARNING("unable to read volume\n"); WARNING("unable to read volume\n");
return -1; return -1;
@ -159,39 +161,42 @@ static int getOssVolumeLevel(void) {
left = level & 0xff; left = level & 0xff;
right = (level & 0xff00) >> 8; right = (level & 0xff00) >> 8;
if(left!=right) { if (left != right) {
WARNING("volume for left and right is not the same, \"%i\" and " WARNING("volume for left and right is not the same, \"%i\" and "
"\"%i\"\n",left,right); "\"%i\"\n", left, right);
} }
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;
if (rel) { if (rel) {
if((current = getOssVolumeLevel()) < 0) { if ((current = getOssVolumeLevel()) < 0) {
commandError(fp, ACK_ERROR_SYSTEM, commandError(fp, ACK_ERROR_SYSTEM,
"problem getting current volume", NULL); "problem getting current volume", NULL);
return -1; return -1;
} }
new = current+change; new = current + change;
} else { } else {
if (ensure_oss_open() < 0) if (ensure_oss_open() < 0)
return -1; return -1;
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;
if(ioctl(volume_ossFd,MIXER_WRITE(volume_ossControl),&level) < 0) { if (ioctl(volume_ossFd, MIXER_WRITE(volume_ossControl), &level) < 0) {
closeOssMixer(); closeOssMixer();
commandError(fp, ACK_ERROR_SYSTEM, "problems setting volume", commandError(fp, ACK_ERROR_SYSTEM, "problems setting volume",
NULL); NULL);
@ -203,39 +208,43 @@ 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;
ConfigParam * param; ConfigParam *param;
err = snd_mixer_open(&volume_alsaMixerHandle,0); err = snd_mixer_open(&volume_alsaMixerHandle, 0);
snd_config_update_free_global(); snd_config_update_free_global();
if (err < 0) { if (err < 0) {
WARNING("problems opening alsa mixer: %s\n",snd_strerror(err)); WARNING("problems opening alsa mixer: %s\n", snd_strerror(err));
return -1; return -1;
} }
if((err = snd_mixer_attach(volume_alsaMixerHandle,card))<0) { if ((err = snd_mixer_attach(volume_alsaMixerHandle, card)) < 0) {
closeAlsaMixer(); closeAlsaMixer();
WARNING("problems problems attaching alsa mixer: %s\n", WARNING("problems problems attaching alsa mixer: %s\n",
snd_strerror(err)); snd_strerror(err));
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));
return -1; return -1;
} }
if((err = snd_mixer_load(volume_alsaMixerHandle))<0) { if ((err = snd_mixer_load(volume_alsaMixerHandle)) < 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));
@ -246,30 +255,29 @@ static int prepAlsaMixer(char * card) {
param = getConfigParam(CONF_MIXER_CONTROL); param = getConfigParam(CONF_MIXER_CONTROL);
if(param) { if (param) {
controlName = param->value; controlName = param->value;
} }
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;
} }
} }
elem = snd_mixer_elem_next(elem); elem = snd_mixer_elem_next(elem);
} }
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;
} }
WARNING("can't find alsa mixer_control \"%s\"\n",controlName); WARNING("can't find alsa mixer_control \"%s\"\n", controlName);
closeAlsaMixer(); closeAlsaMixer();
return -1; return -1;
@ -280,27 +288,29 @@ static int prep_alsa_get_level(long *level)
const char *cmd; const char *cmd;
int err; int err;
if (!volume_alsaMixerHandle && prepAlsaMixer(volume_mixerDevice)<0) if (!volume_alsaMixerHandle && prepAlsaMixer(volume_mixerDevice) < 0)
return -1; return -1;
if ((err = snd_mixer_handle_events(volume_alsaMixerHandle)) < 0) { if ((err = snd_mixer_handle_events(volume_alsaMixerHandle)) < 0) {
cmd = "handle_events"; cmd = "handle_events";
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;
} }
return 0; return 0;
error: error:
WARNING("problems getting alsa volume: %s (snd_mixer_%s)\n", WARNING("problems getting alsa volume: %s (snd_mixer_%s)\n",
snd_strerror(err), cmd); snd_strerror(err), cmd);
closeAlsaMixer(); closeAlsaMixer();
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;
@ -309,16 +319,17 @@ static int getAlsaVolumeLevel(void) {
if (prep_alsa_get_level(&level) < 0) if (prep_alsa_get_level(&level) < 0)
return -1; return -1;
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;
@ -330,29 +341,30 @@ static int changeAlsaVolumeLevel(FILE * fp, int change, int rel) {
return -1; return -1;
if (rel) { if (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;
volume_alsaSet = volume_alsaSet>100 ? 100 : volume_alsaSet = volume_alsaSet > 100 ? 100 :
(volume_alsaSet<0 ? 0 : volume_alsaSet); (volume_alsaSet < 0 ? 0 : volume_alsaSet);
level = (long)(((vol/100.0)*(max-min)+min)+0.5); level = (long)(((vol / 100.0) * (max - min) + min) + 0.5);
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,8 +373,9 @@ 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:
return prepAlsaMixer(device); return prepAlsaMixer(device);
@ -376,8 +389,9 @@ 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:
closeAlsaMixer(); closeAlsaMixer();
@ -391,28 +405,28 @@ 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) {
if(0); if (0) ;
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
else if(strcmp(param->value, VOLUME_MIXER_ALSA)==0) { else if (strcmp(param->value, VOLUME_MIXER_ALSA) == 0) {
volume_mixerType = VOLUME_MIXER_TYPE_ALSA; volume_mixerType = VOLUME_MIXER_TYPE_ALSA;
volume_mixerDevice = VOLUME_MIXER_ALSA_DEFAULT; volume_mixerDevice = VOLUME_MIXER_ALSA_DEFAULT;
} }
#endif #endif
#ifdef HAVE_OSS #ifdef HAVE_OSS
else if(strcmp(param->value, VOLUME_MIXER_OSS)==0) { else if (strcmp(param->value, VOLUME_MIXER_OSS) == 0) {
volume_mixerType = VOLUME_MIXER_TYPE_OSS; volume_mixerType = VOLUME_MIXER_TYPE_OSS;
volume_mixerDevice = VOLUME_MIXER_OSS_DEFAULT; volume_mixerDevice = VOLUME_MIXER_OSS_DEFAULT;
} }
#endif #endif
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);
@ -421,24 +435,27 @@ void initVolume(void) {
param = getConfigParam(CONF_MIXER_DEVICE); param = getConfigParam(CONF_MIXER_DEVICE);
if(param) { if (param) {
volume_mixerDevice = param->value; volume_mixerDevice = param->value;
} }
} }
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:
return getAlsaVolumeLevel(); return getAlsaVolumeLevel();
@ -454,38 +471,47 @@ 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:
return changeAlsaVolumeLevel(fp,change,rel); return changeAlsaVolumeLevel(fp, change, rel);
#endif #endif
#ifdef HAVE_OSS #ifdef HAVE_OSS
case VOLUME_MIXER_TYPE_OSS: case VOLUME_MIXER_TYPE_OSS:
return changeOssVolumeLevel(fp,change,rel); return changeOssVolumeLevel(fp, change, rel);
#endif #endif
case VOLUME_MIXER_TYPE_SOFTWARE: case VOLUME_MIXER_TYPE_SOFTWARE:
return changeSoftwareVolume(fp,change,rel); return changeSoftwareVolume(fp, change, rel);
default: default:
return 0; return 0;
break; break;