diff options
author | J. Alexander Treuman <jat@spatialrift.net> | 2007-05-28 15:50:45 +0000 |
---|---|---|
committer | J. Alexander Treuman <jat@spatialrift.net> | 2007-05-28 15:50:45 +0000 |
commit | 4e05a161e54fe05902b99eff521aa0759b102f05 (patch) | |
tree | 9014ab8ce74e4fb2f0115c5518c62879bc269324 /trunk/src | |
parent | e45bc035931b2c9ef13b85f98a3d4833a8dec8a9 (diff) | |
download | mpd-4e05a161e54fe05902b99eff521aa0759b102f05.tar.gz mpd-4e05a161e54fe05902b99eff521aa0759b102f05.tar.xz mpd-4e05a161e54fe05902b99eff521aa0759b102f05.zip |
Making branch for 0.13.0 fixes.
git-svn-id: https://svn.musicpd.org/mpd/branches/branch-0.13.0-fixes@6330 09075e82-0dd4-0310-85a5-a0d7c8717e4f
Diffstat (limited to '')
131 files changed, 0 insertions, 33405 deletions
diff --git a/trunk/src/Makefile.am b/trunk/src/Makefile.am deleted file mode 100644 index b9c6fa0c7..000000000 --- a/trunk/src/Makefile.am +++ /dev/null @@ -1,148 +0,0 @@ -bin_PROGRAMS = mpd -SUBDIRS = $(MP4FF_SUBDIR) - -mpd_audioOutputs = \ - audioOutputs/audioOutput_alsa.c \ - audioOutputs/audioOutput_ao.c \ - audioOutputs/audioOutput_oss.c \ - audioOutputs/audioOutput_osx.c \ - audioOutputs/audioOutput_pulse.c \ - audioOutputs/audioOutput_mvp.c \ - audioOutputs/audioOutput_shout.c \ - audioOutputs/audioOutput_jack.c - -mpd_inputPlugins = \ - inputPlugins/_flac_common.c \ - inputPlugins/_ogg_common.c \ - inputPlugins/oggflac_plugin.c \ - inputPlugins/oggvorbis_plugin.c \ - inputPlugins/aac_plugin.c \ - inputPlugins/audiofile_plugin.c \ - inputPlugins/flac_plugin.c \ - inputPlugins/mod_plugin.c \ - inputPlugins/mp3_plugin.c \ - inputPlugins/mp4_plugin.c \ - inputPlugins/mpc_plugin.c - - -mpd_headers = \ - ack.h \ - audio.h \ - audioOutput.h \ - buffer2array.h \ - charConv.h \ - command.h \ - conf.h \ - dbUtils.h \ - decode.h \ - directory.h \ - gcc.h \ - inputPlugin.h \ - inputPlugins/_flac_common.h \ - inputPlugins/_ogg_common.h \ - inputStream.h \ - inputStream_file.h \ - inputStream_http.h \ - interface.h \ - list.h \ - listen.h \ - log.h \ - ls.h \ - metadataChunk.h \ - mpd_types.h \ - myfprintf.h \ - normalize.h \ - compress.h \ - outputBuffer.h \ - path.h \ - pcm_utils.h \ - permission.h \ - player.h \ - playerData.h \ - playlist.h \ - replayGain.h \ - signal_check.h \ - sig_handlers.h \ - sllist.h \ - song.h \ - state_file.h \ - stats.h \ - tag.h \ - tagTracker.h \ - tree.h \ - utf8.h \ - utils.h \ - volume.h \ - ioops.h \ - zeroconf.h \ - locate.h \ - storedPlaylist.h - - -mpd_SOURCES = \ - $(mpd_headers) \ - $(mpd_audioOutputs) \ - $(mpd_inputPlugins) \ - audio.c \ - audioOutput.c \ - buffer2array.c \ - charConv.c \ - command.c \ - conf.c \ - dbUtils.c \ - decode.c \ - directory.c \ - inputPlugin.c \ - inputStream.c \ - inputStream_file.c \ - inputStream_http.c \ - interface.c \ - list.c \ - listen.c \ - log.c \ - ls.c \ - main.c \ - metadataChunk.c \ - myfprintf.c \ - normalize.c \ - compress.c \ - outputBuffer.c \ - path.c \ - pcm_utils.c \ - permission.c \ - player.c \ - playerData.c \ - playlist.c \ - replayGain.c \ - sig_handlers.c \ - signal_check.c \ - sllist.c \ - song.c \ - state_file.c \ - stats.c \ - tag.c \ - tagTracker.c \ - tree.c \ - utils.c \ - volume.c \ - utf8.c \ - zeroconf.c \ - locate.c \ - storedPlaylist.c - - -mpd_CFLAGS = $(MPD_CFLAGS) -mpd_LDADD = $(MPD_LIBS) $(MP4FF_LIB) - -DIST_SUBDIRS = mp4ff - -# sparse is a semantic parser -# URL: git://www.kernel.org/pub/scm/devel/sparse/sparse.git -SPARSE = sparse -SPARSE_FLAGS = -sparse-check: - for i in $(mpd_SOURCES); \ - do \ - $(SPARSE) -I. $(mpd_CFLAGS) $(SPARSE_FLAGS) $(srcdir)/$$i || exit; \ - done - diff --git a/trunk/src/ack.h b/trunk/src/ack.h deleted file mode 100644 index 1b2950e20..000000000 --- a/trunk/src/ack.h +++ /dev/null @@ -1,37 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef ACK_H -#define ACK_H - -/* Common Errors */ -#define ACK_ERROR_NOT_LIST 1 -#define ACK_ERROR_ARG 2 -#define ACK_ERROR_PASSWORD 3 -#define ACK_ERROR_PERMISSION 4 -#define ACK_ERROR_UNKNOWN 5 - -#define ACK_ERROR_NO_EXIST 50 -#define ACK_ERROR_PLAYLIST_MAX 51 -#define ACK_ERROR_SYSTEM 52 -#define ACK_ERROR_PLAYLIST_LOAD 53 -#define ACK_ERROR_UPDATE_ALREADY 54 -#define ACK_ERROR_PLAYER_SYNC 55 -#define ACK_ERROR_EXIST 56 - -#endif diff --git a/trunk/src/audio.c b/trunk/src/audio.c deleted file mode 100644 index 912e46ffa..000000000 --- a/trunk/src/audio.c +++ /dev/null @@ -1,518 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "audio.h" -#include "audioOutput.h" -#include "conf.h" -#include "log.h" -#include "sig_handlers.h" -#include "command.h" -#include "playerData.h" -#include "utils.h" -#include "state_file.h" - -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <signal.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <errno.h> -#include <unistd.h> - -#define AUDIO_DEVICE_STATE "audio_device_state:" -#define AUDIO_DEVICE_STATE_LEN 19 /* strlen(AUDIO_DEVICE_STATE) */ -#define AUDIO_BUFFER_SIZE 2*MAXPATHLEN - -static AudioFormat audio_format; - -static AudioFormat *audio_configFormat; - -static AudioOutput *audioOutputArray; -static mpd_uint8 audioOutputArraySize; - -#define DEVICE_OFF 0x00 -#define DEVICE_ENABLE 0x01 /* currently off, but to be turned on */ -#define DEVICE_ON 0x03 -#define DEVICE_DISABLE 0x04 /* currently on, but to be turned off */ - -/* the audioEnabledArray should be stuck into shared memory, and then disable - and enable in playAudio() routine */ -static mpd_uint8 *audioDeviceStates; - -static mpd_uint8 audioOpened; - -static mpd_sint32 audioBufferSize; -static char *audioBuffer; -static mpd_sint32 audioBufferPos; - -size_t audio_device_count(void) -{ - size_t nr = 0; - ConfigParam *param = NULL; - - while ((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param))) - nr++; - if (!nr) - nr = 1; /* we'll always have at least one device */ - return nr; -} - -void copyAudioFormat(AudioFormat * dest, AudioFormat * src) -{ - if (!src) - return; - - memcpy(dest, src, sizeof(AudioFormat)); -} - -int cmpAudioFormat(AudioFormat * f1, AudioFormat * f2) -{ - if (f1 && f2 && (f1->sampleRate == f2->sampleRate) && - (f1->bits == f2->bits) && (f1->channels == f2->channels)) - return 0; - return 1; -} - -void loadAudioDrivers(void) -{ - initAudioOutputPlugins(); - loadAudioOutputPlugin(&alsaPlugin); - loadAudioOutputPlugin(&aoPlugin); - loadAudioOutputPlugin(&ossPlugin); - loadAudioOutputPlugin(&osxPlugin); - loadAudioOutputPlugin(&pulsePlugin); - loadAudioOutputPlugin(&mvpPlugin); - loadAudioOutputPlugin(&shoutPlugin); - loadAudioOutputPlugin(&jackPlugin); -} - -/* make sure initPlayerData is called before this function!! */ -void initAudioDriver(void) -{ - ConfigParam *param = NULL; - int i; - - loadAudioDrivers(); - - audioOutputArraySize = audio_device_count(); - audioDeviceStates = (getPlayerData())->audioDeviceStates; - audioOutputArray = xmalloc(sizeof(AudioOutput) * audioOutputArraySize); - - for (i = 0; i < audioOutputArraySize; i++) - { - AudioOutput *output = &audioOutputArray[i]; - int j; - - param = getNextConfigParam(CONF_AUDIO_OUTPUT, param); - - /* only allow param to be NULL if there just one audioOutput */ - assert(param || (audioOutputArraySize == 1)); - - if (!initAudioOutput(output, param)) { - if (param) - { - FATAL("problems configuring output device " - "defined at line %i\n", param->line); - } - else - { - FATAL("No audio_output specified and unable to " - "detect a default audio output device\n"); - } - } - - /* require output names to be unique: */ - for (j = 0; j < i; j++) { - if (!strcmp(output->name, audioOutputArray[j].name)) { - FATAL("output devices with identical " - "names: %s\n", output->name); - } - } - audioDeviceStates[i] = DEVICE_ENABLE; - } -} - -void getOutputAudioFormat(AudioFormat * inAudioFormat, - AudioFormat * outAudioFormat) -{ - if (audio_configFormat) { - copyAudioFormat(outAudioFormat, audio_configFormat); - } else - copyAudioFormat(outAudioFormat, inAudioFormat); -} - -void initAudioConfig(void) -{ - ConfigParam *param = getConfigParam(CONF_AUDIO_OUTPUT_FORMAT); - - if (NULL == param || NULL == param->value) - return; - - audio_configFormat = xmalloc(sizeof(AudioFormat)); - - if (0 != parseAudioConfig(audio_configFormat, param->value)) { - FATAL("error parsing \"%s\" at line %i\n", - CONF_AUDIO_OUTPUT_FORMAT, param->line); - } -} - -int parseAudioConfig(AudioFormat * audioFormat, char *conf) -{ - char *test; - - memset(audioFormat, 0, sizeof(AudioFormat)); - - audioFormat->sampleRate = strtol(conf, &test, 10); - - if (*test != ':') { - ERROR("error parsing audio output format: %s\n", conf); - return -1; - } - - /*switch(audioFormat->sampleRate) { - case 48000: - case 44100: - case 32000: - case 16000: - break; - default: - ERROR("sample rate %i can not be used for audio output\n", - (int)audioFormat->sampleRate); - return -1 - } */ - - if (audioFormat->sampleRate <= 0) { - ERROR("sample rate %i is not >= 0\n", - (int)audioFormat->sampleRate); - return -1; - } - - audioFormat->bits = strtol(test + 1, &test, 10); - - if (*test != ':') { - ERROR("error parsing audio output format: %s\n", conf); - return -1; - } - - switch (audioFormat->bits) { - case 16: - break; - default: - ERROR("bits %i can not be used for audio output\n", - (int)audioFormat->bits); - return -1; - } - - audioFormat->channels = strtol(test + 1, &test, 10); - - if (*test != '\0') { - ERROR("error parsing audio output format: %s\n", conf); - return -1; - } - - switch (audioFormat->channels) { - case 1: - case 2: - break; - default: - ERROR("channels %i can not be used for audio output\n", - (int)audioFormat->channels); - return -1; - } - - return 0; -} - -void finishAudioConfig(void) -{ - if (audio_configFormat) - free(audio_configFormat); -} - -void finishAudioDriver(void) -{ - int i; - - for (i = 0; i < audioOutputArraySize; i++) { - finishAudioOutput(&audioOutputArray[i]); - } - - free(audioOutputArray); - audioOutputArray = NULL; - audioOutputArraySize = 0; -} - -int isCurrentAudioFormat(AudioFormat * audioFormat) -{ - if (!audioFormat) - return 1; - - if (cmpAudioFormat(audioFormat, &audio_format) != 0) - return 0; - - return 1; -} - -static void syncAudioDeviceStates(void) -{ - int i; - - if (!audio_format.channels) - return; - for (i = 0; i < audioOutputArraySize; ++i ) { - switch (audioDeviceStates[i]) { - case DEVICE_ON: - /* This will reopen only if the audio format changed */ - openAudioOutput(&audioOutputArray[i], &audio_format); - break; - case DEVICE_ENABLE: - openAudioOutput(&audioOutputArray[i], &audio_format); - audioDeviceStates[i] = DEVICE_ON; - break; - case DEVICE_DISABLE: - dropBufferedAudioOutput(&audioOutputArray[i]); - closeAudioOutput(&audioOutputArray[i]); - audioDeviceStates[i] = DEVICE_OFF; - break; - } - } -} - -static int flushAudioBuffer(void) -{ - int ret = -1; - int i, err; - - if (audioBufferPos == 0) - return 0; - - syncAudioDeviceStates(); - - for (i = 0; i < audioOutputArraySize; ++i) { - if (audioDeviceStates[i] != DEVICE_ON) - continue; - err = playAudioOutput(&audioOutputArray[i], audioBuffer, - audioBufferPos); - if (!err) - ret = 0; - else if (err < 0) - /* device should already be closed if the play - * func returned an error */ - audioDeviceStates[i] = DEVICE_ENABLE; - } - - audioBufferPos = 0; - - return ret; -} - -int openAudioDevice(AudioFormat * audioFormat) -{ - int ret = -1; - int i; - - if (!audioOutputArray) - return -1; - - if (!audioOpened || !isCurrentAudioFormat(audioFormat)) { - flushAudioBuffer(); - copyAudioFormat(&audio_format, audioFormat); - audioBufferSize = (audio_format.bits >> 3) * - audio_format.channels; - audioBufferSize *= audio_format.sampleRate >> 5; - audioBuffer = xrealloc(audioBuffer, audioBufferSize); - } - - syncAudioDeviceStates(); - - for (i = 0; i < audioOutputArraySize; ++i) { - if (audioOutputArray[i].open) - ret = 0; - } - - if (ret == 0) - audioOpened = 1; - else { - /* close all devices if there was an error */ - for (i = 0; i < audioOutputArraySize; ++i) { - closeAudioOutput(&audioOutputArray[i]); - } - - audioOpened = 0; - } - - return ret; -} - -int playAudio(char *playChunk, int size) -{ - int send; - - while (size > 0) { - send = audioBufferSize - audioBufferPos; - send = send < size ? send : size; - - memcpy(audioBuffer + audioBufferPos, playChunk, send); - audioBufferPos += send; - size -= send; - playChunk += send; - - if (audioBufferPos == audioBufferSize) { - if (flushAudioBuffer() < 0) - return -1; - } - } - - return 0; -} - -int isAudioDeviceOpen(void) -{ - return audioOpened; -} - -void dropBufferedAudio(void) -{ - int i; - - syncAudioDeviceStates(); - audioBufferPos = 0; - - for (i = 0; i < audioOutputArraySize; ++i) { - if (audioDeviceStates[i] == DEVICE_ON) - dropBufferedAudioOutput(&audioOutputArray[i]); - } -} - -void closeAudioDevice(void) -{ - int i; - - flushAudioBuffer(); - - free(audioBuffer); - audioBuffer = NULL; - audioBufferSize = 0; - - for (i = 0; i < audioOutputArraySize; ++i) { - if (audioDeviceStates[i] == DEVICE_ON) - audioDeviceStates[i] = DEVICE_ENABLE; - closeAudioOutput(&audioOutputArray[i]); - } - - audioOpened = 0; -} - -void sendMetadataToAudioDevice(MpdTag * tag) -{ - int i; - - for (i = 0; i < audioOutputArraySize; ++i) { - sendMetadataToAudioOutput(&audioOutputArray[i], tag); - } -} - -int enableAudioDevice(int fd, int device) -{ - if (device < 0 || device >= audioOutputArraySize) { - commandError(fd, ACK_ERROR_ARG, "audio output device id %i " - "doesn't exist\n", device); - return -1; - } - - if (!(audioDeviceStates[device] & 0x01)) - audioDeviceStates[device] = DEVICE_ENABLE; - - return 0; -} - -int disableAudioDevice(int fd, int device) -{ - if (device < 0 || device >= audioOutputArraySize) { - commandError(fd, ACK_ERROR_ARG, "audio output device id %i " - "doesn't exist\n", device); - return -1; - } - if (audioDeviceStates[device] & 0x01) - audioDeviceStates[device] = DEVICE_DISABLE; - - return 0; -} - -void printAudioDevices(int fd) -{ - int i; - - for (i = 0; i < audioOutputArraySize; i++) { - fdprintf(fd, - "outputid: %i\noutputname: %s\noutputenabled: %i\n", - i, - audioOutputArray[i].name, - audioDeviceStates[i] & 0x01); - } -} - -void saveAudioDevicesState(FILE *fp) -{ - int i; - - assert(audioOutputArraySize != 0); - for (i = 0; i < audioOutputArraySize; i++) { - fprintf(fp, AUDIO_DEVICE_STATE "%d:%s\n", - audioDeviceStates[i] & 0x01, - audioOutputArray[i].name); - } -} - -void readAudioDevicesState(FILE *fp) -{ - char buffer[AUDIO_BUFFER_SIZE]; - int i; - - assert(audioOutputArraySize != 0); - - while (myFgets(buffer, AUDIO_BUFFER_SIZE, fp)) { - char *c, *name; - - if (strncmp(buffer, AUDIO_DEVICE_STATE, AUDIO_DEVICE_STATE_LEN)) - continue; - - c = strchr(buffer, ':'); - if (!c || !(++c)) - goto errline; - - name = strchr(c, ':'); - if (!name || !(++name)) - goto errline; - - for (i = 0; i < audioOutputArraySize; ++i) { - if (!strcmp(name, audioOutputArray[i].name)) { - /* devices default to on */ - if (!atoi(c)) - audioDeviceStates[i] = DEVICE_DISABLE; - break; - } - } - continue; -errline: - /* nonfatal */ - ERROR("invalid line in state_file: %s\n", buffer); - } -} - diff --git a/trunk/src/audio.h b/trunk/src/audio.h deleted file mode 100644 index cc4ac0752..000000000 --- a/trunk/src/audio.h +++ /dev/null @@ -1,83 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef AUDIO_H -#define AUDIO_H - -#include "../config.h" - -#include "mpd_types.h" -#include "tag.h" - -#include <stdio.h> - -#define AUDIO_AO_DRIVER_DEFAULT "default" - -typedef struct _AudioFormat { - volatile mpd_sint8 channels; - volatile mpd_uint32 sampleRate; - volatile mpd_sint8 bits; -} AudioFormat; - -size_t audio_device_count(void); - -void copyAudioFormat(AudioFormat * dest, AudioFormat * src); - -int cmpAudioFormat(AudioFormat * dest, AudioFormat * src); - -void getOutputAudioFormat(AudioFormat * inFormat, AudioFormat * outFormat); - -int parseAudioConfig(AudioFormat * audioFormat, char *conf); - -/* make sure initPlayerData is called before this function!! */ -void initAudioConfig(void); - -void finishAudioConfig(void); - -void initAudioDriver(void); - -void finishAudioDriver(void); - -int openAudioDevice(AudioFormat * audioFormat); - -int playAudio(char *playChunk, int size); - -void dropBufferedAudio(void); - -void closeAudioDevice(void); - -int isAudioDeviceOpen(void); - -int isCurrentAudioFormat(AudioFormat * audioFormat); - -void sendMetadataToAudioDevice(MpdTag * tag); - -/* these functions are called in the main parent process while the child - process is busy playing to the audio */ -int enableAudioDevice(int fd, int device); - -int disableAudioDevice(int fd, int device); - -void printAudioDevices(int fd); - -void readAudioDevicesState(FILE *fp); - -void saveAudioDevicesState(FILE *fp); - -void loadAudioDrivers(void); -#endif diff --git a/trunk/src/audioOutput.c b/trunk/src/audioOutput.c deleted file mode 100644 index 49a7ce258..000000000 --- a/trunk/src/audioOutput.c +++ /dev/null @@ -1,269 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "audioOutput.h" - -#include "list.h" -#include "log.h" -#include "pcm_utils.h" - -#include <string.h> - -#define AUDIO_OUTPUT_TYPE "type" -#define AUDIO_OUTPUT_NAME "name" -#define AUDIO_OUTPUT_FORMAT "format" - -static List *audioOutputPluginList; - -void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin) -{ - if (!audioOutputPlugin->name) - return; - insertInList(audioOutputPluginList, audioOutputPlugin->name, - audioOutputPlugin); -} - -void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin) -{ - if (!audioOutputPlugin->name) - return; - deleteFromList(audioOutputPluginList, audioOutputPlugin->name); -} - -void initAudioOutputPlugins(void) -{ - audioOutputPluginList = makeList(NULL, 0); -} - -void finishAudioOutputPlugins(void) -{ - freeList(audioOutputPluginList); -} - -#define getBlockParam(name, str, force) { \ - bp = getBlockParam(param, name); \ - if(force && bp == NULL) { \ - FATAL("couldn't find parameter \"%s\" in audio output " \ - "definition beginning at %i\n", \ - name, param->line); \ - } \ - if(bp) str = bp->value; \ -} - -int initAudioOutput(AudioOutput *ao, ConfigParam * param) -{ - void *data = NULL; - char *name = NULL; - char *format = NULL; - char *type = NULL; - BlockParam *bp = NULL; - AudioOutputPlugin *plugin = NULL; - - if (param) { - getBlockParam(AUDIO_OUTPUT_NAME, name, 1); - getBlockParam(AUDIO_OUTPUT_TYPE, type, 1); - getBlockParam(AUDIO_OUTPUT_FORMAT, format, 0); - - if (!findInList(audioOutputPluginList, type, &data)) { - FATAL("couldn't find audio output plugin for type " - "\"%s\" at line %i\n", type, param->line); - } - - plugin = (AudioOutputPlugin *) data; - } else { - ListNode *node = audioOutputPluginList->firstNode; - - WARNING("No \"%s\" defined in config file\n", - CONF_AUDIO_OUTPUT); - WARNING("Attempt to detect audio output device\n"); - - while (node) { - plugin = (AudioOutputPlugin *) node->data; - if (plugin->testDefaultDeviceFunc) { - WARNING("Attempting to detect a %s audio " - "device\n", plugin->name); - if (plugin->testDefaultDeviceFunc() == 0) { - WARNING("Successfully detected a %s " - "audio device\n", plugin->name); - break; - } - } - node = node->nextNode; - } - - if (!node) { - WARNING("Unable to detect an audio device\n"); - return 0; - } - - name = "default detected output"; - type = plugin->name; - } - - ao->name = name; - ao->type = type; - ao->finishDriverFunc = plugin->finishDriverFunc; - ao->openDeviceFunc = plugin->openDeviceFunc; - ao->playFunc = plugin->playFunc; - ao->dropBufferedAudioFunc = plugin->dropBufferedAudioFunc; - ao->closeDeviceFunc = plugin->closeDeviceFunc; - ao->sendMetdataFunc = plugin->sendMetdataFunc; - ao->open = 0; - - ao->convertAudioFormat = 0; - ao->sameInAndOutFormats = 0; - ao->convBuffer = NULL; - ao->convBufferLen = 0; - - memset(&ao->inAudioFormat, 0, sizeof(AudioFormat)); - memset(&ao->outAudioFormat, 0, sizeof(AudioFormat)); - memset(&ao->reqAudioFormat, 0, sizeof(AudioFormat)); - memset(&ao->convState, 0, sizeof(ConvState)); - - if (format) { - ao->convertAudioFormat = 1; - - if (0 != parseAudioConfig(&ao->reqAudioFormat, format)) { - FATAL("error parsing format at line %i\n", bp->line); - } - - copyAudioFormat(&ao->outAudioFormat, &ao->reqAudioFormat); - } - - if (plugin->initDriverFunc(ao, param) != 0) - return 0; - - return 1; -} - -int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat) -{ - int ret = 0; - - if (audioOutput->open) - { - if (0==cmpAudioFormat(audioFormat, &audioOutput->inAudioFormat)) - { - return 0; - } - } - - copyAudioFormat(&audioOutput->inAudioFormat, audioFormat); - - if (audioOutput->convertAudioFormat) - { - copyAudioFormat(&audioOutput->outAudioFormat, - &audioOutput->reqAudioFormat); - } - else - { - copyAudioFormat(&audioOutput->outAudioFormat, - &audioOutput->inAudioFormat); - if (audioOutput->open) closeAudioOutput(audioOutput); - } - - if (!audioOutput->open) - { - ret = audioOutput->openDeviceFunc(audioOutput); - } - - audioOutput->sameInAndOutFormats = - !cmpAudioFormat(&audioOutput->inAudioFormat, - &audioOutput->outAudioFormat); - - return ret; -} - -static void convertAudioFormat(AudioOutput * audioOutput, char **chunkArgPtr, - int *sizeArgPtr) -{ - int size = pcm_sizeOfConvBuffer(&(audioOutput->inAudioFormat), - *sizeArgPtr, - &(audioOutput->outAudioFormat)); - - if (size > audioOutput->convBufferLen) { - audioOutput->convBuffer = - xrealloc(audioOutput->convBuffer, size); - audioOutput->convBufferLen = size; - } - - *sizeArgPtr = pcm_convertAudioFormat(&(audioOutput->inAudioFormat), - *chunkArgPtr, *sizeArgPtr, - &(audioOutput->outAudioFormat), - audioOutput->convBuffer, - &audioOutput->convState); - - *chunkArgPtr = audioOutput->convBuffer; -} - -int playAudioOutput(AudioOutput * audioOutput, char *playChunk, int size) -{ - int ret; - - if (!audioOutput->open) - return -1; - - if (!audioOutput->sameInAndOutFormats) { - convertAudioFormat(audioOutput, &playChunk, &size); - } - - ret = audioOutput->playFunc(audioOutput, playChunk, size); - - return ret; -} - -void dropBufferedAudioOutput(AudioOutput * audioOutput) -{ - if (audioOutput->open) - audioOutput->dropBufferedAudioFunc(audioOutput); -} - -void closeAudioOutput(AudioOutput * audioOutput) -{ - if (audioOutput->open) - audioOutput->closeDeviceFunc(audioOutput); -} - -void finishAudioOutput(AudioOutput * audioOutput) -{ - closeAudioOutput(audioOutput); - audioOutput->finishDriverFunc(audioOutput); - if (audioOutput->convBuffer) - free(audioOutput->convBuffer); -} - -void sendMetadataToAudioOutput(AudioOutput * audioOutput, MpdTag * tag) -{ - if (!audioOutput->sendMetdataFunc) - return; - audioOutput->sendMetdataFunc(audioOutput, tag); -} - -void printAllOutputPluginTypes(FILE * fp) -{ - ListNode *node = audioOutputPluginList->firstNode; - AudioOutputPlugin *plugin; - - while (node) { - plugin = (AudioOutputPlugin *) node->data; - fprintf(fp, "%s ", plugin->name); - node = node->nextNode; - } - fprintf(fp, "\n"); - fflush(fp); -} diff --git a/trunk/src/audioOutput.h b/trunk/src/audioOutput.h deleted file mode 100644 index bcbe7997d..000000000 --- a/trunk/src/audioOutput.h +++ /dev/null @@ -1,117 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef AUDIO_OUTPUT_H -#define AUDIO_OUTPUT_H - -#include "../config.h" - -#include "pcm_utils.h" -#include "mpd_types.h" -#include "audio.h" -#include "tag.h" -#include "conf.h" -#include "utils.h" - -#define DISABLED_AUDIO_OUTPUT_PLUGIN(plugin) AudioOutputPlugin plugin; - -typedef struct _AudioOutput AudioOutput; - -typedef int (*AudioOutputTestDefaultDeviceFunc) (); - -typedef int (*AudioOutputInitDriverFunc) (AudioOutput * audioOutput, - ConfigParam * param); - -typedef void (*AudioOutputFinishDriverFunc) (AudioOutput * audioOutput); - -typedef int (*AudioOutputOpenDeviceFunc) (AudioOutput * audioOutput); - -typedef int (*AudioOutputPlayFunc) (AudioOutput * audioOutput, - char *playChunk, int size); - -typedef void (*AudioOutputDropBufferedAudioFunc) (AudioOutput * audioOutput); - -typedef void (*AudioOutputCloseDeviceFunc) (AudioOutput * audioOutput); - -typedef void (*AudioOutputSendMetadataFunc) (AudioOutput * audioOutput, - MpdTag * tag); - -struct _AudioOutput { - int open; - char *name; - char *type; - - AudioOutputFinishDriverFunc finishDriverFunc; - AudioOutputOpenDeviceFunc openDeviceFunc; - AudioOutputPlayFunc playFunc; - AudioOutputDropBufferedAudioFunc dropBufferedAudioFunc; - AudioOutputCloseDeviceFunc closeDeviceFunc; - AudioOutputSendMetadataFunc sendMetdataFunc; - - int convertAudioFormat; - AudioFormat inAudioFormat; - AudioFormat outAudioFormat; - AudioFormat reqAudioFormat; - ConvState convState; - char *convBuffer; - int convBufferLen; - int sameInAndOutFormats; - - void *data; -}; - -typedef struct _AudioOutputPlugin { - char *name; - - AudioOutputTestDefaultDeviceFunc testDefaultDeviceFunc; - AudioOutputInitDriverFunc initDriverFunc; - AudioOutputFinishDriverFunc finishDriverFunc; - AudioOutputOpenDeviceFunc openDeviceFunc; - AudioOutputPlayFunc playFunc; - AudioOutputDropBufferedAudioFunc dropBufferedAudioFunc; - AudioOutputCloseDeviceFunc closeDeviceFunc; - AudioOutputSendMetadataFunc sendMetdataFunc; -} AudioOutputPlugin; - -void initAudioOutputPlugins(void); -void finishAudioOutputPlugins(void); - -void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin); -void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin); - -int initAudioOutput(AudioOutput *, ConfigParam * param); -int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat); -int playAudioOutput(AudioOutput * audioOutput, char *playChunk, int size); -void dropBufferedAudioOutput(AudioOutput * audioOutput); -void closeAudioOutput(AudioOutput * audioOutput); -void finishAudioOutput(AudioOutput * audioOutput); -int keepAudioOutputAlive(AudioOutput * audioOutput, int ms); -void sendMetadataToAudioOutput(AudioOutput * audioOutput, MpdTag * tag); - -void printAllOutputPluginTypes(FILE * fp); - -extern AudioOutputPlugin alsaPlugin; -extern AudioOutputPlugin aoPlugin; -extern AudioOutputPlugin ossPlugin; -extern AudioOutputPlugin osxPlugin; -extern AudioOutputPlugin pulsePlugin; -extern AudioOutputPlugin mvpPlugin; -extern AudioOutputPlugin shoutPlugin; -extern AudioOutputPlugin jackPlugin; - -#endif diff --git a/trunk/src/audioOutputs/audioOutput_alsa.c b/trunk/src/audioOutputs/audioOutput_alsa.c deleted file mode 100644 index 3ade3df46..000000000 --- a/trunk/src/audioOutputs/audioOutput_alsa.c +++ /dev/null @@ -1,427 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../audioOutput.h" - -#include <stdlib.h> - -#ifdef HAVE_ALSA - -#define ALSA_PCM_NEW_HW_PARAMS_API -#define ALSA_PCM_NEW_SW_PARAMS_API - -#define MPD_ALSA_BUFFER_TIME_US 500000 -/* the default period time of xmms is 50 ms, so let's use that as well. - * a user can tweak this parameter via the "period_time" config parameter. - */ -#define MPD_ALSA_PERIOD_TIME_US 50000 -#define MPD_ALSA_RETRY_NR 5 - -#include "../conf.h" -#include "../log.h" - -#include <string.h> - -#include <alsa/asoundlib.h> - -typedef snd_pcm_sframes_t alsa_writei_t(snd_pcm_t * pcm, const void *buffer, - snd_pcm_uframes_t size); - -typedef struct _AlsaData { - char *device; - snd_pcm_t *pcmHandle; - alsa_writei_t *writei; - unsigned int buffer_time; - unsigned int period_time; - int sampleSize; - int useMmap; - int canPause; - int canResume; -} AlsaData; - -static AlsaData *newAlsaData(void) -{ - AlsaData *ret = xmalloc(sizeof(AlsaData)); - - ret->device = NULL; - ret->pcmHandle = NULL; - ret->writei = snd_pcm_writei; - ret->useMmap = 0; - ret->buffer_time = MPD_ALSA_BUFFER_TIME_US; - ret->period_time = MPD_ALSA_PERIOD_TIME_US; - - return ret; -} - -static void freeAlsaData(AlsaData * ad) -{ - if (ad->device) - free(ad->device); - - free(ad); -} - -static int alsa_initDriver(AudioOutput * audioOutput, ConfigParam * param) -{ - AlsaData *ad = newAlsaData(); - - if (param) { - BlockParam *bp = getBlockParam(param, "device"); - ad->device = bp ? xstrdup(bp->value) : xstrdup("default"); - - if ((bp = getBlockParam(param, "use_mmap")) && - !strcasecmp(bp->value, "yes")) - ad->useMmap = 1; - if ((bp = getBlockParam(param, "buffer_time"))) - ad->buffer_time = atoi(bp->value); - if ((bp = getBlockParam(param, "period_time"))) - ad->period_time = atoi(bp->value); - } else - ad->device = xstrdup("default"); - audioOutput->data = ad; - - return 0; -} - -static void alsa_finishDriver(AudioOutput * audioOutput) -{ - AlsaData *ad = audioOutput->data; - - freeAlsaData(ad); -} - -static int alsa_testDefault(void) -{ - snd_pcm_t *handle; - - int ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, - SND_PCM_NONBLOCK); - snd_config_update_free_global(); - - if (ret) { - WARNING("Error opening default alsa device: %s\n", - snd_strerror(-ret)); - return -1; - } else - snd_pcm_close(handle); - - return 0; -} - -static int alsa_openDevice(AudioOutput * audioOutput) -{ - AlsaData *ad = audioOutput->data; - AudioFormat *audioFormat = &audioOutput->outAudioFormat; - snd_pcm_format_t bitformat; - snd_pcm_hw_params_t *hwparams; - snd_pcm_sw_params_t *swparams; - unsigned int sampleRate = audioFormat->sampleRate; - unsigned int channels = audioFormat->channels; - snd_pcm_uframes_t alsa_buffer_size; - snd_pcm_uframes_t alsa_period_size; - int err; - const char *cmd = NULL; - int retry = MPD_ALSA_RETRY_NR; - unsigned int period_time, period_time_ro; - unsigned int buffer_time; - - switch (audioFormat->bits) { - case 8: - bitformat = SND_PCM_FORMAT_S8; - break; - case 16: - bitformat = SND_PCM_FORMAT_S16; - break; - case 24: - bitformat = SND_PCM_FORMAT_S24; - break; - case 32: - bitformat = SND_PCM_FORMAT_S32; - break; - default: - ERROR("ALSA device \"%s\" doesn't support %i bit audio\n", - ad->device, audioFormat->bits); - return -1; - } - - err = snd_pcm_open(&ad->pcmHandle, ad->device, - SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); - snd_config_update_free_global(); - if (err < 0) { - ad->pcmHandle = NULL; - goto error; - } - - cmd = "snd_pcm_nonblock"; - err = snd_pcm_nonblock(ad->pcmHandle, 0); - if (err < 0) - goto error; - - period_time_ro = period_time = ad->period_time; -configure_hw: - /* configure HW params */ - snd_pcm_hw_params_alloca(&hwparams); - - cmd = "snd_pcm_hw_params_any"; - err = snd_pcm_hw_params_any(ad->pcmHandle, hwparams); - if (err < 0) - goto error; - - if (ad->useMmap) { - err = snd_pcm_hw_params_set_access(ad->pcmHandle, hwparams, - SND_PCM_ACCESS_MMAP_INTERLEAVED); - if (err < 0) { - ERROR("Cannot set mmap'ed mode on alsa device \"%s\": " - " %s\n", ad->device, snd_strerror(-err)); - ERROR("Falling back to direct write mode\n"); - ad->useMmap = 0; - } else - ad->writei = snd_pcm_mmap_writei; - } - - if (!ad->useMmap) { - cmd = "snd_pcm_hw_params_set_access"; - err = snd_pcm_hw_params_set_access(ad->pcmHandle, hwparams, - SND_PCM_ACCESS_RW_INTERLEAVED); - if (err < 0) - goto error; - ad->writei = snd_pcm_writei; - } - - err = snd_pcm_hw_params_set_format(ad->pcmHandle, hwparams, bitformat); - if (err < 0) { - ERROR("ALSA device \"%s\" does not support %i bit audio: " - "%s\n", ad->device, audioFormat->bits, snd_strerror(-err)); - goto fail; - } - - err = snd_pcm_hw_params_set_channels_near(ad->pcmHandle, hwparams, - &channels); - if (err < 0) { - ERROR("ALSA device \"%s\" does not support %i channels: " - "%s\n", ad->device, (int)audioFormat->channels, - snd_strerror(-err)); - goto fail; - } - audioFormat->channels = channels; - - err = snd_pcm_hw_params_set_rate_near(ad->pcmHandle, hwparams, - &sampleRate, NULL); - if (err < 0 || sampleRate == 0) { - ERROR("ALSA device \"%s\" does not support %i Hz audio\n", - ad->device, (int)audioFormat->sampleRate); - goto fail; - } - audioFormat->sampleRate = sampleRate; - - buffer_time = ad->buffer_time; - cmd = "snd_pcm_hw_params_set_buffer_time_near"; - err = snd_pcm_hw_params_set_buffer_time_near(ad->pcmHandle, hwparams, - &buffer_time, NULL); - if (err < 0) - goto error; - - period_time = period_time_ro; - cmd = "snd_pcm_hw_params_set_period_time_near"; - err = snd_pcm_hw_params_set_period_time_near(ad->pcmHandle, hwparams, - &period_time, NULL); - if (err < 0) - goto error; - - cmd = "snd_pcm_hw_params"; - err = snd_pcm_hw_params(ad->pcmHandle, hwparams); - if (err == -EPIPE && --retry > 0) { - period_time_ro = period_time_ro >> 1; - goto configure_hw; - } else if (err < 0) - goto error; - if (retry != MPD_ALSA_RETRY_NR) - DEBUG("ALSA period_time set to %d\n", period_time); - - cmd = "snd_pcm_hw_params_get_buffer_size"; - err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_buffer_size); - if (err < 0) - goto error; - - cmd = "snd_pcm_hw_params_get_period_size"; - err = snd_pcm_hw_params_get_period_size(hwparams, &alsa_period_size, - NULL); - if (err < 0) - goto error; - - ad->canPause = snd_pcm_hw_params_can_pause(hwparams); - ad->canResume = snd_pcm_hw_params_can_resume(hwparams); - - /* configure SW params */ - snd_pcm_sw_params_alloca(&swparams); - - cmd = "snd_pcm_sw_params_current"; - err = snd_pcm_sw_params_current(ad->pcmHandle, swparams); - if (err < 0) - goto error; - - cmd = "snd_pcm_sw_params_set_start_threshold"; - err = snd_pcm_sw_params_set_start_threshold(ad->pcmHandle, swparams, - alsa_buffer_size - - alsa_period_size); - if (err < 0) - goto error; - - cmd = "snd_pcm_sw_params_set_avail_min"; - err = snd_pcm_sw_params_set_avail_min(ad->pcmHandle, swparams, - alsa_period_size); - if (err < 0) - goto error; - - cmd = "snd_pcm_sw_params_set_xfer_align"; - err = snd_pcm_sw_params_set_xfer_align(ad->pcmHandle, swparams, 1); - if (err < 0) - goto error; - - cmd = "snd_pcm_sw_params"; - err = snd_pcm_sw_params(ad->pcmHandle, swparams); - if (err < 0) - goto error; - - ad->sampleSize = (audioFormat->bits / 8) * audioFormat->channels; - - audioOutput->open = 1; - - DEBUG("alsa device \"%s\" will be playing %i bit, %i channel audio at " - "%i Hz\n", ad->device, (int)audioFormat->bits, - channels, sampleRate); - - return 0; - -error: - if (cmd) { - ERROR("Error opening alsa device \"%s\" (%s): %s\n", - ad->device, cmd, snd_strerror(-err)); - } else { - ERROR("Error opening alsa device \"%s\": %s\n", ad->device, - snd_strerror(-err)); - } -fail: - if (ad->pcmHandle) - snd_pcm_close(ad->pcmHandle); - ad->pcmHandle = NULL; - audioOutput->open = 0; - return -1; -} - -static int alsa_errorRecovery(AlsaData * ad, int err) -{ - if (err == -EPIPE) { - DEBUG("Underrun on alsa device \"%s\"\n", ad->device); - } else if (err == -ESTRPIPE) { - DEBUG("alsa device \"%s\" was suspended\n", ad->device); - } - - switch (snd_pcm_state(ad->pcmHandle)) { - case SND_PCM_STATE_PAUSED: - err = snd_pcm_pause(ad->pcmHandle, /* disable */ 0); - break; - case SND_PCM_STATE_SUSPENDED: - err = ad->canResume ? - snd_pcm_resume(ad->pcmHandle) : - snd_pcm_prepare(ad->pcmHandle); - break; - case SND_PCM_STATE_SETUP: - case SND_PCM_STATE_XRUN: - err = snd_pcm_prepare(ad->pcmHandle); - break; - case SND_PCM_STATE_DISCONNECTED: - /* so alsa_closeDevice won't try to drain: */ - snd_pcm_close(ad->pcmHandle); - ad->pcmHandle = NULL; - break; - default: - /* unknown state, do nothing */ - break; - } - - return err; -} - -static void alsa_dropBufferedAudio(AudioOutput * audioOutput) -{ - AlsaData *ad = audioOutput->data; - - alsa_errorRecovery(ad, snd_pcm_drop(ad->pcmHandle)); -} - -static void alsa_closeDevice(AudioOutput * audioOutput) -{ - AlsaData *ad = audioOutput->data; - - if (ad->pcmHandle) { - snd_pcm_drain(ad->pcmHandle); - snd_pcm_close(ad->pcmHandle); - ad->pcmHandle = NULL; - } - - audioOutput->open = 0; -} - -static int alsa_playAudio(AudioOutput * audioOutput, char *playChunk, int size) -{ - AlsaData *ad = audioOutput->data; - int ret; - - size /= ad->sampleSize; - - while (size > 0) { - ret = ad->writei(ad->pcmHandle, playChunk, size); - - if (ret == -EAGAIN || ret == -EINTR) - continue; - - if (ret < 0) { - if (alsa_errorRecovery(ad, ret) < 0) { - ERROR("closing alsa device \"%s\" due to write " - "error: %s\n", ad->device, - snd_strerror(-errno)); - alsa_closeDevice(audioOutput); - return -1; - } - continue; - } - - playChunk += ret * ad->sampleSize; - size -= ret; - } - - return 0; -} - -AudioOutputPlugin alsaPlugin = { - "alsa", - alsa_testDefault, - alsa_initDriver, - alsa_finishDriver, - alsa_openDevice, - alsa_playAudio, - alsa_dropBufferedAudio, - alsa_closeDevice, - NULL, /* sendMetadataFunc */ -}; - -#else /* HAVE ALSA */ - -DISABLED_AUDIO_OUTPUT_PLUGIN(alsaPlugin) -#endif /* HAVE_ALSA */ diff --git a/trunk/src/audioOutputs/audioOutput_ao.c b/trunk/src/audioOutputs/audioOutput_ao.c deleted file mode 100644 index a7f437ef4..000000000 --- a/trunk/src/audioOutputs/audioOutput_ao.c +++ /dev/null @@ -1,246 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../audioOutput.h" - -#ifdef HAVE_AO - -#include "../conf.h" -#include "../log.h" - -#include <string.h> - -#include <ao/ao.h> - -static int driverInitCount; - -typedef struct _AoData { - int writeSize; - int driverId; - ao_option *options; - ao_device *device; -} AoData; - -static AoData *newAoData(void) -{ - AoData *ret = xmalloc(sizeof(AoData)); - ret->device = NULL; - ret->options = NULL; - - return ret; -} - -static void audioOutputAo_error(void) -{ - if (errno == AO_ENOTLIVE) { - ERROR("not a live ao device\n"); - } else if (errno == AO_EOPENDEVICE) { - ERROR("not able to open audio device\n"); - } else if (errno == AO_EBADOPTION) { - ERROR("bad driver option\n"); - } -} - -static int audioOutputAo_initDriver(AudioOutput * audioOutput, - ConfigParam * param) -{ - ao_info *ai; - char *dup; - char *stk1; - char *stk2; - char *n1; - char *key; - char *value; - char *test; - AoData *ad = newAoData(); - BlockParam *blockParam; - - audioOutput->data = ad; - - if ((blockParam = getBlockParam(param, "write_size"))) { - ad->writeSize = strtol(blockParam->value, &test, 10); - if (*test != '\0') { - FATAL("\"%s\" is not a valid write size at line %i\n", - blockParam->value, blockParam->line); - } - } else - ad->writeSize = 1024; - - if (driverInitCount == 0) { - ao_initialize(); - } - driverInitCount++; - - blockParam = getBlockParam(param, "driver"); - - if (!blockParam || 0 == strcmp(blockParam->value, "default")) { - ad->driverId = ao_default_driver_id(); - } else if ((ad->driverId = ao_driver_id(blockParam->value)) < 0) { - FATAL("\"%s\" is not a valid ao driver at line %i\n", - blockParam->value, blockParam->line); - } - - if ((ai = ao_driver_info(ad->driverId)) == NULL) { - FATAL("problems getting driver info for device defined at line %i\n" - "you may not have permission to the audio device\n", param->line); - } - - DEBUG("using ao driver \"%s\" for \"%s\"\n", ai->short_name, - audioOutput->name); - - blockParam = getBlockParam(param, "options"); - - if (blockParam) { - dup = xstrdup(blockParam->value); - } else - dup = xstrdup(""); - - if (strlen(dup)) { - stk1 = NULL; - n1 = strtok_r(dup, ";", &stk1); - while (n1) { - stk2 = NULL; - key = strtok_r(n1, "=", &stk2); - if (!key) - FATAL("problems parsing options \"%s\"\n", n1); - /*found = 0; - for(i=0;i<ai->option_count;i++) { - if(strcmp(ai->options[i],key)==0) { - found = 1; - break; - } - } - if(!found) { - FATAL("\"%s\" is not an option for " - "\"%s\" ao driver\n",key, - ai->short_name); - } */ - value = strtok_r(NULL, "", &stk2); - if (!value) - FATAL("problems parsing options \"%s\"\n", n1); - ao_append_option(&ad->options, key, value); - n1 = strtok_r(NULL, ";", &stk1); - } - } - free(dup); - - return 0; -} - -static void freeAoData(AoData * ad) -{ - ao_free_options(ad->options); - free(ad); -} - -static void audioOutputAo_finishDriver(AudioOutput * audioOutput) -{ - AoData *ad = (AoData *) audioOutput->data; - freeAoData(ad); - - driverInitCount--; - - if (driverInitCount == 0) - ao_shutdown(); -} - -static void audioOutputAo_dropBufferedAudio(AudioOutput * audioOutput) -{ - /* not supported by libao */ -} - -static void audioOutputAo_closeDevice(AudioOutput * audioOutput) -{ - AoData *ad = (AoData *) audioOutput->data; - - if (ad->device) { - ao_close(ad->device); - ad->device = NULL; - } - - audioOutput->open = 0; -} - -static int audioOutputAo_openDevice(AudioOutput * audioOutput) -{ - ao_sample_format format; - AoData *ad = (AoData *) audioOutput->data; - - if (ad->device) { - audioOutputAo_closeDevice(audioOutput); - } - - format.bits = audioOutput->outAudioFormat.bits; - format.rate = audioOutput->outAudioFormat.sampleRate; - format.byte_format = AO_FMT_NATIVE; - format.channels = audioOutput->outAudioFormat.channels; - - ad->device = ao_open_live(ad->driverId, &format, ad->options); - - if (ad->device == NULL) - return -1; - - audioOutput->open = 1; - - return 0; -} - -static int audioOutputAo_play(AudioOutput * audioOutput, char *playChunk, - int size) -{ - int send; - AoData *ad = (AoData *) audioOutput->data; - - if (ad->device == NULL) - return -1; - - while (size > 0) { - send = ad->writeSize > size ? size : ad->writeSize; - - if (ao_play(ad->device, playChunk, send) == 0) { - audioOutputAo_error(); - ERROR("closing audio device due to write error\n"); - audioOutputAo_closeDevice(audioOutput); - return -1; - } - - playChunk += send; - size -= send; - } - - return 0; -} - -AudioOutputPlugin aoPlugin = { - "ao", - NULL, - audioOutputAo_initDriver, - audioOutputAo_finishDriver, - audioOutputAo_openDevice, - audioOutputAo_play, - audioOutputAo_dropBufferedAudio, - audioOutputAo_closeDevice, - NULL, /* sendMetadataFunc */ -}; - -#else - -#include <stdio.h> - -DISABLED_AUDIO_OUTPUT_PLUGIN(aoPlugin) -#endif diff --git a/trunk/src/audioOutputs/audioOutput_jack.c b/trunk/src/audioOutputs/audioOutput_jack.c deleted file mode 100644 index 1fdfaf4bb..000000000 --- a/trunk/src/audioOutputs/audioOutput_jack.c +++ /dev/null @@ -1,440 +0,0 @@ -/* jack plug in for the Music Player Daemon (MPD) - * (c)2006 by anarch(anarchsss@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../audioOutput.h" - -#ifdef HAVE_JACK - -#include <stdlib.h> -#include <errno.h> - -#include "../conf.h" -#include "../log.h" - -#include <string.h> -#include <pthread.h> - -#include <jack/jack.h> -#include <jack/types.h> -#include <jack/ringbuffer.h> - -pthread_mutex_t play_audio_lock = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t play_audio = PTHREAD_COND_INITIALIZER; - -/*#include "dmalloc.h"*/ - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -/*#define SAMPLE_SIZE sizeof(jack_default_audio_sample_t);*/ - - -static char *name = "mpd"; -static char *output_ports[2]; -static int ringbuf_sz = 32768; -size_t sample_size = sizeof(jack_default_audio_sample_t); - -typedef struct _JackData { - jack_port_t *ports[2]; - jack_client_t *client; - jack_ringbuffer_t *ringbuffer[2]; - int bps; - int shutdown; -} JackData; - -/*JackData *jd = NULL;*/ - -static JackData *newJackData(void) -{ - JackData *ret; - ret = xcalloc(sizeof(JackData), 1); - - return ret; -} - -static void freeJackData(AudioOutput *audioOutput) -{ - JackData *jd = audioOutput->data; - if (jd) { - if (jd->ringbuffer[0]) - jack_ringbuffer_free(jd->ringbuffer[0]); - if (jd->ringbuffer[1]) - jack_ringbuffer_free(jd->ringbuffer[1]); - free(jd); - audioOutput->data = NULL; - } -} - -static void jack_finishDriver(AudioOutput *audioOutput) -{ - JackData *jd = audioOutput->data; - int i; - - if ( jd && jd->client ) { - jack_deactivate(jd->client); - jack_client_close(jd->client); - } - DEBUG("disconnect_jack (pid=%d)\n", getpid ()); - - if ( strcmp(name, "mpd") ) { - free(name); - name = "mpd"; - } - - for ( i = ARRAY_SIZE(output_ports); --i >= 0; ) { - if (!output_ports[i]) - continue; - free(output_ports[i]); - output_ports[i] = NULL; - } - - freeJackData(audioOutput); -} - -static int srate(jack_nframes_t rate, void *data) -{ - JackData *jd = (JackData *) ((AudioOutput*) data)->data; - AudioFormat *audioFormat = &(((AudioOutput*) data)->outAudioFormat); - - audioFormat->sampleRate = (int)jack_get_sample_rate(jd->client); - - return 0; -} - -static int process(jack_nframes_t nframes, void *arg) -{ - size_t i; - JackData *jd = (JackData *) arg; - jack_default_audio_sample_t *out[2]; - size_t avail_data, avail_frames; - - if ( nframes <= 0 ) - return 0; - - out[0] = jack_port_get_buffer(jd->ports[0], nframes); - out[1] = jack_port_get_buffer(jd->ports[1], nframes); - - while ( nframes ) { - avail_data = jack_ringbuffer_read_space(jd->ringbuffer[1]); - - if ( avail_data > 0 ) { - avail_frames = avail_data / sample_size; - - if (avail_frames > nframes) { - avail_frames = nframes; - avail_data = nframes*sample_size; - } - - jack_ringbuffer_read(jd->ringbuffer[0], (char *)out[0], - avail_data); - jack_ringbuffer_read(jd->ringbuffer[1], (char *)out[1], - avail_data); - - nframes -= avail_frames; - out[0] += avail_data; - out[1] += avail_data; - } else { - for (i = 0; i < nframes; i++) - out[0][i] = out[1][i] = 0.0; - nframes = 0; - } - - if (pthread_mutex_trylock (&play_audio_lock) == 0) { - pthread_cond_signal (&play_audio); - pthread_mutex_unlock (&play_audio_lock); - } - } - - - /*DEBUG("process (pid=%d)\n", getpid());*/ - return 0; -} - -static void shutdown_callback(void *arg) -{ - JackData *jd = (JackData *) arg; - jd->shutdown = 1; -} - -static void set_audioformat(AudioOutput *audioOutput) -{ - JackData *jd = audioOutput->data; - AudioFormat *audioFormat = &audioOutput->outAudioFormat; - - audioFormat->sampleRate = (int) jack_get_sample_rate(jd->client); - DEBUG("samplerate = %d\n", audioFormat->sampleRate); - audioFormat->channels = 2; - audioFormat->bits = 16; - jd->bps = audioFormat->channels - * sizeof(jack_default_audio_sample_t) - * audioFormat->sampleRate; -} - -static void error_callback(const char *msg) -{ - ERROR("jack: %s\n", msg); -} - -static int jack_initDriver(AudioOutput *audioOutput, ConfigParam *param) -{ - BlockParam *bp; - char *endptr; - int val; - char *cp = NULL; - - DEBUG("jack_initDriver (pid=%d)\n", getpid()); - if ( ! param ) return 0; - - if ( (bp = getBlockParam(param, "ports")) ) { - DEBUG("output_ports=%s\n", bp->value); - - if (!(cp = strchr(bp->value, ','))) - FATAL("expected comma and a second value for '%s' " - "at line %d: %s\n", - bp->name, bp->line, bp->value); - - *cp = '\0'; - output_ports[0] = xstrdup(bp->value); - *cp++ = ','; - - if (!*cp) - FATAL("expected a second value for '%s' at line %d: " - "%s\n", bp->name, bp->line, bp->value); - - output_ports[1] = xstrdup(cp); - - if (strchr(cp,',')) - FATAL("Only %d values are supported for '%s' " - "at line %d\n", (int)ARRAY_SIZE(output_ports), - bp->name, bp->line); - } - - if ( (bp = getBlockParam(param, "ringbuffer_size")) ) { - errno = 0; - val = strtol(bp->value, &endptr, 10); - - if ( errno == 0 && endptr != bp->value) { - ringbuf_sz = val < 32768 ? 32768 : val; - DEBUG("ringbuffer_size=%d\n", ringbuf_sz); - } else { - FATAL("%s is not a number; ringbuf_size=%d\n", - bp->value, ringbuf_sz); - } - } - - if ( (bp = getBlockParam(param, "name")) - && (strcmp(bp->value, "mpd") != 0) ) { - name = xstrdup(bp->value); - DEBUG("name=%s\n", name); - } - - return 0; -} - -static int jack_testDefault(void) -{ - return 0; -} - -static int connect_jack(AudioOutput *audioOutput) -{ - JackData *jd = audioOutput->data; - char **jports; - char *port_name; - - if ( (jd->client = jack_client_new(name)) == NULL ) { - ERROR("jack server not running?\n"); - freeJackData(audioOutput); - return -1; - } - - jack_set_error_function(error_callback); - jack_set_process_callback(jd->client, process, (void *)jd); - jack_set_sample_rate_callback(jd->client, (JackProcessCallback)srate, - (void *)audioOutput); - jack_on_shutdown(jd->client, shutdown_callback, (void *)jd); - - if ( jack_activate(jd->client) ) { - ERROR("cannot activate client"); - freeJackData(audioOutput); - return -1; - } - - jd->ports[0] = jack_port_register(jd->client, "left", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, 0); - if ( !jd->ports[0] ) { - ERROR("Cannot register left output port.\n"); - freeJackData(audioOutput); - return -1; - } - - jd->ports[1] = jack_port_register(jd->client, "right", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, 0); - if ( !jd->ports[1] ) { - ERROR("Cannot register right output port.\n"); - freeJackData(audioOutput); - return -1; - } - - /* hay que buscar que hay */ - if ( !output_ports[1] - && (jports = (char **)jack_get_ports(jd->client, NULL, NULL, - JackPortIsPhysical| - JackPortIsInput)) ) { - output_ports[0] = jports[0]; - output_ports[1] = jports[1] ? jports[1] : jports[0]; - DEBUG("output_ports: %s %s\n", output_ports[0], output_ports[1]); - free(jports); - } - - if ( output_ports[1] ) { - jd->ringbuffer[0] = jack_ringbuffer_create(ringbuf_sz); - jd->ringbuffer[1] = jack_ringbuffer_create(ringbuf_sz); - memset(jd->ringbuffer[0]->buf, 0, jd->ringbuffer[0]->size); - memset(jd->ringbuffer[1]->buf, 0, jd->ringbuffer[1]->size); - - port_name = xmalloc(sizeof(char)*(7+strlen(name))); - - sprintf(port_name, "%s:left", name); - if ( (jack_connect(jd->client, port_name, - output_ports[0])) != 0 ) { - ERROR("%s is not a valid Jack Client / Port ", - output_ports[0]); - freeJackData(audioOutput); - free(port_name); - return -1; - } - sprintf(port_name, "%s:right", name); - if ( (jack_connect(jd->client, port_name, - output_ports[1])) != 0 ) { - ERROR("%s is not a valid Jack Client / Port ", - output_ports[1]); - freeJackData(audioOutput); - free(port_name); - return -1; - } - free(port_name); - } - - DEBUG("connect_jack (pid=%d)\n", getpid()); - return 1; -} - -static int jack_openDevice(AudioOutput *audioOutput) -{ - JackData *jd = audioOutput->data; - - if ( !jd ) { - DEBUG("connect!\n"); - jd = newJackData(); - audioOutput->data = jd; - - if (connect_jack(audioOutput) < 0) { - freeJackData(audioOutput); - audioOutput->open = 0; - return -1; - } - } - - set_audioformat(audioOutput); - audioOutput->open = 1; - - DEBUG("jack_openDevice (pid=%d)!\n", getpid ()); - return 0; -} - - -static void jack_closeDevice(AudioOutput * audioOutput) -{ - /*jack_finishDriver(audioOutput);*/ - audioOutput->open = 0; - DEBUG("jack_closeDevice (pid=%d)\n", getpid()); -} - -static void jack_dropBufferedAudio (AudioOutput * audioOutput) -{ -} - -static int jack_playAudio(AudioOutput * audioOutput, char *buff, int size) -{ - JackData *jd = audioOutput->data; - size_t space; - int i; - short *buffer = (short *) buff; - jack_default_audio_sample_t sample; - size_t samples = size/4; - - /*DEBUG("jack_playAudio: (pid=%d)!\n", getpid());*/ - - if ( jd->shutdown ) { - ERROR("Refusing to play, because there is no client thread.\n"); - freeJackData(audioOutput); - audioOutput->open = 0; - return 0; - } - - while ( samples && !jd->shutdown ) { - - if ( (space = jack_ringbuffer_write_space(jd->ringbuffer[0])) - >= samples*sample_size ) { - - /*space = MIN(space, samples*sample_size);*/ - /*space = samples*sample_size;*/ - - /*for(i=0; i<space/sample_size; i++) {*/ - for(i=0; i<samples; i++) { - sample = (jack_default_audio_sample_t) *(buffer++)/32768.0; - - jack_ringbuffer_write(jd->ringbuffer[0], (void*)&sample, - sample_size); - - sample = (jack_default_audio_sample_t) *(buffer++)/32768.0; - - jack_ringbuffer_write(jd->ringbuffer[1], (void*)&sample, - sample_size); - - /*samples--;*/ - } - samples=0; - - } else { - pthread_mutex_lock(&play_audio_lock); - pthread_cond_wait(&play_audio, &play_audio_lock); - pthread_mutex_unlock(&play_audio_lock); - } - - } - return 0; -} - -AudioOutputPlugin jackPlugin = { - "jack", - jack_testDefault, - jack_initDriver, - jack_finishDriver, - jack_openDevice, - jack_playAudio, - jack_dropBufferedAudio, - jack_closeDevice, - NULL, /* sendMetadataFunc */ -}; - -#else /* HAVE JACK */ - -DISABLED_AUDIO_OUTPUT_PLUGIN(jackPlugin) - -#endif /* HAVE_JACK */ diff --git a/trunk/src/audioOutputs/audioOutput_mvp.c b/trunk/src/audioOutputs/audioOutput_mvp.c deleted file mode 100644 index ea365c657..000000000 --- a/trunk/src/audioOutputs/audioOutput_mvp.c +++ /dev/null @@ -1,284 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * Media MVP audio output based on code from MVPMC project: - * http://mvpmc.sourceforge.net/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../audioOutput.h" - -#include <stdlib.h> - -#ifdef HAVE_MVP - -#include "../conf.h" -#include "../log.h" - -#include <string.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> - -typedef struct { - unsigned long dsp_status; - unsigned long stream_decode_type; - unsigned long sample_rate; - unsigned long bit_rate; - unsigned long raw[64 / sizeof(unsigned long)]; -} aud_status_t; - -#define MVP_SET_AUD_STOP _IOW('a',1,int) -#define MVP_SET_AUD_PLAY _IOW('a',2,int) -#define MVP_SET_AUD_PAUSE _IOW('a',3,int) -#define MVP_SET_AUD_UNPAUSE _IOW('a',4,int) -#define MVP_SET_AUD_SRC _IOW('a',5,int) -#define MVP_SET_AUD_MUTE _IOW('a',6,int) -#define MVP_SET_AUD_BYPASS _IOW('a',8,int) -#define MVP_SET_AUD_CHANNEL _IOW('a',9,int) -#define MVP_GET_AUD_STATUS _IOR('a',10,aud_status_t) -#define MVP_SET_AUD_VOLUME _IOW('a',13,int) -#define MVP_GET_AUD_VOLUME _IOR('a',14,int) -#define MVP_SET_AUD_STREAMTYPE _IOW('a',15,int) -#define MVP_SET_AUD_FORMAT _IOW('a',16,int) -#define MVP_GET_AUD_SYNC _IOR('a',21,pts_sync_data_t*) -#define MVP_SET_AUD_STC _IOW('a',22,long long int *) -#define MVP_SET_AUD_SYNC _IOW('a',23,int) -#define MVP_SET_AUD_END_STREAM _IOW('a',25,int) -#define MVP_SET_AUD_RESET _IOW('a',26,int) -#define MVP_SET_AUD_DAC_CLK _IOW('a',27,int) -#define MVP_GET_AUD_REGS _IOW('a',28,aud_ctl_regs_t*) - -typedef struct _MvpData { - int fd; -} MvpData; - -static int pcmfrequencies[][3] = { - {9, 8000, 32000}, - {10, 11025, 44100}, - {11, 12000, 48000}, - {1, 16000, 32000}, - {2, 22050, 44100}, - {3, 24000, 48000}, - {5, 32000, 32000}, - {0, 44100, 44100}, - {7, 48000, 48000}, - {13, 64000, 32000}, - {14, 88200, 44100}, - {15, 96000, 48000} -}; - -static int numfrequencies = sizeof(pcmfrequencies) / 12; - -static int mvp_testDefault(void) -{ - int fd; - - fd = open("/dev/adec_pcm", O_WRONLY); - - if (fd) { - close(fd); - return 0; - } - - WARNING("Error opening PCM device \"/dev/adec_pcm\": %s\n", - strerror(errno)); - - return -1; -} - -static int mvp_initDriver(AudioOutput * audioOutput, ConfigParam * param) -{ - MvpData *md = xmalloc(sizeof(MvpData)); - md->fd = -1; - audioOutput->data = md; - - return 0; -} - -static void mvp_finishDriver(AudioOutput * audioOutput) -{ - MvpData *md = audioOutput->data; - free(md); -} - -static int mvp_setPcmParams(MvpData * md, unsigned long rate, int channels, - int big_endian, int bits) -{ - int iloop; - int mix[5]; - - if (channels == 1) - mix[0] = 1; - else if (channels == 2) - mix[0] = 0; - else - return -1; - - /* 0,1=24bit(24) , 2,3=16bit */ - if (bits == 16) - mix[1] = 2; - else if (bits == 24) - mix[1] = 0; - else - return -1; - - mix[3] = 0; /* stream type? */ - - if (big_endian == 1) - mix[4] = 1; - else if (big_endian == 0) - mix[4] = 0; - else - return -1; - - /* - * if there is an exact match for the frequency, use it. - */ - for (iloop = 0; iloop < numfrequencies; iloop++) { - if (rate == pcmfrequencies[iloop][1]) { - mix[2] = pcmfrequencies[iloop][0]; - break; - } - } - - if (iloop >= numfrequencies) { - ERROR("Can not find suitable output frequency for %ld\n", rate); - return -1; - } - - if (ioctl(md->fd, MVP_SET_AUD_FORMAT, &mix) < 0) { - ERROR("Can not set audio format\n"); - return -1; - } - - if (ioctl(md->fd, MVP_SET_AUD_SYNC, 2) != 0) { - ERROR("Can not set audio sync\n"); - return -1; - } - - if (ioctl(md->fd, MVP_SET_AUD_PLAY, 0) < 0) { - ERROR("Can not set audio play mode\n"); - return -1; - } - - return 0; -} - -static int mvp_openDevice(AudioOutput * audioOutput) -{ - long long int stc = 0; - MvpData *md = audioOutput->data; - AudioFormat *audioFormat = &audioOutput->outAudioFormat; - int mix[5] = { 0, 2, 7, 1, 0 }; - - if ((md->fd = open("/dev/adec_pcm", O_RDWR | O_NONBLOCK)) < 0) { - ERROR("Error opening /dev/adec_pcm: %s\n", strerror(errno)); - return -1; - } - if (ioctl(md->fd, MVP_SET_AUD_SRC, 1) < 0) { - ERROR("Error setting audio source: %s\n", strerror(errno)); - return -1; - } - if (ioctl(md->fd, MVP_SET_AUD_STREAMTYPE, 0) < 0) { - ERROR("Error setting audio streamtype: %s\n", strerror(errno)); - return -1; - } - if (ioctl(md->fd, MVP_SET_AUD_FORMAT, &mix) < 0) { - ERROR("Error setting audio format: %s\n", strerror(errno)); - return -1; - } - ioctl(md->fd, MVP_SET_AUD_STC, &stc); - if (ioctl(md->fd, MVP_SET_AUD_BYPASS, 1) < 0) { - ERROR("Error setting audio streamtype: %s\n", strerror(errno)); - return -1; - } -#ifdef WORDS_BIGENDIAN - mvp_setPcmParams(md, audioFormat->sampleRate, audioFormat->channels, 0, - audioFormat->bits); -#else - mvp_setPcmParams(md, audioFormat->sampleRate, audioFormat->channels, 1, - audioFormat->bits); -#endif - audioOutput->open = 1; - return 0; -} - -static void mvp_closeDevice(AudioOutput * audioOutput) -{ - MvpData *md = audioOutput->data; - if (md->fd >= 0) - close(md->fd); - md->fd = -1; - audioOutput->open = 0; -} - -static void mvp_dropBufferedAudio(AudioOutput * audioOutput) -{ - MvpData *md = audioOutput->data; - if (md->fd >= 0) { - ioctl(md->fd, MVP_SET_AUD_RESET, 0x11); - close(md->fd); - md->fd = -1; - audioOutput->open = 0; - } -} - -static int mvp_playAudio(AudioOutput * audioOutput, char *playChunk, int size) -{ - MvpData *md = audioOutput->data; - int ret; - - /* reopen the device since it was closed by dropBufferedAudio */ - if (md->fd < 0) - mvp_openDevice(audioOutput); - - while (size > 0) { - ret = write(md->fd, playChunk, size); - if (ret < 0) { - if (errno == EINTR) - continue; - ERROR("closing mvp PCM device due to write error: " - "%s\n", strerror(errno)); - mvp_closeDevice(audioOutput); - return -1; - } - playChunk += ret; - size -= ret; - } - return 0; -} - -AudioOutputPlugin mvpPlugin = { - "mvp", - mvp_testDefault, - mvp_initDriver, - mvp_finishDriver, - mvp_openDevice, - mvp_playAudio, - mvp_dropBufferedAudio, - mvp_closeDevice, - NULL, /* sendMetadataFunc */ -}; - -#else /* HAVE_MVP */ - -DISABLED_AUDIO_OUTPUT_PLUGIN(mvpPlugin) -#endif /* HAVE_MVP */ diff --git a/trunk/src/audioOutputs/audioOutput_oss.c b/trunk/src/audioOutputs/audioOutput_oss.c deleted file mode 100644 index 01293cbd1..000000000 --- a/trunk/src/audioOutputs/audioOutput_oss.c +++ /dev/null @@ -1,575 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * OSS audio output (c) 2004, 2005, 2006, 2007 by Eric Wong <eric@petta-tech.com> - * and Warren Dukes <warren.dukes@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../audioOutput.h" - -#include <stdlib.h> - -#ifdef HAVE_OSS - -#include "../conf.h" -#include "../log.h" - -#include <string.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> - -#if defined(__OpenBSD__) || defined(__NetBSD__) -# include <soundcard.h> -#else /* !(defined(__OpenBSD__) || defined(__NetBSD__) */ -# include <sys/soundcard.h> -#endif /* !(defined(__OpenBSD__) || defined(__NetBSD__) */ - -#ifdef WORDS_BIGENDIAN -# define AFMT_S16_MPD AFMT_S16_BE -#else -# define AFMT_S16_MPD AFMT_S16_LE -#endif /* WORDS_BIGENDIAN */ - -typedef struct _OssData { - int fd; - const char *device; - int channels; - int sampleRate; - int bitFormat; - int bits; - int *supported[3]; - int numSupported[3]; - int *unsupported[3]; - int numUnsupported[3]; -} OssData; - -#define OSS_SUPPORTED 1 -#define OSS_UNSUPPORTED 0 -#define OSS_UNKNOWN -1 - -#define OSS_RATE 0 -#define OSS_CHANNELS 1 -#define OSS_BITS 2 - -static int getIndexForParam(int param) -{ - int index = 0; - - switch (param) { - case SNDCTL_DSP_SPEED: - index = OSS_RATE; - break; - case SNDCTL_DSP_CHANNELS: - index = OSS_CHANNELS; - break; - case SNDCTL_DSP_SAMPLESIZE: - index = OSS_BITS; - break; - } - - return index; -} - -static int findSupportedParam(OssData * od, int param, int val) -{ - int i; - int index = getIndexForParam(param); - - for (i = 0; i < od->numSupported[index]; i++) { - if (od->supported[index][i] == val) - return 1; - } - - return 0; -} - -static int canConvert(int index, int val) -{ - switch (index) { - case OSS_BITS: - if (val != 16) - return 0; - break; - case OSS_CHANNELS: - if (val != 2) - return 0; - break; - } - - return 1; -} - -static int getSupportedParam(OssData * od, int param, int val) -{ - int i; - int index = getIndexForParam(param); - int ret = -1; - int least = val; - int diff; - - for (i = 0; i < od->numSupported[index]; i++) { - diff = od->supported[index][i] - val; - if (diff < 0) - diff = -diff; - if (diff < least) { - if (!canConvert(index, od->supported[index][i])) { - continue; - } - least = diff; - ret = od->supported[index][i]; - } - } - - return ret; -} - -static int findUnsupportedParam(OssData * od, int param, int val) -{ - int i; - int index = getIndexForParam(param); - - for (i = 0; i < od->numUnsupported[index]; i++) { - if (od->unsupported[index][i] == val) - return 1; - } - - return 0; -} - -static void addSupportedParam(OssData * od, int param, int val) -{ - int index = getIndexForParam(param); - - od->numSupported[index]++; - od->supported[index] = xrealloc(od->supported[index], - od->numSupported[index] * sizeof(int)); - od->supported[index][od->numSupported[index] - 1] = val; -} - -static void addUnsupportedParam(OssData * od, int param, int val) -{ - int index = getIndexForParam(param); - - od->numUnsupported[index]++; - od->unsupported[index] = xrealloc(od->unsupported[index], - od->numUnsupported[index] * - sizeof(int)); - od->unsupported[index][od->numUnsupported[index] - 1] = val; -} - -static void removeSupportedParam(OssData * od, int param, int val) -{ - int i = 0; - int j = 0; - int index = getIndexForParam(param); - - for (i = 0; i < od->numSupported[index] - 1; i++) { - if (od->supported[index][i] == val) - j = 1; - od->supported[index][i] = od->supported[index][i + j]; - } - - od->numSupported[index]--; - od->supported[index] = xrealloc(od->supported[index], - od->numSupported[index] * sizeof(int)); -} - -static void removeUnsupportedParam(OssData * od, int param, int val) -{ - int i = 0; - int j = 0; - int index = getIndexForParam(param); - - for (i = 0; i < od->numUnsupported[index] - 1; i++) { - if (od->unsupported[index][i] == val) - j = 1; - od->unsupported[index][i] = od->unsupported[index][i + j]; - } - - od->numUnsupported[index]--; - od->unsupported[index] = xrealloc(od->unsupported[index], - od->numUnsupported[index] * - sizeof(int)); -} - -static int isSupportedParam(OssData * od, int param, int val) -{ - if (findSupportedParam(od, param, val)) - return OSS_SUPPORTED; - if (findUnsupportedParam(od, param, val)) - return OSS_UNSUPPORTED; - return OSS_UNKNOWN; -} - -static void supportParam(OssData * od, int param, int val) -{ - int supported = isSupportedParam(od, param, val); - - if (supported == OSS_SUPPORTED) - return; - - if (supported == OSS_UNSUPPORTED) { - removeUnsupportedParam(od, param, val); - } - - addSupportedParam(od, param, val); -} - -static void unsupportParam(OssData * od, int param, int val) -{ - int supported = isSupportedParam(od, param, val); - - if (supported == OSS_UNSUPPORTED) - return; - - if (supported == OSS_SUPPORTED) { - removeSupportedParam(od, param, val); - } - - addUnsupportedParam(od, param, val); -} - -static OssData *newOssData(void) -{ - OssData *ret = xmalloc(sizeof(OssData)); - - ret->device = NULL; - ret->fd = -1; - - ret->supported[OSS_RATE] = NULL; - ret->supported[OSS_CHANNELS] = NULL; - ret->supported[OSS_BITS] = NULL; - ret->unsupported[OSS_RATE] = NULL; - ret->unsupported[OSS_CHANNELS] = NULL; - ret->unsupported[OSS_BITS] = NULL; - - ret->numSupported[OSS_RATE] = 0; - ret->numSupported[OSS_CHANNELS] = 0; - ret->numSupported[OSS_BITS] = 0; - ret->numUnsupported[OSS_RATE] = 0; - ret->numUnsupported[OSS_CHANNELS] = 0; - ret->numUnsupported[OSS_BITS] = 0; - - supportParam(ret, SNDCTL_DSP_SPEED, 48000); - supportParam(ret, SNDCTL_DSP_SPEED, 44100); - supportParam(ret, SNDCTL_DSP_CHANNELS, 2); - supportParam(ret, SNDCTL_DSP_SAMPLESIZE, 16); - - return ret; -} - -static void freeOssData(OssData * od) -{ - if (od->supported[OSS_RATE]) - free(od->supported[OSS_RATE]); - if (od->supported[OSS_CHANNELS]) - free(od->supported[OSS_CHANNELS]); - if (od->supported[OSS_BITS]) - free(od->supported[OSS_BITS]); - if (od->unsupported[OSS_RATE]) - free(od->unsupported[OSS_RATE]); - if (od->unsupported[OSS_CHANNELS]) - free(od->unsupported[OSS_CHANNELS]); - if (od->unsupported[OSS_BITS]) - free(od->unsupported[OSS_BITS]); - - free(od); -} - -#define OSS_STAT_NO_ERROR 0 -#define OSS_STAT_NOT_CHAR_DEV -1 -#define OSS_STAT_NO_PERMS -2 -#define OSS_STAT_DOESN_T_EXIST -3 -#define OSS_STAT_OTHER -4 - -static int oss_statDevice(const char *device, int *stErrno) -{ - struct stat st; - - if (0 == stat(device, &st)) { - if (!S_ISCHR(st.st_mode)) { - return OSS_STAT_NOT_CHAR_DEV; - } - } else { - *stErrno = errno; - - switch (errno) { - case ENOENT: - case ENOTDIR: - return OSS_STAT_DOESN_T_EXIST; - case EACCES: - return OSS_STAT_NO_PERMS; - default: - return OSS_STAT_OTHER; - } - } - - return 0; -} - -static const char *default_devices[] = { "/dev/sound/dsp", "/dev/dsp" }; - -static int oss_testDefault(void) -{ - int fd, i; - - for (i = ARRAY_SIZE(default_devices); --i >= 0; ) { - if ((fd = open(default_devices[i], O_WRONLY)) >= 0) { - xclose(fd); - return 0; - } - WARNING("Error opening OSS device \"%s\": %s\n", - default_devices[i], strerror(errno)); - } - - return -1; -} - -static int oss_open_default(AudioOutput *ao, ConfigParam *param, OssData *od) -{ - int i; - int err[ARRAY_SIZE(default_devices)]; - int ret[ARRAY_SIZE(default_devices)]; - - for (i = ARRAY_SIZE(default_devices); --i >= 0; ) { - ret[i] = oss_statDevice(default_devices[i], &err[i]); - if (ret[i] == 0) { - od->device = default_devices[i]; - return 0; - } - } - - if (param) - ERROR("error trying to open specified OSS device" - " at line %i\n", param->line); - else - ERROR("error trying to open default OSS device\n"); - - for (i = ARRAY_SIZE(default_devices); --i >= 0; ) { - const char *dev = default_devices[i]; - switch(ret[i]) { - case OSS_STAT_DOESN_T_EXIST: - ERROR("%s not found\n", dev); - break; - case OSS_STAT_NOT_CHAR_DEV: - ERROR("%s is not a character device\n", dev); - break; - case OSS_STAT_NO_PERMS: - ERROR("%s: permission denied\n", dev); - break; - default: - ERROR("Error accessing %s: %s", dev, strerror(err[i])); - } - } - exit(EXIT_FAILURE); - return 0; /* some compilers can be dumb... */ -} - -static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) -{ - OssData *od = newOssData(); - audioOutput->data = od; - if (param) { - BlockParam *bp = getBlockParam(param, "device"); - if (bp) { - od->device = bp->value; - return 0; - } - } - return oss_open_default(audioOutput, param, od); -} - -static void oss_finishDriver(AudioOutput * audioOutput) -{ - OssData *od = audioOutput->data; - - freeOssData(od); -} - -static int setParam(OssData * od, int param, int *value) -{ - int val = *value; - int copy; - int supported = isSupportedParam(od, param, val); - - do { - if (supported == OSS_UNSUPPORTED) { - val = getSupportedParam(od, param, val); - if (copy < 0) - return -1; - } - copy = val; - if (ioctl(od->fd, param, ©)) { - unsupportParam(od, param, val); - supported = OSS_UNSUPPORTED; - } else { - if (supported == OSS_UNKNOWN) { - supportParam(od, param, val); - supported = OSS_SUPPORTED; - } - val = copy; - } - } while (supported == OSS_UNSUPPORTED); - - *value = val; - - return 0; -} - -static void oss_close(OssData * od) -{ - if (od->fd >= 0) - while (close(od->fd) && errno == EINTR) ; - od->fd = -1; -} - -static int oss_open(AudioOutput * audioOutput) -{ - int tmp; - OssData *od = audioOutput->data; - - if ((od->fd = open(od->device, O_WRONLY)) < 0) { - ERROR("Error opening OSS device \"%s\": %s\n", od->device, - strerror(errno)); - goto fail; - } - - if (setParam(od, SNDCTL_DSP_CHANNELS, &od->channels)) { - ERROR("OSS device \"%s\" does not support %i channels: %s\n", - od->device, od->channels, strerror(errno)); - goto fail; - } - - if (setParam(od, SNDCTL_DSP_SPEED, &od->sampleRate)) { - ERROR("OSS device \"%s\" does not support %i Hz audio: %s\n", - od->device, od->sampleRate, strerror(errno)); - goto fail; - } - - switch (od->bits) { - case 8: - tmp = AFMT_S8; - break; - case 16: - tmp = AFMT_S16_MPD; - } - - if (setParam(od, SNDCTL_DSP_SAMPLESIZE, &tmp)) { - ERROR("OSS device \"%s\" does not support %i bit audio: %s\n", - od->device, tmp, strerror(errno)); - goto fail; - } - - audioOutput->open = 1; - - return 0; - -fail: - oss_close(od); - audioOutput->open = 0; - return -1; -} - -static int oss_openDevice(AudioOutput * audioOutput) -{ - int ret = -1; - OssData *od = audioOutput->data; - AudioFormat *audioFormat = &audioOutput->outAudioFormat; - - od->channels = audioFormat->channels; - od->sampleRate = audioFormat->sampleRate; - od->bits = audioFormat->bits; - - if ((ret = oss_open(audioOutput)) < 0) - return ret; - - audioFormat->channels = od->channels; - audioFormat->sampleRate = od->sampleRate; - audioFormat->bits = od->bits; - - DEBUG("oss device \"%s\" will be playing %i bit %i channel audio at " - "%i Hz\n", od->device, od->bits, od->channels, od->sampleRate); - - return ret; -} - -static void oss_closeDevice(AudioOutput * audioOutput) -{ - OssData *od = audioOutput->data; - - oss_close(od); - - audioOutput->open = 0; -} - -static void oss_dropBufferedAudio(AudioOutput * audioOutput) -{ - OssData *od = audioOutput->data; - - if (od->fd >= 0) { - ioctl(od->fd, SNDCTL_DSP_RESET, 0); - oss_close(od); - } -} - -static int oss_playAudio(AudioOutput * audioOutput, char *playChunk, int size) -{ - OssData *od = audioOutput->data; - int ret; - - /* reopen the device since it was closed by dropBufferedAudio */ - if (od->fd < 0 && oss_open(audioOutput) < 0) - return -1; - - while (size > 0) { - ret = write(od->fd, playChunk, size); - if (ret < 0) { - if (errno == EINTR) - continue; - ERROR("closing oss device \"%s\" due to write error: " - "%s\n", od->device, strerror(errno)); - oss_closeDevice(audioOutput); - return -1; - } - playChunk += ret; - size -= ret; - } - - return 0; -} - -AudioOutputPlugin ossPlugin = { - "oss", - oss_testDefault, - oss_initDriver, - oss_finishDriver, - oss_openDevice, - oss_playAudio, - oss_dropBufferedAudio, - oss_closeDevice, - NULL, /* sendMetadataFunc */ -}; - -#else /* HAVE OSS */ - -DISABLED_AUDIO_OUTPUT_PLUGIN(ossPlugin) -#endif /* HAVE_OSS */ diff --git a/trunk/src/audioOutputs/audioOutput_osx.c b/trunk/src/audioOutputs/audioOutput_osx.c deleted file mode 100644 index 1caebade5..000000000 --- a/trunk/src/audioOutputs/audioOutput_osx.c +++ /dev/null @@ -1,374 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../audioOutput.h" - -#ifdef HAVE_OSX - -#include <AudioUnit/AudioUnit.h> -#include <stdlib.h> -#include <pthread.h> - -#include "../log.h" - -typedef struct _OsxData { - AudioUnit au; - pthread_mutex_t mutex; - pthread_cond_t condition; - char *buffer; - int bufferSize; - int pos; - int len; - int started; -} OsxData; - -static OsxData *newOsxData() -{ - OsxData *ret = xmalloc(sizeof(OsxData)); - - pthread_mutex_init(&ret->mutex, NULL); - pthread_cond_init(&ret->condition, NULL); - - ret->pos = 0; - ret->len = 0; - ret->started = 0; - ret->buffer = NULL; - ret->bufferSize = 0; - - return ret; -} - -static int osx_testDefault() -{ - /*AudioUnit au; - ComponentDescription desc; - Component comp; - - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_Output; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - - comp = FindNextComponent(NULL, &desc); - if(!comp) { - ERROR("Unable to open default OS X defice\n"); - return -1; - } - - if(OpenAComponent(comp, &au) != noErr) { - ERROR("Unable to open default OS X defice\n"); - return -1; - } - - CloseComponent(au); */ - - return 0; -} - -static int osx_initDriver(AudioOutput * audioOutput, ConfigParam * param) -{ - OsxData *od = newOsxData(); - - audioOutput->data = od; - - return 0; -} - -static void freeOsxData(OsxData * od) -{ - if (od->buffer) - free(od->buffer); - pthread_mutex_destroy(&od->mutex); - pthread_cond_destroy(&od->condition); - free(od); -} - -static void osx_finishDriver(AudioOutput * audioOutput) -{ - OsxData *od = (OsxData *) audioOutput->data; - freeOsxData(od); -} - -static void osx_dropBufferedAudio(AudioOutput * audioOutput) -{ - OsxData *od = (OsxData *) audioOutput->data; - - pthread_mutex_lock(&od->mutex); - od->len = 0; - pthread_mutex_unlock(&od->mutex); -} - -static void osx_closeDevice(AudioOutput * audioOutput) -{ - OsxData *od = (OsxData *) audioOutput->data; - - pthread_mutex_lock(&od->mutex); - while (od->len) { - pthread_cond_wait(&od->condition, &od->mutex); - } - pthread_mutex_unlock(&od->mutex); - - if (od->started) { - AudioOutputUnitStop(od->au); - od->started = 0; - } - - CloseComponent(od->au); - AudioUnitUninitialize(od->au); - - audioOutput->open = 0; -} - -static OSStatus osx_render(void *vdata, - AudioUnitRenderActionFlags * ioActionFlags, - const AudioTimeStamp * inTimeStamp, - UInt32 inBusNumber, UInt32 inNumberFrames, - AudioBufferList * bufferList) -{ - OsxData *od = (OsxData *) vdata; - AudioBuffer *buffer = &bufferList->mBuffers[0]; - int bufferSize = buffer->mDataByteSize; - int bytesToCopy; - int curpos = 0; - - /*DEBUG("osx_render: enter : %i\n", (int)bufferList->mNumberBuffers); - DEBUG("osx_render: ioActionFlags: %p\n", ioActionFlags); - if(ioActionFlags) { - if(*ioActionFlags & kAudioUnitRenderAction_PreRender) { - DEBUG("prerender\n"); - } - if(*ioActionFlags & kAudioUnitRenderAction_PostRender) { - DEBUG("post render\n"); - } - if(*ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) { - DEBUG("post render\n"); - } - if(*ioActionFlags & kAudioOfflineUnitRenderAction_Preflight) { - DEBUG("prefilight\n"); - } - if(*ioActionFlags & kAudioOfflineUnitRenderAction_Render) { - DEBUG("render\n"); - } - if(*ioActionFlags & kAudioOfflineUnitRenderAction_Complete) { - DEBUG("complete\n"); - } - } */ - - /* while(bufferSize) { - DEBUG("osx_render: lock\n"); */ - pthread_mutex_lock(&od->mutex); - /* - DEBUG("%i:%i\n", bufferSize, od->len); - while(od->go && od->len < bufferSize && - od->len < od->bufferSize) - { - DEBUG("osx_render: wait\n"); - pthread_cond_wait(&od->condition, &od->mutex); - } - */ - - bytesToCopy = od->len < bufferSize ? od->len : bufferSize; - bufferSize = bytesToCopy; - od->len -= bytesToCopy; - - if (od->pos + bytesToCopy > od->bufferSize) { - int bytes = od->bufferSize - od->pos; - memcpy(buffer->mData + curpos, od->buffer + od->pos, bytes); - od->pos = 0; - curpos += bytes; - bytesToCopy -= bytes; - } - - memcpy(buffer->mData + curpos, od->buffer + od->pos, bytesToCopy); - od->pos += bytesToCopy; - curpos += bytesToCopy; - - if (od->pos >= od->bufferSize) - od->pos = 0; - /* DEBUG("osx_render: unlock\n"); */ - pthread_mutex_unlock(&od->mutex); - pthread_cond_signal(&od->condition); - /* } */ - - buffer->mDataByteSize = bufferSize; - - if (!bufferSize) { - my_usleep(1000); - } - - /* DEBUG("osx_render: leave\n"); */ - return 0; -} - -static int osx_openDevice(AudioOutput * audioOutput) -{ - OsxData *od = (OsxData *) audioOutput->data; - ComponentDescription desc; - Component comp; - AURenderCallbackStruct callback; - AudioFormat *audioFormat = &audioOutput->outAudioFormat; - AudioStreamBasicDescription streamDesc; - - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_DefaultOutput; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - - comp = FindNextComponent(NULL, &desc); - if (comp == 0) { - ERROR("Error finding OS X component\n"); - return -1; - } - - if (OpenAComponent(comp, &od->au) != noErr) { - ERROR("Unable to open OS X component\n"); - return -1; - } - - if (AudioUnitInitialize(od->au) != 0) { - CloseComponent(od->au); - ERROR("Unable to initialize OS X audio unit\n"); - return -1; - } - - callback.inputProc = osx_render; - callback.inputProcRefCon = od; - - if (AudioUnitSetProperty(od->au, kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Input, 0, - &callback, sizeof(callback)) != 0) { - AudioUnitUninitialize(od->au); - CloseComponent(od->au); - ERROR("unable to set callback for OS X audio unit\n"); - return -1; - } - - streamDesc.mSampleRate = audioFormat->sampleRate; - streamDesc.mFormatID = kAudioFormatLinearPCM; - streamDesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; -#ifdef WORDS_BIGENDIAN - streamDesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; -#endif - - streamDesc.mBytesPerPacket = - audioFormat->channels * audioFormat->bits / 8; - streamDesc.mFramesPerPacket = 1; - streamDesc.mBytesPerFrame = streamDesc.mBytesPerPacket; - streamDesc.mChannelsPerFrame = audioFormat->channels; - streamDesc.mBitsPerChannel = audioFormat->bits; - - if (AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, 0, - &streamDesc, sizeof(streamDesc)) != 0) { - AudioUnitUninitialize(od->au); - CloseComponent(od->au); - ERROR("Unable to set format on OS X device\n"); - return -1; - } - - /* create a buffer of 1s */ - od->bufferSize = (audioFormat->sampleRate) * - (audioFormat->bits >> 3) * (audioFormat->channels); - od->buffer = xrealloc(od->buffer, od->bufferSize); - - od->pos = 0; - od->len = 0; - - audioOutput->open = 1; - - return 0; -} - -static int osx_play(AudioOutput * audioOutput, char *playChunk, int size) -{ - OsxData *od = (OsxData *) audioOutput->data; - int bytesToCopy; - int curpos; - - /* DEBUG("osx_play: enter\n"); */ - - if (!od->started) { - int err; - od->started = 1; - err = AudioOutputUnitStart(od->au); - if (err) { - ERROR("unable to start audio output: %i\n", err); - return -1; - } - } - - pthread_mutex_lock(&od->mutex); - - while (size) { - /* DEBUG("osx_play: lock\n"); */ - curpos = od->pos + od->len; - if (curpos >= od->bufferSize) - curpos -= od->bufferSize; - - bytesToCopy = od->bufferSize < size ? od->bufferSize : size; - - while (od->len > od->bufferSize - bytesToCopy) { - /* DEBUG("osx_play: wait\n"); */ - pthread_cond_wait(&od->condition, &od->mutex); - } - - bytesToCopy = od->bufferSize - od->len; - bytesToCopy = bytesToCopy < size ? bytesToCopy : size; - size -= bytesToCopy; - od->len += bytesToCopy; - - if (curpos + bytesToCopy > od->bufferSize) { - int bytes = od->bufferSize - curpos; - memcpy(od->buffer + curpos, playChunk, bytes); - curpos = 0; - playChunk += bytes; - bytesToCopy -= bytes; - } - - memcpy(od->buffer + curpos, playChunk, bytesToCopy); - curpos += bytesToCopy; - playChunk += bytesToCopy; - - } - /* DEBUG("osx_play: unlock\n"); */ - pthread_mutex_unlock(&od->mutex); - - /* DEBUG("osx_play: leave\n"); */ - return 0; -} - -AudioOutputPlugin osxPlugin = { - "osx", - osx_testDefault, - osx_initDriver, - osx_finishDriver, - osx_openDevice, - osx_play, - osx_dropBufferedAudio, - osx_closeDevice, - NULL, /* sendMetadataFunc */ -}; - -#else - -#include <stdio.h> - -DISABLED_AUDIO_OUTPUT_PLUGIN(osxPlugin) -#endif diff --git a/trunk/src/audioOutputs/audioOutput_pulse.c b/trunk/src/audioOutputs/audioOutput_pulse.c deleted file mode 100644 index 8948e0263..000000000 --- a/trunk/src/audioOutputs/audioOutput_pulse.c +++ /dev/null @@ -1,221 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../audioOutput.h" - -#include <stdlib.h> - -#ifdef HAVE_PULSE - -#include "../conf.h" -#include "../log.h" - -#include <string.h> -#include <time.h> - -#include <pulse/simple.h> -#include <pulse/error.h> - -#define MPD_PULSE_NAME "mpd" -#define CONN_ATTEMPT_INTERVAL 60 - -typedef struct _PulseData { - pa_simple *s; - char *server; - char *sink; - int connAttempts; - time_t lastAttempt; -} PulseData; - -static PulseData *newPulseData(void) -{ - PulseData *ret; - - ret = xmalloc(sizeof(PulseData)); - - ret->s = NULL; - ret->server = NULL; - ret->sink = NULL; - ret->connAttempts = 0; - ret->lastAttempt = 0; - - return ret; -} - -static void freePulseData(PulseData * pd) -{ - if (pd->server) - free(pd->server); - if (pd->sink) - free(pd->sink); - free(pd); -} - -static int pulse_initDriver(AudioOutput * audioOutput, ConfigParam * param) -{ - BlockParam *server = NULL; - BlockParam *sink = NULL; - PulseData *pd; - - if (param) { - server = getBlockParam(param, "server"); - sink = getBlockParam(param, "sink"); - } - - pd = newPulseData(); - pd->server = server ? xstrdup(server->value) : NULL; - pd->sink = sink ? xstrdup(sink->value) : NULL; - audioOutput->data = pd; - - return 0; -} - -static void pulse_finishDriver(AudioOutput * audioOutput) -{ - freePulseData((PulseData *) audioOutput->data); -} - -static int pulse_testDefault(void) -{ - pa_simple *s; - pa_sample_spec ss; - int error; - - ss.format = PA_SAMPLE_S16NE; - ss.rate = 44100; - ss.channels = 2; - - s = pa_simple_new(NULL, MPD_PULSE_NAME, PA_STREAM_PLAYBACK, NULL, - MPD_PULSE_NAME, &ss, NULL, NULL, &error); - if (!s) { - WARNING("Cannot connect to default PulseAudio server: %s\n", - pa_strerror(error)); - return -1; - } - - pa_simple_free(s); - - return 0; -} - -static int pulse_openDevice(AudioOutput * audioOutput) -{ - PulseData *pd; - AudioFormat *audioFormat; - pa_sample_spec ss; - time_t t; - int error; - - t = time(NULL); - pd = audioOutput->data; - audioFormat = &audioOutput->outAudioFormat; - - if (pd->connAttempts != 0 && - (t - pd->lastAttempt) < CONN_ATTEMPT_INTERVAL) - return -1; - - pd->connAttempts++; - pd->lastAttempt = t; - - if (audioFormat->bits != 16) { - ERROR("PulseAudio doesn't support %i bit audio\n", - audioFormat->bits); - return -1; - } - - ss.format = PA_SAMPLE_S16NE; - ss.rate = audioFormat->sampleRate; - ss.channels = audioFormat->channels; - - pd->s = pa_simple_new(pd->server, MPD_PULSE_NAME, PA_STREAM_PLAYBACK, - pd->sink, audioOutput->name, &ss, NULL, NULL, - &error); - if (!pd->s) { - ERROR("Cannot connect to server in PulseAudio output " - "\"%s\" (attempt %i): %s\n", audioOutput->name, - pd->connAttempts, pa_strerror(error)); - return -1; - } - - pd->connAttempts = 0; - audioOutput->open = 1; - - DEBUG("PulseAudio output \"%s\" connected and playing %i bit, %i " - "channel audio at %i Hz\n", audioOutput->name, audioFormat->bits, - audioFormat->channels, audioFormat->sampleRate); - - return 0; -} - -static void pulse_dropBufferedAudio(AudioOutput * audioOutput) -{ - PulseData *pd; - int error; - - pd = audioOutput->data; - if (pa_simple_flush(pd->s, &error) < 0) - WARNING("Flush failed in PulseAudio output \"%s\": %s\n", - audioOutput->name, pa_strerror(error)); -} - -static void pulse_closeDevice(AudioOutput * audioOutput) -{ - PulseData *pd; - - pd = audioOutput->data; - if (pd->s) { - pa_simple_drain(pd->s, NULL); - pa_simple_free(pd->s); - } - - audioOutput->open = 0; -} - -static int pulse_playAudio(AudioOutput * audioOutput, char *playChunk, int size) -{ - PulseData *pd; - int error; - - pd = audioOutput->data; - - if (pa_simple_write(pd->s, playChunk, size, &error) < 0) { - ERROR("PulseAudio output \"%s\" disconnecting due to write " - "error: %s\n", audioOutput->name, pa_strerror(error)); - pulse_closeDevice(audioOutput); - return -1; - } - - return 0; -} - -AudioOutputPlugin pulsePlugin = { - "pulse", - pulse_testDefault, - pulse_initDriver, - pulse_finishDriver, - pulse_openDevice, - pulse_playAudio, - pulse_dropBufferedAudio, - pulse_closeDevice, - NULL, /* sendMetadataFunc */ -}; - -#else /* HAVE_PULSE */ - -DISABLED_AUDIO_OUTPUT_PLUGIN(pulsePlugin) -#endif /* HAVE_PULSE */ diff --git a/trunk/src/audioOutputs/audioOutput_shout.c b/trunk/src/audioOutputs/audioOutput_shout.c deleted file mode 100644 index 7d93f8f85..000000000 --- a/trunk/src/audioOutputs/audioOutput_shout.c +++ /dev/null @@ -1,636 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../audioOutput.h" - -#include <stdlib.h> - -#ifdef HAVE_SHOUT - -#include "../conf.h" -#include "../log.h" -#include "../pcm_utils.h" - -#include <string.h> -#include <time.h> - -#include <shout/shout.h> -#include <vorbis/vorbisenc.h> - -#define CONN_ATTEMPT_INTERVAL 60 - -static int shoutInitCount; - -/* lots of this code blatantly stolent from bossogg/bossao2 */ - -typedef struct _ShoutData { - shout_t *shoutConn; - int shoutError; - - ogg_stream_state os; - ogg_page og; - ogg_packet op; - ogg_packet header_main; - ogg_packet header_comments; - ogg_packet header_codebooks; - - vorbis_dsp_state vd; - vorbis_block vb; - vorbis_info vi; - vorbis_comment vc; - - float quality; - int bitrate; - - int opened; - - MpdTag *tag; - int tagToSend; - - int connAttempts; - time_t lastAttempt; - int last_err; - - /* just a pointer to audioOutput->outAudioFormat */ - AudioFormat *audioFormat; -} ShoutData; - -static ShoutData *newShoutData(void) -{ - ShoutData *ret = xmalloc(sizeof(ShoutData)); - - ret->shoutConn = shout_new(); - ret->opened = 0; - ret->tag = NULL; - ret->tagToSend = 0; - ret->bitrate = -1; - ret->quality = -2.0; - ret->connAttempts = 0; - ret->lastAttempt = 0; - ret->audioFormat = NULL; - ret->last_err = SHOUTERR_UNCONNECTED; - - return ret; -} - -static void freeShoutData(ShoutData * sd) -{ - if (sd->shoutConn) - shout_free(sd->shoutConn); - if (sd->tag) - freeMpdTag(sd->tag); - - free(sd); -} - -#define checkBlockParam(name) { \ - blockParam = getBlockParam(param, name); \ - if (!blockParam) { \ - FATAL("no \"%s\" defined for shout device defined at line " \ - "%i\n", name, param->line); \ - } \ -} - -static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) -{ - ShoutData *sd; - char *test; - int port; - char *host; - char *mount; - char *passwd; - char *user; - char *name; - BlockParam *blockParam; - unsigned int public = 0; - - sd = newShoutData(); - - if (shoutInitCount == 0) - shout_init(); - - shoutInitCount++; - - checkBlockParam("host"); - host = blockParam->value; - - checkBlockParam("mount"); - mount = blockParam->value; - - checkBlockParam("port"); - - port = strtol(blockParam->value, &test, 10); - - if (*test != '\0' || port <= 0) { - FATAL("shout port \"%s\" is not a positive integer, line %i\n", - blockParam->value, blockParam->line); - } - - checkBlockParam("password"); - passwd = blockParam->value; - - checkBlockParam("name"); - name = blockParam->value; - - blockParam = getBlockParam(param, "public"); - if (blockParam) { - if (0 == strcmp(blockParam->value, "yes")) { - public = 1; - } else if (0 == strcmp(blockParam->value, "no")) { - public = 0; - } else { - FATAL("public \"%s\" is not \"yes\" or \"no\" at line " - "%i\n", param->value, param->line); - } - } - - blockParam = getBlockParam(param, "user"); - if (blockParam) - user = blockParam->value; - else - user = "source"; - - blockParam = getBlockParam(param, "quality"); - - if (blockParam) { - int line = blockParam->line; - - sd->quality = strtod(blockParam->value, &test); - - if (*test != '\0' || sd->quality < -1.0 || sd->quality > 10.0) { - FATAL("shout quality \"%s\" is not a number in the " - "range -1 to 10, line %i\n", blockParam->value, - blockParam->line); - } - - blockParam = getBlockParam(param, "bitrate"); - - if (blockParam) { - FATAL("quality (line %i) and bitrate (line %i) are " - "both defined for shout output\n", line, - blockParam->line); - } - } else { - blockParam = getBlockParam(param, "bitrate"); - - if (!blockParam) { - FATAL("neither bitrate nor quality defined for shout " - "output at line %i\n", param->line); - } - - sd->bitrate = strtol(blockParam->value, &test, 10); - - if (*test != '\0' || sd->bitrate <= 0) { - FATAL("bitrate at line %i should be a positive integer " - "\n", blockParam->line); - } - } - - checkBlockParam("format"); - sd->audioFormat = &audioOutput->outAudioFormat; - - if (shout_set_host(sd->shoutConn, host) != SHOUTERR_SUCCESS || - shout_set_port(sd->shoutConn, port) != SHOUTERR_SUCCESS || - shout_set_password(sd->shoutConn, passwd) != SHOUTERR_SUCCESS || - shout_set_mount(sd->shoutConn, mount) != SHOUTERR_SUCCESS || - shout_set_name(sd->shoutConn, name) != SHOUTERR_SUCCESS || - shout_set_user(sd->shoutConn, user) != SHOUTERR_SUCCESS || - shout_set_public(sd->shoutConn, public) != SHOUTERR_SUCCESS || - shout_set_nonblocking(sd->shoutConn, 1) != SHOUTERR_SUCCESS || - shout_set_format(sd->shoutConn, SHOUT_FORMAT_VORBIS) - != SHOUTERR_SUCCESS || - shout_set_protocol(sd->shoutConn, SHOUT_PROTOCOL_HTTP) - != SHOUTERR_SUCCESS || - shout_set_agent(sd->shoutConn, "MPD") != SHOUTERR_SUCCESS) { - FATAL("error configuring shout defined at line %i: %s\n", - param->line, shout_get_error(sd->shoutConn)); - } - - /* optional paramters */ - blockParam = getBlockParam(param, "genre"); - if (blockParam && shout_set_genre(sd->shoutConn, blockParam->value)) { - FATAL("error configuring shout defined at line %i: %s\n", - param->line, shout_get_error(sd->shoutConn)); - } - - blockParam = getBlockParam(param, "description"); - if (blockParam && shout_set_description(sd->shoutConn, - blockParam->value)) { - FATAL("error configuring shout defined at line %i: %s\n", - param->line, shout_get_error(sd->shoutConn)); - } - - { - char temp[11]; - memset(temp, 0, sizeof(temp)); - - snprintf(temp, sizeof(temp), "%d", sd->audioFormat->channels); - shout_set_audio_info(sd->shoutConn, SHOUT_AI_CHANNELS, temp); - - snprintf(temp, sizeof(temp), "%d", sd->audioFormat->sampleRate); - - shout_set_audio_info(sd->shoutConn, SHOUT_AI_SAMPLERATE, temp); - - if (sd->quality >= -1.0) { - snprintf(temp, sizeof(temp), "%2.2f", sd->quality); - shout_set_audio_info(sd->shoutConn, SHOUT_AI_QUALITY, - temp); - } else { - snprintf(temp, sizeof(temp), "%d", sd->bitrate); - shout_set_audio_info(sd->shoutConn, SHOUT_AI_BITRATE, - temp); - } - } - - audioOutput->data = sd; - - return 0; -} - -static int myShout_handleError(ShoutData * sd, int err) -{ - switch (err) { - case SHOUTERR_SUCCESS: - break; - case SHOUTERR_UNCONNECTED: - case SHOUTERR_SOCKET: - ERROR("Lost shout connection to %s:%i : %s\n", - shout_get_host(sd->shoutConn), - shout_get_port(sd->shoutConn), - shout_get_error(sd->shoutConn)); - sd->shoutError = 1; - return -1; - default: - ERROR("shout: connection to %s:%i error : %s\n", - shout_get_host(sd->shoutConn), - shout_get_port(sd->shoutConn), - shout_get_error(sd->shoutConn)); - sd->shoutError = 1; - return -1; - } - - return 0; -} - -static int write_page(ShoutData * sd) -{ - int err = 0; - - /*DEBUG("shout_delay: %i\n", shout_delay(sd->shoutConn)); */ - shout_sync(sd->shoutConn); - err = shout_send(sd->shoutConn, sd->og.header, sd->og.header_len); - if (myShout_handleError(sd, err) < 0) - return -1; - err = shout_send(sd->shoutConn, sd->og.body, sd->og.body_len); - if (myShout_handleError(sd, err) < 0) - return -1; - - return 0; -} - -static void finishEncoder(ShoutData * sd) -{ - vorbis_analysis_wrote(&sd->vd, 0); - - while (vorbis_analysis_blockout(&sd->vd, &sd->vb) == 1) { - vorbis_analysis(&sd->vb, NULL); - vorbis_bitrate_addblock(&sd->vb); - while (vorbis_bitrate_flushpacket(&sd->vd, &sd->op)) { - ogg_stream_packetin(&sd->os, &sd->op); - } - } -} - -static int flushEncoder(ShoutData * sd) -{ - return (ogg_stream_pageout(&sd->os, &sd->og) > 0); -} - -static void clearEncoder(ShoutData * sd) -{ - finishEncoder(sd); - while (1 == flushEncoder(sd)) { - if (!sd->shoutError) - write_page(sd); - } - - vorbis_comment_clear(&sd->vc); - ogg_stream_clear(&sd->os); - vorbis_block_clear(&sd->vb); - vorbis_dsp_clear(&sd->vd); - vorbis_info_clear(&sd->vi); -} - -static void myShout_closeShoutConn(ShoutData * sd) -{ - if (sd->opened) { - clearEncoder(sd); - - if (shout_close(sd->shoutConn) != SHOUTERR_SUCCESS) { - ERROR("problem closing connection to shout server: " - "%s\n", shout_get_error(sd->shoutConn)); - } - } - - sd->last_err = SHOUTERR_UNCONNECTED; - sd->opened = 0; -} - -static void myShout_finishDriver(AudioOutput * audioOutput) -{ - ShoutData *sd = (ShoutData *) audioOutput->data; - - myShout_closeShoutConn(sd); - - freeShoutData(sd); - - shoutInitCount--; - - if (shoutInitCount == 0) - shout_shutdown(); -} - -static void myShout_dropBufferedAudio(AudioOutput * audioOutput) -{ - /* needs to be implemented */ -} - -static void myShout_closeDevice(AudioOutput * audioOutput) -{ - ShoutData *sd = (ShoutData *) audioOutput->data; - - myShout_closeShoutConn(sd); - - audioOutput->open = 0; -} - -#define addTag(name, value) { \ - if(value) vorbis_comment_add_tag(&(sd->vc), name, value); \ -} - -static void copyTagToVorbisComment(ShoutData * sd) -{ - if (sd->tag) { - int i; - - for (i = 0; i < sd->tag->numOfItems; i++) { - switch (sd->tag->items[i].type) { - case TAG_ITEM_ARTIST: - addTag("ARTIST", sd->tag->items[i].value); - break; - case TAG_ITEM_ALBUM: - addTag("ALBUM", sd->tag->items[i].value); - break; - case TAG_ITEM_TITLE: - addTag("TITLE", sd->tag->items[i].value); - break; - } - } - } -} - -static int initEncoder(ShoutData * sd) -{ - vorbis_info_init(&(sd->vi)); - - if (sd->quality >= -1.0) { - if (0 != vorbis_encode_init_vbr(&(sd->vi), - sd->audioFormat->channels, - sd->audioFormat->sampleRate, - sd->quality * 0.1)) { - ERROR("problem setting up vorbis encoder for shout\n"); - vorbis_info_clear(&(sd->vi)); - return -1; - } - } else { - if (0 != vorbis_encode_init(&(sd->vi), - sd->audioFormat->channels, - sd->audioFormat->sampleRate, -1.0, - sd->bitrate * 1000, -1.0)) { - ERROR("problem setting up vorbis encoder for shout\n"); - vorbis_info_clear(&(sd->vi)); - return -1; - } - } - - vorbis_analysis_init(&(sd->vd), &(sd->vi)); - vorbis_block_init(&(sd->vd), &(sd->vb)); - - ogg_stream_init(&(sd->os), rand()); - - vorbis_comment_init(&(sd->vc)); - - return 0; -} - -static int myShout_openShoutConn(AudioOutput * audioOutput) -{ - ShoutData *sd = (ShoutData *) audioOutput->data; - time_t t = time(NULL); - - if (sd->connAttempts != 0 && - (t - sd->lastAttempt) < CONN_ATTEMPT_INTERVAL) { - return -1; - } - - sd->connAttempts++; - - if (sd->last_err == SHOUTERR_UNCONNECTED) - sd->last_err = shout_open(sd->shoutConn); - switch (sd->last_err) { - case SHOUTERR_SUCCESS: - case SHOUTERR_CONNECTED: - break; - case SHOUTERR_BUSY: - sd->last_err = shout_get_connected(sd->shoutConn); - if (sd->last_err == SHOUTERR_CONNECTED) - break; - return -1; - default: - sd->lastAttempt = t; - ERROR("problem opening connection to shout server %s:%i " - "(attempt %i): %s\n", - shout_get_host(sd->shoutConn), - shout_get_port(sd->shoutConn), - sd->connAttempts, shout_get_error(sd->shoutConn)); - return -1; - } - - if (initEncoder(sd) < 0) { - shout_close(sd->shoutConn); - return -1; - } - - sd->shoutError = 0; - - copyTagToVorbisComment(sd); - - vorbis_analysis_headerout(&(sd->vd), &(sd->vc), &(sd->header_main), - &(sd->header_comments), - &(sd->header_codebooks)); - - ogg_stream_packetin(&(sd->os), &(sd->header_main)); - ogg_stream_packetin(&(sd->os), &(sd->header_comments)); - ogg_stream_packetin(&(sd->os), &(sd->header_codebooks)); - - sd->opened = 1; - sd->tagToSend = 0; - - while (ogg_stream_flush(&(sd->os), &(sd->og))) { - if (write_page(sd) < 0) { - myShout_closeShoutConn(sd); - return -1; - } - } - - sd->connAttempts = 0; - - return 0; -} - -static int myShout_openDevice(AudioOutput * audioOutput) -{ - ShoutData *sd = (ShoutData *) audioOutput->data; - - audioOutput->open = 1; - - if (sd->opened) - return 0; - - if (myShout_openShoutConn(audioOutput) < 0) { - audioOutput->open = 0; - return -1; - } - - return 0; -} - -static void myShout_sendMetadata(ShoutData * sd) -{ - if (!sd->opened || !sd->tag) - return; - - clearEncoder(sd); - if (initEncoder(sd) < 0) - return; - - copyTagToVorbisComment(sd); - - vorbis_analysis_headerout(&(sd->vd), &(sd->vc), &(sd->header_main), - &(sd->header_comments), - &(sd->header_codebooks)); - - ogg_stream_packetin(&(sd->os), &(sd->header_main)); - ogg_stream_packetin(&(sd->os), &(sd->header_comments)); - ogg_stream_packetin(&(sd->os), &(sd->header_codebooks)); - - while (ogg_stream_flush(&(sd->os), &(sd->og))) { - if (write_page(sd) < 0) { - myShout_closeShoutConn(sd); - return; - } - } - - /*if(sd->tag) freeMpdTag(sd->tag); - sd->tag = NULL; */ - sd->tagToSend = 0; -} - -static int myShout_play(AudioOutput * audioOutput, char *playChunk, int size) -{ - int i, j; - ShoutData *sd = (ShoutData *) audioOutput->data; - float **vorbbuf; - int samples; - int bytes = sd->audioFormat->bits / 8; - - if (sd->opened && sd->tagToSend) - myShout_sendMetadata(sd); - - if (!sd->opened) { - if (myShout_openShoutConn(audioOutput) < 0) { - return -1; - } - } - - samples = size / (bytes * sd->audioFormat->channels); - - /* this is for only 16-bit audio */ - - vorbbuf = vorbis_analysis_buffer(&(sd->vd), samples); - - for (i = 0; i < samples; i++) { - for (j = 0; j < sd->audioFormat->channels; j++) { - vorbbuf[j][i] = (*((mpd_sint16 *) playChunk)) / 32768.0; - playChunk += bytes; - } - } - - vorbis_analysis_wrote(&(sd->vd), samples); - - while (1 == vorbis_analysis_blockout(&(sd->vd), &(sd->vb))) { - vorbis_analysis(&(sd->vb), NULL); - vorbis_bitrate_addblock(&(sd->vb)); - - while (vorbis_bitrate_flushpacket(&(sd->vd), &(sd->op))) { - ogg_stream_packetin(&(sd->os), &(sd->op)); - } - } - - while (ogg_stream_pageout(&(sd->os), &(sd->og)) != 0) { - if (write_page(sd) < 0) { - myShout_closeShoutConn(sd); - return -1; - } - } - - return 0; -} - -static void myShout_setTag(AudioOutput * audioOutput, MpdTag * tag) -{ - ShoutData *sd = (ShoutData *) audioOutput->data; - - if (sd->tag) - freeMpdTag(sd->tag); - sd->tag = NULL; - sd->tagToSend = 0; - - if (!tag) - return; - - sd->tag = mpdTagDup(tag); - sd->tagToSend = 1; -} - -AudioOutputPlugin shoutPlugin = { - "shout", - NULL, - myShout_initDriver, - myShout_finishDriver, - myShout_openDevice, - myShout_play, - myShout_dropBufferedAudio, - myShout_closeDevice, - myShout_setTag, -}; - -#else - -DISABLED_AUDIO_OUTPUT_PLUGIN(shoutPlugin) -#endif diff --git a/trunk/src/buffer2array.c b/trunk/src/buffer2array.c deleted file mode 100644 index d7bfc4561..000000000 --- a/trunk/src/buffer2array.c +++ /dev/null @@ -1,132 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "buffer2array.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - - -static inline -int -isWhiteSpace(char c) -{ - return (c == ' ' || c == '\t'); -} - -int buffer2array(char *buffer, char *array[], const int max) -{ - int i = 0; - char *c = buffer; - - while (*c != '\0' && i < max) { - if (*c == '\"') { - array[i++] = ++c; - while (*c != '\0') { - if (*c == '\"') { - *(c++) = '\0'; - break; - } - else if (*(c++) == '\\' && *c != '\0') { - memmove(c - 1, c, strlen(c) + 1); - } - } - } else { - while (isWhiteSpace(*c)) - ++c; - array[i++] = c++; - if (*c == '\0') - return i; - while (!isWhiteSpace(*c) && *c != '\0') - ++c; - } - if (*c == '\0') - return i; - *(c++) = '\0'; - while (isWhiteSpace(*c)) - ++c; - } - return i; -} - -#ifdef UNIT_TEST - -#include <stdio.h> -#include <string.h> -#include <assert.h> - -int main() -{ - char *a[4] = { NULL }; - char *b; - int max; - - b = strdup("lsinfo \"/some/dir/name \\\"test\\\"\""); - max = buffer2array(b, a, 4); - assert( !strcmp("lsinfo", a[0]) ); - assert( !strcmp("/some/dir/name \"test\"", a[1]) ); - assert( !a[2] ); - - b = strdup("lsinfo \"/some/dir/name \\\"test\\\" something else\""); - max = buffer2array(b, a, 4); - assert( !strcmp("lsinfo", a[0]) ); - assert( !strcmp("/some/dir/name \"test\" something else", a[1]) ); - assert( !a[2] ); - - b = strdup("lsinfo \"/some/dir\\\\name\""); - max = buffer2array(b, a, 4); - assert( !strcmp("lsinfo", a[0]) ); - assert( !strcmp("/some/dir\\name", a[1]) ); - assert( !a[2] ); - - b = strdup("lsinfo \"/some/dir name\""); - max = buffer2array(b, a, 4); - assert( !strcmp("lsinfo", a[0]) ); - assert( !strcmp("/some/dir name", a[1]) ); - assert( !a[2] ); - - b = strdup("lsinfo \"\\\"/some/dir\\\"\""); - max = buffer2array(b, a, 4); - assert( !strcmp("lsinfo", a[0]) ); - assert( !strcmp("\"/some/dir\"", a[1]) ); - assert( !a[2] ); - - b = strdup("lsinfo \"\\\"/some/dir\\\" x\""); - max = buffer2array(b, a, 4); - assert( !strcmp("lsinfo", a[0]) ); - assert( !strcmp("\"/some/dir\" x", a[1]) ); - assert( !a[2] ); - - b = strdup("lsinfo \"single quote\\'d from php magicquotes\""); - max = buffer2array(b, a, 4); - assert( !strcmp("lsinfo", a[0]) ); - assert( !strcmp("single quote\'d from php magicquotes", a[1]) ); - assert( !a[2] ); - - b = strdup("lsinfo \"double quote\\\"d from php magicquotes\""); - max = buffer2array(b, a, 4); - assert( !strcmp("lsinfo", a[0]) ); - assert( !strcmp("double quote\"d from php magicquotes", a[1]) ); - assert( !a[2] ); - - return 0; -} - -#endif diff --git a/trunk/src/buffer2array.h b/trunk/src/buffer2array.h deleted file mode 100644 index ece663994..000000000 --- a/trunk/src/buffer2array.h +++ /dev/null @@ -1,32 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef BUFFER_2_ARRAY_H -#define BUFFER_2_ARRAY_H - -#include "../config.h" - -/* tokenizes up to max elements in buffer (a null-terminated string) and - * stores the result in array (which must be capable of holding up to - * max elements). Tokenization is based on C string quoting rules. - * The arguments buffer and array are modified. - * Returns the number of elements tokenized. - */ -int buffer2array(char *buffer, char *array[], const int max); - -#endif diff --git a/trunk/src/charConv.c b/trunk/src/charConv.c deleted file mode 100644 index 69777c47a..000000000 --- a/trunk/src/charConv.c +++ /dev/null @@ -1,168 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "charConv.h" -#include "mpd_types.h" -#include "utf8.h" -#include "utils.h" - -#include <stdlib.h> -#include <errno.h> -#include <string.h> - -#ifdef HAVE_ICONV -#include <iconv.h> -static iconv_t char_conv_iconv; -#endif - -static char *char_conv_to; -static char *char_conv_from; -static mpd_sint8 char_conv_same; -static mpd_sint8 char_conv_use_iconv; - -/* 1 is to use latin1ToUtf8 - 0 is not to use latin1/utf8 converter - -1 is to use utf8ToLatin1*/ -static mpd_sint8 char_conv_latin1ToUtf8; - -#define BUFFER_SIZE 1024 - -static void closeCharSetConversion(void); - -int setCharSetConversion(char *to, char *from) -{ - if (char_conv_to && char_conv_from) { - if (char_conv_latin1ToUtf8 && - !strcmp(from, char_conv_to) && - !strcmp(to, char_conv_from)) { - char *swap = char_conv_from; - char_conv_from = char_conv_to; - char_conv_to = swap; - char_conv_latin1ToUtf8 *= -1; - return 0; - } else if (!strcmp(to, char_conv_to) && - !strcmp(from,char_conv_from)) { - return 0; - } - } - - closeCharSetConversion(); - - if (0 == strcmp(to, from)) { - char_conv_same = 1; - char_conv_to = xstrdup(to); - char_conv_from = xstrdup(from); - return 0; - } - - if (strcmp(to, "UTF-8") == 0 && strcmp(from, "ISO-8859-1") == 0) { - char_conv_latin1ToUtf8 = 1; - } else if (strcmp(to, "ISO-8859-1") == 0 && strcmp(from, "UTF-8") == 0) { - char_conv_latin1ToUtf8 = -1; - } - - if (char_conv_latin1ToUtf8 != 0) { - char_conv_to = xstrdup(to); - char_conv_from = xstrdup(from); - return 0; - } -#ifdef HAVE_ICONV - if ((char_conv_iconv = iconv_open(to, from)) == (iconv_t) (-1)) - return -1; - - char_conv_to = xstrdup(to); - char_conv_from = xstrdup(from); - char_conv_use_iconv = 1; - - return 0; -#endif - - return -1; -} - -char *convStrDup(char *string) -{ - if (!char_conv_to) - return NULL; - - if (char_conv_same) - return xstrdup(string); - -#ifdef HAVE_ICONV - if (char_conv_use_iconv) { - char buffer[BUFFER_SIZE]; - size_t inleft = strlen(string); - char *ret; - size_t outleft; - size_t retlen = 0; - size_t err; - char *bufferPtr; - - ret = xmalloc(1); - ret[0] = '\0'; - - while (inleft) { - bufferPtr = buffer; - outleft = BUFFER_SIZE; - err = - iconv(char_conv_iconv, &string, &inleft, &bufferPtr, - &outleft); - if (outleft == BUFFER_SIZE - || (err == -1L && errno != E2BIG)) { - free(ret); - return NULL; - } - - ret = xrealloc(ret, retlen + BUFFER_SIZE - outleft + 1); - memcpy(ret + retlen, buffer, BUFFER_SIZE - outleft); - retlen += BUFFER_SIZE - outleft; - ret[retlen] = '\0'; - } - - return ret; - } -#endif - - switch (char_conv_latin1ToUtf8) { - case 1: - return latin1StrToUtf8Dup(string); - break; - case -1: - return utf8StrToLatin1Dup(string); - break; - } - - return NULL; -} - -static void closeCharSetConversion(void) -{ - if (char_conv_to) { -#ifdef HAVE_ICONV - if (char_conv_use_iconv) - iconv_close(char_conv_iconv); -#endif - free(char_conv_to); - free(char_conv_from); - char_conv_to = NULL; - char_conv_from = NULL; - char_conv_same = 0; - char_conv_latin1ToUtf8 = 0; - char_conv_use_iconv = 0; - } -} diff --git a/trunk/src/charConv.h b/trunk/src/charConv.h deleted file mode 100644 index 4b1ed4237..000000000 --- a/trunk/src/charConv.h +++ /dev/null @@ -1,28 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef CHAR_CONV_H -#define CHAR_CONV_H - -#include "../config.h" - -int setCharSetConversion(char *to, char *from); - -char *convStrDup(char *string); - -#endif diff --git a/trunk/src/command.c b/trunk/src/command.c deleted file mode 100644 index 84a30db2b..000000000 --- a/trunk/src/command.c +++ /dev/null @@ -1,1299 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "command.h" -#include "player.h" -#include "playlist.h" -#include "ls.h" -#include "directory.h" -#include "volume.h" -#include "stats.h" -#include "myfprintf.h" -#include "list.h" -#include "permission.h" -#include "buffer2array.h" -#include "log.h" -#include "tag.h" -#include "utils.h" -#include "storedPlaylist.h" - -#include <assert.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#define COMMAND_PLAY "play" -#define COMMAND_PLAYID "playid" -#define COMMAND_STOP "stop" -#define COMMAND_PAUSE "pause" -#define COMMAND_STATUS "status" -#define COMMAND_KILL "kill" -#define COMMAND_CLOSE "close" -#define COMMAND_ADD "add" -#define COMMAND_ADDID "addid" -#define COMMAND_DELETE "delete" -#define COMMAND_DELETEID "deleteid" -#define COMMAND_PLAYLIST "playlist" -#define COMMAND_SHUFFLE "shuffle" -#define COMMAND_CLEAR "clear" -#define COMMAND_SAVE "save" -#define COMMAND_LOAD "load" -#define COMMAND_LISTPLAYLIST "listplaylist" -#define COMMAND_LISTPLAYLISTINFO "listplaylistinfo" -#define COMMAND_LSINFO "lsinfo" -#define COMMAND_RM "rm" -#define COMMAND_PLAYLISTINFO "playlistinfo" -#define COMMAND_PLAYLISTID "playlistid" -#define COMMAND_FIND "find" -#define COMMAND_SEARCH "search" -#define COMMAND_UPDATE "update" -#define COMMAND_NEXT "next" -#define COMMAND_PREVIOUS "previous" -#define COMMAND_LISTALL "listall" -#define COMMAND_VOLUME "volume" -#define COMMAND_REPEAT "repeat" -#define COMMAND_RANDOM "random" -#define COMMAND_STATS "stats" -#define COMMAND_CLEAR_ERROR "clearerror" -#define COMMAND_LIST "list" -#define COMMAND_MOVE "move" -#define COMMAND_MOVEID "moveid" -#define COMMAND_SWAP "swap" -#define COMMAND_SWAPID "swapid" -#define COMMAND_SEEK "seek" -#define COMMAND_SEEKID "seekid" -#define COMMAND_LISTALLINFO "listallinfo" -#define COMMAND_PING "ping" -#define COMMAND_SETVOL "setvol" -#define COMMAND_PASSWORD "password" -#define COMMAND_CROSSFADE "crossfade" -#define COMMAND_URL_HANDLERS "urlhandlers" -#define COMMAND_PLCHANGES "plchanges" -#define COMMAND_PLCHANGESPOSID "plchangesposid" -#define COMMAND_CURRENTSONG "currentsong" -#define COMMAND_ENABLE_DEV "enableoutput" -#define COMMAND_DISABLE_DEV "disableoutput" -#define COMMAND_DEVICES "outputs" -#define COMMAND_COMMANDS "commands" -#define COMMAND_NOTCOMMANDS "notcommands" -#define COMMAND_PLAYLISTCLEAR "playlistclear" -#define COMMAND_PLAYLISTADD "playlistadd" -#define COMMAND_PLAYLISTFIND "playlistfind" -#define COMMAND_PLAYLISTSEARCH "playlistsearch" -#define COMMAND_PLAYLISTMOVE "playlistmove" -#define COMMAND_PLAYLISTDELETE "playlistdelete" -#define COMMAND_TAGTYPES "tagtypes" -#define COMMAND_COUNT "count" -#define COMMAND_RENAME "rename" - -#define COMMAND_STATUS_VOLUME "volume" -#define COMMAND_STATUS_STATE "state" -#define COMMAND_STATUS_REPEAT "repeat" -#define COMMAND_STATUS_RANDOM "random" -#define COMMAND_STATUS_PLAYLIST "playlist" -#define COMMAND_STATUS_PLAYLIST_LENGTH "playlistlength" -#define COMMAND_STATUS_SONG "song" -#define COMMAND_STATUS_SONGID "songid" -#define COMMAND_STATUS_TIME "time" -#define COMMAND_STATUS_BITRATE "bitrate" -#define COMMAND_STATUS_ERROR "error" -#define COMMAND_STATUS_CROSSFADE "xfade" -#define COMMAND_STATUS_AUDIO "audio" -#define COMMAND_STATUS_UPDATING_DB "updating_db" - -/* - * The most we ever use is for search/find, and that limits it to the - * number of tags we can have. Add one for the command, and one extra - * to catch errors clients may send us - */ -#define COMMAND_ARGV_MAX (2+(TAG_NUM_OF_ITEM_TYPES*2)) - -typedef struct _CommandEntry CommandEntry; - -typedef int (*CommandHandlerFunction) (int, int *, int, char **); -typedef int (*CommandListHandlerFunction) - (int, int *, int, char **, struct strnode *, CommandEntry *); - -/* if min: -1 don't check args * - * if max: -1 no max args */ -struct _CommandEntry { - char *cmd; - int min; - int max; - int reqPermission; - CommandHandlerFunction handler; - CommandListHandlerFunction listHandler; -}; - -static char *current_command; -static int command_listNum; - -static CommandEntry *getCommandEntryFromString(char *string, int *permission); - -static List *commandList; - -static CommandEntry *newCommandEntry(void) -{ - CommandEntry *cmd = xmalloc(sizeof(CommandEntry)); - cmd->cmd = NULL; - cmd->min = 0; - cmd->max = 0; - cmd->handler = NULL; - cmd->listHandler = NULL; - cmd->reqPermission = 0; - return cmd; -} - -static void addCommand(char *name, - int reqPermission, - int minargs, - int maxargs, - CommandHandlerFunction handler_func, - CommandListHandlerFunction listHandler_func) -{ - CommandEntry *cmd = newCommandEntry(); - cmd->cmd = name; - cmd->min = minargs; - cmd->max = maxargs; - cmd->handler = handler_func; - cmd->listHandler = listHandler_func; - cmd->reqPermission = reqPermission; - - insertInList(commandList, cmd->cmd, cmd); -} - -static int handleUrlHandlers(int fd, int *permission, int argc, char *argv[]) -{ - return printRemoteUrlHandlers(fd); -} - -static int handleTagTypes(int fd, int *permission, int argc, char *argv[]) -{ - printTagTypes(fd); - return 0; -} - -static int handlePlay(int fd, int *permission, int argc, char *argv[]) -{ - int song = -1; - char *test; - - if (argc == 2) { - song = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "need a positive integer"); - return -1; - } - } - return playPlaylist(fd, song, 0); -} - -static int handlePlayId(int fd, int *permission, int argc, char *argv[]) -{ - int id = -1; - char *test; - - if (argc == 2) { - id = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "need a positive integer"); - return -1; - } - } - return playPlaylistById(fd, id, 0); -} - -static int handleStop(int fd, int *permission, int argc, char *argv[]) -{ - return stopPlaylist(fd); -} - -static int handleCurrentSong(int fd, int *permission, int argc, char *argv[]) -{ - int song = getPlaylistCurrentSong(); - - if (song >= 0) { - return playlistInfo(fd, song); - } else - return 0; -} - -static int handlePause(int fd, int *permission, int argc, char *argv[]) -{ - if (argc == 2) { - char *test; - int pause = strtol(argv[1], &test, 10); - if (*test != '\0' || (pause != 0 && pause != 1)) { - commandError(fd, ACK_ERROR_ARG, "\"%s\" is not 0 or 1", - argv[1]); - return -1; - } - return playerSetPause(fd, pause); - } - return playerPause(fd); -} - -static int commandStatus(int fd, int *permission, int argc, char *argv[]) -{ - char *state = NULL; - int updateJobId; - int song; - - /*syncPlayerAndPlaylist(); */ - playPlaylistIfPlayerStopped(); - switch (getPlayerState()) { - case PLAYER_STATE_STOP: - state = COMMAND_STOP; - break; - case PLAYER_STATE_PAUSE: - state = COMMAND_PAUSE; - break; - case PLAYER_STATE_PLAY: - state = COMMAND_PLAY; - break; - } - - fdprintf(fd, "%s: %i\n", COMMAND_STATUS_VOLUME, getVolumeLevel()); - fdprintf(fd, "%s: %i\n", COMMAND_STATUS_REPEAT, - getPlaylistRepeatStatus()); - fdprintf(fd, "%s: %i\n", COMMAND_STATUS_RANDOM, - getPlaylistRandomStatus()); - fdprintf(fd, "%s: %li\n", COMMAND_STATUS_PLAYLIST, - getPlaylistVersion()); - fdprintf(fd, "%s: %i\n", COMMAND_STATUS_PLAYLIST_LENGTH, - getPlaylistLength()); - fdprintf(fd, "%s: %i\n", COMMAND_STATUS_CROSSFADE, - (int)(getPlayerCrossFade() + 0.5)); - - fdprintf(fd, "%s: %s\n", COMMAND_STATUS_STATE, state); - - song = getPlaylistCurrentSong(); - if (song >= 0) { - fdprintf(fd, "%s: %i\n", COMMAND_STATUS_SONG, song); - fdprintf(fd, "%s: %i\n", COMMAND_STATUS_SONGID, - getPlaylistSongId(song)); - } - if (getPlayerState() != PLAYER_STATE_STOP) { - fdprintf(fd, "%s: %i:%i\n", COMMAND_STATUS_TIME, - getPlayerElapsedTime(), getPlayerTotalTime()); - fdprintf(fd, "%s: %li\n", COMMAND_STATUS_BITRATE, - getPlayerBitRate()); - fdprintf(fd, "%s: %u:%i:%i\n", COMMAND_STATUS_AUDIO, - getPlayerSampleRate(), getPlayerBits(), - getPlayerChannels()); - } - - if ((updateJobId = isUpdatingDB())) { - fdprintf(fd, "%s: %i\n", COMMAND_STATUS_UPDATING_DB, - updateJobId); - } - - if (getPlayerError() != PLAYER_ERROR_NOERROR) { - fdprintf(fd, "%s: %s\n", COMMAND_STATUS_ERROR, - getPlayerErrorStr()); - } - - return 0; -} - -static int handleKill(int fd, int *permission, int argc, char *argv[]) -{ - return COMMAND_RETURN_KILL; -} - -static int handleClose(int fd, int *permission, int argc, char *argv[]) -{ - return COMMAND_RETURN_CLOSE; -} - -static int handleAdd(int fd, int *permission, int argc, char *argv[]) -{ - char *path = argv[1]; - - if (isRemoteUrl(path)) - return addToPlaylist(fd, path, 0); - - return addAllIn(fd, path); -} - -static int handleAddId(int fd, int *permission, int argc, char *argv[]) -{ - return addToPlaylist(fd, argv[1], 1); -} - -static int handleDelete(int fd, int *permission, int argc, char *argv[]) -{ - int song; - char *test; - - song = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, "need a positive integer"); - return -1; - } - return deleteFromPlaylist(fd, song); -} - -static int handleDeleteId(int fd, int *permission, int argc, char *argv[]) -{ - int id; - char *test; - - id = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, "need a positive integer"); - return -1; - } - return deleteFromPlaylistById(fd, id); -} - -static int handlePlaylist(int fd, int *permission, int argc, char *argv[]) -{ - return showPlaylist(fd); -} - -static int handleShuffle(int fd, int *permission, int argc, char *argv[]) -{ - return shufflePlaylist(fd); -} - -static int handleClear(int fd, int *permission, int argc, char *argv[]) -{ - return clearPlaylist(fd); -} - -static int handleSave(int fd, int *permission, int argc, char *argv[]) -{ - return savePlaylist(fd, argv[1]); -} - -static int handleLoad(int fd, int *permission, int argc, char *argv[]) -{ - return loadPlaylist(fd, argv[1]); -} - -static int handleListPlaylist(int fd, int *permission, int argc, char *argv[]) -{ - return PlaylistInfo(fd, argv[1], 0); -} - -static int handleListPlaylistInfo(int fd, int *permission, - int argc, char *argv[]) -{ - return PlaylistInfo(fd, argv[1], 1); -} - -static int handleLsInfo(int fd, int *permission, int argc, char *argv[]) -{ - char *path = ""; - - if (argc == 2) - path = argv[1]; - - if (printDirectoryInfo(fd, path) < 0) - return -1; - - if (isRootDirectory(path)) - return lsPlaylists(fd, path); - - return 0; -} - -static int handleRm(int fd, int *permission, int argc, char *argv[]) -{ - return deletePlaylist(fd, argv[1]); -} - -static int handleRename(int fd, int *permission, int argc, char *argv[]) -{ - return renameStoredPlaylist(fd, argv[1], argv[2]); -} - -static int handlePlaylistChanges(int fd, int *permission, - int argc, char *argv[]) -{ - unsigned long version; - char *test; - - version = strtoul(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, "need a positive integer"); - return -1; - } - return playlistChanges(fd, version); -} - -static int handlePlaylistChangesPosId(int fd, int *permission, - int argc, char *argv[]) -{ - unsigned long version; - char *test; - - version = strtoul(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, "need a positive integer"); - return -1; - } - return playlistChangesPosId(fd, version); -} - -static int handlePlaylistInfo(int fd, int *permission, int argc, char *argv[]) -{ - int song = -1; - char *test; - - if (argc == 2) { - song = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "need a positive integer"); - return -1; - } - } - return playlistInfo(fd, song); -} - -static int handlePlaylistId(int fd, int *permission, int argc, char *argv[]) -{ - int id = -1; - char *test; - - if (argc == 2) { - id = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "need a positive integer"); - return -1; - } - } - return playlistId(fd, id); -} - -static int handleFind(int fd, int *permission, int argc, char *argv[]) -{ - int ret; - - LocateTagItem *items; - int numItems = newLocateTagItemArrayFromArgArray(argv + 1, - argc - 1, - &items); - - if (numItems <= 0) { - commandError(fd, ACK_ERROR_ARG, "incorrect arguments"); - return -1; - } - - ret = findSongsIn(fd, NULL, numItems, items); - - freeLocateTagItemArray(numItems, items); - - return ret; -} - -static int handleSearch(int fd, int *permission, int argc, char *argv[]) -{ - int ret; - - LocateTagItem *items; - int numItems = newLocateTagItemArrayFromArgArray(argv + 1, - argc - 1, - &items); - - if (numItems <= 0) { - commandError(fd, ACK_ERROR_ARG, "incorrect arguments"); - return -1; - } - - ret = searchForSongsIn(fd, NULL, numItems, items); - - freeLocateTagItemArray(numItems, items); - - return ret; -} - -static int handleCount(int fd, int *permission, int argc, char *argv[]) -{ - int ret; - - LocateTagItem *items; - int numItems = newLocateTagItemArrayFromArgArray(argv + 1, - argc - 1, - &items); - - if (numItems <= 0) { - commandError(fd, ACK_ERROR_ARG, "incorrect arguments"); - return -1; - } - - ret = searchStatsForSongsIn(fd, NULL, numItems, items); - - freeLocateTagItemArray(numItems, items); - - return ret; -} - -static int handlePlaylistFind(int fd, int *permission, int argc, char *argv[]) -{ - LocateTagItem *items; - int numItems = newLocateTagItemArrayFromArgArray(argv + 1, - argc - 1, - &items); - - if (numItems <= 0) { - commandError(fd, ACK_ERROR_ARG, "incorrect arguments"); - return -1; - } - - findSongsInPlaylist(fd, numItems, items); - - freeLocateTagItemArray(numItems, items); - - return 0; -} - -static int handlePlaylistSearch(int fd, int *permission, int argc, char *argv[]) -{ - LocateTagItem *items; - int numItems = newLocateTagItemArrayFromArgArray(argv + 1, - argc - 1, - &items); - - if (numItems <= 0) { - commandError(fd, ACK_ERROR_ARG, "incorrect arguments"); - return -1; - } - - searchForSongsInPlaylist(fd, numItems, items); - - freeLocateTagItemArray(numItems, items); - - return 0; -} - -static int handlePlaylistDelete(int fd, int *permission, int argc, char *argv[]) { - char *playlist = argv[1]; - int from; - char *test; - - from = strtol(argv[2], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[2]); - return -1; - } - - return removeOneSongFromStoredPlaylistByPath(fd, playlist, from); -} - -static int handlePlaylistMove(int fd, int *permission, int argc, char *argv[]) -{ - char *playlist = argv[1]; - int from, to; - char *test; - - from = strtol(argv[2], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[2]); - return -1; - } - to = strtol(argv[3], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[3]); - return -1; - } - - return moveSongInStoredPlaylistByPath(fd, playlist, from, to); -} - -static int listHandleUpdate(int fd, - int *permission, - int argc, - char *argv[], - struct strnode *cmdnode, CommandEntry * cmd) -{ - static List *pathList; - CommandEntry *nextCmd = NULL; - struct strnode *next = cmdnode->next; - - if (!pathList) - pathList = makeList(NULL, 1); - - if (argc == 2) - insertInList(pathList, argv[1], NULL); - else - insertInList(pathList, "", NULL); - - if (next) - nextCmd = getCommandEntryFromString(next->data, permission); - - if (cmd != nextCmd) { - int ret = updateInit(fd, pathList); - freeList(pathList); - pathList = NULL; - return ret; - } - - return 0; -} - -static int handleUpdate(int fd, int *permission, int argc, char *argv[]) -{ - if (argc == 2) { - int ret; - List *pathList = makeList(NULL, 1); - insertInList(pathList, argv[1], NULL); - ret = updateInit(fd, pathList); - freeList(pathList); - return ret; - } - return updateInit(fd, NULL); -} - -static int handleNext(int fd, int *permission, int argc, char *argv[]) -{ - return nextSongInPlaylist(fd); -} - -static int handlePrevious(int fd, int *permission, int argc, char *argv[]) -{ - return previousSongInPlaylist(fd); -} - -static int handleListAll(int fd, int *permission, int argc, char *argv[]) -{ - char *directory = NULL; - - if (argc == 2) - directory = argv[1]; - return printAllIn(fd, directory); -} - -static int handleVolume(int fd, int *permission, int argc, char *argv[]) -{ - int change; - char *test; - - change = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, "need an integer"); - return -1; - } - return changeVolumeLevel(fd, change, 1); -} - -static int handleSetVol(int fd, int *permission, int argc, char *argv[]) -{ - int level; - char *test; - - level = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, "need an integer"); - return -1; - } - return changeVolumeLevel(fd, level, 0); -} - -static int handleRepeat(int fd, int *permission, int argc, char *argv[]) -{ - int status; - char *test; - - status = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, "need an integer"); - return -1; - } - return setPlaylistRepeatStatus(fd, status); -} - -static int handleRandom(int fd, int *permission, int argc, char *argv[]) -{ - int status; - char *test; - - status = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, "need an integer"); - return -1; - } - return setPlaylistRandomStatus(fd, status); -} - -static int handleStats(int fd, int *permission, int argc, char *argv[]) -{ - return printStats(fd); -} - -static int handleClearError(int fd, int *permission, int argc, char *argv[]) -{ - clearPlayerError(); - return 0; -} - -static int handleList(int fd, int *permission, int argc, char *argv[]) -{ - int numConditionals = 0; - LocateTagItem *conditionals = NULL; - int tagType = getLocateTagItemType(argv[1]); - int ret; - - if (tagType < 0) { - commandError(fd, ACK_ERROR_ARG, "\"%s\" is not known", argv[1]); - return -1; - } - - if (tagType == LOCATE_TAG_ANY_TYPE) { - commandError(fd, ACK_ERROR_ARG, - "\"any\" is not a valid return tag type"); - return -1; - } - - /* for compatibility with < 0.12.0 */ - if (argc == 3) { - if (tagType != TAG_ITEM_ALBUM) { - commandError(fd, ACK_ERROR_ARG, - "should be \"%s\" for 3 arguments", - mpdTagItemKeys[TAG_ITEM_ALBUM]); - return -1; - } - conditionals = newLocateTagItem(mpdTagItemKeys[TAG_ITEM_ARTIST], - argv[2]); - numConditionals = 1; - } else { - numConditionals = - newLocateTagItemArrayFromArgArray(argv + 2, - argc - 2, &conditionals); - - if (numConditionals < 0) { - commandError(fd, ACK_ERROR_ARG, - "not able to parse args"); - return -1; - } - } - - ret = listAllUniqueTags(fd, tagType, numConditionals, conditionals); - - if (conditionals) - freeLocateTagItemArray(numConditionals, conditionals); - - return ret; -} - -static int handleMove(int fd, int *permission, int argc, char *argv[]) -{ - int from; - int to; - char *test; - - from = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[1]); - return -1; - } - to = strtol(argv[2], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[2]); - return -1; - } - return moveSongInPlaylist(fd, from, to); -} - -static int handleMoveId(int fd, int *permission, int argc, char *argv[]) -{ - int id; - int to; - char *test; - - id = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[1]); - return -1; - } - to = strtol(argv[2], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[2]); - return -1; - } - return moveSongInPlaylistById(fd, id, to); -} - -static int handleSwap(int fd, int *permission, int argc, char *argv[]) -{ - int song1; - int song2; - char *test; - - song1 = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[1]); - return -1; - } - song2 = strtol(argv[2], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, "\"%s\" is not a integer", - argv[2]); - return -1; - } - return swapSongsInPlaylist(fd, song1, song2); -} - -static int handleSwapId(int fd, int *permission, int argc, char *argv[]) -{ - int id1; - int id2; - char *test; - - id1 = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[1]); - return -1; - } - id2 = strtol(argv[2], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, "\"%s\" is not a integer", - argv[2]); - return -1; - } - return swapSongsInPlaylistById(fd, id1, id2); -} - -static int handleSeek(int fd, int *permission, int argc, char *argv[]) -{ - int song; - int time; - char *test; - - song = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[1]); - return -1; - } - time = strtol(argv[2], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[2]); - return -1; - } - return seekSongInPlaylist(fd, song, time); -} - -static int handleSeekId(int fd, int *permission, int argc, char *argv[]) -{ - int id; - int time; - char *test; - - id = strtol(argv[1], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[1]); - return -1; - } - time = strtol(argv[2], &test, 10); - if (*test != '\0') { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer", argv[2]); - return -1; - } - return seekSongInPlaylistById(fd, id, time); -} - -static int handleListAllInfo(int fd, int *permission, int argc, char *argv[]) -{ - char *directory = NULL; - - if (argc == 2) - directory = argv[1]; - return printInfoForAllIn(fd, directory); -} - -static int handlePing(int fd, int *permission, int argc, char *argv[]) -{ - return 0; -} - -static int handlePassword(int fd, int *permission, int argc, char *argv[]) -{ - if (getPermissionFromPassword(argv[1], permission) < 0) { - commandError(fd, ACK_ERROR_PASSWORD, "incorrect password"); - return -1; - } - - return 0; -} - -static int handleCrossfade(int fd, int *permission, int argc, char *argv[]) -{ - int time; - char *test; - - time = strtol(argv[1], &test, 10); - if (*test != '\0' || time < 0) { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer >= 0", argv[1]); - return -1; - } - - setPlayerCrossFade(time); - - return 0; -} - -static int handleEnableDevice(int fd, int *permission, int argc, char *argv[]) -{ - int device; - char *test; - - device = strtol(argv[1], &test, 10); - if (*test != '\0' || device < 0) { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer >= 0", argv[1]); - return -1; - } - - return enableAudioDevice(fd, device); -} - -static int handleDisableDevice(int fd, int *permission, int argc, char *argv[]) -{ - int device; - char *test; - - device = strtol(argv[1], &test, 10); - if (*test != '\0' || device < 0) { - commandError(fd, ACK_ERROR_ARG, - "\"%s\" is not a integer >= 0", argv[1]); - return -1; - } - - return disableAudioDevice(fd, device); -} - -static int handleDevices(int fd, int *permission, int argc, char *argv[]) -{ - printAudioDevices(fd); - - return 0; -} - -/* don't be fooled, this is the command handler for "commands" command */ -static int handleCommands(int fd, int *permission, int argc, char *argv[]) -{ - ListNode *node = commandList->firstNode; - CommandEntry *cmd; - - while (node != NULL) { - cmd = (CommandEntry *) node->data; - if (cmd->reqPermission == (*permission & cmd->reqPermission)) { - fdprintf(fd, "command: %s\n", cmd->cmd); - } - - node = node->nextNode; - } - - return 0; -} - -static int handleNotcommands(int fd, int *permission, int argc, char *argv[]) -{ - ListNode *node = commandList->firstNode; - CommandEntry *cmd; - - while (node != NULL) { - cmd = (CommandEntry *) node->data; - - if (cmd->reqPermission != (*permission & cmd->reqPermission)) { - fdprintf(fd, "command: %s\n", cmd->cmd); - } - - node = node->nextNode; - } - - return 0; -} - -static int handlePlaylistClear(int fd, int *permission, int argc, char *argv[]) -{ - return clearStoredPlaylist(fd, argv[1]); -} - -static int handlePlaylistAdd(int fd, int *permission, int argc, char *argv[]) -{ - char *playlist = argv[1]; - char *path = argv[2]; - - if (isRemoteUrl(path)) - return addToStoredPlaylist(fd, path, playlist); - - return addAllInToStoredPlaylist(fd, path, playlist); -} - -void initCommands(void) -{ - commandList = makeList(free, 1); - - /* addCommand(name, permission, min, max, handler, list handler); */ - addCommand(COMMAND_PLAY, PERMISSION_CONTROL, 0, 1, handlePlay, NULL); - addCommand(COMMAND_PLAYID, PERMISSION_CONTROL, 0, 1, handlePlayId, NULL); - addCommand(COMMAND_STOP, PERMISSION_CONTROL, 0, 0, handleStop, NULL); - addCommand(COMMAND_CURRENTSONG, PERMISSION_READ, 0, 0, handleCurrentSong, NULL); - addCommand(COMMAND_PAUSE, PERMISSION_CONTROL, 0, 1, handlePause, NULL); - addCommand(COMMAND_STATUS, PERMISSION_READ, 0, 0, commandStatus, NULL); - addCommand(COMMAND_KILL, PERMISSION_ADMIN, -1, -1, handleKill, NULL); - addCommand(COMMAND_CLOSE, PERMISSION_NONE, -1, -1, handleClose, NULL); - addCommand(COMMAND_ADD, PERMISSION_ADD, 1, 1, handleAdd, NULL); - addCommand(COMMAND_ADDID, PERMISSION_ADD, 1, 1, handleAddId, NULL); - addCommand(COMMAND_DELETE, PERMISSION_CONTROL, 1, 1, handleDelete, NULL); - addCommand(COMMAND_DELETEID, PERMISSION_CONTROL, 1, 1, handleDeleteId, NULL); - addCommand(COMMAND_PLAYLIST, PERMISSION_READ, 0, 0, handlePlaylist, NULL); - addCommand(COMMAND_PLAYLISTID, PERMISSION_READ, 0, 1, handlePlaylistId, NULL); - addCommand(COMMAND_SHUFFLE, PERMISSION_CONTROL, 0, 0, handleShuffle, NULL); - addCommand(COMMAND_CLEAR, PERMISSION_CONTROL, 0, 0, handleClear, NULL); - addCommand(COMMAND_SAVE, PERMISSION_CONTROL, 1, 1, handleSave, NULL); - addCommand(COMMAND_LOAD, PERMISSION_ADD, 1, 1, handleLoad, NULL); - addCommand(COMMAND_LISTPLAYLIST, PERMISSION_READ, 1, 1, handleListPlaylist, NULL); - addCommand(COMMAND_LISTPLAYLISTINFO, PERMISSION_READ, 1, 1, handleListPlaylistInfo, NULL); - addCommand(COMMAND_LSINFO, PERMISSION_READ, 0, 1, handleLsInfo, NULL); - addCommand(COMMAND_RM, PERMISSION_CONTROL, 1, 1, handleRm, NULL); - addCommand(COMMAND_PLAYLISTINFO, PERMISSION_READ, 0, 1, handlePlaylistInfo, NULL); - addCommand(COMMAND_FIND, PERMISSION_READ, 2, -1, handleFind, NULL); - addCommand(COMMAND_SEARCH, PERMISSION_READ, 2, -1, handleSearch, NULL); - addCommand(COMMAND_UPDATE, PERMISSION_ADMIN, 0, 1, handleUpdate, listHandleUpdate); - addCommand(COMMAND_NEXT, PERMISSION_CONTROL, 0, 0, handleNext, NULL); - addCommand(COMMAND_PREVIOUS, PERMISSION_CONTROL, 0, 0, handlePrevious, NULL); - addCommand(COMMAND_LISTALL, PERMISSION_READ, 0, 1, handleListAll, NULL); - addCommand(COMMAND_VOLUME, PERMISSION_CONTROL, 1, 1, handleVolume, NULL); - addCommand(COMMAND_REPEAT, PERMISSION_CONTROL, 1, 1, handleRepeat, NULL); - addCommand(COMMAND_RANDOM, PERMISSION_CONTROL, 1, 1, handleRandom, NULL); - addCommand(COMMAND_STATS, PERMISSION_READ, 0, 0, handleStats, NULL); - addCommand(COMMAND_CLEAR_ERROR, PERMISSION_CONTROL, 0, 0, handleClearError, NULL); - addCommand(COMMAND_LIST, PERMISSION_READ, 1, -1, handleList, NULL); - addCommand(COMMAND_MOVE, PERMISSION_CONTROL, 2, 2, handleMove, NULL); - addCommand(COMMAND_MOVEID, PERMISSION_CONTROL, 2, 2, handleMoveId, NULL); - addCommand(COMMAND_SWAP, PERMISSION_CONTROL, 2, 2, handleSwap, NULL); - addCommand(COMMAND_SWAPID, PERMISSION_CONTROL, 2, 2, handleSwapId, NULL); - addCommand(COMMAND_SEEK, PERMISSION_CONTROL, 2, 2, handleSeek, NULL); - addCommand(COMMAND_SEEKID, PERMISSION_CONTROL, 2, 2, handleSeekId, NULL); - addCommand(COMMAND_LISTALLINFO, PERMISSION_READ, 0, 1, handleListAllInfo, NULL); - addCommand(COMMAND_PING, PERMISSION_NONE, 0, 0, handlePing, NULL); - addCommand(COMMAND_SETVOL, PERMISSION_CONTROL, 1, 1, handleSetVol, NULL); - addCommand(COMMAND_PASSWORD, PERMISSION_NONE, 1, 1, handlePassword, NULL); - addCommand(COMMAND_CROSSFADE, PERMISSION_CONTROL, 1, 1, handleCrossfade, NULL); - addCommand(COMMAND_URL_HANDLERS, PERMISSION_READ, 0, 0, handleUrlHandlers, NULL); - addCommand(COMMAND_PLCHANGES, PERMISSION_READ, 1, 1, handlePlaylistChanges, NULL); - addCommand(COMMAND_PLCHANGESPOSID, PERMISSION_READ, 1, 1, handlePlaylistChangesPosId, NULL); - addCommand(COMMAND_ENABLE_DEV, PERMISSION_ADMIN, 1, 1, handleEnableDevice, NULL); - addCommand(COMMAND_DISABLE_DEV, PERMISSION_ADMIN, 1, 1, handleDisableDevice, NULL); - addCommand(COMMAND_DEVICES, PERMISSION_READ, 0, 0, handleDevices, NULL); - addCommand(COMMAND_COMMANDS, PERMISSION_NONE, 0, 0, handleCommands, NULL); - addCommand(COMMAND_NOTCOMMANDS, PERMISSION_NONE, 0, 0, handleNotcommands, NULL); - addCommand(COMMAND_PLAYLISTCLEAR, PERMISSION_CONTROL, 1, 1, handlePlaylistClear, NULL); - addCommand(COMMAND_PLAYLISTADD, PERMISSION_CONTROL, 2, 2, handlePlaylistAdd, NULL); - addCommand(COMMAND_PLAYLISTFIND, PERMISSION_READ, 2, -1, handlePlaylistFind, NULL); - addCommand(COMMAND_PLAYLISTSEARCH, PERMISSION_READ, 2, -1, handlePlaylistSearch, NULL); - addCommand(COMMAND_PLAYLISTMOVE, PERMISSION_CONTROL, 3, 3, handlePlaylistMove, NULL); - addCommand(COMMAND_PLAYLISTDELETE, PERMISSION_CONTROL, 2, 2, handlePlaylistDelete, NULL); - addCommand(COMMAND_TAGTYPES, PERMISSION_READ, 0, 0, handleTagTypes, NULL); - addCommand(COMMAND_COUNT, PERMISSION_READ, 2, -1, handleCount, NULL); - addCommand(COMMAND_RENAME, PERMISSION_CONTROL, 2, 2, handleRename, NULL); - - sortList(commandList); -} - -void finishCommands(void) -{ - freeList(commandList); -} - -static int checkArgcAndPermission(CommandEntry * cmd, int fd, - int permission, int argc, char *argv[]) -{ - int min = cmd->min + 1; - int max = cmd->max + 1; - - if (cmd->reqPermission != (permission & cmd->reqPermission)) { - if (fd) { - commandError(fd, ACK_ERROR_PERMISSION, - "you don't have permission for \"%s\"", - cmd->cmd); - } - return -1; - } - - if (min == 0) - return 0; - - if (min == max && max != argc) { - if (fd) { - commandError(fd, ACK_ERROR_ARG, - "wrong number of arguments for \"%s\"", - argv[0]); - } - return -1; - } else if (argc < min) { - if (fd) { - commandError(fd, ACK_ERROR_ARG, - "too few arguments for \"%s\"", argv[0]); - } - return -1; - } else if (argc > max && max /* != 0 */ ) { - if (fd) { - commandError(fd, ACK_ERROR_ARG, - "too many arguments for \"%s\"", argv[0]); - } - return -1; - } else - return 0; -} - -static CommandEntry *getCommandEntryAndCheckArgcAndPermission(int fd, - int *permission, - int argc, - char *argv[]) -{ - static char unknown[] = ""; - CommandEntry *cmd; - - current_command = unknown; - - if (argc == 0) - return NULL; - - if (!findInList(commandList, argv[0], (void *)&cmd)) { - if (fd) { - commandError(fd, ACK_ERROR_UNKNOWN, - "unknown command \"%s\"", argv[0]); - } - return NULL; - } - - current_command = cmd->cmd; - - if (checkArgcAndPermission(cmd, fd, *permission, argc, argv) < 0) { - return NULL; - } - - return cmd; -} - -static CommandEntry *getCommandEntryFromString(char *string, int *permission) -{ - CommandEntry *cmd = NULL; - char *argv[COMMAND_ARGV_MAX] = { NULL }; - int argc = buffer2array(string, argv, COMMAND_ARGV_MAX); - - if (0 == argc) - return NULL; - - cmd = getCommandEntryAndCheckArgcAndPermission(0, permission, - argc, argv); - - return cmd; -} - -static int processCommandInternal(int fd, int *permission, - char *commandString, struct strnode *cmdnode) -{ - int argc; - char *argv[COMMAND_ARGV_MAX] = { NULL }; - CommandEntry *cmd; - int ret = -1; - - argc = buffer2array(commandString, argv, COMMAND_ARGV_MAX); - - if (argc == 0) - return 0; - - if ((cmd = getCommandEntryAndCheckArgcAndPermission(fd, permission, - argc, argv))) { - if (!cmdnode || !cmd->listHandler) { - ret = cmd->handler(fd, permission, argc, argv); - } else { - ret = cmd->listHandler(fd, permission, argc, argv, - cmdnode, cmd); - } - } - - current_command = NULL; - - return ret; -} - -int processListOfCommands(int fd, int *permission, int *expired, - int listOK, struct strnode *list) -{ - struct strnode *cur = list; - int ret = 0; - - command_listNum = 0; - - while (cur) { - DEBUG("processListOfCommands: process command \"%s\"\n", - cur->data); - ret = processCommandInternal(fd, permission, cur->data, cur); - DEBUG("processListOfCommands: command returned %i\n", ret); - if (ret != 0 || (*expired) != 0) - goto out; - else if (listOK) - fdprintf(fd, "list_OK\n"); - command_listNum++; - cur = cur->next; - } -out: - command_listNum = 0; - return ret; -} - -int processCommand(int fd, int *permission, char *commandString) -{ - return processCommandInternal(fd, permission, commandString, NULL); -} - -mpd_fprintf_ void commandError(int fd, int error, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - - if (current_command && fd != STDERR_FILENO) { - fdprintf(fd, "ACK [%i@%i] {%s} ", - (int)error, command_listNum, current_command); - vfdprintf(fd, fmt, args); - fdprintf(fd, "\n"); - current_command = NULL; - } else { - fdprintf(STDERR_FILENO, "ACK [%i@%i] ", - (int)error, command_listNum); - vfdprintf(STDERR_FILENO, fmt, args); - fdprintf(STDERR_FILENO, "\n"); - } - - va_end(args); -} diff --git a/trunk/src/command.h b/trunk/src/command.h deleted file mode 100644 index a560b9484..000000000 --- a/trunk/src/command.h +++ /dev/null @@ -1,50 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef COMMAND_H -#define COMMAND_H - -#include "../config.h" - -#include "list.h" -#include "myfprintf.h" -#include "log.h" -#include "ack.h" -#include "sllist.h" - -#include <unistd.h> -#include <stdio.h> - -#define COMMAND_RETURN_KILL 10 -#define COMMAND_RETURN_CLOSE 20 -#define COMMAND_MASTER_READY 30 - -int processListOfCommands(int fd, int *permission, int *expired, - int listOK, struct strnode *list); - -int processCommand(int fd, int *permission, char *commandString); - -void initCommands(void); - -void finishCommands(void); - -#define commandSuccess(fd) fdprintf(fd, "OK\n") - -mpd_fprintf_ void commandError(int fd, int error, const char *fmt, ...); - -#endif diff --git a/trunk/src/compress.c b/trunk/src/compress.c deleted file mode 100644 index d8db7ab64..000000000 --- a/trunk/src/compress.c +++ /dev/null @@ -1,411 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * Compressor logic by - * (c)2003-6 fluffy@beesbuzz.biz - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> - -#include "compress.h" -#include "utils.h" - -#ifdef USE_X -#include <X11/Xlib.h> -#include <X11/Xutil.h> - -static Display *display; -static Window window; -static Visual *visual; -static int screen; -static GC blackGC, whiteGC, blueGC, yellowGC, dkyellowGC, redGC; -#endif - -static int *peaks; -static int gainCurrent, gainTarget; - -static struct { - int show_mon; - int anticlip; - int target; - int gainmax; - int gainsmooth; - int buckets; -} prefs; - -#ifdef USE_X -static int mon_init; -#endif - -void CompressCfg(int show_mon, int anticlip, int target, int gainmax, - int gainsmooth, int buckets) -{ - static int lastsize; - - prefs.show_mon = show_mon; - prefs.anticlip = anticlip; - prefs.target = target; - prefs.gainmax = gainmax; - prefs.gainsmooth = gainsmooth; - prefs.buckets = buckets; - - /* Allocate the peak structure */ - peaks = xrealloc(peaks, sizeof(int)*prefs.buckets); - - if (prefs.buckets > lastsize) - memset(peaks + lastsize, 0, sizeof(int)*(prefs.buckets - - lastsize)); - lastsize = prefs.buckets; - -#ifdef USE_X - /* Configure the monitor window if needed */ - if (show_mon && !mon_init) - { - display = XOpenDisplay(getenv("DISPLAY")); - - /* We really shouldn't try to init X if there's no X */ - if (!display) - { - fprintf(stderr, - "X not detected; disabling monitor window\n"); - show_mon = prefs.show_mon = 0; - } - } - - if (show_mon && !mon_init) - { - XGCValues gcv; - XColor col; - - gainCurrent = gainTarget = (1 << GAINSHIFT); - - - - screen = DefaultScreen(display); - visual = DefaultVisual(display, screen); - window = XCreateSimpleWindow(display, - RootWindow(display, screen), - 0, 0, prefs.buckets, 128 + 8, 0, - BlackPixel(display, screen), - WhitePixel(display, screen)); - XStoreName(display, window, "AudioCompress monitor"); - - gcv.foreground = BlackPixel(display, screen); - blackGC = XCreateGC(display, window, GCForeground, &gcv); - gcv.foreground = WhitePixel(display, screen); - whiteGC = XCreateGC(display, window, GCForeground, &gcv); - col.red = 0; - col.green = 0; - col.blue = 65535; - XAllocColor(display, DefaultColormap(display, screen), &col); - gcv.foreground = col.pixel; - blueGC = XCreateGC(display, window, GCForeground, &gcv); - col.red = 65535; - col.green = 65535; - col.blue = 0; - XAllocColor(display, DefaultColormap(display, screen), &col); - gcv.foreground = col.pixel; - yellowGC = XCreateGC(display, window, GCForeground, &gcv); - col.red = 32767; - col.green = 32767; - col.blue = 0; - XAllocColor(display, DefaultColormap(display, screen), &col); - gcv.foreground = col.pixel; - dkyellowGC = XCreateGC(display, window, GCForeground, &gcv); - col.red = 65535; - col.green = 0; - col.blue = 0; - XAllocColor(display, DefaultColormap(display, screen), &col); - gcv.foreground = col.pixel; - redGC = XCreateGC(display, window, GCForeground, &gcv); - mon_init = 1; - } - - if (mon_init) - { - if (show_mon) - XMapWindow(display, window); - else - XUnmapWindow(display, window); - XResizeWindow(display, window, prefs.buckets, 128 + 8); - XFlush(display); - } -#endif -} - -void CompressFree(void) -{ -#ifdef USE_X - if (mon_init) - { - XFreeGC(display, blackGC); - XFreeGC(display, whiteGC); - XFreeGC(display, blueGC); - XFreeGC(display, yellowGC); - XFreeGC(display, dkyellowGC); - XFreeGC(display, redGC); - XDestroyWindow(display, window); - XCloseDisplay(display); - } -#endif - - if (peaks) - free(peaks); -} - -void CompressDo(void *data, unsigned int length) -{ - int16_t *audio = (int16_t *)data, *ap; - int peak, pos; - int i; - int gr, gf, gn; - static int pn = -1; -#ifdef STATS - static int clip; -#endif - static int clipped; - - if (!peaks) - return; - - if (pn == -1) - { - for (i = 0; i < prefs.buckets; i++) - peaks[i] = 0; - } - pn = (pn + 1)%prefs.buckets; - -#ifdef DEBUG - fprintf(stderr, "modifyNative16(0x%08x, %d)\n",(unsigned int)data, - length); -#endif - - /* Determine peak's value and position */ - peak = 1; - pos = 0; - -#ifdef DEBUG - fprintf(stderr, "finding peak(b=%d)\n", pn); -#endif - - ap = audio; - for (i = 0; i < length/2; i++) - { - int val = *ap; - if (val > peak) - { - peak = val; - pos = i; - } else if (-val > peak) - { - peak = -val; - pos = i; - } - ap++; - } - peaks[pn] = peak; - - /* Only draw if needed, of course */ -#ifdef USE_X - if (prefs.show_mon) - { - /* current amplitude */ - XDrawLine(display, window, whiteGC, - pn, 0, - pn, - 127 - - (peaks[pn]*gainCurrent >> (GAINSHIFT + 8))); - - /* amplification */ - XDrawLine(display, window, yellowGC, - pn, - 127 - (peaks[pn]*gainCurrent - >> (GAINSHIFT + 8)), - pn, 127); - - /* peak */ - XDrawLine(display, window, blackGC, - pn, 127 - (peaks[pn] >> 8), pn, 127); - - /* clip indicator */ - if (clipped) - XDrawLine(display, window, redGC, - (pn + prefs.buckets - 1)%prefs.buckets, - 126 - clipped/(length*512), - (pn + prefs.buckets - 1)%prefs.buckets, - 127); - clipped = 0; - - /* target line */ - /* XDrawPoint(display, window, redGC, */ - /* pn, 127 - TARGET/256); */ - /* amplification edge */ - XDrawLine(display, window, dkyellowGC, - pn, - 127 - (peaks[pn]*gainCurrent - >> (GAINSHIFT + 8)), - pn - 1, - 127 - - (peaks[(pn + prefs.buckets - - 1)%prefs.buckets]*gainCurrent - >> (GAINSHIFT + 8))); - } -#endif - - for (i = 0; i < prefs.buckets; i++) - { - if (peaks[i] > peak) - { - peak = peaks[i]; - pos = 0; - } - } - - /* Determine target gain */ - gn = (1 << GAINSHIFT)*prefs.target/peak; - - if (gn <(1 << GAINSHIFT)) - gn = 1 << GAINSHIFT; - - gainTarget = (gainTarget *((1 << prefs.gainsmooth) - 1) + gn) - >> prefs.gainsmooth; - - /* Give it an extra insignifigant nudge to counteract possible - ** rounding error - */ - - if (gn < gainTarget) - gainTarget--; - else if (gn > gainTarget) - gainTarget++; - - if (gainTarget > prefs.gainmax << GAINSHIFT) - gainTarget = prefs.gainmax << GAINSHIFT; - - -#ifdef USE_X - if (prefs.show_mon) - { - int x; - - /* peak*gain */ - XDrawPoint(display, window, redGC, - pn, - 127 - (peak*gainCurrent - >> (GAINSHIFT + 8))); - - /* gain indicator */ - XFillRectangle(display, window, whiteGC, 0, 128, - prefs.buckets, 8); - x = (gainTarget - (1 << GAINSHIFT))*prefs.buckets - / ((prefs.gainmax - 1) << GAINSHIFT); - XDrawLine(display, window, redGC, x, - 128, x, 128 + 8); - - x = (gn - (1 << GAINSHIFT))*prefs.buckets - / ((prefs.gainmax - 1) << GAINSHIFT); - - XDrawLine(display, window, blackGC, - x, 132 - 1, - x, 132 + 1); - - /* blue peak line */ - XDrawLine(display, window, blueGC, - 0, 127 - (peak >> 8), prefs.buckets, - 127 - (peak >> 8)); - XFlush(display); - XDrawLine(display, window, whiteGC, - 0, 127 - (peak >> 8), prefs.buckets, - 127 - (peak >> 8)); - } -#endif - - /* See if a peak is going to clip */ - gn = (1 << GAINSHIFT)*32768/peak; - - if (gn < gainTarget) - { - gainTarget = gn; - - if (prefs.anticlip) - pos = 0; - - } else - { - /* We're ramping up, so draw it out over the whole frame */ - pos = length; - } - - /* Determine gain rate necessary to make target */ - if (!pos) - pos = 1; - - gr = ((gainTarget - gainCurrent) << 16)/pos; - - /* Do the shiznit */ - gf = gainCurrent << 16; - -#ifdef STATS - fprintf(stderr, "\rgain = %2.2f%+.2e ", - gainCurrent*1.0/(1 << GAINSHIFT), - (gainTarget - gainCurrent)*1.0/(1 << GAINSHIFT)); -#endif - - ap = audio; - for (i = 0; i < length/2; i++) - { - int sample; - - /* Interpolate the gain */ - gainCurrent = gf >> 16; - if (i < pos) - gf += gr; - else if (i == pos) - gf = gainTarget << 16; - - /* Amplify */ - sample = (*ap)*gainCurrent >> GAINSHIFT; - if (sample < -32768) - { -#ifdef STATS - clip++; -#endif - clipped += -32768 - sample; - sample = -32768; - } else if (sample > 32767) - { -#ifdef STATS - clip++; -#endif - clipped += sample - 32767; - sample = 32767; - } - *ap++ = sample; - } -#ifdef STATS - fprintf(stderr, "clip %d b%-3d ", clip, pn); -#endif - -#ifdef DEBUG - fprintf(stderr, "\ndone\n"); -#endif -} - diff --git a/trunk/src/compress.h b/trunk/src/compress.h deleted file mode 100644 index 42638f788..000000000 --- a/trunk/src/compress.h +++ /dev/null @@ -1,47 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * interface to audio compression - * (c)2003-6 fluffy@beesbuzz.biz - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef COMPRESS_H -#define COMPRESS_H - -/* These are copied from the AudioCompress config.h, mainly because CompressDo - * needs GAINSHIFT defined. The rest are here so they can be used as defaults - * to pass to CompressCfg(). -- jat */ -#define ANTICLIP 0 /* Strict clipping protection */ -#define TARGET 25000 /* Target level */ -#define GAINMAX 32 /* The maximum amount to amplify by */ -#define GAINSHIFT 10 /* How fine-grained the gain is */ -#define GAINSMOOTH 8 /* How much inertia ramping has*/ -#define BUCKETS 400 /* How long of a history to store */ - -void CompressCfg(int monitor, - int anticlip, - int target, - int maxgain, - int smooth, - int buckets); - -void CompressDo(void *data, unsigned int numSamples); - -void CompressFree(void); - -#endif diff --git a/trunk/src/conf.c b/trunk/src/conf.c deleted file mode 100644 index 8ab59a505..000000000 --- a/trunk/src/conf.c +++ /dev/null @@ -1,450 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "conf.h" - -#include "log.h" - -#include "utils.h" -#include "buffer2array.h" -#include "list.h" - -#include <sys/param.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <pwd.h> -#include <errno.h> - -#define MAX_STRING_SIZE MAXPATHLEN+80 - -#define CONF_COMMENT '#' -#define CONF_BLOCK_BEGIN "{" -#define CONF_BLOCK_END "}" - -#define CONF_REPEATABLE_MASK 0x01 -#define CONF_BLOCK_MASK 0x02 -#define CONF_LINE_TOKEN_MAX 3 - -typedef struct _configEntry { - unsigned char mask; - List *configParamList; -} ConfigEntry; - -static List *configEntriesList; - -static ConfigParam *newConfigParam(char *value, int line) -{ - ConfigParam *ret = xmalloc(sizeof(ConfigParam)); - - if (!value) - ret->value = NULL; - else - ret->value = xstrdup(value); - - ret->line = line; - - ret->numberOfBlockParams = 0; - ret->blockParams = NULL; - - return ret; -} - -static void freeConfigParam(ConfigParam * param) -{ - int i; - - if (param->value) - free(param->value); - - for (i = 0; i < param->numberOfBlockParams; i++) { - if (param->blockParams[i].name) { - free(param->blockParams[i].name); - } - if (param->blockParams[i].value) { - free(param->blockParams[i].value); - } - } - - if (param->numberOfBlockParams) - free(param->blockParams); - - free(param); -} - -static ConfigEntry *newConfigEntry(int repeatable, int block) -{ - ConfigEntry *ret = xmalloc(sizeof(ConfigEntry)); - - ret->mask = 0; - ret->configParamList = - makeList((ListFreeDataFunc *) freeConfigParam, 1); - - if (repeatable) - ret->mask |= CONF_REPEATABLE_MASK; - if (block) - ret->mask |= CONF_BLOCK_MASK; - - return ret; -} - -static void freeConfigEntry(ConfigEntry * entry) -{ - freeList(entry->configParamList); - free(entry); -} - -static void registerConfigParam(char *name, int repeatable, int block) -{ - ConfigEntry *entry; - - if (findInList(configEntriesList, name, NULL)) - FATAL("config parameter \"%s\" already registered\n", name); - - entry = newConfigEntry(repeatable, block); - - insertInList(configEntriesList, name, entry); -} - -void finishConf(void) -{ - freeList(configEntriesList); -} - -void initConf(void) -{ - configEntriesList = makeList((ListFreeDataFunc *) freeConfigEntry, 1); - - /* registerConfigParam(name, repeatable, block); */ - registerConfigParam(CONF_MUSIC_DIR, 0, 0); - registerConfigParam(CONF_PLAYLIST_DIR, 0, 0); - registerConfigParam(CONF_DB_FILE, 0, 0); - registerConfigParam(CONF_LOG_FILE, 0, 0); - registerConfigParam(CONF_ERROR_FILE, 0, 0); - registerConfigParam(CONF_PID_FILE, 0, 0); - registerConfigParam(CONF_STATE_FILE, 0, 0); - registerConfigParam(CONF_USER, 0, 0); - registerConfigParam(CONF_BIND_TO_ADDRESS, 1, 0); - registerConfigParam(CONF_PORT, 0, 0); - registerConfigParam(CONF_LOG_LEVEL, 0, 0); - registerConfigParam(CONF_ZEROCONF_NAME, 0, 0); - registerConfigParam(CONF_PASSWORD, 1, 0); - registerConfigParam(CONF_DEFAULT_PERMS, 0, 0); - registerConfigParam(CONF_AUDIO_OUTPUT, 1, 1); - registerConfigParam(CONF_AUDIO_OUTPUT_FORMAT, 0, 0); - registerConfigParam(CONF_MIXER_TYPE, 0, 0); - registerConfigParam(CONF_MIXER_DEVICE, 0, 0); - registerConfigParam(CONF_MIXER_CONTROL, 0, 0); - registerConfigParam(CONF_REPLAYGAIN, 0, 0); - registerConfigParam(CONF_REPLAYGAIN_PREAMP, 0, 0); - registerConfigParam(CONF_VOLUME_NORMALIZATION, 0, 0); - registerConfigParam(CONF_SAMPLERATE_CONVERTER, 0, 0); - registerConfigParam(CONF_AUDIO_BUFFER_SIZE, 0, 0); - registerConfigParam(CONF_BUFFER_BEFORE_PLAY, 0, 0); - registerConfigParam(CONF_HTTP_BUFFER_SIZE, 0, 0); - registerConfigParam(CONF_HTTP_PREBUFFER_SIZE, 0, 0); - registerConfigParam(CONF_HTTP_PROXY_HOST, 0, 0); - registerConfigParam(CONF_HTTP_PROXY_PORT, 0, 0); - registerConfigParam(CONF_HTTP_PROXY_USER, 0, 0); - registerConfigParam(CONF_HTTP_PROXY_PASSWORD, 0, 0); - registerConfigParam(CONF_CONN_TIMEOUT, 0, 0); - registerConfigParam(CONF_MAX_CONN, 0, 0); - registerConfigParam(CONF_MAX_PLAYLIST_LENGTH, 0, 0); - registerConfigParam(CONF_MAX_COMMAND_LIST_SIZE, 0, 0); - registerConfigParam(CONF_MAX_OUTPUT_BUFFER_SIZE, 0, 0); - registerConfigParam(CONF_FS_CHARSET, 0, 0); - registerConfigParam(CONF_ID3V1_ENCODING, 0, 0); - registerConfigParam(CONF_METADATA_TO_USE, 0, 0); - registerConfigParam(CONF_SAVE_ABSOLUTE_PATHS, 0, 0); - registerConfigParam(CONF_GAPLESS_MP3_PLAYBACK, 0, 0); -} - -static void addBlockParam(ConfigParam * param, char *name, char *value, - int line) -{ - param->numberOfBlockParams++; - - param->blockParams = xrealloc(param->blockParams, - param->numberOfBlockParams * - sizeof(BlockParam)); - - param->blockParams[param->numberOfBlockParams - 1].name = xstrdup(name); - param->blockParams[param->numberOfBlockParams - 1].value = - xstrdup(value); - param->blockParams[param->numberOfBlockParams - 1].line = line; -} - -static ConfigParam *readConfigBlock(FILE * fp, int *count, char *string) -{ - ConfigParam *ret = newConfigParam(NULL, *count); - - int i; - int numberOfArgs; - int argsMinusComment; - - while (myFgets(string, MAX_STRING_SIZE, fp)) { - char *array[CONF_LINE_TOKEN_MAX] = { NULL }; - - (*count)++; - - numberOfArgs = buffer2array(string, array, CONF_LINE_TOKEN_MAX); - - for (i = 0; i < numberOfArgs; i++) { - if (array[i][0] == CONF_COMMENT) - break; - } - - argsMinusComment = i; - - if (0 == argsMinusComment) { - continue; - } - - if (1 == argsMinusComment && - 0 == strcmp(array[0], CONF_BLOCK_END)) { - break; - } - - if (2 != argsMinusComment) { - FATAL("improperly formatted config file at line %i:" - " %s\n", *count, string); - } - - if (0 == strcmp(array[0], CONF_BLOCK_BEGIN) || - 0 == strcmp(array[1], CONF_BLOCK_BEGIN) || - 0 == strcmp(array[0], CONF_BLOCK_END) || - 0 == strcmp(array[1], CONF_BLOCK_END)) { - FATAL("improperly formatted config file at line %i: %s\n" - "in block beginning at line %i\n", - *count, string, ret->line);; - } - - addBlockParam(ret, array[0], array[1], *count); - } - - return ret; -} - -void readConf(char *file) -{ - FILE *fp; - char string[MAX_STRING_SIZE + 1]; - int i; - int numberOfArgs; - int argsMinusComment; - int count = 0; - ConfigEntry *entry; - void *voidPtr; - ConfigParam *param; - - if (!(fp = fopen(file, "r"))) { - FATAL("problems opening file %s for reading: %s\n", file, - strerror(errno)); - } - - while (myFgets(string, MAX_STRING_SIZE, fp)) { - char *array[CONF_LINE_TOKEN_MAX] = { NULL }; - count++; - - numberOfArgs = buffer2array(string, array, CONF_LINE_TOKEN_MAX); - - for (i = 0; i < numberOfArgs; i++) { - if (array[i][0] == CONF_COMMENT) - break; - } - - argsMinusComment = i; - - if (0 == argsMinusComment) { - continue; - } - - if (2 != argsMinusComment) { - FATAL("improperly formatted config file at line %i:" - " %s\n", count, string); - } - - if (!findInList(configEntriesList, array[0], &voidPtr)) { - FATAL("unrecognized parameter in config file at line " - "%i: %s\n", count, string); - } - - entry = (ConfigEntry *) voidPtr; - - if (!(entry->mask & CONF_REPEATABLE_MASK) && - entry->configParamList->numberOfNodes) { - param = entry->configParamList->firstNode->data; - FATAL("config parameter \"%s\" is first defined on line " - "%i and redefined on line %i\n", array[0], - param->line, count); - } - - if (entry->mask & CONF_BLOCK_MASK) { - if (0 != strcmp(array[1], CONF_BLOCK_BEGIN)) { - FATAL("improperly formatted config file at " - "line %i: %s\n", count, string); - } - param = readConfigBlock(fp, &count, string); - } else - param = newConfigParam(array[1], count); - - insertInListWithoutKey(entry->configParamList, param); - } - fclose(fp); -} - -ConfigParam *getNextConfigParam(char *name, ConfigParam * last) -{ - void *voidPtr; - ConfigEntry *entry; - ListNode *node; - ConfigParam *param; - - if (!findInList(configEntriesList, name, &voidPtr)) - return NULL; - - entry = voidPtr; - - node = entry->configParamList->firstNode; - - if (last) { - while (node != NULL) { - param = node->data; - node = node->nextNode; - if (param == last) - break; - } - } - - if (node == NULL) - return NULL; - - param = node->data; - - return param; -} - -char *getConfigParamValue(char *name) -{ - ConfigParam *param = getConfigParam(name); - - if (!param) - return NULL; - - return param->value; -} - -int getBoolConfigParam(char *name) -{ - ConfigParam *param; - - param = getConfigParam(name); - if (!param) return -1; - - if (strcmp("yes", param->value) == 0) return 1; - else if (strcmp("no", param->value) == 0) return 0; - - ERROR("%s is not \"yes\" or \"no\" on line %i\n", name, param->line); - - return -2; -} - -BlockParam *getBlockParam(ConfigParam * param, char *name) -{ - BlockParam *ret = NULL; - int i; - - for (i = 0; i < param->numberOfBlockParams; i++) { - if (0 == strcmp(name, param->blockParams[i].name)) { - if (ret) { - ERROR("\"%s\" first defined on line %i, and " - "redefined on line %i\n", name, - ret->line, param->blockParams[i].line); - } - ret = param->blockParams + i; - } - } - - return ret; -} - -ConfigParam *parseConfigFilePath(char *name, int force) -{ - ConfigParam *param = getConfigParam(name); - char *path; - - if (!param && force) - FATAL("config parameter \"%s\" not found\n", name); - - if (!param) - return NULL; - - path = param->value; - - if (path[0] != '/' && path[0] != '~') { - FATAL("\"%s\" is not an absolute path at line %i\n", - param->value, param->line); - } - /* Parse ~ in path */ - else if (path[0] == '~') { - struct passwd *pwd = NULL; - char *newPath; - int pos = 1; - if (path[1] == '/' || path[1] == '\0') { - ConfigParam *userParam = getConfigParam(CONF_USER); - - if (userParam) { - pwd = getpwnam(userParam->value); - if (!pwd) { - FATAL("no such user %s at line %i\n", - userParam->value, - userParam->line); - } - } else { - uid_t uid = geteuid(); - if ((pwd = getpwuid(uid)) == NULL) { - FATAL("problems getting passwd entry " - "for current user\n"); - } - } - } else { - int foundSlash = 0; - char *ch = path + 1; - for (; *ch != '\0' && *ch != '/'; ch++) ; - if (*ch == '/') - foundSlash = 1; - *ch = '\0'; - pos += ch - path - 1; - if ((pwd = getpwnam(path + 1)) == NULL) { - FATAL("user \"%s\" not found at line %i\n", - path + 1, param->line); - } - if (foundSlash) - *ch = '/'; - } - newPath = xmalloc(strlen(pwd->pw_dir) + strlen(path + pos) + 1); - strcpy(newPath, pwd->pw_dir); - strcat(newPath, path + pos); - free(param->value); - param->value = newPath; - } - - return param; -} diff --git a/trunk/src/conf.h b/trunk/src/conf.h deleted file mode 100644 index 7059eaa90..000000000 --- a/trunk/src/conf.h +++ /dev/null @@ -1,98 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef CONF_H -#define CONF_H - -#include "../config.h" - -#define CONF_MUSIC_DIR "music_directory" -#define CONF_PLAYLIST_DIR "playlist_directory" -#define CONF_DB_FILE "db_file" -#define CONF_LOG_FILE "log_file" -#define CONF_ERROR_FILE "error_file" -#define CONF_PID_FILE "pid_file" -#define CONF_STATE_FILE "state_file" -#define CONF_USER "user" -#define CONF_BIND_TO_ADDRESS "bind_to_address" -#define CONF_PORT "port" -#define CONF_LOG_LEVEL "log_level" -#define CONF_ZEROCONF_NAME "zeroconf_name" -#define CONF_PASSWORD "password" -#define CONF_DEFAULT_PERMS "default_permissions" -#define CONF_AUDIO_OUTPUT "audio_output" -#define CONF_AUDIO_OUTPUT_FORMAT "audio_output_format" -#define CONF_MIXER_TYPE "mixer_type" -#define CONF_MIXER_DEVICE "mixer_device" -#define CONF_MIXER_CONTROL "mixer_control" -#define CONF_REPLAYGAIN "replaygain" -#define CONF_REPLAYGAIN_PREAMP "replaygain_preamp" -#define CONF_VOLUME_NORMALIZATION "volume_normalization" -#define CONF_SAMPLERATE_CONVERTER "samplerate_converter" -#define CONF_AUDIO_BUFFER_SIZE "audio_buffer_size" -#define CONF_BUFFER_BEFORE_PLAY "buffer_before_play" -#define CONF_HTTP_BUFFER_SIZE "http_buffer_size" -#define CONF_HTTP_PREBUFFER_SIZE "http_prebuffer_size" -#define CONF_HTTP_PROXY_HOST "http_proxy_host" -#define CONF_HTTP_PROXY_PORT "http_proxy_port" -#define CONF_HTTP_PROXY_USER "http_proxy_user" -#define CONF_HTTP_PROXY_PASSWORD "http_proxy_password" -#define CONF_CONN_TIMEOUT "connection_timeout" -#define CONF_MAX_CONN "max_connections" -#define CONF_MAX_PLAYLIST_LENGTH "max_playlist_length" -#define CONF_MAX_COMMAND_LIST_SIZE "max_command_list_size" -#define CONF_MAX_OUTPUT_BUFFER_SIZE "max_output_buffer_size" -#define CONF_FS_CHARSET "filesystem_charset" -#define CONF_ID3V1_ENCODING "id3v1_encoding" -#define CONF_METADATA_TO_USE "metadata_to_use" -#define CONF_SAVE_ABSOLUTE_PATHS "save_absolute_paths_in_playlists" -#define CONF_GAPLESS_MP3_PLAYBACK "gapless_mp3_playback" - -typedef struct _BlockParam { - char *name; - char *value; - int line; -} BlockParam; - -typedef struct _ConfigParam { - char *value; - unsigned int line; - BlockParam *blockParams; - int numberOfBlockParams; -} ConfigParam; - -void initConf(void); -void finishConf(void); - -void readConf(char *file); - -/* don't free the returned value - set _last_ to NULL to get first entry */ -ConfigParam *getNextConfigParam(char *name, ConfigParam * last); - -#define getConfigParam(name) getNextConfigParam(name, NULL) - -char *getConfigParamValue(char *name); - -int getBoolConfigParam(char *name); - -BlockParam *getBlockParam(ConfigParam * param, char *name); - -ConfigParam *parseConfigFilePath(char *name, int force); - -#endif diff --git a/trunk/src/dbUtils.c b/trunk/src/dbUtils.c deleted file mode 100644 index f83ae4c21..000000000 --- a/trunk/src/dbUtils.c +++ /dev/null @@ -1,341 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "dbUtils.h" - -#include "directory.h" -#include "myfprintf.h" -#include "utils.h" -#include "playlist.h" -#include "song.h" -#include "tag.h" -#include "tagTracker.h" -#include "log.h" -#include "storedPlaylist.h" - -typedef struct _ListCommandItem { - mpd_sint8 tagType; - int numConditionals; - LocateTagItem *conditionals; -} ListCommandItem; - -typedef struct _LocateTagItemArray { - int numItems; - LocateTagItem *items; -} LocateTagItemArray; - -typedef struct _SearchStats { - LocateTagItemArray locateArray; - int numberOfSongs; - unsigned long playTime; -} SearchStats; - -static int countSongsInDirectory(int fd, Directory * directory, void *data) -{ - int *count = (int *)data; - - *count += directory->songs->numberOfNodes; - - return 0; -} - -static int printDirectoryInDirectory(int fd, Directory * directory, - void *data) -{ - if (directory->path) { - fdprintf(fd, "directory: %s\n", getDirectoryPath(directory)); - } - return 0; -} - -static int printSongInDirectory(int fd, Song * song, void *data) -{ - printSongUrl(fd, song); - return 0; -} - -static int searchInDirectory(int fd, Song * song, void *data) -{ - LocateTagItemArray *array = data; - - if (strstrSearchTags(song, array->numItems, array->items)) - printSongInfo(fd, song); - - return 0; -} - -int searchForSongsIn(int fd, char *name, int numItems, LocateTagItem * items) -{ - int ret = -1; - int i; - - char **originalNeedles = xmalloc(numItems * sizeof(char *)); - LocateTagItemArray array; - - for (i = 0; i < numItems; i++) { - originalNeedles[i] = items[i].needle; - items[i].needle = strDupToUpper(originalNeedles[i]); - } - - array.numItems = numItems; - array.items = items; - - ret = traverseAllIn(fd, name, searchInDirectory, NULL, &array); - - for (i = 0; i < numItems; i++) { - free(items[i].needle); - items[i].needle = originalNeedles[i]; - } - - free(originalNeedles); - - return ret; -} - -static int findInDirectory(int fd, Song * song, void *data) -{ - LocateTagItemArray *array = data; - - if (tagItemsFoundAndMatches(song, array->numItems, array->items)) - printSongInfo(fd, song); - - return 0; -} - -int findSongsIn(int fd, char *name, int numItems, LocateTagItem * items) -{ - LocateTagItemArray array; - - array.numItems = numItems; - array.items = items; - - return traverseAllIn(fd, name, findInDirectory, NULL, (void *)&array); -} - -static void printSearchStats(int fd, SearchStats *stats) -{ - fdprintf(fd, "songs: %i\n", stats->numberOfSongs); - fdprintf(fd, "playtime: %li\n", stats->playTime); -} - -static int searchStatsInDirectory(int fd, Song * song, void *data) -{ - SearchStats *stats = data; - - if (tagItemsFoundAndMatches(song, stats->locateArray.numItems, - stats->locateArray.items)) { - stats->numberOfSongs++; - if (song->tag->time > 0) - stats->playTime += song->tag->time; - } - - return 0; -} - -int searchStatsForSongsIn(int fd, char *name, int numItems, - LocateTagItem * items) -{ - SearchStats stats; - int ret; - - stats.locateArray.numItems = numItems; - stats.locateArray.items = items; - stats.numberOfSongs = 0; - stats.playTime = 0; - - ret = traverseAllIn(fd, name, searchStatsInDirectory, NULL, &stats); - if (ret == 0) - printSearchStats(fd, &stats); - - return ret; -} - -int printAllIn(int fd, char *name) -{ - return traverseAllIn(fd, name, printSongInDirectory, - printDirectoryInDirectory, NULL); -} - -static int directoryAddSongToPlaylist(int fd, Song * song, void *data) -{ - return addSongToPlaylist(fd, song, 0); -} - -static int directoryAddSongToStoredPlaylist(int fd, Song *song, void *data) -{ - if (appendSongToStoredPlaylistByPath(fd, (char *)data, song) != 0) - return -1; - return 0; -} - -int addAllIn(int fd, char *name) -{ - return traverseAllIn(fd, name, directoryAddSongToPlaylist, NULL, NULL); -} - -int addAllInToStoredPlaylist(int fd, char *name, char *utf8file) -{ - return traverseAllIn(fd, name, directoryAddSongToStoredPlaylist, NULL, - (void *)utf8file); -} - -static int directoryPrintSongInfo(int fd, Song * song, void *data) -{ - return printSongInfo(fd, song); -} - -static int sumSongTime(int fd, Song * song, void *data) -{ - unsigned long *time = (unsigned long *)data; - - if (song->tag && song->tag->time >= 0) - *time += song->tag->time; - - return 0; -} - -int printInfoForAllIn(int fd, char *name) -{ - return traverseAllIn(fd, name, directoryPrintSongInfo, - printDirectoryInDirectory, NULL); -} - -int countSongsIn(int fd, char *name) -{ - int count = 0; - void *ptr = (void *)&count; - - traverseAllIn(fd, name, NULL, countSongsInDirectory, ptr); - - return count; -} - -unsigned long sumSongTimesIn(int fd, char *name) -{ - unsigned long dbPlayTime = 0; - void *ptr = (void *)&dbPlayTime; - - traverseAllIn(fd, name, sumSongTime, NULL, ptr); - - return dbPlayTime; -} - -static ListCommandItem *newListCommandItem(int tagType, int numConditionals, - LocateTagItem * conditionals) -{ - ListCommandItem *item = xmalloc(sizeof(ListCommandItem)); - - item->tagType = tagType; - item->numConditionals = numConditionals; - item->conditionals = conditionals; - - return item; -} - -static void freeListCommandItem(ListCommandItem * item) -{ - free(item); -} - -static void visitTag(int fd, Song * song, int tagType) -{ - int i; - MpdTag *tag = song->tag; - - if (tagType == LOCATE_TAG_FILE_TYPE) { - printSongUrl(fd, song); - return; - } - - if (!tag) - return; - - for (i = 0; i < tag->numOfItems; i++) { - if (tag->items[i].type == tagType) { - visitInTagTracker(tagType, tag->items[i].value); - } - } -} - -static int listUniqueTagsInDirectory(int fd, Song * song, void *data) -{ - ListCommandItem *item = data; - - if (tagItemsFoundAndMatches(song, item->numConditionals, - item->conditionals)) { - visitTag(fd, song, item->tagType); - } - - return 0; -} - -int listAllUniqueTags(int fd, int type, int numConditionals, - LocateTagItem * conditionals) -{ - int ret; - ListCommandItem *item = newListCommandItem(type, numConditionals, - conditionals); - - if (type >= 0 && type <= TAG_NUM_OF_ITEM_TYPES) { - resetVisitedFlagsInTagTracker(type); - } - - ret = traverseAllIn(fd, NULL, listUniqueTagsInDirectory, NULL, - (void *)item); - - if (type >= 0 && type <= TAG_NUM_OF_ITEM_TYPES) { - printVisitedInTagTracker(fd, type); - } - - freeListCommandItem(item); - - return ret; -} - -static int sumSavedFilenameMemoryInDirectory(int fd, Directory * dir, - void *data) -{ - int *sum = data; - - if (!dir->path) - return 0; - - *sum += (strlen(getDirectoryPath(dir)) + 1 - sizeof(Directory *)) * - dir->songs->numberOfNodes; - - return 0; -} - -static int sumSavedFilenameMemoryInSong(int fd, Song * song, void *data) -{ - int *sum = data; - - *sum += strlen(song->url) + 1; - - return 0; -} - -void printSavedMemoryFromFilenames(void) -{ - int sum = 0; - - traverseAllIn(STDERR_FILENO, NULL, sumSavedFilenameMemoryInSong, - sumSavedFilenameMemoryInDirectory, (void *)&sum); - - DEBUG("saved memory from filenames: %i\n", sum); -} diff --git a/trunk/src/dbUtils.h b/trunk/src/dbUtils.h deleted file mode 100644 index 0607bc3b5..000000000 --- a/trunk/src/dbUtils.h +++ /dev/null @@ -1,51 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DB_UTILS_H -#define DB_UTILS_H - -#include <stdio.h> - -#include "locate.h" - -int printAllIn(int fd, char *name); - -int addAllIn(int fd, char *name); - -int addAllInToStoredPlaylist(int fd, char *name, char *utf8file); - -int printInfoForAllIn(int fd, char *name); - -int searchForSongsIn(int fd, char *name, int numItems, - LocateTagItem * items); - -int findSongsIn(int fd, char *name, int numItems, LocateTagItem * items); - -int searchStatsForSongsIn(int fd, char *name, int numItems, - LocateTagItem * items); - -int countSongsIn(int fd, char *name); - -unsigned long sumSongTimesIn(int fd, char *name); - -int listAllUniqueTags(int fd, int type, int numConditiionals, - LocateTagItem * conditionals); - -void printSavedMemoryFromFilenames(void); - -#endif diff --git a/trunk/src/decode.c b/trunk/src/decode.c deleted file mode 100644 index 82eba19b9..000000000 --- a/trunk/src/decode.c +++ /dev/null @@ -1,706 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "decode.h" - -#include "player.h" -#include "playerData.h" -#include "utils.h" -#include "pcm_utils.h" -#include "audio.h" -#include "path.h" -#include "log.h" -#include "sig_handlers.h" -#include "ls.h" -#include "utf8.h" - -#include <signal.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <sys/wait.h> -#include <unistd.h> -#include <string.h> - -static int decode_pid; - -void decodeSigHandler(int sig, siginfo_t * si, void *v) -{ - if (sig == SIGCHLD) { - int status; - if (decode_pid == wait3(&status, WNOHANG, NULL)) { - if (WIFSIGNALED(status)) { - if (WTERMSIG(status) != SIGTERM) { - ERROR("decode process died from " - "signal: %i\n", WTERMSIG(status)); - } - } - decode_pid = 0; - getPlayerData()->playerControl.decode_pid = 0; - } - } else if (sig == SIGTERM) { - int pid = decode_pid; - if (pid > 0) { - DEBUG("player (or child) got SIGTERM\n"); - kill(pid, SIGTERM); - } else - DEBUG("decoder (or child) got SIGTERM\n"); - exit(EXIT_SUCCESS); - } -} - -static void stopDecode(DecoderControl * dc) -{ - if (decode_pid > 0 && (dc->start || dc->state != DECODE_STATE_STOP)) { - dc->stop = 1; - while (decode_pid > 0 && dc->stop) - my_usleep(10000); - } -} - -static void quitDecode(PlayerControl * pc, DecoderControl * dc) -{ - stopDecode(dc); - pc->state = PLAYER_STATE_STOP; - dc->seek = 0; - pc->play = 0; - pc->stop = 0; - pc->pause = 0; - kill(getppid(), SIGUSR1); -} - -static int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) -{ - long chunks; - - if (pc->crossFade <= 0) - return 0; - - chunks = (af->sampleRate * af->bits * af->channels / 8.0 / CHUNK_SIZE); - chunks = (chunks * pc->crossFade + 0.5); - - if (chunks > (buffered_chunks - buffered_before_play)) { - chunks = buffered_chunks - buffered_before_play; - } - - if (chunks < 0) - chunks = 0; - - return (int)chunks; -} - -#define handleDecodeStart() \ - if(decodeWaitedOn) { \ - if(dc->state!=DECODE_STATE_START && decode_pid > 0 && \ - dc->error==DECODE_ERROR_NOERROR) \ - { \ - decodeWaitedOn = 0; \ - if(openAudioDevice(&(cb->audioFormat))<0) { \ - pathcpy_trunc(pc->erroredUrl, pc->utf8url); \ - pc->error = PLAYER_ERROR_AUDIO; \ - ERROR("problems opening audio device while playing \"%s\"\n", pc->utf8url); \ - quitDecode(pc,dc); \ - return; \ - } \ - pc->totalTime = dc->totalTime; \ - pc->sampleRate = dc->audioFormat.sampleRate; \ - pc->bits = dc->audioFormat.bits; \ - pc->channels = dc->audioFormat.channels; \ - sizeToTime = 8.0/cb->audioFormat.bits/ \ - cb->audioFormat.channels/ \ - cb->audioFormat.sampleRate; \ - } \ - else if(dc->state!=DECODE_STATE_START || decode_pid <= 0) { \ - pathcpy_trunc(pc->erroredUrl, pc->utf8url); \ - pc->error = PLAYER_ERROR_FILE; \ - quitDecode(pc,dc); \ - return; \ - } \ - else { \ - my_usleep(10000); \ - continue; \ - } \ - } - -static int waitOnDecode(PlayerControl * pc, DecoderControl * dc, - OutputBuffer * cb, int *decodeWaitedOn) -{ - MpdTag *tag = NULL; - pathcpy_trunc(pc->currentUrl, pc->utf8url); - - while (decode_pid > 0 && dc->start) - my_usleep(10000); - - if (dc->start || dc->error != DECODE_ERROR_NOERROR) { - pathcpy_trunc(pc->erroredUrl, pc->utf8url); - pc->error = PLAYER_ERROR_FILE; - quitDecode(pc, dc); - return -1; - } - - if ((tag = metadataChunkToMpdTagDup(&(pc->fileMetadataChunk)))) { - sendMetadataToAudioDevice(tag); - freeMpdTag(tag); - } - - pc->totalTime = pc->fileTime; - pc->bitRate = 0; - pc->sampleRate = 0; - pc->bits = 0; - pc->channels = 0; - *decodeWaitedOn = 1; - - return 0; -} - -static int decodeSeek(PlayerControl * pc, DecoderControl * dc, - OutputBuffer * cb, int *decodeWaitedOn, int *next) -{ - int ret = -1; - - if (decode_pid > 0) { - if (dc->state == DECODE_STATE_STOP || dc->error || - strcmp(dc->utf8url, pc->utf8url) != 0) { - stopDecode(dc); - *next = -1; - cb->begin = 0; - cb->end = 0; - dc->error = 0; - dc->start = 1; - waitOnDecode(pc, dc, cb, decodeWaitedOn); - } - if (decode_pid > 0 && dc->state != DECODE_STATE_STOP && - dc->seekable) { - *next = -1; - dc->seekWhere = pc->seekWhere > pc->totalTime - 0.1 ? - pc->totalTime - 0.1 : pc->seekWhere; - dc->seekWhere = 0 > dc->seekWhere ? 0 : dc->seekWhere; - dc->seekError = 0; - dc->seek = 1; - while (decode_pid > 0 && dc->seek) - my_usleep(10000); - if (!dc->seekError) { - pc->elapsedTime = dc->seekWhere; - ret = 0; - } - } - } - pc->seek = 0; - - return ret; -} - -#define processDecodeInput() \ - if(pc->cycleLogFiles) { \ - cycle_log_files(); \ - pc->cycleLogFiles = 0; \ - } \ - if(pc->lockQueue) { \ - pc->queueLockState = PLAYER_QUEUE_LOCKED; \ - pc->lockQueue = 0; \ - } \ - if(pc->unlockQueue) { \ - pc->queueLockState = PLAYER_QUEUE_UNLOCKED; \ - pc->unlockQueue = 0; \ - } \ - if(pc->pause) { \ - pause = !pause; \ - if (pause) pc->state = PLAYER_STATE_PAUSE; \ - else { \ - if (openAudioDevice(NULL) >= 0) pc->state = PLAYER_STATE_PLAY; \ - else { \ - pathcpy_trunc(pc->erroredUrl, pc->utf8url); \ - pc->error = PLAYER_ERROR_AUDIO; \ - ERROR("problems opening audio device while playing \"%s\"\n", pc->utf8url); \ - pause = -1; \ - } \ - } \ - pc->pause = 0; \ - kill(getppid(), SIGUSR1); \ - if (pause == -1) pause = 1; \ - else if (pause) { \ - dropBufferedAudio(); \ - closeAudioDevice(); \ - } \ - } \ - if(pc->seek) { \ - dropBufferedAudio(); \ - if(decodeSeek(pc,dc,cb,&decodeWaitedOn,&next) == 0) { \ - doCrossFade = 0; \ - nextChunk = -1; \ - bbp = 0; \ - } \ - } \ - if(pc->stop) { \ - dropBufferedAudio(); \ - quitDecode(pc,dc); \ - return; \ - } - -static void decodeStart(PlayerControl * pc, OutputBuffer * cb, - DecoderControl * dc) -{ - int ret; - InputStream inStream; - InputPlugin *plugin = NULL; - char *path; - - if (isRemoteUrl(pc->utf8url)) - path = utf8StrToLatin1Dup(pc->utf8url); - else - path = xstrdup(rmp2amp(utf8ToFsCharset(pc->utf8url))); - - if (!path) { - dc->error = DECODE_ERROR_FILE; - dc->state = DECODE_STATE_STOP; - dc->start = 0; - return; - } - - copyMpdTagToOutputBuffer(cb, NULL); - - pathcpy_trunc(dc->utf8url, pc->utf8url); - - if (openInputStream(&inStream, path) < 0) { - dc->error = DECODE_ERROR_FILE; - dc->state = DECODE_STATE_STOP; - dc->start = 0; - free(path); - return; - } - - dc->state = DECODE_STATE_START; - dc->start = 0; - - while (!inputStreamAtEOF(&inStream) && bufferInputStream(&inStream) < 0 - && !dc->stop) { - /* sleep so we don't consume 100% of the cpu */ - my_usleep(1000); - } - - /* for http streams, seekable is determined in bufferInputStream */ - dc->seekable = inStream.seekable; - - if (dc->stop) { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - free(path); - return; - } - - /*if(inStream.metaName) { - MpdTag * tag = newMpdTag(); - tag->name = xstrdup(inStream.metaName); - copyMpdTagToOutputBuffer(cb, tag); - freeMpdTag(tag); - } */ - - /* reset Metadata in OutputBuffer */ - - ret = DECODE_ERROR_UNKTYPE; - if (isRemoteUrl(dc->utf8url)) { - unsigned int next = 0; - cb->acceptMetadata = 1; - - /* first we try mime types: */ - while (ret - && (plugin = - getInputPluginFromMimeType(inStream.mime, next++))) { - if (!plugin->streamDecodeFunc) - continue; - if (!(plugin->streamTypes & INPUT_PLUGIN_STREAM_URL)) - continue; - if (plugin->tryDecodeFunc - && !plugin->tryDecodeFunc(&inStream)) - continue; - ret = plugin->streamDecodeFunc(cb, dc, &inStream); - break; - } - - /* if that fails, try suffix matching the URL: */ - if (plugin == NULL) { - char *s = getSuffix(dc->utf8url); - next = 0; - while (ret - && (plugin = - getInputPluginFromSuffix(s, next++))) { - if (!plugin->streamDecodeFunc) - continue; - if (!(plugin->streamTypes & - INPUT_PLUGIN_STREAM_URL)) - continue; - if (plugin->tryDecodeFunc && - !plugin->tryDecodeFunc(&inStream)) - continue; - ret = - plugin->streamDecodeFunc(cb, dc, &inStream); - break; - } - } - /* fallback to mp3: */ - /* this is needed for bastard streams that don't have a suffix - or set the mimeType */ - if (plugin == NULL) { - /* we already know our mp3Plugin supports streams, no - * need to check for stream{Types,DecodeFunc} */ - if ((plugin = getInputPluginFromName("mp3"))) - ret = plugin->streamDecodeFunc(cb, dc, - &inStream); - } - } else { - unsigned int next = 0; - char *s = getSuffix(dc->utf8url); - cb->acceptMetadata = 0; - while (ret && (plugin = getInputPluginFromSuffix(s, next++))) { - if (!plugin->streamTypes & INPUT_PLUGIN_STREAM_FILE) - continue; - if (plugin->tryDecodeFunc - && !plugin->tryDecodeFunc(&inStream)) - continue; - - if (plugin->streamDecodeFunc) { - ret = - plugin->streamDecodeFunc(cb, dc, &inStream); - break; - } else if (plugin->fileDecodeFunc) { - closeInputStream(&inStream); - ret = plugin->fileDecodeFunc(cb, dc, path); - } - } - } - - if (ret < 0 || ret == DECODE_ERROR_UNKTYPE) { - pathcpy_trunc(pc->erroredUrl, dc->utf8url); - if (ret != DECODE_ERROR_UNKTYPE) - dc->error = DECODE_ERROR_FILE; - else { - dc->error = DECODE_ERROR_UNKTYPE; - closeInputStream(&inStream); - } - dc->stop = 0; - dc->state = DECODE_STATE_STOP; - } - - free(path); -} - -static int decoderInit(PlayerControl * pc, OutputBuffer * cb, - DecoderControl * dc) -{ - blockSignals(); - getPlayerData()->playerControl.decode_pid = 0; - decode_pid = fork(); - - if (decode_pid == 0) { - /* CHILD */ - unblockSignals(); - - while (1) { - if (dc->cycleLogFiles) { - cycle_log_files(); - dc->cycleLogFiles = 0; - } else if (dc->start || dc->seek) - decodeStart(pc, cb, dc); - else if (dc->stop) { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } else - my_usleep(10000); - } - - exit(EXIT_SUCCESS); - /* END OF CHILD */ - } else if (decode_pid < 0) { - unblockSignals(); - pathcpy_trunc(pc->erroredUrl, pc->utf8url); - pc->error = PLAYER_ERROR_SYSTEM; - return -1; - } - DEBUG("decoder PID: %d\n", decode_pid); - getPlayerData()->playerControl.decode_pid = decode_pid; - unblockSignals(); - - return 0; -} - -static void handleMetadata(OutputBuffer * cb, PlayerControl * pc, int *previous, - int *currentChunkSent, MetadataChunk * currentChunk) -{ - if (cb->begin != cb->end) { - int meta = cb->metaChunk[cb->begin]; - if (meta != *previous) { - DEBUG("player: metadata change\n"); - if (meta >= 0 && cb->metaChunkSet[meta]) { - DEBUG("player: new metadata from decoder!\n"); - memcpy(currentChunk, - cb->metadataChunks + meta, - sizeof(MetadataChunk)); - *currentChunkSent = 0; - cb->metaChunkSet[meta] = 0; - } - } - *previous = meta; - } - if (!(*currentChunkSent) && pc->metadataState == - PLAYER_METADATA_STATE_WRITE) { - MpdTag *tag = NULL; - - *currentChunkSent = 1; - - if ((tag = metadataChunkToMpdTagDup(currentChunk))) { - sendMetadataToAudioDevice(tag); - freeMpdTag(tag); - } - - memcpy(&(pc->metadataChunk), currentChunk, - sizeof(MetadataChunk)); - pc->metadataState = PLAYER_METADATA_STATE_READ; - kill(getppid(), SIGUSR1); - } -} - -static void advanceOutputBufferTo(OutputBuffer * cb, PlayerControl * pc, - int *previous, int *currentChunkSent, - MetadataChunk * currentChunk, int to) -{ - while (cb->begin != to) { - handleMetadata(cb, pc, previous, currentChunkSent, - currentChunk); - if (cb->begin + 1 >= buffered_chunks) { - cb->begin = 0; - } - else cb->begin++; - } -} - -static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) -{ - int pause = 0; - int quit = 0; - int bbp = buffered_before_play; - int doCrossFade = 0; - int crossFadeChunks = 0; - int fadePosition; - int nextChunk = -1; - int test; - int decodeWaitedOn = 0; - char silence[CHUNK_SIZE]; - double sizeToTime = 0.0; - int previousMetadataChunk = -1; - MetadataChunk currentMetadataChunk; - int currentChunkSent = 1; - int end; - int next = -1; - - memset(silence, 0, CHUNK_SIZE); - - if (waitOnDecode(pc, dc, cb, &decodeWaitedOn) < 0) - return; - - pc->elapsedTime = 0; - pc->state = PLAYER_STATE_PLAY; - pc->play = 0; - kill(getppid(), SIGUSR1); - - while (decode_pid > 0 && - cb->end - cb->begin < bbp && - cb->end != buffered_chunks - 1 && - dc->state != DECODE_STATE_STOP) { - processDecodeInput(); - my_usleep(1000); - } - - while (!quit) { - processDecodeInput(); - handleDecodeStart(); - handleMetadata(cb, pc, &previousMetadataChunk, - ¤tChunkSent, ¤tMetadataChunk); - if (dc->state == DECODE_STATE_STOP && - pc->queueState == PLAYER_QUEUE_FULL && - pc->queueLockState == PLAYER_QUEUE_UNLOCKED) { - next = cb->end; - dc->start = 1; - pc->queueState = PLAYER_QUEUE_DECODE; - kill(getppid(), SIGUSR1); - } - if (next >= 0 && doCrossFade == 0 && !dc->start && - dc->state != DECODE_STATE_START) { - nextChunk = -1; - if (isCurrentAudioFormat(&(cb->audioFormat))) { - doCrossFade = 1; - crossFadeChunks = - calculateCrossFadeChunks(pc, - &(cb-> - audioFormat)); - if (!crossFadeChunks - || pc->crossFade >= dc->totalTime) { - doCrossFade = -1; - } - } else - doCrossFade = -1; - } - - /* copy these to local variables to prevent any potential - race conditions and weirdness */ - end = cb->end; - - if (pause) - my_usleep(10000); - else if (cb->begin != end && cb->begin != next) { - if (doCrossFade == 1 && next >= 0 && - ((next > cb->begin && - (fadePosition = next - cb->begin) - <= crossFadeChunks) || - (cb->begin > next && - (fadePosition = next - cb->begin + - buffered_chunks) <= crossFadeChunks))) { - if (nextChunk < 0) { - crossFadeChunks = fadePosition; - } - test = end; - if (end < cb->begin) - test += buffered_chunks; - nextChunk = cb->begin + crossFadeChunks; - if (nextChunk < test) { - if (nextChunk >= buffered_chunks) { - nextChunk -= buffered_chunks; - } - pcm_mix(cb->chunks + - cb->begin * CHUNK_SIZE, - cb->chunks + - nextChunk * CHUNK_SIZE, - cb->chunkSize[cb->begin], - cb->chunkSize[nextChunk], - &(cb->audioFormat), - ((float)fadePosition) / - crossFadeChunks); - if (cb->chunkSize[nextChunk] > - cb->chunkSize[cb->begin] - ) { - cb->chunkSize[cb->begin] - = cb->chunkSize[nextChunk]; - } - } else { - if (dc->state == DECODE_STATE_STOP) { - doCrossFade = -1; - } else - continue; - } - } - pc->elapsedTime = cb->times[cb->begin]; - pc->bitRate = cb->bitRate[cb->begin]; - pcm_volumeChange(cb->chunks + cb->begin * - CHUNK_SIZE, - cb->chunkSize[cb->begin], - &(cb->audioFormat), - pc->softwareVolume); - if (playAudio(cb->chunks + cb->begin * CHUNK_SIZE, - cb->chunkSize[cb->begin]) < 0) { - quit = 1; - } - pc->totalPlayTime += - sizeToTime * cb->chunkSize[cb->begin]; - if (cb->begin + 1 >= buffered_chunks) { - cb->begin = 0; - } else - cb->begin++; - } else if (cb->begin != end && cb->begin == next) { - if (doCrossFade == 1 && nextChunk >= 0) { - nextChunk = cb->begin + crossFadeChunks; - test = end; - if (end < cb->begin) - test += buffered_chunks; - if (nextChunk < test) { - if (nextChunk >= buffered_chunks) { - nextChunk -= buffered_chunks; - } - advanceOutputBufferTo(cb, pc, - &previousMetadataChunk, - ¤tChunkSent, - ¤tMetadataChunk, - nextChunk); - } - } - while (pc->queueState == PLAYER_QUEUE_DECODE || - pc->queueLockState == PLAYER_QUEUE_LOCKED) { - processDecodeInput(); - if (quit) { - quitDecode(pc, dc); - return; - } - my_usleep(10000); - } - if (pc->queueState != PLAYER_QUEUE_PLAY) { - quit = 1; - break; - } else { - next = -1; - if (waitOnDecode(pc, dc, cb, &decodeWaitedOn) < - 0) { - return; - } - nextChunk = -1; - doCrossFade = 0; - crossFadeChunks = 0; - pc->queueState = PLAYER_QUEUE_EMPTY; - kill(getppid(), SIGUSR1); - } - } else if (decode_pid <= 0 || - (dc->state == DECODE_STATE_STOP && !dc->start)) { - quit = 1; - break; - } else { - /*DEBUG("waiting for decoded audio, play silence\n");*/ - if (playAudio(silence, CHUNK_SIZE) < 0) - quit = 1; - } - } - - quitDecode(pc, dc); -} - -/* decode w/ buffering - * this will fork another process - * child process does decoding - * parent process does playing audio - */ -void decode(void) -{ - OutputBuffer *cb; - PlayerControl *pc; - DecoderControl *dc; - - cb = &(getPlayerData()->buffer); - - clearAllMetaChunkSets(cb); - cb->begin = 0; - cb->end = 0; - pc = &(getPlayerData()->playerControl); - dc = &(getPlayerData()->decoderControl); - dc->error = 0; - dc->seek = 0; - dc->stop = 0; - dc->start = 1; - - if (decode_pid <= 0) { - if (decoderInit(pc, cb, dc) < 0) - return; - } - - decodeParent(pc, dc, cb); -} diff --git a/trunk/src/decode.h b/trunk/src/decode.h deleted file mode 100644 index f073c0d55..000000000 --- a/trunk/src/decode.h +++ /dev/null @@ -1,69 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DECODE_H -#define DECODE_H - -#include "../config.h" -#include "tag.h" - -#include "mpd_types.h" -#include "audio.h" - -#include <stdio.h> -#include <sys/param.h> -#include <signal.h> - -#define DECODE_TYPE_FILE 0 -#define DECODE_TYPE_URL 1 - -#define DECODE_STATE_STOP 0 -#define DECODE_STATE_START 1 -#define DECODE_STATE_DECODE 2 - -#define DECODE_ERROR_NOERROR 0 -#define DECODE_ERROR_UNKTYPE 10 -#define DECODE_ERROR_FILE 20 - -#define DECODE_SUFFIX_MP3 1 -#define DECODE_SUFFIX_OGG 2 -#define DECODE_SUFFIX_FLAC 3 -#define DECODE_SUFFIX_AAC 4 -#define DECODE_SUFFIX_MP4 5 -#define DECODE_SUFFIX_WAVE 6 - -typedef struct _DecoderControl { - volatile mpd_sint8 state; - volatile mpd_sint8 stop; - volatile mpd_sint8 start; - volatile mpd_uint16 error; - volatile mpd_sint8 seek; - volatile mpd_sint8 seekError; - volatile mpd_sint8 seekable; - volatile mpd_sint8 cycleLogFiles; - volatile double seekWhere; - AudioFormat audioFormat; - char utf8url[MAXPATHLEN + 1]; - volatile float totalTime; -} DecoderControl; - -void decodeSigHandler(int sig, siginfo_t * siginfo, void *v); - -void decode(void); - -#endif diff --git a/trunk/src/directory.c b/trunk/src/directory.c deleted file mode 100644 index 560c04b7b..000000000 --- a/trunk/src/directory.c +++ /dev/null @@ -1,1362 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "directory.h" - -#include "command.h" -#include "conf.h" -#include "dbUtils.h" -#include "interface.h" -#include "list.h" -#include "listen.h" -#include "log.h" -#include "ls.h" -#include "mpd_types.h" -#include "path.h" -#include "player.h" -#include "playlist.h" -#include "sig_handlers.h" -#include "stats.h" -#include "tagTracker.h" -#include "utils.h" -#include "volume.h" - -#include <sys/wait.h> -#include <dirent.h> -#include <errno.h> -#include <assert.h> -#include <libgen.h> - -#define DIRECTORY_DIR "directory: " -#define DIRECTORY_MTIME "mtime: " -#define DIRECTORY_BEGIN "begin: " -#define DIRECTORY_END "end: " -#define DIRECTORY_INFO_BEGIN "info_begin" -#define DIRECTORY_INFO_END "info_end" -#define DIRECTORY_MPD_VERSION "mpd_version: " -#define DIRECTORY_FS_CHARSET "fs_charset: " - -#define DIRECTORY_UPDATE_EXIT_NOUPDATE 0 -#define DIRECTORY_UPDATE_EXIT_UPDATE 1 -#define DIRECTORY_UPDATE_EXIT_ERROR 2 - -#define DIRECTORY_RETURN_NOUPDATE 0 -#define DIRECTORY_RETURN_UPDATE 1 -#define DIRECTORY_RETURN_ERROR -1 - -static Directory *mp3rootDirectory; - -static time_t directory_dbModTime; - -static volatile int directory_updatePid; - -static volatile int directory_reReadDB; - -static volatile mpd_uint16 directory_updateJobId; - -static DirectoryList *newDirectoryList(); - -static int addToDirectory(Directory * directory, char *shortname, char *name); - -static void freeDirectoryList(DirectoryList * list); - -static void freeDirectory(Directory * directory); - -static int exploreDirectory(Directory * directory); - -static int updateDirectory(Directory * directory); - -static void deleteEmptyDirectoriesInDirectory(Directory * directory); - -static void removeSongFromDirectory(Directory * directory, char *shortname); - -static int addSubDirectoryToDirectory(Directory * directory, char *shortname, - char *name, struct stat *st); - -static Directory *getDirectoryDetails(char *name, char **shortname); - -static Directory *getDirectory(char *name); - -static Song *getSongDetails(char *file, char **shortnameRet, - Directory ** directoryRet); - -static int updatePath(char *utf8path); - -static void sortDirectory(Directory * directory); - -static int inodeFoundInParent(Directory * parent, ino_t inode, dev_t device); - -static int statDirectory(Directory * dir); - -static char *getDbFile(void) -{ - ConfigParam *param = parseConfigFilePath(CONF_DB_FILE, 1); - - assert(param); - assert(param->value); - - return param->value; -} - -static void clearUpdatePid(void) -{ - directory_updatePid = 0; -} - -int isUpdatingDB(void) -{ - if (directory_updatePid > 0 || directory_reReadDB) { - return directory_updateJobId; - } - return 0; -} - -void directory_sigChldHandler(int pid, int status) -{ - if (directory_updatePid == pid) { - if (WIFSIGNALED(status) && WTERMSIG(status) != SIGTERM) { - ERROR("update process died from a " - "non-TERM signal: %i\n", WTERMSIG(status)); - } else if (!WIFSIGNALED(status)) { - switch (WEXITSTATUS(status)) { - case DIRECTORY_UPDATE_EXIT_UPDATE: - directory_reReadDB = 1; - DEBUG("directory_sigChldHandler: " - "updated db\n"); - case DIRECTORY_UPDATE_EXIT_NOUPDATE: - DEBUG("directory_sigChldHandler: " - "update exited succesffully\n"); - break; - default: - ERROR("error updating db\n"); - } - } - clearUpdatePid(); - } -} - -void readDirectoryDBIfUpdateIsFinished(void) -{ - if (directory_reReadDB && 0 == directory_updatePid) { - DEBUG("readDirectoryDB since update finished successfully\n"); - readDirectoryDB(); - playlistVersionChange(); - directory_reReadDB = 0; - } -} - -int updateInit(int fd, List * pathList) -{ - if (directory_updatePid > 0) { - commandError(fd, ACK_ERROR_UPDATE_ALREADY, "already updating"); - return -1; - } - - /* need to block CHLD signal, cause it can exit before we - even get a chance to assign directory_updatePID */ - blockSignals(); - directory_updatePid = fork(); - if (directory_updatePid == 0) { - /* child */ - int dbUpdated = 0; - clearPlayerPid(); - - unblockSignals(); - - finishSigHandlers(); - closeAllListenSockets(); - freeAllInterfaces(); - finishPlaylist(); - finishVolume(); - - if (pathList) { - ListNode *node = pathList->firstNode; - - while (node) { - switch (updatePath(node->key)) { - case 1: - dbUpdated = 1; - break; - case 0: - break; - default: - exit(DIRECTORY_UPDATE_EXIT_ERROR); - } - node = node->nextNode; - } - } else { - if ((dbUpdated = updateDirectory(mp3rootDirectory)) < 0) { - exit(DIRECTORY_UPDATE_EXIT_ERROR); - } - } - - if (!dbUpdated) - exit(DIRECTORY_UPDATE_EXIT_NOUPDATE); - - /* ignore signals since we don't want them to corrupt the db */ - ignoreSignals(); - if (writeDirectoryDB() < 0) { - exit(DIRECTORY_UPDATE_EXIT_ERROR); - } - exit(DIRECTORY_UPDATE_EXIT_UPDATE); - } else if (directory_updatePid < 0) { - unblockSignals(); - ERROR("updateInit: Problems forking()'ing\n"); - commandError(fd, ACK_ERROR_SYSTEM, - "problems trying to update"); - directory_updatePid = 0; - return -1; - } - unblockSignals(); - - directory_updateJobId++; - if (directory_updateJobId > 1 << 15) - directory_updateJobId = 1; - DEBUG("updateInit: fork()'d update child for update job id %i\n", - (int)directory_updateJobId); - fdprintf(fd, "updating_db: %i\n", (int)directory_updateJobId); - - return 0; -} - -static DirectoryStat *newDirectoryStat(struct stat *st) -{ - DirectoryStat *ret = xmalloc(sizeof(DirectoryStat)); - ret->inode = st->st_ino; - ret->device = st->st_dev; - return ret; -} - -static void freeDirectoryStatFromDirectory(Directory * dir) -{ - if (dir->stat) - free(dir->stat); - dir->stat = NULL; -} - -static DirectoryList *newDirectoryList(void) -{ - return makeList((ListFreeDataFunc *) freeDirectory, 1); -} - -static Directory *newDirectory(char *dirname, Directory * parent) -{ - Directory *directory; - - directory = xmalloc(sizeof(Directory)); - - if (dirname && strlen(dirname)) - directory->path = xstrdup(dirname); - else - directory->path = NULL; - directory->subDirectories = newDirectoryList(); - directory->songs = newSongList(); - directory->stat = NULL; - directory->parent = parent; - - return directory; -} - -static void freeDirectory(Directory * directory) -{ - freeDirectoryList(directory->subDirectories); - freeSongList(directory->songs); - if (directory->path) - free(directory->path); - freeDirectoryStatFromDirectory(directory); - free(directory); - /* this resets last dir returned */ - /*getDirectoryPath(NULL); */ -} - -static void freeDirectoryList(DirectoryList * directoryList) -{ - freeList(directoryList); -} - -static void removeSongFromDirectory(Directory * directory, char *shortname) -{ - void *song; - - if (findInList(directory->songs, shortname, &song)) { - LOG("removing: %s\n", getSongUrl((Song *) song)); - deleteFromList(directory->songs, shortname); - } -} - -static void deleteEmptyDirectoriesInDirectory(Directory * directory) -{ - ListNode *node = directory->subDirectories->firstNode; - ListNode *nextNode; - Directory *subDir; - - while (node) { - subDir = (Directory *) node->data; - deleteEmptyDirectoriesInDirectory(subDir); - nextNode = node->nextNode; - if (subDir->subDirectories->numberOfNodes == 0 && - subDir->songs->numberOfNodes == 0) { - deleteNodeFromList(directory->subDirectories, node); - } - node = nextNode; - } -} - -/* return values: - -1 -> error - 0 -> no error, but nothing updated - 1 -> no error, and stuff updated - */ -static int updateInDirectory(Directory * directory, char *shortname, char *name) -{ - void *song; - void *subDir; - struct stat st; - - if (myStat(name, &st)) - return -1; - - if (S_ISREG(st.st_mode) && hasMusicSuffix(name, 0)) { - if (0 == findInList(directory->songs, shortname, &song)) { - addToDirectory(directory, shortname, name); - return DIRECTORY_RETURN_UPDATE; - } else if (st.st_mtime != ((Song *) song)->mtime) { - LOG("updating %s\n", name); - if (updateSongInfo((Song *) song) < 0) { - removeSongFromDirectory(directory, shortname); - } - return 1; - } - } else if (S_ISDIR(st.st_mode)) { - if (findInList - (directory->subDirectories, shortname, (void **)&subDir)) { - freeDirectoryStatFromDirectory(subDir); - ((Directory *) subDir)->stat = newDirectoryStat(&st); - return updateDirectory((Directory *) subDir); - } else { - return addSubDirectoryToDirectory(directory, shortname, - name, &st); - } - } - - return 0; -} - -/* return values: - -1 -> error - 0 -> no error, but nothing removed - 1 -> no error, and stuff removed - */ -static int removeDeletedFromDirectory(Directory * directory, DIR * dir) -{ - char cwd[2]; - struct dirent *ent; - char *dirname = getDirectoryPath(directory); - List *entList = makeList(free, 1); - void *name; - char *s; - char *utf8; - ListNode *node; - ListNode *tmpNode; - int ret = 0; - - cwd[0] = '.'; - cwd[1] = '\0'; - if (dirname == NULL) - dirname = cwd; - - while ((ent = readdir(dir))) { - if (ent->d_name[0] == '.') - continue; /* hide hidden stuff */ - if (strchr(ent->d_name, '\n')) - continue; - - utf8 = fsCharsetToUtf8(ent->d_name); - - if (!utf8) - continue; - - if (directory->path) { - s = xmalloc(strlen(getDirectoryPath(directory)) - + strlen(utf8) + 2); - sprintf(s, "%s/%s", getDirectoryPath(directory), utf8); - } else - s = xstrdup(utf8); - insertInList(entList, utf8, s); - } - - node = directory->subDirectories->firstNode; - while (node) { - tmpNode = node->nextNode; - if (findInList(entList, node->key, &name)) { - if (!isDir((char *)name)) { - LOG("removing directory: %s\n", (char *)name); - deleteFromList(directory->subDirectories, - node->key); - ret = 1; - } - } else { - LOG("removing directory: %s/%s\n", - getDirectoryPath(directory), node->key); - deleteFromList(directory->subDirectories, node->key); - ret = 1; - } - node = tmpNode; - } - - node = directory->songs->firstNode; - while (node) { - tmpNode = node->nextNode; - if (findInList(entList, node->key, (void **)&name)) { - if (!isMusic(name, NULL, 0)) { - removeSongFromDirectory(directory, node->key); - ret = 1; - } - } else { - removeSongFromDirectory(directory, node->key); - ret = 1; - } - node = tmpNode; - } - - freeList(entList); - - return ret; -} - -static Directory *addDirectoryPathToDB(char *utf8path, char **shortname) -{ - char *parent; - Directory *parentDirectory; - void *directory; - - parent = xstrdup(parentPath(utf8path)); - - if (strlen(parent) == 0) - parentDirectory = (void *)mp3rootDirectory; - else - parentDirectory = addDirectoryPathToDB(parent, shortname); - - if (!parentDirectory) { - free(parent); - return NULL; - } - - *shortname = utf8path + strlen(parent); - while (*(*shortname) && *(*shortname) == '/') - (*shortname)++; - - if (!findInList - (parentDirectory->subDirectories, *shortname, &directory)) { - struct stat st; - if (myStat(utf8path, &st) < 0 || - inodeFoundInParent(parentDirectory, st.st_ino, st.st_dev)) { - free(parent); - return NULL; - } else { - directory = newDirectory(utf8path, parentDirectory); - insertInList(parentDirectory->subDirectories, - *shortname, directory); - } - } - - /* if we're adding directory paths, make sure to delete filenames - with potentially the same name */ - removeSongFromDirectory(parentDirectory, *shortname); - - free(parent); - - return (Directory *) directory; -} - -static Directory *addParentPathToDB(char *utf8path, char **shortname) -{ - char *parent; - Directory *parentDirectory; - - parent = xstrdup(parentPath(utf8path)); - - if (strlen(parent) == 0) - parentDirectory = (void *)mp3rootDirectory; - else - parentDirectory = addDirectoryPathToDB(parent, shortname); - - if (!parentDirectory) { - free(parent); - return NULL; - } - - *shortname = utf8path + strlen(parent); - while (*(*shortname) && *(*shortname) == '/') - (*shortname)++; - - free(parent); - - return (Directory *) parentDirectory; -} - -/* return values: - -1 -> error - 0 -> no error, but nothing updated - 1 -> no error, and stuff updated - */ -static int updatePath(char *utf8path) -{ - Directory *directory; - Directory *parentDirectory; - Song *song; - char *shortname; - char *path = sanitizePathDup(utf8path); - time_t mtime; - int ret = 0; - - if (NULL == path) - return -1; - - /* if path is in the DB try to update it, or else delete it */ - if ((directory = getDirectoryDetails(path, &shortname))) { - parentDirectory = directory->parent; - - /* if this update directory is successfull, we are done */ - if ((ret = updateDirectory(directory)) >= 0) { - free(path); - sortDirectory(directory); - return ret; - } - /* we don't want to delete the root directory */ - else if (directory == mp3rootDirectory) { - free(path); - return 0; - } - /* if updateDirectory fails, means we should delete it */ - else { - LOG("removing directory: %s\n", path); - deleteFromList(parentDirectory->subDirectories, - shortname); - ret = 1; - /* don't return, path maybe a song now */ - } - } else if ((song = getSongDetails(path, &shortname, &parentDirectory))) { - if (!parentDirectory->stat - && statDirectory(parentDirectory) < 0) { - free(path); - return 0; - } - /* if this song update is successfull, we are done */ - else if (0 == inodeFoundInParent(parentDirectory->parent, - parentDirectory->stat->inode, - parentDirectory->stat->device) - && song && isMusic(getSongUrl(song), &mtime, 0)) { - free(path); - if (song->mtime == mtime) - return 0; - else if (updateSongInfo(song) == 0) - return 1; - else { - removeSongFromDirectory(parentDirectory, - shortname); - return 1; - } - } - /* if updateDirectory fails, means we should delete it */ - else { - removeSongFromDirectory(parentDirectory, shortname); - ret = 1; - /* don't return, path maybe a directory now */ - } - } - - /* path not found in the db, see if it actually exists on the fs. - * Also, if by chance a directory was replaced by a file of the same - * name or vice versa, we need to add it to the db - */ - if (isDir(path) || isMusic(path, NULL, 0)) { - parentDirectory = addParentPathToDB(path, &shortname); - if (!parentDirectory || (!parentDirectory->stat && - statDirectory(parentDirectory) < 0)) { - } else if (0 == inodeFoundInParent(parentDirectory->parent, - parentDirectory->stat->inode, - parentDirectory->stat-> - device) - && addToDirectory(parentDirectory, shortname, path) - > 0) { - ret = 1; - } - } - - free(path); - - return ret; -} - -/* return values: - -1 -> error - 0 -> no error, but nothing updated - 1 -> no error, and stuff updated - */ -static int updateDirectory(Directory * directory) -{ - DIR *dir; - char cwd[2]; - struct dirent *ent; - char *s; - char *utf8; - char *dirname = getDirectoryPath(directory); - int ret = 0; - - { - if (!directory->stat && statDirectory(directory) < 0) { - return -1; - } else if (inodeFoundInParent(directory->parent, - directory->stat->inode, - directory->stat->device)) { - return -1; - } - } - - cwd[0] = '.'; - cwd[1] = '\0'; - if (dirname == NULL) - dirname = cwd; - - if ((dir = opendir(rmp2amp(utf8ToFsCharset(dirname)))) == NULL) - return -1; - - if (removeDeletedFromDirectory(directory, dir) > 0) - ret = 1; - - rewinddir(dir); - - while ((ent = readdir(dir))) { - if (ent->d_name[0] == '.') - continue; /* hide hidden stuff */ - if (strchr(ent->d_name, '\n')) - continue; - - utf8 = fsCharsetToUtf8(ent->d_name); - - if (!utf8) - continue; - - utf8 = xstrdup(utf8); - - if (directory->path) { - s = xmalloc(strlen(getDirectoryPath(directory)) + - strlen(utf8) + 2); - sprintf(s, "%s/%s", getDirectoryPath(directory), utf8); - } else - s = xstrdup(utf8); - if (updateInDirectory(directory, utf8, s) > 0) - ret = 1; - free(utf8); - free(s); - } - - closedir(dir); - - return ret; -} - -/* return values: - -1 -> error - 0 -> no error, but nothing found - 1 -> no error, and stuff found - */ -static int exploreDirectory(Directory * directory) -{ - DIR *dir; - char cwd[2]; - struct dirent *ent; - char *s; - char *utf8; - char *dirname = getDirectoryPath(directory); - int ret = 0; - - cwd[0] = '.'; - cwd[1] = '\0'; - if (dirname == NULL) - dirname = cwd; - - DEBUG("explore: attempting to opendir: %s\n", dirname); - if ((dir = opendir(rmp2amp(utf8ToFsCharset(dirname)))) == NULL) - return -1; - - DEBUG("explore: %s\n", dirname); - while ((ent = readdir(dir))) { - if (ent->d_name[0] == '.') - continue; /* hide hidden stuff */ - if (strchr(ent->d_name, '\n')) - continue; - - utf8 = fsCharsetToUtf8(ent->d_name); - - if (!utf8) - continue; - - utf8 = xstrdup(utf8); - - DEBUG("explore: found: %s (%s)\n", ent->d_name, utf8); - - if (directory->path) { - s = xmalloc(strlen(getDirectoryPath(directory)) + - strlen(utf8) + 2); - sprintf(s, "%s/%s", getDirectoryPath(directory), utf8); - } else - s = xstrdup(utf8); - if (addToDirectory(directory, utf8, s) > 0) - ret = 1; - free(utf8); - free(s); - } - - closedir(dir); - - return ret; -} - -static int statDirectory(Directory * dir) -{ - struct stat st; - - if (myStat(getDirectoryPath(dir) ? getDirectoryPath(dir) : "", &st) < 0) - { - return -1; - } - - dir->stat = newDirectoryStat(&st); - - return 0; -} - -static int inodeFoundInParent(Directory * parent, ino_t inode, dev_t device) -{ - while (parent) { - if (!parent->stat) { - if (statDirectory(parent) < 0) - return -1; - } - if (parent->stat->inode == inode && - parent->stat->device == device) { - DEBUG("recursive directory found\n"); - return 1; - } - parent = parent->parent; - } - - return 0; -} - -static int addSubDirectoryToDirectory(Directory * directory, char *shortname, - char *name, struct stat *st) -{ - Directory *subDirectory; - - if (inodeFoundInParent(directory, st->st_ino, st->st_dev)) - return 0; - - subDirectory = newDirectory(name, directory); - subDirectory->stat = newDirectoryStat(st); - - if (exploreDirectory(subDirectory) < 1) { - freeDirectory(subDirectory); - return 0; - } - - insertInList(directory->subDirectories, shortname, subDirectory); - - return 1; -} - -static int addToDirectory(Directory * directory, char *shortname, char *name) -{ - struct stat st; - - if (myStat(name, &st)) { - DEBUG("failed to stat %s: %s\n", name, strerror(errno)); - return -1; - } - - if (S_ISREG(st.st_mode) && hasMusicSuffix(name, 0)) { - Song *song; - song = addSongToList(directory->songs, shortname, name, - SONG_TYPE_FILE, directory); - if (!song) - return -1; - LOG("added %s\n", name); - return 1; - } else if (S_ISDIR(st.st_mode)) { - return addSubDirectoryToDirectory(directory, shortname, name, - &st); - } - - DEBUG("addToDirectory: %s is not a directory or music\n", name); - - return -1; -} - -void closeMp3Directory(void) -{ - freeDirectory(mp3rootDirectory); -} - -static Directory *findSubDirectory(Directory * directory, char *name) -{ - void *subDirectory; - char *dup = xstrdup(name); - char *key; - - key = strtok(dup, "/"); - if (!key) { - free(dup); - return NULL; - } - - if (findInList(directory->subDirectories, key, &subDirectory)) { - free(dup); - return (Directory *) subDirectory; - } - - free(dup); - return NULL; -} - -int isRootDirectory(char *name) -{ - if (name == NULL || name[0] == '\0' || strcmp(name, "/") == 0) { - return 1; - } - return 0; -} - -static Directory *getSubDirectory(Directory * directory, char *name, - char **shortname) -{ - Directory *subDirectory; - int len; - - if (isRootDirectory(name)) { - return directory; - } - - if ((subDirectory = findSubDirectory(directory, name)) == NULL) - return NULL; - - *shortname = name; - - len = 0; - while (name[len] != '/' && name[len] != '\0') - len++; - while (name[len] == '/') - len++; - - return getSubDirectory(subDirectory, &(name[len]), shortname); -} - -static Directory *getDirectoryDetails(char *name, char **shortname) -{ - *shortname = NULL; - - return getSubDirectory(mp3rootDirectory, name, shortname); -} - -static Directory *getDirectory(char *name) -{ - char *shortname; - - return getSubDirectory(mp3rootDirectory, name, &shortname); -} - -static int printDirectoryList(int fd, DirectoryList * directoryList) -{ - ListNode *node = directoryList->firstNode; - Directory *directory; - - while (node != NULL) { - directory = (Directory *) node->data; - fdprintf(fd, "%s%s\n", DIRECTORY_DIR, - getDirectoryPath(directory)); - node = node->nextNode; - } - - return 0; -} - -int printDirectoryInfo(int fd, char *name) -{ - Directory *directory; - - if ((directory = getDirectory(name)) == NULL) { - commandError(fd, ACK_ERROR_NO_EXIST, "directory not found"); - return -1; - } - - printDirectoryList(fd, directory->subDirectories); - printSongInfoFromList(fd, directory->songs); - - return 0; -} - -static void writeDirectoryInfo(FILE * fp, Directory * directory) -{ - ListNode *node = (directory->subDirectories)->firstNode; - Directory *subDirectory; - - if (directory->path) { - fprintf(fp, "%s%s\n", DIRECTORY_BEGIN, - getDirectoryPath(directory)); - } - - while (node != NULL) { - subDirectory = (Directory *) node->data; - fprintf(fp, "%s%s\n", DIRECTORY_DIR, node->key); - writeDirectoryInfo(fp, subDirectory); - node = node->nextNode; - } - - writeSongInfoFromList(fp, directory->songs); - - if (directory->path) { - fprintf(fp, "%s%s\n", DIRECTORY_END, - getDirectoryPath(directory)); - } -} - -static void readDirectoryInfo(FILE * fp, Directory * directory) -{ - char buffer[MAXPATHLEN * 2]; - int bufferSize = MAXPATHLEN * 2; - char *key; - Directory *subDirectory; - int strcmpRet; - char *name; - ListNode *nextDirNode = directory->subDirectories->firstNode; - ListNode *nodeTemp; - - while (myFgets(buffer, bufferSize, fp) - && 0 != strncmp(DIRECTORY_END, buffer, strlen(DIRECTORY_END))) { - if (0 == strncmp(DIRECTORY_DIR, buffer, strlen(DIRECTORY_DIR))) { - key = xstrdup(&(buffer[strlen(DIRECTORY_DIR)])); - if (!myFgets(buffer, bufferSize, fp)) - FATAL("Error reading db, fgets\n"); - /* for compatibility with db's prior to 0.11 */ - if (0 == strncmp(DIRECTORY_MTIME, buffer, - strlen(DIRECTORY_MTIME))) { - if (!myFgets(buffer, bufferSize, fp)) - FATAL("Error reading db, fgets\n"); - } - if (strncmp - (DIRECTORY_BEGIN, buffer, - strlen(DIRECTORY_BEGIN))) { - FATAL("Error reading db at line: %s\n", buffer); - } - name = xstrdup(&(buffer[strlen(DIRECTORY_BEGIN)])); - - while (nextDirNode && (strcmpRet = - strcmp(key, - nextDirNode->key)) > 0) { - nodeTemp = nextDirNode->nextNode; - deleteNodeFromList(directory->subDirectories, - nextDirNode); - nextDirNode = nodeTemp; - } - - if (NULL == nextDirNode) { - subDirectory = newDirectory(name, directory); - insertInList(directory->subDirectories, - key, (void *)subDirectory); - } else if (strcmpRet == 0) { - subDirectory = (Directory *) nextDirNode->data; - nextDirNode = nextDirNode->nextNode; - } else { - subDirectory = newDirectory(name, directory); - insertInListBeforeNode(directory-> - subDirectories, - nextDirNode, -1, key, - (void *)subDirectory); - } - - free(name); - free(key); - readDirectoryInfo(fp, subDirectory); - } else if (0 == strncmp(SONG_BEGIN, buffer, strlen(SONG_BEGIN))) { - readSongInfoIntoList(fp, directory->songs, directory); - } else { - FATAL("Unknown line in db: %s\n", buffer); - } - } - - while (nextDirNode) { - nodeTemp = nextDirNode->nextNode; - deleteNodeFromList(directory->subDirectories, nextDirNode); - nextDirNode = nodeTemp; - } -} - -static void sortDirectory(Directory * directory) -{ - ListNode *node = directory->subDirectories->firstNode; - Directory *subDir; - - sortList(directory->subDirectories); - sortList(directory->songs); - - while (node != NULL) { - subDir = (Directory *) node->data; - sortDirectory(subDir); - node = node->nextNode; - } -} - -int checkDirectoryDB(void) -{ - struct stat st; - char *dbFile; - char *dirPath; - char *dbPath; - - dbFile = getDbFile(); - - /* Check if the file exists */ - if (access(dbFile, F_OK)) { - /* If the file doesn't exist, we can't check if we can write - * it, so we are going to try to get the directory path, and - * see if we can write a file in that */ - dbPath = xstrdup(dbFile); - dirPath = dirname(dbPath); - - /* Check that the parent part of the path is a directory */ - if (stat(dirPath, &st) < 0) { - ERROR("Couldn't stat parent directory of db file " - "\"%s\": %s\n", dbFile, strerror(errno)); - free(dbPath); - return -1; - } - - if (!S_ISDIR(st.st_mode)) { - ERROR("Couldn't create db file \"%s\" because the " - "parent path is not a directory\n", dbFile); - free(dbPath); - return -1; - } - - /* Check if we can write to the directory */ - if (access(dirPath, R_OK | W_OK)) { - ERROR("Can't create db file in \"%s\": %s\n", dirPath, - strerror(errno)); - free(dbPath); - return -1; - - } - - free(dbPath); - return 0; - } - - /* Path exists, now check if it's a regular file */ - if (stat(dbFile, &st) < 0) { - ERROR("Couldn't stat db file \"%s\": %s\n", dbFile, - strerror(errno)); - return -1; - } - - if (!S_ISREG(st.st_mode)) { - ERROR("db file \"%s\" is not a regular file\n", dbFile); - return -1; - } - - /* And check that we can write to it */ - if (access(dbFile, R_OK | W_OK)) { - ERROR("Can't open db file \"%s\" for reading/writing: %s\n", - dbFile, strerror(errno)); - return -1; - } - - return 0; -} - -int writeDirectoryDB(void) -{ - FILE *fp; - char *dbFile = getDbFile(); - struct stat st; - - DEBUG("removing empty directories from DB\n"); - deleteEmptyDirectoriesInDirectory(mp3rootDirectory); - - DEBUG("sorting DB\n"); - - sortDirectory(mp3rootDirectory); - - DEBUG("writing DB\n"); - - while (!(fp = fopen(dbFile, "w")) && errno == EINTR); - if (!fp) { - ERROR("unable to write to db file \"%s\": %s\n", - dbFile, strerror(errno)); - return -1; - } - - /* block signals when writing the db so we don't get a corrupted db */ - fprintf(fp, "%s\n", DIRECTORY_INFO_BEGIN); - fprintf(fp, "%s%s\n", DIRECTORY_MPD_VERSION, VERSION); - fprintf(fp, "%s%s\n", DIRECTORY_FS_CHARSET, getFsCharset()); - fprintf(fp, "%s\n", DIRECTORY_INFO_END); - - writeDirectoryInfo(fp, mp3rootDirectory); - - while (fclose(fp) && errno == EINTR); - - if (stat(dbFile, &st) == 0) - directory_dbModTime = st.st_mtime; - - return 0; -} - -int readDirectoryDB(void) -{ - FILE *fp = NULL; - char *dbFile = getDbFile(); - struct stat st; - - if (!mp3rootDirectory) - mp3rootDirectory = newDirectory(NULL, NULL); - while (!(fp = fopen(dbFile, "r")) && errno == EINTR) ; - if (fp == NULL) { - ERROR("unable to open db file \"%s\": %s\n", - dbFile, strerror(errno)); - return -1; - } - - /* get initial info */ - { - char buffer[100]; - int bufferSize = 100; - int foundFsCharset = 0; - int foundVersion = 0; - - if (!myFgets(buffer, bufferSize, fp)) - FATAL("Error reading db, fgets\n"); - if (0 == strcmp(DIRECTORY_INFO_BEGIN, buffer)) { - while (myFgets(buffer, bufferSize, fp) && - 0 != strcmp(DIRECTORY_INFO_END, buffer)) { - if (0 == strncmp(DIRECTORY_MPD_VERSION, buffer, - strlen(DIRECTORY_MPD_VERSION))) - { - if (foundVersion) - FATAL("already found version in db\n"); - foundVersion = 1; - } else if (0 == - strncmp(DIRECTORY_FS_CHARSET, buffer, - strlen - (DIRECTORY_FS_CHARSET))) { - char *fsCharset; - char *tempCharset; - - if (foundFsCharset) - FATAL("already found fs charset in db\n"); - - foundFsCharset = 1; - - fsCharset = &(buffer[strlen(DIRECTORY_FS_CHARSET)]); - if ((tempCharset = getConfigParamValue(CONF_FS_CHARSET)) - && strcmp(fsCharset, tempCharset)) { - WARNING("Using \"%s\" for the " - "filesystem charset " - "instead of \"%s\"\n", - fsCharset, tempCharset); - WARNING("maybe you need to " - "recreate the db?\n"); - setFsCharset(fsCharset); - } - } else { - FATAL("directory: unknown line in db info: %s\n", - buffer); - } - } - } else { - ERROR("db info not found in db file\n"); - ERROR("you should recreate the db using --create-db\n"); - fseek(fp, 0, SEEK_SET); - return -1; - } - } - - DEBUG("reading DB\n"); - - readDirectoryInfo(fp, mp3rootDirectory); - while (fclose(fp) && errno == EINTR) ; - - stats.numberOfSongs = countSongsIn(STDERR_FILENO, NULL); - stats.dbPlayTime = sumSongTimesIn(STDERR_FILENO, NULL); - - if (stat(dbFile, &st) == 0) - directory_dbModTime = st.st_mtime; - - return 0; -} - -void updateMp3Directory(void) -{ - switch (updateDirectory(mp3rootDirectory)) { - case 0: - /* nothing updated */ - return; - case 1: - if (writeDirectoryDB() < 0) - exit(EXIT_FAILURE); - break; - default: - /* something was updated and db should be written */ - FATAL("problems updating music db\n"); - } - - return; -} - -static int traverseAllInSubDirectory(int fd, Directory * directory, - int (*forEachSong) (int, Song *, - void *), - int (*forEachDir) (int, Directory *, - void *), void *data) -{ - ListNode *node = directory->songs->firstNode; - Song *song; - Directory *dir; - int errFlag = 0; - - if (forEachDir) { - errFlag = forEachDir(fd, directory, data); - if (errFlag) - return errFlag; - } - - if (forEachSong) { - while (node != NULL && !errFlag) { - song = (Song *) node->data; - errFlag = forEachSong(fd, song, data); - node = node->nextNode; - } - if (errFlag) - return errFlag; - } - - node = directory->subDirectories->firstNode; - - while (node != NULL && !errFlag) { - dir = (Directory *) node->data; - errFlag = traverseAllInSubDirectory(fd, dir, forEachSong, - forEachDir, data); - node = node->nextNode; - } - - return errFlag; -} - -int traverseAllIn(int fd, char *name, - int (*forEachSong) (int, Song *, void *), - int (*forEachDir) (int, Directory *, void *), void *data) -{ - Directory *directory; - - if ((directory = getDirectory(name)) == NULL) { - Song *song; - if ((song = getSongFromDB(name)) && forEachSong) { - return forEachSong(fd, song, data); - } - commandError(fd, ACK_ERROR_NO_EXIST, - "directory or file not found"); - return -1; - } - - return traverseAllInSubDirectory(fd, directory, forEachSong, forEachDir, - data); -} - -static void freeAllDirectoryStats(Directory * directory) -{ - ListNode *node = directory->subDirectories->firstNode; - - while (node != NULL) { - freeAllDirectoryStats((Directory *) node->data); - node = node->nextNode; - } - - freeDirectoryStatFromDirectory(directory); -} - -void initMp3Directory(void) -{ - mp3rootDirectory = newDirectory(NULL, NULL); - exploreDirectory(mp3rootDirectory); - freeAllDirectoryStats(mp3rootDirectory); - stats.numberOfSongs = countSongsIn(STDERR_FILENO, NULL); - stats.dbPlayTime = sumSongTimesIn(STDERR_FILENO, NULL); -} - -static Song *getSongDetails(char *file, char **shortnameRet, - Directory ** directoryRet) -{ - void *song = NULL; - Directory *directory; - char *dir = NULL; - char *dup = xstrdup(file); - char *shortname = dup; - char *c = strtok(dup, "/"); - - DEBUG("get song: %s\n", file); - - while (c) { - shortname = c; - c = strtok(NULL, "/"); - } - - if (shortname != dup) { - for (c = dup; c < shortname - 1; c++) { - if (*c == '\0') - *c = '/'; - } - dir = dup; - } - - if (!(directory = getDirectory(dir))) { - free(dup); - return NULL; - } - - if (!findInList(directory->songs, shortname, &song)) { - free(dup); - return NULL; - } - - free(dup); - if (shortnameRet) - *shortnameRet = shortname; - if (directoryRet) - *directoryRet = directory; - return (Song *) song; -} - -Song *getSongFromDB(char *file) -{ - return getSongDetails(file, NULL, NULL); -} - -time_t getDbModTime(void) -{ - return directory_dbModTime; -} diff --git a/trunk/src/directory.h b/trunk/src/directory.h deleted file mode 100644 index b1482988f..000000000 --- a/trunk/src/directory.h +++ /dev/null @@ -1,76 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DIRECTORY_H -#define DIRECTORY_H - -#include "../config.h" - -#include "song.h" -#include "list.h" - -typedef List DirectoryList; - -typedef struct _DirectoryStat { - ino_t inode; - dev_t device; -} DirectoryStat; - -typedef struct _Directory { - char *path; - DirectoryList *subDirectories; - SongList *songs; - struct _Directory *parent; - DirectoryStat *stat; -} Directory; - -void readDirectoryDBIfUpdateIsFinished(void); - -int isUpdatingDB(void); - -void directory_sigChldHandler(int pid, int status); - -int updateInit(int fd, List * pathList); - -void initMp3Directory(void); - -void closeMp3Directory(void); - -int isRootDirectory(char *name); - -int printDirectoryInfo(int fd, char *dirname); - -int checkDirectoryDB(void); - -int writeDirectoryDB(void); - -int readDirectoryDB(void); - -void updateMp3Directory(void); - -Song *getSongFromDB(char *file); - -time_t getDbModTime(void); - -int traverseAllIn(int fd, char *name, - int (*forEachSong) (int, Song *, void *), - int (*forEachDir) (int, Directory *, void *), void *data); - -#define getDirectoryPath(dir) ((dir && dir->path) ? dir->path : "") - -#endif diff --git a/trunk/src/gcc.h b/trunk/src/gcc.h deleted file mode 100644 index 4ae18c46b..000000000 --- a/trunk/src/gcc.h +++ /dev/null @@ -1,67 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MPD_GCC_H -#define MPD_GCC_H - -/* this allows us to take advantage of special gcc features while still - * allowing other compilers to compile: - * - * example taken from: http://rlove.org/log/2005102601 - */ - -#if defined(__GNUC__) && (__GNUC__ >= 3) -# define mpd_const __attribute__ ((const)) -# define mpd_deprecated __attribute__ ((deprecated)) -# define mpd_malloc __attribute__ ((malloc)) -# define mpd_must_check __attribute__ ((warn_unused_result)) -# define mpd_noreturn __attribute__ ((noreturn)) -# define mpd_packed __attribute__ ((packed)) -/* these are very useful for type checking */ -# define mpd_printf __attribute__ ((format(printf,1,2))) -# define mpd_fprintf __attribute__ ((format(printf,2,3))) -# define mpd_fprintf_ __attribute__ ((format(printf,3,4))) -# define mpd_pure __attribute__ ((pure)) -# define mpd_scanf __attribute__ ((format(scanf,1,2))) -# define mpd_unused __attribute__ ((unused)) -# define mpd_used __attribute__ ((used)) -/* # define inline inline __attribute__ ((always_inline)) */ -# define mpd_noinline __attribute__ ((noinline)) -# define mpd_likely(x) __builtin_expect (!!(x), 1) -# define mpd_unlikely(x) __builtin_expect (!!(x), 0) -#else -# define mpd_const -# define mpd_deprecated -# define mpd_malloc -# define mpd_must_check -# define mpd_noreturn -# define mpd_packed -# define mpd_printf -# define mpd_fprintf -# define mpd_fprintf_ -# define mpd_pure -# define mpd_scanf -# define mpd_unused -# define mpd_used -/* # define inline */ -# define mpd_noinline -# define mpd_likely(x) (x) -# define mpd_unlikely(x) (x) -#endif - -#endif /* MPD_GCC_H */ diff --git a/trunk/src/inputPlugin.c b/trunk/src/inputPlugin.c deleted file mode 100644 index 60e60947b..000000000 --- a/trunk/src/inputPlugin.c +++ /dev/null @@ -1,158 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "inputPlugin.h" - -#include "list.h" -#include "myfprintf.h" - -#include <stdlib.h> -#include <string.h> - -static List *inputPlugin_list; - -void loadInputPlugin(InputPlugin * inputPlugin) -{ - if (!inputPlugin) - return; - if (!inputPlugin->name) - return; - - if (inputPlugin->initFunc && inputPlugin->initFunc() < 0) - return; - - insertInList(inputPlugin_list, inputPlugin->name, (void *)inputPlugin); -} - -void unloadInputPlugin(InputPlugin * inputPlugin) -{ - if (inputPlugin->finishFunc) - inputPlugin->finishFunc(); - deleteFromList(inputPlugin_list, inputPlugin->name); -} - -static int stringFoundInStringArray(char **array, char *suffix) -{ - while (array && *array) { - if (strcasecmp(*array, suffix) == 0) - return 1; - array++; - } - - return 0; -} - -InputPlugin *getInputPluginFromSuffix(char *suffix, unsigned int next) -{ - static ListNode *pos; - ListNode *node; - InputPlugin *plugin; - - if (suffix == NULL) - return NULL; - - if (next) { - if (pos) - node = pos; - else - return NULL; - } else - node = inputPlugin_list->firstNode; - - while (node != NULL) { - plugin = node->data; - if (stringFoundInStringArray(plugin->suffixes, suffix)) { - pos = node->nextNode; - return plugin; - } - node = node->nextNode; - } - - return NULL; -} - -InputPlugin *getInputPluginFromMimeType(char *mimeType, unsigned int next) -{ - static ListNode *pos; - ListNode *node; - InputPlugin *plugin; - - if (mimeType == NULL) - return NULL; - - node = (next && pos) ? pos : inputPlugin_list->firstNode; - - while (node != NULL) { - plugin = node->data; - if (stringFoundInStringArray(plugin->mimeTypes, mimeType)) { - pos = node->nextNode; - return plugin; - } - node = node->nextNode; - } - - return NULL; -} - -InputPlugin *getInputPluginFromName(char *name) -{ - void *plugin = NULL; - - findInList(inputPlugin_list, name, &plugin); - - return (InputPlugin *) plugin; -} - -void printAllInputPluginSuffixes(FILE * fp) -{ - ListNode *node = inputPlugin_list->firstNode; - InputPlugin *plugin; - char **suffixes; - - while (node) { - plugin = (InputPlugin *) node->data; - suffixes = plugin->suffixes; - while (suffixes && *suffixes) { - fprintf(fp, "%s ", *suffixes); - suffixes++; - } - node = node->nextNode; - } - fprintf(fp, "\n"); - fflush(fp); -} - -void initInputPlugins(void) -{ - inputPlugin_list = makeList(NULL, 1); - - /* load plugins here */ - loadInputPlugin(&mp3Plugin); - loadInputPlugin(&oggvorbisPlugin); - loadInputPlugin(&oggflacPlugin); - loadInputPlugin(&flacPlugin); - loadInputPlugin(&audiofilePlugin); - loadInputPlugin(&mp4Plugin); - loadInputPlugin(&mpcPlugin); - loadInputPlugin(&modPlugin); -} - -void finishInputPlugins(void) -{ - freeList(inputPlugin_list); -} diff --git a/trunk/src/inputPlugin.h b/trunk/src/inputPlugin.h deleted file mode 100644 index 398ddc1cb..000000000 --- a/trunk/src/inputPlugin.h +++ /dev/null @@ -1,109 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef INPUT_PLUGIN_H -#define INPUT_PLUGIN_H - -#include "../config.h" -#include "inputStream.h" -#include "decode.h" -#include "outputBuffer.h" -#include "tag.h" - -/* valid values for streamTypes in the InputPlugin struct: */ -#define INPUT_PLUGIN_STREAM_FILE 0x01 -#define INPUT_PLUGIN_STREAM_URL 0x02 - -/* 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 */ -typedef int (*InputPlugin_initFunc) (); - -/* optional, set this to NULL if the InputPlugin doesn't have/need one */ -typedef void (*InputPlugin_finishFunc) (); - -/* boolean return value, returns 1 if the InputStream is decodable by - * the InputPlugin, 0 if not */ -typedef unsigned int (*InputPlugin_tryDecodeFunc) (InputStream *); - -/* this will be used to decode InputStreams, and is recommended for files - * and networked (HTTP) connections. - * - * returns -1 on error, 0 on success */ -typedef int (*InputPlugin_streamDecodeFunc) (OutputBuffer *, DecoderControl *, - InputStream *); - -/* use this if and only if your InputPlugin can only be passed a filename or - * handle as input, and will not allow callbacks to be set (like Ogg-Vorbis - * and FLAC libraries allow) - * - * returns -1 on error, 0 on success */ -typedef int (*InputPlugin_fileDecodeFunc) (OutputBuffer *, DecoderControl *, - char *path); - -/* file should be the full path! Returns NULL if a tag cannot be found - * or read */ -typedef MpdTag *(*InputPlugin_tagDupFunc) (char *file); - -typedef struct _InputPlugin { - char *name; - InputPlugin_initFunc initFunc; - InputPlugin_finishFunc finishFunc; - InputPlugin_tryDecodeFunc tryDecodeFunc; - InputPlugin_streamDecodeFunc streamDecodeFunc; - InputPlugin_fileDecodeFunc fileDecodeFunc; - InputPlugin_tagDupFunc tagDupFunc; - - /* one or more of the INPUT_PLUGIN_STREAM_* values OR'd together */ - unsigned char streamTypes; - - /* last element in these arrays must always be a NULL: */ - char **suffixes; - char **mimeTypes; -} InputPlugin; - -/* individual functions to load/unload plugins */ -void loadInputPlugin(InputPlugin * inputPlugin); -void unloadInputPlugin(InputPlugin * inputPlugin); - -/* interface for using plugins */ - -InputPlugin *getInputPluginFromSuffix(char *suffix, unsigned int next); - -InputPlugin *getInputPluginFromMimeType(char *mimeType, unsigned int next); - -InputPlugin *getInputPluginFromName(char *name); - -void printAllInputPluginSuffixes(FILE * fp); - -/* this is where we "load" all the "plugins" ;-) */ -void initInputPlugins(void); - -/* this is where we "unload" all the "plugins" */ -void finishInputPlugins(void); - -extern InputPlugin mp3Plugin; -extern InputPlugin oggvorbisPlugin; -extern InputPlugin flacPlugin; -extern InputPlugin oggflacPlugin; -extern InputPlugin audiofilePlugin; -extern InputPlugin mp4Plugin; -extern InputPlugin mpcPlugin; -extern InputPlugin aacPlugin; -extern InputPlugin modPlugin; - -#endif diff --git a/trunk/src/inputPlugins/_flac_common.c b/trunk/src/inputPlugins/_flac_common.c deleted file mode 100644 index 11126cd1b..000000000 --- a/trunk/src/inputPlugins/_flac_common.c +++ /dev/null @@ -1,211 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * Common data structures and functions used by FLAC and OggFLAC - * (c) 2005 by Eric Wong <normalperson@yhbt.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../inputPlugin.h" - -#if defined(HAVE_FLAC) || defined(HAVE_OGGFLAC) - -#include "_flac_common.h" - -#include "../log.h" -#include "../tag.h" -#include "../inputStream.h" -#include "../outputBuffer.h" -#include "../decode.h" -#include "../replayGain.h" - -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <FLAC/format.h> -#include <FLAC/metadata.h> - -void init_FlacData(FlacData * data, OutputBuffer * cb, - DecoderControl * dc, InputStream * inStream) -{ - data->chunk_length = 0; - data->time = 0; - data->position = 0; - data->bitRate = 0; - data->cb = cb; - data->dc = dc; - data->inStream = inStream; - data->replayGainInfo = NULL; - data->tag = NULL; -} - -static int flacFindVorbisCommentFloat(const FLAC__StreamMetadata * block, - const char *cmnt, float *fl) -{ - int offset = - FLAC__metadata_object_vorbiscomment_find_entry_from(block, 0, cmnt); - - if (offset >= 0) { - size_t pos = strlen(cmnt) + 1; /* 1 is for '=' */ - int len = block->data.vorbis_comment.comments[offset].length - - pos; - if (len > 0) { - unsigned char tmp; - unsigned char *dup = &(block->data.vorbis_comment. - comments[offset].entry[pos]); - tmp = dup[len]; - dup[len] = '\0'; - *fl = atof((char *)dup); - dup[len] = tmp; - - return 1; - } - } - - return 0; -} - -/* replaygain stuff by AliasMrJones */ -static void flacParseReplayGain(const FLAC__StreamMetadata * block, - FlacData * data) -{ - int found = 0; - - if (data->replayGainInfo) - freeReplayGainInfo(data->replayGainInfo); - - data->replayGainInfo = newReplayGainInfo(); - - found |= flacFindVorbisCommentFloat(block, "replaygain_album_gain", - &data->replayGainInfo->albumGain); - found |= flacFindVorbisCommentFloat(block, "replaygain_album_peak", - &data->replayGainInfo->albumPeak); - found |= flacFindVorbisCommentFloat(block, "replaygain_track_gain", - &data->replayGainInfo->trackGain); - found |= flacFindVorbisCommentFloat(block, "replaygain_track_peak", - &data->replayGainInfo->trackPeak); - - if (!found) { - freeReplayGainInfo(data->replayGainInfo); - data->replayGainInfo = NULL; - } -} - -/* tracknumber is used in VCs, MPD uses "track" ..., all the other - * tag names match */ -static const char *VORBIS_COMMENT_TRACK_KEY = "tracknumber"; -static const char *VORBIS_COMMENT_DISC_KEY = "discnumber"; - -static unsigned int commentMatchesAddToTag(const - FLAC__StreamMetadata_VorbisComment_Entry - * entry, unsigned int itemType, - MpdTag ** tag) -{ - const char *str; - size_t slen; - int vlen; - - switch (itemType) { - case TAG_ITEM_TRACK: - str = VORBIS_COMMENT_TRACK_KEY; - break; - case TAG_ITEM_DISC: - str = VORBIS_COMMENT_DISC_KEY; - break; - default: - str = mpdTagItemKeys[itemType]; - } - slen = strlen(str); - vlen = entry->length - slen - 1; - - if ((vlen > 0) && (0 == strncasecmp(str, (char *)entry->entry, slen)) - && (*(entry->entry + slen) == '=')) { - if (!*tag) - *tag = newMpdTag(); - - addItemToMpdTagWithLen(*tag, itemType, - (char *)(entry->entry + slen + 1), vlen); - - return 1; - } - - return 0; -} - -MpdTag *copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block, - MpdTag * tag) -{ - unsigned int i, j; - FLAC__StreamMetadata_VorbisComment_Entry *comments; - - comments = block->data.vorbis_comment.comments; - - for (i = block->data.vorbis_comment.num_comments; i != 0; --i) { - for (j = TAG_NUM_OF_ITEM_TYPES; j--;) { - if (commentMatchesAddToTag(comments, j, &tag)) - break; - } - comments++; - } - - return tag; -} - -void flac_metadata_common_cb(const FLAC__StreamMetadata * block, - FlacData * data) -{ - DecoderControl *dc = data->dc; - const FLAC__StreamMetadata_StreamInfo *si = &(block->data.stream_info); - - switch (block->type) { - case FLAC__METADATA_TYPE_STREAMINFO: - dc->audioFormat.bits = si->bits_per_sample; - dc->audioFormat.sampleRate = si->sample_rate; - dc->audioFormat.channels = si->channels; - dc->totalTime = ((float)si->total_samples) / (si->sample_rate); - getOutputAudioFormat(&(dc->audioFormat), - &(data->cb->audioFormat)); - break; - case FLAC__METADATA_TYPE_VORBIS_COMMENT: - flacParseReplayGain(block, data); - default: - break; - } -} - -void flac_error_common_cb(const char *plugin, - const FLAC__StreamDecoderErrorStatus status, - FlacData * data) -{ - if (data->dc->stop) - return; - - switch (status) { - case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC: - ERROR("%s lost sync\n", plugin); - break; - case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER: - ERROR("bad %s header\n", plugin); - break; - case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH: - ERROR("%s crc mismatch\n", plugin); - break; - default: - ERROR("unknown %s error\n", plugin); - } -} - -#endif /* HAVE_FLAC || HAVE_OGGFLAC */ diff --git a/trunk/src/inputPlugins/_flac_common.h b/trunk/src/inputPlugins/_flac_common.h deleted file mode 100644 index e04e70693..000000000 --- a/trunk/src/inputPlugins/_flac_common.h +++ /dev/null @@ -1,187 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * Common data structures and functions used by FLAC and OggFLAC - * (c) 2005 by Eric Wong <normalperson@yhbt.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _FLAC_COMMON_H -#define _FLAC_COMMON_H - -#include "../inputPlugin.h" - -#if defined(HAVE_FLAC) || defined(HAVE_OGGFLAC) - -#include "../tag.h" -#include "../inputStream.h" -#include "../outputBuffer.h" -#include "../decode.h" -#include <FLAC/export.h> -#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 -# include <FLAC/seekable_stream_decoder.h> -# define flac_decoder FLAC__SeekableStreamDecoder -# define flac_new() FLAC__seekable_stream_decoder_new() - -# define flac_ogg_init(a,b,c,d,e,f,g,h,i,j) (0) - -# define flac_get_decode_position(x,y) \ - FLAC__seekable_stream_decoder_get_decode_position(x,y) -# define flac_get_state(x) FLAC__seekable_stream_decoder_get_state(x) -# define flac_process_single(x) FLAC__seekable_stream_decoder_process_single(x) -# define flac_process_metadata(x) \ - FLAC__seekable_stream_decoder_process_until_end_of_metadata(x) -# define flac_seek_absolute(x,y) \ - FLAC__seekable_stream_decoder_seek_absolute(x,y) -# define flac_finish(x) FLAC__seekable_stream_decoder_finish(x) -# define flac_delete(x) FLAC__seekable_stream_decoder_delete(x) - -# define flac_decoder_eof FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM - -typedef unsigned flac_read_status_size_t; -# define flac_read_status FLAC__SeekableStreamDecoderReadStatus -# define flac_read_status_continue \ - FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK -# define flac_read_status_eof FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK -# define flac_read_status_abort \ - FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR - -# define flac_seek_status FLAC__SeekableStreamDecoderSeekStatus -# define flac_seek_status_ok FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK -# define flac_seek_status_error FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR - -# define flac_tell_status FLAC__SeekableStreamDecoderTellStatus -# define flac_tell_status_ok FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK -# define flac_tell_status_error \ - FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR -# define flac_tell_status_unsupported \ - FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR - -# define flac_length_status FLAC__SeekableStreamDecoderLengthStatus -# define flac_length_status_ok FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK -# define flac_length_status_error \ - FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR -# define flac_length_status_unsupported \ - FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR - -# ifdef HAVE_OGGFLAC -# include <OggFLAC/seekable_stream_decoder.h> -# endif -#else /* FLAC_API_VERSION_CURRENT >= 7 */ - - /* OggFLAC support is handled by our flac_plugin already, and - * thus we *can* always have it if libFLAC was compiled with it */ -# ifndef HAVE_OGGFLAC -# define HAVE_OGGFLAC 1 -# endif -# include "_ogg_common.h" -# undef HAVE_OGGFLAC /* we don't need this defined anymore */ - -# include <FLAC/stream_decoder.h> -# define flac_decoder FLAC__StreamDecoder -# define flac_new() FLAC__stream_decoder_new() - -# define flac_init(a,b,c,d,e,f,g,h,i,j) \ - (FLAC__stream_decoder_init_stream(a,b,c,d,e,f,g,h,i,j) \ - == FLAC__STREAM_DECODER_INIT_STATUS_OK) -# define flac_ogg_init(a,b,c,d,e,f,g,h,i,j) \ - (FLAC__stream_decoder_init_ogg_stream(a,b,c,d,e,f,g,h,i,j) \ - == FLAC__STREAM_DECODER_INIT_STATUS_OK) - -# define flac_get_decode_position(x,y) \ - FLAC__stream_decoder_get_decode_position(x,y) -# define flac_get_state(x) FLAC__stream_decoder_get_state(x) -# define flac_process_single(x) FLAC__stream_decoder_process_single(x) -# define flac_process_metadata(x) \ - FLAC__stream_decoder_process_until_end_of_metadata(x) -# define flac_seek_absolute(x,y) FLAC__stream_decoder_seek_absolute(x,y) -# define flac_finish(x) FLAC__stream_decoder_finish(x) -# define flac_delete(x) FLAC__stream_decoder_delete(x) - -# define flac_decoder_eof FLAC__STREAM_DECODER_END_OF_STREAM - -typedef size_t flac_read_status_size_t; -# define flac_read_status FLAC__StreamDecoderReadStatus -# define flac_read_status_continue \ - FLAC__STREAM_DECODER_READ_STATUS_CONTINUE -# define flac_read_status_eof FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM -# define flac_read_status_abort FLAC__STREAM_DECODER_READ_STATUS_ABORT - -# define flac_seek_status FLAC__StreamDecoderSeekStatus -# define flac_seek_status_ok FLAC__STREAM_DECODER_SEEK_STATUS_OK -# define flac_seek_status_error FLAC__STREAM_DECODER_SEEK_STATUS_ERROR -# define flac_seek_status_unsupported \ - FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED - -# define flac_tell_status FLAC__StreamDecoderTellStatus -# define flac_tell_status_ok FLAC__STREAM_DECODER_TELL_STATUS_OK -# define flac_tell_status_error FLAC__STREAM_DECODER_TELL_STATUS_ERROR -# define flac_tell_status_unsupported \ - FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED - -# define flac_length_status FLAC__StreamDecoderLengthStatus -# define flac_length_status_ok FLAC__STREAM_DECODER_LENGTH_STATUS_OK -# define flac_length_status_error FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR -# define flac_length_status_unsupported \ - FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED - -#endif /* FLAC_API_VERSION_CURRENT >= 7 */ - -#include <FLAC/metadata.h> - -#define FLAC_CHUNK_SIZE 4080 - -typedef struct { - unsigned char chunk[FLAC_CHUNK_SIZE]; - int chunk_length; - float time; - int bitRate; - FLAC__uint64 position; - OutputBuffer *cb; - DecoderControl *dc; - InputStream *inStream; - ReplayGainInfo *replayGainInfo; - MpdTag *tag; -} FlacData; - -/* initializes a given FlacData struct */ -void init_FlacData(FlacData * data, OutputBuffer * cb, - DecoderControl * dc, InputStream * inStream); -void flac_metadata_common_cb(const FLAC__StreamMetadata * block, - FlacData * data); -void flac_error_common_cb(const char *plugin, - FLAC__StreamDecoderErrorStatus status, - FlacData * data); - -MpdTag *copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block, - MpdTag * tag); - -/* keep this inlined, this is just macro but prettier :) */ -static inline int flacSendChunk(FlacData * data) -{ - if (sendDataToOutputBuffer(data->cb, NULL, data->dc, 1, data->chunk, - data->chunk_length, data->time, - data->bitRate, - data->replayGainInfo) == - OUTPUT_BUFFER_DC_STOP) - return -1; - - return 0; -} - -#endif /* HAVE_FLAC || HAVE_OGGFLAC */ - -#endif /* _FLAC_COMMON_H */ diff --git a/trunk/src/inputPlugins/_ogg_common.c b/trunk/src/inputPlugins/_ogg_common.c deleted file mode 100644 index c83e46103..000000000 --- a/trunk/src/inputPlugins/_ogg_common.c +++ /dev/null @@ -1,73 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * Common functions used for Ogg data streams (Ogg-Vorbis and OggFLAC) - * (c) 2005 by Eric Wong <normalperson@yhbt.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../inputPlugin.h" - -#if defined(HAVE_OGGFLAC) || defined(HAVE_OGGVORBIS) - -#include "../utils.h" -#include "_ogg_common.h" - -#include <string.h> - -ogg_stream_type ogg_stream_type_detect(InputStream * inStream) -{ - /* oggflac detection based on code in ogg123 and this post - * http://lists.xiph.org/pipermail/flac/2004-December/000393.html - * ogg123 trunk still doesn't have this patch as of June 2005 */ - unsigned char buf[41]; - size_t r, to_read = 41; - - seekInputStream(inStream, 0, SEEK_SET); - - while (to_read) { - r = readFromInputStream(inStream, buf, 1, to_read); - if (inStream->error) - break; - to_read -= r; - if (!r && !inputStreamAtEOF(inStream)) - my_usleep(10000); - else - break; - } - - seekInputStream(inStream, 0, SEEK_SET); - - if (r >= 32 && memcmp(buf, "OggS", 4) == 0 && ((memcmp - (buf + 29, "FLAC", - 4) == 0 - && memcmp(buf + 37, - "fLaC", - 4) == 0) - || - (memcmp - (buf + 28, "FLAC", - 4) == 0) - || - (memcmp - (buf + 28, "fLaC", - 4) == 0))) { - return FLAC; - } - return VORBIS; -} - -#endif /* defined(HAVE_OGGFLAC || defined(HAVE_OGGVORBIS) */ diff --git a/trunk/src/inputPlugins/_ogg_common.h b/trunk/src/inputPlugins/_ogg_common.h deleted file mode 100644 index 5821e6641..000000000 --- a/trunk/src/inputPlugins/_ogg_common.h +++ /dev/null @@ -1,35 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * Common functions used for Ogg data streams (Ogg-Vorbis and OggFLAC) - * (c) 2005 by Eric Wong <normalperson@yhbt.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _OGG_COMMON_H -#define _OGG_COMMON_H - -#include "../inputPlugin.h" - -#if defined(HAVE_OGGFLAC) || defined(HAVE_OGGVORBIS) - -typedef enum _ogg_stream_type { VORBIS, FLAC } ogg_stream_type; - -ogg_stream_type ogg_stream_type_detect(InputStream * inStream); - -#endif /* defined(HAVE_OGGFLAC || defined(HAVE_OGGVORBIS) */ - -#endif /* _OGG_COMMON_H */ diff --git a/trunk/src/inputPlugins/aac_plugin.c b/trunk/src/inputPlugins/aac_plugin.c deleted file mode 100644 index 529689706..000000000 --- a/trunk/src/inputPlugins/aac_plugin.c +++ /dev/null @@ -1,475 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../inputPlugin.h" - -#ifdef HAVE_FAAD - -#define AAC_MAX_CHANNELS 6 - -#include "../utils.h" -#include "../audio.h" -#include "../log.h" -#include "../inputStream.h" -#include "../outputBuffer.h" - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <faad.h> - -/* all code here is either based on or copied from FAAD2's frontend code */ -typedef struct { - InputStream *inStream; - long bytesIntoBuffer; - long bytesConsumed; - long fileOffset; - unsigned char *buffer; - int atEof; -} AacBuffer; - -static void fillAacBuffer(AacBuffer * b) -{ - if (b->bytesConsumed > 0) { - int bread; - - if (b->bytesIntoBuffer) { - memmove((void *)b->buffer, (void *)(b->buffer + - b->bytesConsumed), - b->bytesIntoBuffer); - } - - if (!b->atEof) { - bread = readFromInputStream(b->inStream, - (void *)(b->buffer + - b-> - bytesIntoBuffer), - 1, b->bytesConsumed); - if (bread != b->bytesConsumed) - b->atEof = 1; - b->bytesIntoBuffer += bread; - } - - b->bytesConsumed = 0; - - if (b->bytesIntoBuffer > 3) { - if (memcmp(b->buffer, "TAG", 3) == 0) - b->bytesIntoBuffer = 0; - } - if (b->bytesIntoBuffer > 11) { - if (memcmp(b->buffer, "LYRICSBEGIN", 11) == 0) { - b->bytesIntoBuffer = 0; - } - } - if (b->bytesIntoBuffer > 8) { - if (memcmp(b->buffer, "APETAGEX", 8) == 0) { - b->bytesIntoBuffer = 0; - } - } - } -} - -static void advanceAacBuffer(AacBuffer * b, int bytes) -{ - b->fileOffset += bytes; - b->bytesConsumed = bytes; - b->bytesIntoBuffer -= bytes; -} - -static int adtsSampleRates[] = - { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, - 16000, 12000, 11025, 8000, 7350, 0, 0, 0 -}; - -static int adtsParse(AacBuffer * b, float *length) -{ - int frames, frameLength; - int tFrameLength = 0; - int sampleRate = 0; - float framesPerSec, bytesPerFrame; - - /* Read all frames to ensure correct time and bitrate */ - for (frames = 0;; frames++) { - fillAacBuffer(b); - - if (b->bytesIntoBuffer > 7) { - /* check syncword */ - if (!((b->buffer[0] == 0xFF) && - ((b->buffer[1] & 0xF6) == 0xF0))) { - break; - } - - if (frames == 0) { - sampleRate = adtsSampleRates[(b-> - buffer[2] & 0x3c) - >> 2]; - } - - frameLength = ((((unsigned int)b->buffer[3] & 0x3)) - << 11) | (((unsigned int)b->buffer[4]) - << 3) | (b->buffer[5] >> 5); - - tFrameLength += frameLength; - - if (frameLength > b->bytesIntoBuffer) - break; - - advanceAacBuffer(b, frameLength); - } else - break; - } - - framesPerSec = (float)sampleRate / 1024.0; - if (frames != 0) { - bytesPerFrame = (float)tFrameLength / (float)(frames * 1000); - } else - bytesPerFrame = 0; - if (framesPerSec != 0) - *length = (float)frames / framesPerSec; - - return 1; -} - -static void initAacBuffer(InputStream * inStream, AacBuffer * b, float *length, - size_t * retFileread, size_t * retTagsize) -{ - size_t fileread; - size_t bread; - size_t tagsize; - - if (length) - *length = -1; - - memset(b, 0, sizeof(AacBuffer)); - - b->inStream = inStream; - - fileread = inStream->size; - - b->buffer = xmalloc(FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS); - memset(b->buffer, 0, FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS); - - bread = readFromInputStream(inStream, b->buffer, 1, - FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS); - b->bytesIntoBuffer = bread; - b->bytesConsumed = 0; - b->fileOffset = 0; - - if (bread != FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS) - b->atEof = 1; - - tagsize = 0; - if (!memcmp(b->buffer, "ID3", 3)) { - tagsize = (b->buffer[6] << 21) | (b->buffer[7] << 14) | - (b->buffer[8] << 7) | (b->buffer[9] << 0); - - tagsize += 10; - advanceAacBuffer(b, tagsize); - fillAacBuffer(b); - } - - if (retFileread) - *retFileread = fileread; - if (retTagsize) - *retTagsize = tagsize; - - if (length == NULL) - return; - - if ((b->buffer[0] == 0xFF) && ((b->buffer[1] & 0xF6) == 0xF0)) { - adtsParse(b, length); - seekInputStream(b->inStream, tagsize, SEEK_SET); - - bread = readFromInputStream(b->inStream, b->buffer, 1, - FAAD_MIN_STREAMSIZE * - AAC_MAX_CHANNELS); - if (bread != FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS) - b->atEof = 1; - else - b->atEof = 0; - b->bytesIntoBuffer = bread; - b->bytesConsumed = 0; - b->fileOffset = tagsize; - } else if (memcmp(b->buffer, "ADIF", 4) == 0) { - int bitRate; - int skipSize = (b->buffer[4] & 0x80) ? 9 : 0; - bitRate = - ((unsigned int)(b-> - buffer[4 + - skipSize] & 0x0F) << 19) | ((unsigned - int)b-> - buffer[5 - + - skipSize] - << 11) | - ((unsigned int)b-> - buffer[6 + skipSize] << 3) | ((unsigned int)b->buffer[7 + - skipSize] - & 0xE0); - - if (fileread != 0 && bitRate != 0) - *length = fileread * 8.0 / bitRate; - else - *length = fileread; - } -} - -static float getAacFloatTotalTime(char *file) -{ - AacBuffer b; - float length; - size_t fileread, tagsize; - faacDecHandle decoder; - faacDecConfigurationPtr config; - unsigned long sampleRate; - unsigned char channels; - InputStream inStream; - long bread; - - if (openInputStream(&inStream, file) < 0) - return -1; - - initAacBuffer(&inStream, &b, &length, &fileread, &tagsize); - - if (length < 0) { - decoder = faacDecOpen(); - - config = faacDecGetCurrentConfiguration(decoder); - config->outputFormat = FAAD_FMT_16BIT; - faacDecSetConfiguration(decoder, config); - - fillAacBuffer(&b); -#ifdef HAVE_FAAD_BUFLEN_FUNCS - bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer, - &sampleRate, &channels); -#else - bread = faacDecInit(decoder, b.buffer, &sampleRate, &channels); -#endif - if (bread >= 0 && sampleRate > 0 && channels > 0) - length = 0; - - faacDecClose(decoder); - } - - if (b.buffer) - free(b.buffer); - closeInputStream(&inStream); - - return length; -} - -static int getAacTotalTime(char *file) -{ - int time = -1; - float length; - - if ((length = getAacFloatTotalTime(file)) >= 0) - time = length + 0.5; - - return time; -} - -static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char *path) -{ - float time; - float totalTime; - faacDecHandle decoder; - faacDecFrameInfo frameInfo; - faacDecConfigurationPtr config; - long bread; - unsigned long sampleRate; - unsigned char channels; - int eof = 0; - unsigned int sampleCount; - char *sampleBuffer; - size_t sampleBufferLen; - /*float * seekTable; - long seekTableEnd = -1; - int seekPositionFound = 0; */ - mpd_uint16 bitRate = 0; - AacBuffer b; - InputStream inStream; - - if ((totalTime = getAacFloatTotalTime(path)) < 0) - return -1; - - if (openInputStream(&inStream, path) < 0) - return -1; - - initAacBuffer(&inStream, &b, NULL, NULL, NULL); - - decoder = faacDecOpen(); - - config = faacDecGetCurrentConfiguration(decoder); - config->outputFormat = FAAD_FMT_16BIT; -#ifdef HAVE_FAACDECCONFIGURATION_DOWNMATRIX - config->downMatrix = 1; -#endif -#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR - config->dontUpSampleImplicitSBR = 0; -#endif - faacDecSetConfiguration(decoder, config); - - fillAacBuffer(&b); - -#ifdef HAVE_FAAD_BUFLEN_FUNCS - bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer, - &sampleRate, &channels); -#else - bread = faacDecInit(decoder, b.buffer, &sampleRate, &channels); -#endif - if (bread < 0) { - ERROR("Error not a AAC stream.\n"); - faacDecClose(decoder); - closeInputStream(b.inStream); - if (b.buffer) - free(b.buffer); - return -1; - } - - dc->audioFormat.bits = 16; - - dc->totalTime = totalTime; - - time = 0.0; - - advanceAacBuffer(&b, bread); - - while (!eof) { - fillAacBuffer(&b); - - if (b.bytesIntoBuffer == 0) { - eof = 1; - break; - } -#ifdef HAVE_FAAD_BUFLEN_FUNCS - sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer, - b.bytesIntoBuffer); -#else - sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer); -#endif - - if (frameInfo.error > 0) { - ERROR("error decoding AAC file: %s\n", path); - ERROR("faad2 error: %s\n", - faacDecGetErrorMessage(frameInfo.error)); - eof = 1; - break; - } -#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE - sampleRate = frameInfo.samplerate; -#endif - - if (dc->state != DECODE_STATE_DECODE) { - dc->audioFormat.channels = frameInfo.channels; - dc->audioFormat.sampleRate = sampleRate; - getOutputAudioFormat(&(dc->audioFormat), - &(cb->audioFormat)); - dc->state = DECODE_STATE_DECODE; - } - - advanceAacBuffer(&b, frameInfo.bytesconsumed); - - sampleCount = (unsigned long)(frameInfo.samples); - - if (sampleCount > 0) { - bitRate = frameInfo.bytesconsumed * 8.0 * - frameInfo.channels * sampleRate / - frameInfo.samples / 1000 + 0.5; - time += - (float)(frameInfo.samples) / frameInfo.channels / - sampleRate; - } - - sampleBufferLen = sampleCount * 2; - - sendDataToOutputBuffer(cb, NULL, dc, 0, sampleBuffer, - sampleBufferLen, time, bitRate, NULL); - if (dc->seek) { - dc->seekError = 1; - dc->seek = 0; - } else if (dc->stop) { - eof = 1; - break; - } - } - - flushOutputBuffer(cb); - - faacDecClose(decoder); - closeInputStream(b.inStream); - if (b.buffer) - free(b.buffer); - - if (dc->state != DECODE_STATE_DECODE) - return -1; - - if (dc->seek) { - dc->seekError = 1; - dc->seek = 0; - } - - if (dc->stop) { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } else - dc->state = DECODE_STATE_STOP; - - return 0; -} - -static MpdTag *aacTagDup(char *file) -{ - MpdTag *ret = NULL; - int time; - - time = getAacTotalTime(file); - - if (time >= 0) { - if ((ret = id3Dup(file)) == NULL) - ret = newMpdTag(); - ret->time = time; - } else { - DEBUG("aacTagDup: Failed to get total song time from: %s\n", - file); - } - - return ret; -} - -static char *aacSuffixes[] = { "aac", NULL }; - -InputPlugin aacPlugin = { - "aac", - NULL, - NULL, - NULL, - NULL, - aac_decode, - aacTagDup, - INPUT_PLUGIN_STREAM_FILE, - aacSuffixes, - NULL -}; - -#else - -InputPlugin aacPlugin; - -#endif /* HAVE_FAAD */ diff --git a/trunk/src/inputPlugins/audiofile_plugin.c b/trunk/src/inputPlugins/audiofile_plugin.c deleted file mode 100644 index 35fb48b8a..000000000 --- a/trunk/src/inputPlugins/audiofile_plugin.c +++ /dev/null @@ -1,188 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * libaudiofile (wave) support added by Eric Wong <normalperson@yhbt.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../inputPlugin.h" - -#ifdef HAVE_AUDIOFILE - -#include "../utils.h" -#include "../audio.h" -#include "../log.h" -#include "../pcm_utils.h" -#include "../playerData.h" - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <audiofile.h> - -static int getAudiofileTotalTime(char *file) -{ - int time; - AFfilehandle af_fp = afOpenFile(file, "r", NULL); - if (af_fp == AF_NULL_FILEHANDLE) { - return -1; - } - time = (int) - ((double)afGetFrameCount(af_fp, AF_DEFAULT_TRACK) - / afGetRate(af_fp, AF_DEFAULT_TRACK)); - afCloseFile(af_fp); - return time; -} - -static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char *path) -{ - int fs, frame_count; - AFfilehandle af_fp; - int bits; - mpd_uint16 bitRate; - struct stat st; - - if (stat(path, &st) < 0) { - ERROR("failed to stat: %s\n", path); - return -1; - } - - af_fp = afOpenFile(path, "r", NULL); - if (af_fp == AF_NULL_FILEHANDLE) { - ERROR("failed to open: %s\n", path); - return -1; - } - - afSetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK, - AF_SAMPFMT_TWOSCOMP, 16); - afGetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits); - dc->audioFormat.bits = bits; - dc->audioFormat.sampleRate = afGetRate(af_fp, AF_DEFAULT_TRACK); - dc->audioFormat.channels = afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK); - getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat)); - - frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK); - - dc->totalTime = - ((float)frame_count / (float)dc->audioFormat.sampleRate); - - bitRate = st.st_size * 8.0 / dc->totalTime / 1000.0 + 0.5; - - if (dc->audioFormat.bits != 8 && dc->audioFormat.bits != 16) { - ERROR("Only 8 and 16-bit files are supported. %s is %i-bit\n", - path, dc->audioFormat.bits); - afCloseFile(af_fp); - return -1; - } - - fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1); - - dc->state = DECODE_STATE_DECODE; - { - int ret, eof = 0, current = 0; - char chunk[CHUNK_SIZE]; - - while (!eof) { - if (dc->seek) { - clearOutputBuffer(cb); - current = dc->seekWhere * - dc->audioFormat.sampleRate; - afSeekFrame(af_fp, AF_DEFAULT_TRACK, current); - dc->seek = 0; - } - - ret = - afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk, - CHUNK_SIZE / fs); - if (ret <= 0) - eof = 1; - else { - current += ret; - sendDataToOutputBuffer(cb, - NULL, - dc, - 1, - chunk, - ret * fs, - (float)current / - (float)dc->audioFormat. - sampleRate, bitRate, - NULL); - if (dc->stop) - break; - } - } - - flushOutputBuffer(cb); - - /*if(dc->seek) { - dc->seekError = 1; - dc->seek = 0; - } */ - - if (dc->stop) { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } else - dc->state = DECODE_STATE_STOP; - } - afCloseFile(af_fp); - - return 0; -} - -static MpdTag *audiofileTagDup(char *file) -{ - MpdTag *ret = NULL; - int time = getAudiofileTotalTime(file); - - if (time >= 0) { - if (!ret) - ret = newMpdTag(); - ret->time = time; - } else { - DEBUG - ("audiofileTagDup: Failed to get total song time from: %s\n", - file); - } - - return ret; -} - -static char *audiofileSuffixes[] = { "wav", "au", "aiff", "aif", NULL }; - -InputPlugin audiofilePlugin = { - "audiofile", - NULL, - NULL, - NULL, - NULL, - audiofile_decode, - audiofileTagDup, - INPUT_PLUGIN_STREAM_FILE, - audiofileSuffixes, - NULL -}; - -#else - -InputPlugin audiofilePlugin; - -#endif /* HAVE_AUDIOFILE */ diff --git a/trunk/src/inputPlugins/flac_plugin.c b/trunk/src/inputPlugins/flac_plugin.c deleted file mode 100644 index 3f3a4b4f1..000000000 --- a/trunk/src/inputPlugins/flac_plugin.c +++ /dev/null @@ -1,530 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "_flac_common.h" - -#ifdef HAVE_FLAC - -#include "../utils.h" -#include "../log.h" -#include "../pcm_utils.h" -#include "../inputStream.h" -#include "../outputBuffer.h" -#include "../replayGain.h" -#include "../audio.h" - -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <assert.h> - -/* this code was based on flac123, from flac-tools */ - -static flac_read_status flacRead(const flac_decoder * flacDec, - FLAC__byte buf[], - flac_read_status_size_t *bytes, - void *fdata) -{ - FlacData *data = (FlacData *) fdata; - size_t r; - - while (1) { - r = readFromInputStream(data->inStream, (void *)buf, 1, *bytes); - if (r == 0 && !inputStreamAtEOF(data->inStream) && - !data->dc->stop) - my_usleep(10000); - else - break; - } - *bytes = r; - - if (r == 0 && !data->dc->stop) { - if (inputStreamAtEOF(data->inStream)) - return flac_read_status_eof; - else - return flac_read_status_abort; - } - return flac_read_status_continue; -} - -static flac_seek_status flacSeek(const flac_decoder * flacDec, - FLAC__uint64 offset, - void *fdata) -{ - FlacData *data = (FlacData *) fdata; - - if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) { - return flac_seek_status_error; - } - - return flac_seek_status_ok; -} - -static flac_tell_status flacTell(const flac_decoder * flacDec, - FLAC__uint64 * offset, - void *fdata) -{ - FlacData *data = (FlacData *) fdata; - - *offset = (long)(data->inStream->offset); - - return flac_tell_status_ok; -} - -static flac_length_status flacLength(const flac_decoder * flacDec, - FLAC__uint64 * length, - void *fdata) -{ - FlacData *data = (FlacData *) fdata; - - *length = (size_t) (data->inStream->size); - - return flac_length_status_ok; -} - -static FLAC__bool flacEOF(const flac_decoder * flacDec, void *fdata) -{ - FlacData *data = (FlacData *) fdata; - - if (inputStreamAtEOF(data->inStream) == 1) - return true; - return false; -} - -static void flacError(const flac_decoder *dec, - FLAC__StreamDecoderErrorStatus status, void *fdata) -{ - flac_error_common_cb("flac", status, (FlacData *) fdata); -} - -#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 -static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state) -{ - const char *str = ""; /* "" to silence compiler warning */ - switch (state) { - case FLAC__SEEKABLE_STREAM_DECODER_OK: - case FLAC__SEEKABLE_STREAM_DECODER_SEEKING: - case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM: - return; - case FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR: - str = "allocation error"; - break; - case FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR: - str = "read error"; - break; - case FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR: - str = "seek error"; - break; - case FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR: - str = "seekable stream error"; - break; - case FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED: - str = "decoder already initialized"; - break; - case FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK: - str = "invalid callback"; - break; - case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED: - str = "decoder uninitialized"; - } - ERROR("flac %s\n", str); -} - -static int flac_init(FLAC__SeekableStreamDecoder *dec, - FLAC__SeekableStreamDecoderReadCallback read_cb, - FLAC__SeekableStreamDecoderSeekCallback seek_cb, - FLAC__SeekableStreamDecoderTellCallback tell_cb, - FLAC__SeekableStreamDecoderLengthCallback length_cb, - FLAC__SeekableStreamDecoderEofCallback eof_cb, - FLAC__SeekableStreamDecoderWriteCallback write_cb, - FLAC__SeekableStreamDecoderMetadataCallback metadata_cb, - FLAC__SeekableStreamDecoderErrorCallback error_cb, - void *data) -{ - int s = 1; - s &= FLAC__seekable_stream_decoder_set_read_callback(dec, read_cb); - s &= FLAC__seekable_stream_decoder_set_seek_callback(dec, seek_cb); - s &= FLAC__seekable_stream_decoder_set_tell_callback(dec, tell_cb); - s &= FLAC__seekable_stream_decoder_set_length_callback(dec, length_cb); - s &= FLAC__seekable_stream_decoder_set_eof_callback(dec, eof_cb); - s &= FLAC__seekable_stream_decoder_set_write_callback(dec, write_cb); - s &= FLAC__seekable_stream_decoder_set_metadata_callback(dec, - metadata_cb); - s &= FLAC__seekable_stream_decoder_set_metadata_respond(dec, - FLAC__METADATA_TYPE_VORBIS_COMMENT); - s &= FLAC__seekable_stream_decoder_set_error_callback(dec, error_cb); - s &= FLAC__seekable_stream_decoder_set_client_data(dec, data); - if (!s || (FLAC__seekable_stream_decoder_init(dec) != - FLAC__SEEKABLE_STREAM_DECODER_OK)) - return 0; - return 1; -} -#else /* FLAC_API_VERSION_CURRENT >= 7 */ -static void flacPrintErroredState(FLAC__StreamDecoderState state) -{ - const char *str = ""; /* "" to silence compiler warning */ - switch (state) { - case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: - case FLAC__STREAM_DECODER_READ_METADATA: - case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: - case FLAC__STREAM_DECODER_READ_FRAME: - case FLAC__STREAM_DECODER_END_OF_STREAM: - return; - case FLAC__STREAM_DECODER_OGG_ERROR: - str = "error in the Ogg layer"; - break; - case FLAC__STREAM_DECODER_SEEK_ERROR: - str = "seek error"; - break; - case FLAC__STREAM_DECODER_ABORTED: - str = "decoder aborted by read"; - break; - case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR: - str = "allocation error"; - break; - case FLAC__STREAM_DECODER_UNINITIALIZED: - str = "decoder uninitialized"; - } - ERROR("flac %s\n", str); -} -#endif /* FLAC_API_VERSION_CURRENT >= 7 */ - -static void flacMetadata(const flac_decoder * dec, - const FLAC__StreamMetadata * block, void *vdata) -{ - flac_metadata_common_cb(block, (FlacData *) vdata); -} - -static FLAC__StreamDecoderWriteStatus flacWrite(const flac_decoder *dec, - const FLAC__Frame * frame, - const FLAC__int32 * const buf[], - void *vdata) -{ - FlacData *data = (FlacData *) vdata; - FLAC__uint32 samples = frame->header.blocksize; - FLAC__uint16 u16; - unsigned char *uc; - int c_samp, c_chan, d_samp; - int i; - float timeChange; - FLAC__uint64 newPosition = 0; - - timeChange = ((float)samples) / frame->header.sample_rate; - data->time += timeChange; - - flac_get_decode_position(dec, &newPosition); - if (data->position) { - data->bitRate = - ((newPosition - data->position) * 8.0 / timeChange) - / 1000 + 0.5; - } - data->position = newPosition; - - for (c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) { - for (c_chan = 0; c_chan < frame->header.channels; - c_chan++, d_samp++) { - u16 = buf[c_chan][c_samp]; - uc = (unsigned char *)&u16; - for (i = 0; i < (data->dc->audioFormat.bits / 8); i++) { - if (data->chunk_length >= FLAC_CHUNK_SIZE) { - if (flacSendChunk(data) < 0) { - return - FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; - } - data->chunk_length = 0; - if (data->dc->seek) { - return - FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; - } - } - data->chunk[data->chunk_length++] = *(uc++); - } - } - } - - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; -} - -static MpdTag *flacMetadataDup(char *file, int *vorbisCommentFound) -{ - MpdTag *ret = NULL; - FLAC__Metadata_SimpleIterator *it; - FLAC__StreamMetadata *block = NULL; - - *vorbisCommentFound = 0; - - it = FLAC__metadata_simple_iterator_new(); - if (!FLAC__metadata_simple_iterator_init(it, file, 1, 0)) { - switch (FLAC__metadata_simple_iterator_status(it)) { - case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT: - DEBUG - ("flacMetadataDup: Reading '%s' metadata gave the following error: Illegal Input\n", - file); - break; - case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE: - DEBUG - ("flacMetadataDup: Reading '%s' metadata gave the following error: Error Opening File\n", - file); - break; - 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); - break; - default: - DEBUG("flacMetadataDup: Reading '%s' metadata failed\n", - file); - } - FLAC__metadata_simple_iterator_delete(it); - return ret; - } - - do { - block = FLAC__metadata_simple_iterator_get_block(it); - if (!block) - break; - if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { - ret = copyVorbisCommentBlockToMpdTag(block, ret); - - if (ret) - *vorbisCommentFound = 1; - } else if (block->type == FLAC__METADATA_TYPE_STREAMINFO) { - if (!ret) - ret = newMpdTag(); - ret->time = ((float)block->data.stream_info. - total_samples) / - block->data.stream_info.sample_rate + 0.5; - } - FLAC__metadata_object_delete(block); - } while (FLAC__metadata_simple_iterator_next(it)); - - FLAC__metadata_simple_iterator_delete(it); - return ret; -} - -static MpdTag *flacTagDup(char *file) -{ - MpdTag *ret = NULL; - int foundVorbisComment = 0; - - ret = flacMetadataDup(file, &foundVorbisComment); - if (!ret) { - DEBUG("flacTagDup: Failed to grab information from: %s\n", - file); - return NULL; - } - if (!foundVorbisComment) { - MpdTag *temp = id3Dup(file); - if (temp) { - temp->time = ret->time; - freeMpdTag(ret); - ret = temp; - } - } - - return ret; -} - -static int flac_decode_internal(OutputBuffer * cb, DecoderControl * dc, - InputStream * inStream, int is_ogg) -{ - flac_decoder *flacDec; - FlacData data; - const char *err = NULL; - - if (!(flacDec = flac_new())) - return -1; - init_FlacData(&data, cb, dc, inStream); - if (is_ogg) { - if (!flac_ogg_init(flacDec, flacRead, flacSeek, flacTell, - flacLength, flacEOF, flacWrite, flacMetadata, - flacError, (void *)&data)) { - err = "doing Ogg init()"; - goto fail; - } - } else { - if (!flac_init(flacDec, flacRead, flacSeek, flacTell, - flacLength, flacEOF, flacWrite, flacMetadata, - flacError, (void *)&data)) { - err = "doing init()"; - goto fail; - } - if (!flac_process_metadata(flacDec)) { - err = "problem reading metadata"; - goto fail; - } - } - - dc->state = DECODE_STATE_DECODE; - - while (1) { - if (!flac_process_single(flacDec)) - break; - if (flac_get_state(flacDec) == flac_decoder_eof) - break; - if (dc->seek) { - FLAC__uint64 sampleToSeek = dc->seekWhere * - dc->audioFormat.sampleRate + 0.5; - if (flac_seek_absolute(flacDec, sampleToSeek)) { - clearOutputBuffer(cb); - data.time = ((float)sampleToSeek) / - dc->audioFormat.sampleRate; - data.position = 0; - } else - dc->seekError = 1; - dc->seek = 0; - } - } - if (!dc->stop) { - flacPrintErroredState(flac_get_state(flacDec)); - flac_finish(flacDec); - } - /* send last little bit */ - if (data.chunk_length > 0 && !dc->stop) { - flacSendChunk(&data); - flushOutputBuffer(data.cb); - } - - /*if(dc->seek) { - dc->seekError = 1; - dc->seek = 0; - } */ - - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - -fail: - if (data.replayGainInfo) - freeReplayGainInfo(data.replayGainInfo); - - if (flacDec) - flac_delete(flacDec); - - closeInputStream(inStream); - - if (err) { - ERROR("flac %s\n", err); - return -1; - } - return 0; -} - -static int flac_decode(OutputBuffer * cb, DecoderControl * dc, - InputStream * inStream) -{ - return flac_decode_internal(cb, dc, inStream, 0); -} - -#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 -# define flac_plugin_init NULL -#else /* FLAC_API_VERSION_CURRENT >= 7 */ -/* some of this stuff is duplicated from oggflac_plugin.c */ -extern InputPlugin oggflacPlugin; - -static MpdTag *oggflac_tag_dup(char *file) -{ - MpdTag *ret = NULL; - FLAC__Metadata_Iterator *it; - FLAC__StreamMetadata *block; - FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new(); - - if (!(FLAC__metadata_chain_read_ogg(chain, file))) - goto out; - it = FLAC__metadata_iterator_new(); - FLAC__metadata_iterator_init(it, chain); - do { - if (!(block = FLAC__metadata_iterator_get_block(it))) - break; - if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { - ret = copyVorbisCommentBlockToMpdTag(block, ret); - } else if (block->type == FLAC__METADATA_TYPE_STREAMINFO) { - if (!ret) - ret = newMpdTag(); - ret->time = ((float)block->data.stream_info. - total_samples) / - block->data.stream_info.sample_rate + 0.5; - } - } while (FLAC__metadata_iterator_next(it)); - FLAC__metadata_iterator_delete(it); -out: - FLAC__metadata_chain_delete(chain); - return ret; -} - -static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc, - InputStream * inStream) -{ - return flac_decode_internal(cb, dc, inStream, 1); -} - -static unsigned int oggflac_try_decode(InputStream * inStream) -{ - return (ogg_stream_type_detect(inStream) == FLAC) ? 1 : 0; -} - -static char *oggflac_suffixes[] = { "ogg", NULL }; -static char *oggflac_mime_types[] = { "audio/x-flac+ogg", - "application/ogg", - "application/x-ogg", - NULL }; - -static int flac_plugin_init(void) -{ - if (!FLAC_API_SUPPORTS_OGG_FLAC) { - DEBUG("libFLAC does not support OggFLAC\n"); - return 1; - } - DEBUG("libFLAC supports OggFLAC, initializing OggFLAC support\n"); - assert(oggflacPlugin.name == NULL); - oggflacPlugin.name = "oggflac"; - oggflacPlugin.tryDecodeFunc = oggflac_try_decode; - oggflacPlugin.streamDecodeFunc = oggflac_decode; - oggflacPlugin.tagDupFunc = oggflac_tag_dup; - oggflacPlugin.streamTypes = INPUT_PLUGIN_STREAM_URL | - INPUT_PLUGIN_STREAM_FILE; - oggflacPlugin.suffixes = oggflac_suffixes; - oggflacPlugin.mimeTypes = oggflac_mime_types; - loadInputPlugin(&oggflacPlugin); - return 1; -} - -#endif /* FLAC_API_VERSION_CURRENT >= 7 */ - -static char *flacSuffixes[] = { "flac", NULL }; -static char *flac_mime_types[] = { "audio/x-flac", - "application/x-flac", - NULL }; - -InputPlugin flacPlugin = { - "flac", - flac_plugin_init, - NULL, - NULL, - flac_decode, - NULL, - flacTagDup, - INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE, - flacSuffixes, - flac_mime_types -}; - -#else /* !HAVE_FLAC */ - -InputPlugin flacPlugin; - -#endif /* HAVE_FLAC */ diff --git a/trunk/src/inputPlugins/mod_plugin.c b/trunk/src/inputPlugins/mod_plugin.c deleted file mode 100644 index 800abc95f..000000000 --- a/trunk/src/inputPlugins/mod_plugin.c +++ /dev/null @@ -1,299 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../inputPlugin.h" - -#ifdef HAVE_MIKMOD - -#include "../utils.h" -#include "../audio.h" -#include "../log.h" -#include "../pcm_utils.h" -#include "../playerData.h" - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <mikmod.h> - -/* this is largely copied from alsaplayer */ - -#define MIKMOD_FRAME_SIZE 4096 - -static BOOL mod_mpd_Init(void) -{ - return VC_Init(); -} - -static void mod_mpd_Exit(void) -{ - VC_Exit(); -} - -static void mod_mpd_Update(void) -{ -} - -static BOOL mod_mpd_IsThere(void) -{ - return 1; -} - -static MDRIVER drv_mpd = { - NULL, - "MPD", - "MPD Output Driver v0.1", - 0, - 255, -#if (LIBMIKMOD_VERSION > 0x030106) - "mpd", /* Alias */ -#if (LIBMIKMOD_VERSION > 0x030200) - NULL, /* CmdLineHelp */ -#endif - NULL, /* CommandLine */ -#endif - mod_mpd_IsThere, - VC_SampleLoad, - VC_SampleUnload, - VC_SampleSpace, - VC_SampleLength, - mod_mpd_Init, - mod_mpd_Exit, - NULL, - VC_SetNumVoices, - VC_PlayStart, - VC_PlayStop, - mod_mpd_Update, - NULL, - VC_VoiceSetVolume, - VC_VoiceGetVolume, - VC_VoiceSetFrequency, - VC_VoiceGetFrequency, - VC_VoiceSetPanning, - VC_VoiceGetPanning, - VC_VoicePlay, - VC_VoiceStop, - VC_VoiceStopped, - VC_VoiceGetPosition, - VC_VoiceRealVolume -}; - -static int mod_mikModInitiated; -static int mod_mikModInitError; - -static int mod_initMikMod(void) -{ - if (mod_mikModInitError) - return -1; - - if (!mod_mikModInitiated) { - mod_mikModInitiated = 1; - - md_device = 0; - md_reverb = 0; - - MikMod_RegisterDriver(&drv_mpd); - MikMod_RegisterAllLoaders(); - } - - md_pansep = 64; - md_mixfreq = 44100; - md_mode = (DMODE_SOFT_MUSIC | DMODE_INTERP | DMODE_STEREO | - DMODE_16BITS); - - if (MikMod_Init("")) { - ERROR("Could not init MikMod: %s\n", - MikMod_strerror(MikMod_errno)); - mod_mikModInitError = 1; - return -1; - } - - return 0; -} - -static void mod_finishMikMod(void) -{ - MikMod_Exit(); -} - -typedef struct _mod_Data { - MODULE *moduleHandle; - SBYTE *audio_buffer; -} mod_Data; - -static mod_Data *mod_open(char *path) -{ - MODULE *moduleHandle; - mod_Data *data; - - if (!(moduleHandle = Player_Load(path, 128, 0))) - return NULL; - - /* Prevent module from looping forever */ - moduleHandle->loop = 0; - - data = xmalloc(sizeof(mod_Data)); - - data->audio_buffer = xmalloc(MIKMOD_FRAME_SIZE); - data->moduleHandle = moduleHandle; - - Player_Start(data->moduleHandle); - - return data; -} - -static void mod_close(mod_Data * data) -{ - Player_Stop(); - Player_Free(data->moduleHandle); - free(data->audio_buffer); - free(data); -} - -static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char *path) -{ - mod_Data *data; - float time = 0.0; - int ret; - float secPerByte; - - if (mod_initMikMod() < 0) - return -1; - - if (!(data = mod_open(path))) { - ERROR("failed to open mod: %s\n", path); - MikMod_Exit(); - return -1; - } - - dc->totalTime = 0; - dc->audioFormat.bits = 16; - dc->audioFormat.sampleRate = 44100; - dc->audioFormat.channels = 2; - getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat)); - - secPerByte = - 1.0 / ((dc->audioFormat.bits * dc->audioFormat.channels / 8.0) * - (float)dc->audioFormat.sampleRate); - - dc->state = DECODE_STATE_DECODE; - while (1) { - if (dc->seek) { - dc->seekError = 1; - dc->seek = 0; - } - - if (dc->stop) - break; - - if (!Player_Active()) - break; - - ret = VC_WriteBytes(data->audio_buffer, MIKMOD_FRAME_SIZE); - time += ret * secPerByte; - sendDataToOutputBuffer(cb, NULL, dc, 0, - (char *)data->audio_buffer, ret, time, - 0, NULL); - } - - flushOutputBuffer(cb); - - mod_close(data); - - MikMod_Exit(); - - if (dc->stop) { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } else - dc->state = DECODE_STATE_STOP; - - return 0; -} - -static MpdTag *modTagDup(char *file) -{ - MpdTag *ret = NULL; - MODULE *moduleHandle; - char *title; - - if (mod_initMikMod() < 0) { - DEBUG("modTagDup: Failed to initialize MikMod\n"); - return NULL; - } - - if (!(moduleHandle = Player_Load(file, 128, 0))) { - DEBUG("modTagDup: Failed to open file: %s\n", file); - MikMod_Exit(); - return NULL; - - } - Player_Free(moduleHandle); - - ret = newMpdTag(); - - ret->time = 0; - title = xstrdup(Player_LoadTitle(file)); - if (title) - addItemToMpdTag(ret, TAG_ITEM_TITLE, title); - - MikMod_Exit(); - - return ret; -} - -static char *modSuffixes[] = { "amf", - "dsm", - "far", - "gdm", - "imf", - "it", - "med", - "mod", - "mtm", - "s3m", - "stm", - "stx", - "ult", - "uni", - "xm", - NULL -}; - -InputPlugin modPlugin = { - "mod", - NULL, - mod_finishMikMod, - NULL, - NULL, - mod_decode, - modTagDup, - INPUT_PLUGIN_STREAM_FILE, - modSuffixes, - NULL -}; - -#else - -InputPlugin modPlugin; - -#endif /* HAVE_MIKMOD */ diff --git a/trunk/src/inputPlugins/mp3_plugin.c b/trunk/src/inputPlugins/mp3_plugin.c deleted file mode 100644 index a920b98a1..000000000 --- a/trunk/src/inputPlugins/mp3_plugin.c +++ /dev/null @@ -1,1092 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../inputPlugin.h" - -#ifdef HAVE_MAD - -#include "../pcm_utils.h" -#include <mad.h> - -#ifdef HAVE_ID3TAG -#include <id3tag.h> -#endif - -#include "../log.h" -#include "../utils.h" -#include "../replayGain.h" -#include "../tag.h" -#include "../conf.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> - -#define FRAMES_CUSHION 2000 - -#define READ_BUFFER_SIZE 40960 - -#define DECODE_SKIP -3 -#define DECODE_BREAK -2 -#define DECODE_CONT -1 -#define DECODE_OK 0 - -#define MUTEFRAME_SKIP 1 -#define MUTEFRAME_SEEK 2 - -/* the number of samples of silence the decoder inserts at start */ -#define DECODERDELAY 529 - -#define DEFAULT_GAPLESS_MP3_PLAYBACK 1 - -static int gaplessPlayback; - -/* this is stolen from mpg321! */ -struct audio_dither { - mad_fixed_t error[3]; - mad_fixed_t random; -}; - -static unsigned long prng(unsigned long state) -{ - return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL; -} - -static signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample, - struct audio_dither *dither) -{ - unsigned int scalebits; - mad_fixed_t output, mask, random; - - enum { - MIN = -MAD_F_ONE, - MAX = MAD_F_ONE - 1 - }; - - sample += dither->error[0] - dither->error[1] + dither->error[2]; - - dither->error[2] = dither->error[1]; - dither->error[1] = dither->error[0] / 2; - - output = sample + (1L << (MAD_F_FRACBITS + 1 - bits - 1)); - - scalebits = MAD_F_FRACBITS + 1 - bits; - mask = (1L << scalebits) - 1; - - random = prng(dither->random); - output += (random & mask) - (dither->random & mask); - - dither->random = random; - - if (output > MAX) { - output = MAX; - - if (sample > MAX) - sample = MAX; - } else if (output < MIN) { - output = MIN; - - if (sample < MIN) - sample = MIN; - } - - output &= ~mask; - - dither->error[0] = sample - output; - - return output >> scalebits; -} - -/* end of stolen stuff from mpg321 */ - -static int mp3_plugin_init(void) -{ - gaplessPlayback = getBoolConfigParam(CONF_GAPLESS_MP3_PLAYBACK); - if (gaplessPlayback == -1) gaplessPlayback = DEFAULT_GAPLESS_MP3_PLAYBACK; - else if (gaplessPlayback < 0) exit(EXIT_FAILURE); - return 1; -} - -/* decoder stuff is based on madlld */ - -#define MP3_DATA_OUTPUT_BUFFER_SIZE 4096 - -typedef struct _mp3DecodeData { - struct mad_stream stream; - struct mad_frame frame; - struct mad_synth synth; - mad_timer_t timer; - unsigned char readBuffer[READ_BUFFER_SIZE]; - char outputBuffer[MP3_DATA_OUTPUT_BUFFER_SIZE]; - char *outputPtr; - char *outputBufferEnd; - float totalTime; - float elapsedTime; - int muteFrame; - long *frameOffset; - mad_timer_t *times; - long highestFrame; - long maxFrames; - long currentFrame; - int dropFramesAtStart; - int dropFramesAtEnd; - int dropSamplesAtStart; - int dropSamplesAtEnd; - int foundXing; - int foundFirstFrame; - int decodedFirstFrame; - int flush; - unsigned long bitRate; - InputStream *inStream; - struct audio_dither dither; - enum mad_layer layer; -} mp3DecodeData; - -static void initMp3DecodeData(mp3DecodeData * data, InputStream * inStream) -{ - data->outputPtr = data->outputBuffer; - data->outputBufferEnd = - data->outputBuffer + MP3_DATA_OUTPUT_BUFFER_SIZE; - data->muteFrame = 0; - data->highestFrame = 0; - data->maxFrames = 0; - data->frameOffset = NULL; - data->times = NULL; - data->currentFrame = 0; - data->dropFramesAtStart = 0; - data->dropFramesAtEnd = 0; - data->dropSamplesAtStart = 0; - data->dropSamplesAtEnd = 0; - data->foundXing = 0; - data->foundFirstFrame = 0; - data->decodedFirstFrame = 0; - data->flush = 1; - data->inStream = inStream; - data->layer = 0; - memset(&(data->dither), 0, sizeof(struct audio_dither)); - - mad_stream_init(&data->stream); - mad_stream_options(&data->stream, MAD_OPTION_IGNORECRC); - mad_frame_init(&data->frame); - mad_synth_init(&data->synth); - mad_timer_reset(&data->timer); -} - -static int seekMp3InputBuffer(mp3DecodeData * data, long offset) -{ - if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) { - return -1; - } - - mad_stream_buffer(&data->stream, data->readBuffer, 0); - (data->stream).error = 0; - - return 0; -} - -static int fillMp3InputBuffer(mp3DecodeData * data) -{ - size_t readSize; - size_t remaining; - size_t readed; - unsigned char *readStart; - - if ((data->stream).next_frame != NULL) { - remaining = (data->stream).bufend - (data->stream).next_frame; - memmove(data->readBuffer, (data->stream).next_frame, remaining); - readStart = (data->readBuffer) + remaining; - readSize = READ_BUFFER_SIZE - remaining; - } else { - readSize = READ_BUFFER_SIZE; - readStart = data->readBuffer, remaining = 0; - } - - /* we've exhausted the read buffer, so give up!, these potential - * mp3 frames are way too big, and thus unlikely to be mp3 frames */ - if (readSize == 0) - return -1; - - readed = readFromInputStream(data->inStream, readStart, (size_t) 1, - readSize); - if (readed <= 0 && inputStreamAtEOF(data->inStream)) - return -1; - /* sleep for a fraction of a second! */ - else if (readed <= 0) { - readed = 0; - my_usleep(10000); - } - - mad_stream_buffer(&data->stream, data->readBuffer, readed + remaining); - (data->stream).error = 0; - - return 0; -} - -#ifdef HAVE_ID3TAG -static ReplayGainInfo *parseId3ReplayGainInfo(struct id3_tag *tag) -{ - int i; - char *key; - char *value; - struct id3_frame *frame; - int found = 0; - ReplayGainInfo *replayGainInfo; - - replayGainInfo = newReplayGainInfo(); - - for (i = 0; (frame = id3_tag_findframe(tag, "TXXX", i)); i++) { - if (frame->nfields < 3) - continue; - - key = (char *) - id3_ucs4_latin1duplicate(id3_field_getstring - (&frame->fields[1])); - value = (char *) - id3_ucs4_latin1duplicate(id3_field_getstring - (&frame->fields[2])); - - if (strcasecmp(key, "replaygain_track_gain") == 0) { - replayGainInfo->trackGain = atof(value); - found = 1; - } else if (strcasecmp(key, "replaygain_album_gain") == 0) { - replayGainInfo->albumGain = atof(value); - found = 1; - } else if (strcasecmp(key, "replaygain_track_peak") == 0) { - replayGainInfo->trackPeak = atof(value); - found = 1; - } else if (strcasecmp(key, "replaygain_album_peak") == 0) { - replayGainInfo->albumPeak = atof(value); - found = 1; - } - - free(key); - free(value); - } - - if (found) - return replayGainInfo; - freeReplayGainInfo(replayGainInfo); - return NULL; -} -#endif - -#ifdef HAVE_ID3TAG -static void mp3_parseId3Tag(mp3DecodeData * data, signed long tagsize, - MpdTag ** mpdTag, ReplayGainInfo ** replayGainInfo) -{ - struct id3_tag *id3Tag = NULL; - id3_length_t count; - id3_byte_t const *id3_data; - id3_byte_t *allocated = NULL; - MpdTag *tmpMpdTag; - ReplayGainInfo *tmpReplayGainInfo; - - count = data->stream.bufend - data->stream.this_frame; - - if (tagsize <= count) { - id3_data = data->stream.this_frame; - mad_stream_skip(&(data->stream), tagsize); - } else { - allocated = xmalloc(tagsize); - if (!allocated) - goto fail; - - memcpy(allocated, data->stream.this_frame, count); - mad_stream_skip(&(data->stream), count); - - while (count < tagsize) { - int len; - - len = readFromInputStream(data->inStream, - allocated + count, (size_t) 1, - tagsize - count); - if (len <= 0 && inputStreamAtEOF(data->inStream)) { - break; - } else if (len <= 0) - my_usleep(10000); - else - count += len; - } - - if (count != tagsize) { - DEBUG("mp3_decode: error parsing ID3 tag\n"); - goto fail; - } - - id3_data = allocated; - } - - id3Tag = id3_tag_parse(id3_data, tagsize); - if (!id3Tag) - goto fail; - - if (mpdTag) { - tmpMpdTag = parseId3Tag(id3Tag); - if (tmpMpdTag) { - if (*mpdTag) - freeMpdTag(*mpdTag); - *mpdTag = tmpMpdTag; - } - } - - if (replayGainInfo) { - tmpReplayGainInfo = parseId3ReplayGainInfo(id3Tag); - if (tmpReplayGainInfo) { - if (*replayGainInfo) - freeReplayGainInfo(*replayGainInfo); - *replayGainInfo = tmpReplayGainInfo; - } - } - - id3_tag_delete(id3Tag); -fail: - if (allocated) - free(allocated); -} -#endif - -static int decodeNextFrameHeader(mp3DecodeData * data, MpdTag ** tag, - ReplayGainInfo ** replayGainInfo) -{ - enum mad_layer layer; - - if ((data->stream).buffer == NULL - || (data->stream).error == MAD_ERROR_BUFLEN) { - if (fillMp3InputBuffer(data) < 0) { - return DECODE_BREAK; - } - } - if (mad_header_decode(&data->frame.header, &data->stream)) { -#ifdef HAVE_ID3TAG - if ((data->stream).error == MAD_ERROR_LOSTSYNC && - (data->stream).this_frame) { - signed long tagsize = id3_tag_query((data->stream). - this_frame, - (data->stream). - bufend - - (data->stream). - this_frame); - - if (tagsize > 0) { - if (tag && !(*tag)) { - mp3_parseId3Tag(data, tagsize, tag, - replayGainInfo); - } else { - mad_stream_skip(&(data->stream), - tagsize); - } - return DECODE_CONT; - } - } -#endif - if (MAD_RECOVERABLE((data->stream).error)) { - return DECODE_SKIP; - } else { - if ((data->stream).error == MAD_ERROR_BUFLEN) - return DECODE_CONT; - else { - ERROR("unrecoverable frame level error " - "(%s).\n", - mad_stream_errorstr(&data->stream)); - data->flush = 0; - return DECODE_BREAK; - } - } - } - - layer = data->frame.header.layer; - if (!data->layer) { - if (layer != MAD_LAYER_II && layer != MAD_LAYER_III) { - /* Only layer 2 and 3 have been tested to work */ - return DECODE_SKIP; - } - data->layer = layer; - } else if (layer != data->layer) { - /* Don't decode frames with a different layer than the first */ - return DECODE_SKIP; - } - - return DECODE_OK; -} - -static int decodeNextFrame(mp3DecodeData * data) -{ - if ((data->stream).buffer == NULL - || (data->stream).error == MAD_ERROR_BUFLEN) { - if (fillMp3InputBuffer(data) < 0) { - return DECODE_BREAK; - } - } - if (mad_frame_decode(&data->frame, &data->stream)) { -#ifdef HAVE_ID3TAG - if ((data->stream).error == MAD_ERROR_LOSTSYNC) { - signed long tagsize = id3_tag_query((data->stream). - this_frame, - (data->stream). - bufend - - (data->stream). - this_frame); - if (tagsize > 0) { - mad_stream_skip(&(data->stream), tagsize); - return DECODE_CONT; - } - } -#endif - if (MAD_RECOVERABLE((data->stream).error)) { - return DECODE_SKIP; - } else { - if ((data->stream).error == MAD_ERROR_BUFLEN) - return DECODE_CONT; - else { - ERROR("unrecoverable frame level error " - "(%s).\n", - mad_stream_errorstr(&data->stream)); - data->flush = 0; - return DECODE_BREAK; - } - } - } - - return DECODE_OK; -} - -/* xing stuff stolen from alsaplayer, and heavily modified by jat */ -#define XI_MAGIC (('X' << 8) | 'i') -#define NG_MAGIC (('n' << 8) | 'g') -#define IN_MAGIC (('I' << 8) | 'n') -#define FO_MAGIC (('f' << 8) | 'o') - -enum xing_magic { - XING_MAGIC_XING, /* VBR */ - XING_MAGIC_INFO /* CBR */ -}; - -struct xing { - long flags; /* valid fields (see below) */ - unsigned long frames; /* total number of frames */ - unsigned long bytes; /* total number of bytes */ - unsigned char toc[100]; /* 100-point seek table */ - long scale; /* VBR quality */ - enum xing_magic magic; /* header magic */ -}; - -enum { - XING_FRAMES = 0x00000001L, - XING_BYTES = 0x00000002L, - XING_TOC = 0x00000004L, - XING_SCALE = 0x00000008L -}; - -struct lame { - char encoder[10]; /* 9 byte encoder name/version ("LAME3.97b") */ -#if 0 - /* See related comment in parse_lame() */ - float peak; /* replaygain peak */ - float trackGain; /* replaygain track gain */ - float albumGain; /* replaygain album gain */ -#endif - int encoderDelay; /* # of added samples at start of mp3 */ - int encoderPadding; /* # of added samples at end of mp3 */ -}; - -static int parse_xing(struct xing *xing, struct mad_bitptr *ptr, int *oldbitlen) -{ - unsigned long bits; - int bitlen; - int bitsleft; - int i; - - bitlen = *oldbitlen; - - if (bitlen < 16) goto fail; - bits = mad_bit_read(ptr, 16); - bitlen -= 16; - - if (bits == XI_MAGIC) { - if (bitlen < 16) goto fail; - if (mad_bit_read(ptr, 16) != NG_MAGIC) goto fail; - bitlen -= 16; - xing->magic = XING_MAGIC_XING; - } else if (bits == IN_MAGIC) { - if (bitlen < 16) goto fail; - if (mad_bit_read(ptr, 16) != FO_MAGIC) goto fail; - bitlen -= 16; - xing->magic = XING_MAGIC_INFO; - } - else if (bits == NG_MAGIC) xing->magic = XING_MAGIC_XING; - else if (bits == FO_MAGIC) xing->magic = XING_MAGIC_INFO; - else goto fail; - - if (bitlen < 32) goto fail; - xing->flags = mad_bit_read(ptr, 32); - bitlen -= 32; - - if (xing->flags & XING_FRAMES) { - if (bitlen < 32) goto fail; - xing->frames = mad_bit_read(ptr, 32); - bitlen -= 32; - } - - if (xing->flags & XING_BYTES) { - if (bitlen < 32) goto fail; - xing->bytes = mad_bit_read(ptr, 32); - bitlen -= 32; - } - - if (xing->flags & XING_TOC) { - if (bitlen < 800) goto fail; - for (i = 0; i < 100; ++i) xing->toc[i] = mad_bit_read(ptr, 8); - bitlen -= 800; - } - - if (xing->flags & XING_SCALE) { - if (bitlen < 32) goto fail; - xing->scale = mad_bit_read(ptr, 32); - bitlen -= 32; - } - - /* Make sure we consume no less than 120 bytes (960 bits) in hopes that - * the LAME tag is found there, and not right after the Xing header */ - bitsleft = 960 - ((*oldbitlen) - bitlen); - if (bitsleft < 0) goto fail; - else if (bitsleft > 0) { - mad_bit_read(ptr, bitsleft); - bitlen -= bitsleft; - } - - *oldbitlen = bitlen; - - return 1; -fail: - xing->flags = 0; - return 0; -} - -static int parse_lame(struct lame *lame, struct mad_bitptr *ptr, int *bitlen) -{ - int i; - - /* Unlike the xing header, the lame tag has a fixed length. Fail if - * not all 36 bytes (288 bits) are there. */ - if (*bitlen < 288) return 0; - - for (i = 0; i < 9; i++) lame->encoder[i] = (char)mad_bit_read(ptr, 8); - lame->encoder[9] = '\0'; - - /* This is technically incorrect, since the encoder might not be lame. - * But there's no other way to determine if this is a lame tag, and we - * wouldn't want to go reading a tag that's not there. */ - if (strncmp(lame->encoder, "LAME", 4) != 0) return 0; - -#if 0 - /* Apparently lame versions <3.97b1 do not calculate replaygain. I'm - * using lame 3.97b2, and while it does calculate replaygain, it's - * setting the values to 0. Using --replaygain-(fast|accurate) doesn't - * make any difference. Leaving this code unused until we have a way - * of testing it. -- jat */ - - mad_bit_read(ptr, 16); - - mad_bit_read(ptr, 32); /* peak */ - - mad_bit_read(ptr, 6); /* header */ - bits = mad_bit_read(ptr, 1); /* sign bit */ - lame->trackGain = mad_bit_read(ptr, 9); /* gain*10 */ - lame->trackGain = (bits ? -lame->trackGain : lame->trackGain) / 10; - - mad_bit_read(ptr, 6); /* header */ - bits = mad_bit_read(ptr, 1); /* sign bit */ - lame->albumGain = mad_bit_read(ptr, 9); /* gain*10 */ - lame->albumGain = (bits ? -lame->albumGain : lame->albumGain) / 10; - - mad_bit_read(ptr, 16); -#else - mad_bit_read(ptr, 96); -#endif - - lame->encoderDelay = mad_bit_read(ptr, 12); - lame->encoderPadding = mad_bit_read(ptr, 12); - - mad_bit_read(ptr, 96); - - *bitlen -= 288; - - return 1; -} - -static int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc, - MpdTag ** tag, ReplayGainInfo ** replayGainInfo) -{ - struct xing xing; - struct lame lame; - struct mad_bitptr ptr; - int bitlen; - int ret; - - /* stfu gcc */ - memset(&xing, 0, sizeof(struct xing)); - xing.flags = 0; - - while (1) { - while ((ret = decodeNextFrameHeader(data, tag, replayGainInfo)) == DECODE_CONT && - (!dc || !dc->stop)); - if (ret == DECODE_BREAK || (dc && dc->stop)) return -1; - if (ret == DECODE_SKIP) continue; - - while ((ret = decodeNextFrame(data)) == DECODE_CONT && - (!dc || !dc->stop)); - if (ret == DECODE_BREAK || (dc && dc->stop)) return -1; - if (ret == DECODE_OK) break; - } - - ptr = data->stream.anc_ptr; - bitlen = data->stream.anc_bitlen; - - /* - * Attempt to calulcate the length of the song from filesize - */ - { - size_t offset = data->inStream->offset; - mad_timer_t duration = data->frame.header.duration; - float frameTime = ((float)mad_timer_count(duration, - MAD_UNITS_MILLISECONDS)) / 1000; - - if (data->stream.this_frame != NULL) - offset -= data->stream.bufend - data->stream.this_frame; - else - offset -= data->stream.bufend - data->stream.buffer; - - if (data->inStream->size >= offset) { - data->totalTime = ((data->inStream->size - offset) * - 8.0) / (data->frame).header.bitrate; - data->maxFrames = data->totalTime / frameTime + - FRAMES_CUSHION; - } else { - data->maxFrames = FRAMES_CUSHION; - data->totalTime = 0; - } - } - /* - * if an xing tag exists, use that! - */ - if (parse_xing(&xing, &ptr, &bitlen)) { - data->foundXing = 1; - data->muteFrame = MUTEFRAME_SKIP; - - if (gaplessPlayback && data->inStream->seekable && - parse_lame(&lame, &ptr, &bitlen)) { - data->dropSamplesAtStart = lame.encoderDelay + DECODERDELAY; - data->dropSamplesAtEnd = lame.encoderPadding; - } - - if ((xing.flags & XING_FRAMES) && xing.frames) { - mad_timer_t duration = data->frame.header.duration; - mad_timer_multiply(&duration, xing.frames); - data->totalTime = ((float)mad_timer_count(duration, MAD_UNITS_MILLISECONDS)) / 1000; - data->maxFrames = xing.frames; - } - } - - if (!data->maxFrames) return -1; - - data->frameOffset = xmalloc(sizeof(long) * data->maxFrames); - data->times = xmalloc(sizeof(mad_timer_t) * data->maxFrames); - - return 0; -} - -static void mp3DecodeDataFinalize(mp3DecodeData * data) -{ - mad_synth_finish(&data->synth); - mad_frame_finish(&data->frame); - mad_stream_finish(&data->stream); - - if (data->frameOffset) free(data->frameOffset); - if (data->times) free(data->times); -} - -/* this is primarily used for getting total time for tags */ -static int getMp3TotalTime(char *file) -{ - InputStream inStream; - mp3DecodeData data; - int ret; - - if (openInputStream(&inStream, file) < 0) - return -1; - initMp3DecodeData(&data, &inStream); - if (decodeFirstFrame(&data, NULL, NULL, NULL) < 0) - ret = -1; - else - ret = data.totalTime + 0.5; - mp3DecodeDataFinalize(&data); - closeInputStream(&inStream); - - return ret; -} - -static int openMp3FromInputStream(InputStream * inStream, mp3DecodeData * data, - DecoderControl * dc, MpdTag ** tag, - ReplayGainInfo ** replayGainInfo) -{ - initMp3DecodeData(data, inStream); - *tag = NULL; - if (decodeFirstFrame(data, dc, tag, replayGainInfo) < 0) { - mp3DecodeDataFinalize(data); - if (tag && *tag) - freeMpdTag(*tag); - return -1; - } - - return 0; -} - -static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc, - ReplayGainInfo ** replayGainInfo) -{ - int samplesPerFrame; - int samplesLeft; - int i; - int ret; - int skip; - - if (data->currentFrame >= data->highestFrame) { - mad_timer_add(&data->timer, (data->frame).header.duration); - data->bitRate = (data->frame).header.bitrate; - if (data->currentFrame >= data->maxFrames) { - data->currentFrame = data->maxFrames - 1; - } else { - data->highestFrame++; - } - data->frameOffset[data->currentFrame] = data->inStream->offset; - if (data->stream.this_frame != NULL) { - data->frameOffset[data->currentFrame] -= - data->stream.bufend - data->stream.this_frame; - } else { - data->frameOffset[data->currentFrame] -= - data->stream.bufend - data->stream.buffer; - } - data->times[data->currentFrame] = data->timer; - } else { - data->timer = data->times[data->currentFrame]; - } - data->currentFrame++; - data->elapsedTime = - ((float)mad_timer_count(data->timer, MAD_UNITS_MILLISECONDS)) / - 1000; - - switch (data->muteFrame) { - case MUTEFRAME_SKIP: - data->muteFrame = 0; - break; - case MUTEFRAME_SEEK: - if (dc->seekWhere <= data->elapsedTime) { - data->outputPtr = data->outputBuffer; - clearOutputBuffer(cb); - data->muteFrame = 0; - dc->seek = 0; - } - break; - default: - mad_synth_frame(&data->synth, &data->frame); - - if (!data->foundFirstFrame) { - samplesPerFrame = (data->synth).pcm.length; - data->dropFramesAtStart = data->dropSamplesAtStart / samplesPerFrame; - data->dropFramesAtEnd = data->dropSamplesAtEnd / samplesPerFrame; - data->dropSamplesAtStart = data->dropSamplesAtStart % samplesPerFrame; - data->dropSamplesAtEnd = data->dropSamplesAtEnd % samplesPerFrame; - data->foundFirstFrame = 1; - } - - if (data->dropFramesAtStart > 0) { - data->dropFramesAtStart--; - break; - } else if ((data->dropFramesAtEnd > 0) && - (data->currentFrame == (data->maxFrames + 1 - data->dropFramesAtEnd))) { - /* stop decoding, effectively dropping all remaining - * frames */ - return DECODE_BREAK; - } - - if (data->inStream->metaTitle) { - MpdTag *tag = newMpdTag(); - if (data->inStream->metaName) { - addItemToMpdTag(tag, - TAG_ITEM_NAME, - data->inStream->metaName); - } - addItemToMpdTag(tag, TAG_ITEM_TITLE, - data->inStream->metaTitle); - free(data->inStream->metaTitle); - data->inStream->metaTitle = NULL; - copyMpdTagToOutputBuffer(cb, tag); - freeMpdTag(tag); - } - - samplesLeft = (data->synth).pcm.length; - - for (i = 0; i < (data->synth).pcm.length; i++) { - mpd_sint16 *sample; - - samplesLeft--; - - if (!data->decodedFirstFrame && - (i < data->dropSamplesAtStart)) { - continue; - } else if (data->dropSamplesAtEnd && - (data->currentFrame == (data->maxFrames - data->dropFramesAtEnd)) && - (samplesLeft < data->dropSamplesAtEnd)) { - /* stop decoding, effectively dropping - * all remaining samples */ - return DECODE_BREAK; - } - - sample = (mpd_sint16 *) data->outputPtr; - *sample = (mpd_sint16) audio_linear_dither(16, - (data->synth).pcm.samples[0][i], - &(data->dither)); - data->outputPtr += 2; - - if (MAD_NCHANNELS(&(data->frame).header) == 2) { - sample = (mpd_sint16 *) data->outputPtr; - *sample = (mpd_sint16) audio_linear_dither(16, - (data->synth).pcm.samples[1][i], - &(data->dither)); - data->outputPtr += 2; - } - - if (data->outputPtr >= data->outputBufferEnd) { - ret = sendDataToOutputBuffer(cb, - data->inStream, - dc, - data->inStream->seekable, - data->outputBuffer, - data->outputPtr - data->outputBuffer, - data->elapsedTime, - data->bitRate / 1000, - (replayGainInfo != NULL) ? *replayGainInfo : NULL); - if (ret == OUTPUT_BUFFER_DC_STOP) { - data->flush = 0; - return DECODE_BREAK; - } - - data->outputPtr = data->outputBuffer; - - if (ret == OUTPUT_BUFFER_DC_SEEK) - break; - } - } - - data->decodedFirstFrame = 1; - - if (dc->seek && data->inStream->seekable) { - long j = 0; - data->muteFrame = MUTEFRAME_SEEK; - while (j < data->highestFrame && dc->seekWhere > - ((float)mad_timer_count(data->times[j], - MAD_UNITS_MILLISECONDS)) - / 1000) { - j++; - } - if (j < data->highestFrame) { - if (seekMp3InputBuffer(data, - data->frameOffset[j]) == - 0) { - data->outputPtr = data->outputBuffer; - clearOutputBuffer(cb); - data->currentFrame = j; - } else - dc->seekError = 1; - data->muteFrame = 0; - dc->seek = 0; - } - } else if (dc->seek && !data->inStream->seekable) { - dc->seek = 0; - dc->seekError = 1; - } - } - - while (1) { - skip = 0; - while ((ret = - decodeNextFrameHeader(data, NULL, - replayGainInfo)) == DECODE_CONT - && !dc->stop) ; - if (ret == DECODE_BREAK || dc->stop || dc->seek) - break; - else if (ret == DECODE_SKIP) - skip = 1; - if (!data->muteFrame) { - while ((ret = decodeNextFrame(data)) == DECODE_CONT && - !dc->stop && !dc->seek) ; - if (ret == DECODE_BREAK || dc->stop || dc->seek) - break; - } - if (!skip && ret == DECODE_OK) - break; - } - - if (dc->stop) - return DECODE_BREAK; - - return ret; -} - -static void initAudioFormatFromMp3DecodeData(mp3DecodeData * data, - AudioFormat * af) -{ - af->bits = 16; - af->sampleRate = (data->frame).header.samplerate; - af->channels = MAD_NCHANNELS(&(data->frame).header); -} - -static int mp3_decode(OutputBuffer * cb, DecoderControl * dc, - InputStream * inStream) -{ - mp3DecodeData data; - MpdTag *tag = NULL; - ReplayGainInfo *replayGainInfo = NULL; - - if (openMp3FromInputStream(inStream, &data, dc, &tag, &replayGainInfo) < - 0) { - closeInputStream(inStream); - if (!dc->stop) { - ERROR - ("Input does not appear to be a mp3 bit stream.\n"); - return -1; - } else { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } - return 0; - } - - initAudioFormatFromMp3DecodeData(&data, &(dc->audioFormat)); - getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat)); - - dc->totalTime = data.totalTime; - - if (inStream->metaTitle) { - if (tag) - freeMpdTag(tag); - tag = newMpdTag(); - addItemToMpdTag(tag, TAG_ITEM_TITLE, inStream->metaTitle); - free(inStream->metaTitle); - inStream->metaTitle = NULL; - if (inStream->metaName) { - addItemToMpdTag(tag, TAG_ITEM_NAME, inStream->metaName); - } - copyMpdTagToOutputBuffer(cb, tag); - freeMpdTag(tag); - } else if (tag) { - if (inStream->metaName) { - clearItemsFromMpdTag(tag, TAG_ITEM_NAME); - addItemToMpdTag(tag, TAG_ITEM_NAME, inStream->metaName); - } - copyMpdTagToOutputBuffer(cb, tag); - freeMpdTag(tag); - } else if (inStream->metaName) { - tag = newMpdTag(); - if (inStream->metaName) { - addItemToMpdTag(tag, TAG_ITEM_NAME, inStream->metaName); - } - copyMpdTagToOutputBuffer(cb, tag); - freeMpdTag(tag); - } - - dc->state = DECODE_STATE_DECODE; - - while (mp3Read(&data, cb, dc, &replayGainInfo) != DECODE_BREAK) ; - /* send last little bit if not dc->stop */ - if (!dc->stop && data.outputPtr != data.outputBuffer && data.flush) { - sendDataToOutputBuffer(cb, NULL, dc, - data.inStream->seekable, - data.outputBuffer, - data.outputPtr - data.outputBuffer, - data.elapsedTime, data.bitRate / 1000, - replayGainInfo); - } - - if (replayGainInfo) - freeReplayGainInfo(replayGainInfo); - - closeInputStream(inStream); - - if (dc->seek && data.muteFrame == MUTEFRAME_SEEK) { - clearOutputBuffer(cb); - dc->seek = 0; - } - - flushOutputBuffer(cb); - mp3DecodeDataFinalize(&data); - - if (dc->stop) { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } else - dc->state = DECODE_STATE_STOP; - - return 0; -} - -static MpdTag *mp3_tagDup(char *file) -{ - MpdTag *ret = NULL; - int time; - - ret = id3Dup(file); - - time = getMp3TotalTime(file); - - if (time >= 0) { - if (!ret) - ret = newMpdTag(); - ret->time = time; - } else { - DEBUG("mp3_tagDup: Failed to get total song time from: %s\n", - file); - } - - return ret; -} - -static char *mp3_suffixes[] = { "mp3", "mp2", NULL }; -static char *mp3_mimeTypes[] = { "audio/mpeg", NULL }; - -InputPlugin mp3Plugin = { - "mp3", - mp3_plugin_init, - NULL, - NULL, - mp3_decode, - NULL, - mp3_tagDup, - INPUT_PLUGIN_STREAM_FILE | INPUT_PLUGIN_STREAM_URL, - mp3_suffixes, - mp3_mimeTypes -}; -#else - -InputPlugin mp3Plugin; - -#endif /* HAVE_MAD */ diff --git a/trunk/src/inputPlugins/mp4_plugin.c b/trunk/src/inputPlugins/mp4_plugin.c deleted file mode 100644 index 1ebf556c6..000000000 --- a/trunk/src/inputPlugins/mp4_plugin.c +++ /dev/null @@ -1,455 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../inputPlugin.h" - -#ifdef HAVE_FAAD - -#include "../utils.h" -#include "../audio.h" -#include "../log.h" -#include "../pcm_utils.h" -#include "../inputStream.h" -#include "../outputBuffer.h" -#include "../decode.h" - -#include "../mp4ff/mp4ff.h" - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <faad.h> - -/* all code here is either based on or copied from FAAD2's frontend code */ - -static int mp4_getAACTrack(mp4ff_t * infile) -{ - /* find AAC track */ - int i, rc; - int numTracks = mp4ff_total_tracks(infile); - - for (i = 0; i < numTracks; i++) { - unsigned char *buff = NULL; - unsigned int buff_size = 0; -#ifdef HAVE_MP4AUDIOSPECIFICCONFIG - mp4AudioSpecificConfig mp4ASC; -#else - unsigned long dummy1_32; - unsigned char dummy2_8, dummy3_8, dummy4_8, dummy5_8, dummy6_8, - dummy7_8, dummy8_8; -#endif - - mp4ff_get_decoder_config(infile, i, &buff, &buff_size); - - if (buff) { -#ifdef HAVE_MP4AUDIOSPECIFICCONFIG - rc = AudioSpecificConfig(buff, buff_size, &mp4ASC); -#else - rc = AudioSpecificConfig(buff, &dummy1_32, &dummy2_8, - &dummy3_8, &dummy4_8, - &dummy5_8, &dummy6_8, - &dummy7_8, &dummy8_8); -#endif - free(buff); - if (rc < 0) - continue; - return i; - } - } - - /* can't decode this */ - return -1; -} - -static uint32_t mp4_inputStreamReadCallback(void *inStream, void *buffer, - uint32_t length) -{ - return readFromInputStream((InputStream *) inStream, buffer, 1, length); -} - -static uint32_t mp4_inputStreamSeekCallback(void *inStream, uint64_t position) -{ - return seekInputStream((InputStream *) inStream, position, SEEK_SET); -} - -static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char *path) -{ - mp4ff_t *mp4fh; - mp4ff_callback_t *mp4cb; - int32_t track; - float time; - int32_t scale; - faacDecHandle decoder; - faacDecFrameInfo frameInfo; - faacDecConfigurationPtr config; - unsigned char *mp4Buffer; - unsigned int mp4BufferSize; - unsigned long sampleRate; - unsigned char channels; - long sampleId; - long numSamples; - int eof = 0; - long dur; - unsigned int sampleCount; - char *sampleBuffer; - size_t sampleBufferLen; - unsigned int initial = 1; - float *seekTable; - long seekTableEnd = -1; - int seekPositionFound = 0; - long offset; - mpd_uint16 bitRate = 0; - InputStream inStream; - int seeking = 0; - - if (openInputStream(&inStream, path) < 0) { - ERROR("failed to open %s\n", path); - return -1; - } - - mp4cb = xmalloc(sizeof(mp4ff_callback_t)); - mp4cb->read = mp4_inputStreamReadCallback; - mp4cb->seek = mp4_inputStreamSeekCallback; - mp4cb->user_data = &inStream; - - mp4fh = mp4ff_open_read(mp4cb); - if (!mp4fh) { - ERROR("Input does not appear to be a mp4 stream.\n"); - free(mp4cb); - closeInputStream(&inStream); - return -1; - } - - track = mp4_getAACTrack(mp4fh); - if (track < 0) { - ERROR("No AAC track found in mp4 stream.\n"); - mp4ff_close(mp4fh); - closeInputStream(&inStream); - free(mp4cb); - return -1; - } - - decoder = faacDecOpen(); - - config = faacDecGetCurrentConfiguration(decoder); - config->outputFormat = FAAD_FMT_16BIT; -#ifdef HAVE_FAACDECCONFIGURATION_DOWNMATRIX - config->downMatrix = 1; -#endif -#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR - config->dontUpSampleImplicitSBR = 0; -#endif - faacDecSetConfiguration(decoder, config); - - dc->audioFormat.bits = 16; - - mp4Buffer = NULL; - mp4BufferSize = 0; - mp4ff_get_decoder_config(mp4fh, track, &mp4Buffer, &mp4BufferSize); - - if (faacDecInit2 - (decoder, mp4Buffer, mp4BufferSize, &sampleRate, &channels) < 0) { - ERROR("Error not a AAC stream.\n"); - faacDecClose(decoder); - mp4ff_close(mp4fh); - free(mp4cb); - closeInputStream(&inStream); - return -1; - } - - dc->audioFormat.sampleRate = sampleRate; - dc->audioFormat.channels = channels; - time = mp4ff_get_track_duration_use_offsets(mp4fh, track); - scale = mp4ff_time_scale(mp4fh, track); - - if (mp4Buffer) - free(mp4Buffer); - - if (scale < 0) { - ERROR("Error getting audio format of mp4 AAC track.\n"); - faacDecClose(decoder); - mp4ff_close(mp4fh); - closeInputStream(&inStream); - free(mp4cb); - return -1; - } - dc->totalTime = ((float)time) / scale; - - numSamples = mp4ff_num_samples(mp4fh, track); - - time = 0.0; - - seekTable = xmalloc(sizeof(float) * numSamples); - - for (sampleId = 0; sampleId < numSamples && !eof; sampleId++) { - if (dc->seek) - seeking = 1; - - if (seeking && seekTableEnd > 1 && - seekTable[seekTableEnd] >= dc->seekWhere) { - int i = 2; - while (seekTable[i] < dc->seekWhere) - i++; - sampleId = i - 1; - time = seekTable[sampleId]; - } - - dur = mp4ff_get_sample_duration(mp4fh, track, sampleId); - offset = mp4ff_get_sample_offset(mp4fh, track, sampleId); - - if (sampleId > seekTableEnd) { - seekTable[sampleId] = time; - seekTableEnd = sampleId; - } - - if (sampleId == 0) - dur = 0; - if (offset > dur) - dur = 0; - else - dur -= offset; - time += ((float)dur) / scale; - - if (seeking && time > dc->seekWhere) - seekPositionFound = 1; - - if (seeking && seekPositionFound) { - seekPositionFound = 0; - clearOutputBuffer(cb); - seeking = 0; - dc->seek = 0; - } - - if (seeking) - continue; - - if (mp4ff_read_sample(mp4fh, track, sampleId, &mp4Buffer, - &mp4BufferSize) == 0) { - eof = 1; - continue; - } -#ifdef HAVE_FAAD_BUFLEN_FUNCS - sampleBuffer = faacDecDecode(decoder, &frameInfo, mp4Buffer, - mp4BufferSize); -#else - sampleBuffer = faacDecDecode(decoder, &frameInfo, mp4Buffer); -#endif - - if (mp4Buffer) - free(mp4Buffer); - if (frameInfo.error > 0) { - ERROR("error decoding MP4 file: %s\n", path); - ERROR("faad2 error: %s\n", - faacDecGetErrorMessage(frameInfo.error)); - eof = 1; - break; - } - - if (dc->state != DECODE_STATE_DECODE) { - channels = frameInfo.channels; -#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE - scale = frameInfo.samplerate; -#endif - dc->audioFormat.sampleRate = scale; - dc->audioFormat.channels = frameInfo.channels; - getOutputAudioFormat(&(dc->audioFormat), - &(cb->audioFormat)); - dc->state = DECODE_STATE_DECODE; - } - - if (channels * (dur + offset) > frameInfo.samples) { - dur = frameInfo.samples / channels; - offset = 0; - } - - sampleCount = (unsigned long)(dur * channels); - - if (sampleCount > 0) { - initial = 0; - bitRate = frameInfo.bytesconsumed * 8.0 * - frameInfo.channels * scale / - frameInfo.samples / 1000 + 0.5; - } - - sampleBufferLen = sampleCount * 2; - - sampleBuffer += offset * channels * 2; - - sendDataToOutputBuffer(cb, NULL, dc, 1, sampleBuffer, - sampleBufferLen, time, bitRate, NULL); - if (dc->stop) { - eof = 1; - break; - } - } - - free(seekTable); - faacDecClose(decoder); - mp4ff_close(mp4fh); - closeInputStream(&inStream); - free(mp4cb); - - if (dc->state != DECODE_STATE_DECODE) - return -1; - - if (dc->seek && seeking) { - clearOutputBuffer(cb); - dc->seek = 0; - } - flushOutputBuffer(cb); - - if (dc->stop) { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } else - dc->state = DECODE_STATE_STOP; - - return 0; -} - -static MpdTag *mp4DataDup(char *file, int *mp4MetadataFound) -{ - MpdTag *ret = NULL; - InputStream inStream; - mp4ff_t *mp4fh; - mp4ff_callback_t *cb; - int32_t track; - int32_t time; - int32_t scale; - int i; - - *mp4MetadataFound = 0; - - if (openInputStream(&inStream, file) < 0) { - DEBUG("mp4DataDup: Failed to open file: %s\n", file); - return NULL; - } - - cb = xmalloc(sizeof(mp4ff_callback_t)); - cb->read = mp4_inputStreamReadCallback; - cb->seek = mp4_inputStreamSeekCallback; - cb->user_data = &inStream; - - mp4fh = mp4ff_open_read(cb); - if (!mp4fh) { - free(cb); - closeInputStream(&inStream); - return NULL; - } - - track = mp4_getAACTrack(mp4fh); - if (track < 0) { - mp4ff_close(mp4fh); - closeInputStream(&inStream); - free(cb); - return NULL; - } - - ret = newMpdTag(); - time = mp4ff_get_track_duration_use_offsets(mp4fh, track); - scale = mp4ff_time_scale(mp4fh, track); - if (scale < 0) { - mp4ff_close(mp4fh); - closeInputStream(&inStream); - free(cb); - freeMpdTag(ret); - return NULL; - } - ret->time = ((float)time) / scale + 0.5; - - for (i = 0; i < mp4ff_meta_get_num_items(mp4fh); i++) { - char *item; - char *value; - - mp4ff_meta_get_by_index(mp4fh, i, &item, &value); - - if (0 == strcasecmp("artist", item)) { - addItemToMpdTag(ret, TAG_ITEM_ARTIST, value); - *mp4MetadataFound = 1; - } else if (0 == strcasecmp("title", item)) { - addItemToMpdTag(ret, TAG_ITEM_TITLE, value); - *mp4MetadataFound = 1; - } else if (0 == strcasecmp("album", item)) { - addItemToMpdTag(ret, TAG_ITEM_ALBUM, value); - *mp4MetadataFound = 1; - } else if (0 == strcasecmp("track", item)) { - addItemToMpdTag(ret, TAG_ITEM_TRACK, value); - *mp4MetadataFound = 1; - } else if (0 == strcasecmp("disc", item)) { /* Is that the correct id? */ - addItemToMpdTag(ret, TAG_ITEM_DISC, value); - *mp4MetadataFound = 1; - } else if (0 == strcasecmp("genre", item)) { - addItemToMpdTag(ret, TAG_ITEM_GENRE, value); - *mp4MetadataFound = 1; - } else if (0 == strcasecmp("date", item)) { - addItemToMpdTag(ret, TAG_ITEM_DATE, value); - *mp4MetadataFound = 1; - } - - free(item); - free(value); - } - - mp4ff_close(mp4fh); - closeInputStream(&inStream); - free(cb); - - return ret; -} - -static MpdTag *mp4TagDup(char *file) -{ - MpdTag *ret = NULL; - int mp4MetadataFound = 0; - - ret = mp4DataDup(file, &mp4MetadataFound); - if (!ret) - return NULL; - if (!mp4MetadataFound) { - MpdTag *temp = id3Dup(file); - if (temp) { - temp->time = ret->time; - freeMpdTag(ret); - ret = temp; - } - } - - return ret; -} - -static char *mp4Suffixes[] = { "m4a", "mp4", NULL }; - -InputPlugin mp4Plugin = { - "mp4", - NULL, - NULL, - NULL, - NULL, - mp4_decode, - mp4TagDup, - INPUT_PLUGIN_STREAM_FILE, - mp4Suffixes, - NULL -}; - -#else - -InputPlugin mp4Plugin; - -#endif /* HAVE_FAAD */ diff --git a/trunk/src/inputPlugins/mpc_plugin.c b/trunk/src/inputPlugins/mpc_plugin.c deleted file mode 100644 index 885f6cfc9..000000000 --- a/trunk/src/inputPlugins/mpc_plugin.c +++ /dev/null @@ -1,359 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../inputPlugin.h" - -#ifdef HAVE_MPCDEC - -#include "../utils.h" -#include "../audio.h" -#include "../log.h" -#include "../pcm_utils.h" -#include "../inputStream.h" -#include "../outputBuffer.h" -#include "../replayGain.h" - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <mpcdec/mpcdec.h> -#include <errno.h> -#include <math.h> - -typedef struct _MpcCallbackData { - InputStream *inStream; - DecoderControl *dc; -} MpcCallbackData; - -static mpc_int32_t mpc_read_cb(void *vdata, void *ptr, mpc_int32_t size) -{ - mpc_int32_t ret = 0; - MpcCallbackData *data = (MpcCallbackData *) vdata; - - while (1) { - ret = readFromInputStream(data->inStream, ptr, 1, size); - if (ret == 0 && !inputStreamAtEOF(data->inStream) && - (data->dc && !data->dc->stop)) { - my_usleep(10000); - } else - break; - } - - return ret; -} - -static mpc_bool_t mpc_seek_cb(void *vdata, mpc_int32_t offset) -{ - MpcCallbackData *data = (MpcCallbackData *) vdata; - - return seekInputStream(data->inStream, offset, SEEK_SET) < 0 ? 0 : 1; -} - -static mpc_int32_t mpc_tell_cb(void *vdata) -{ - MpcCallbackData *data = (MpcCallbackData *) vdata; - - return (long)(data->inStream->offset); -} - -static mpc_bool_t mpc_canseek_cb(void *vdata) -{ - MpcCallbackData *data = (MpcCallbackData *) vdata; - - return data->inStream->seekable; -} - -static mpc_int32_t mpc_getsize_cb(void *vdata) -{ - MpcCallbackData *data = (MpcCallbackData *) vdata; - - return data->inStream->size; -} - -/* this _looks_ performance-critical, don't de-inline -- eric */ -static inline mpd_sint16 convertSample(MPC_SAMPLE_FORMAT sample) -{ - /* only doing 16-bit audio for now */ - mpd_sint32 val; - - const int clip_min = -1 << (16 - 1); - const int clip_max = (1 << (16 - 1)) - 1; - -#ifdef MPC_FIXED_POINT - const int shift = 16 - MPC_FIXED_POINT_SCALE_SHIFT; - - if (sample > 0) { - sample <<= shift; - } else if (shift < 0) { - sample >>= -shift; - } - val = sample; -#else - const int float_scale = 1 << (16 - 1); - - val = sample * float_scale; -#endif - - if (val < clip_min) - val = clip_min; - else if (val > clip_max) - val = clip_max; - - return val; -} - -static int mpc_decode(OutputBuffer * cb, DecoderControl * dc, - InputStream * inStream) -{ - mpc_decoder decoder; - mpc_reader reader; - mpc_streaminfo info; - - MpcCallbackData data; - - MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH]; - - int eof = 0; - long ret; -#define MPC_CHUNK_SIZE 4096 - char chunk[MPC_CHUNK_SIZE]; - int chunkpos = 0; - long bitRate = 0; - mpd_sint16 *s16 = (mpd_sint16 *) chunk; - unsigned long samplePos = 0; - mpc_uint32_t vbrUpdateAcc; - mpc_uint32_t vbrUpdateBits; - float time; - int i; - ReplayGainInfo *replayGainInfo = NULL; - - data.inStream = inStream; - data.dc = dc; - - reader.read = mpc_read_cb; - reader.seek = mpc_seek_cb; - reader.tell = mpc_tell_cb; - reader.get_size = mpc_getsize_cb; - reader.canseek = mpc_canseek_cb; - reader.data = &data; - - mpc_streaminfo_init(&info); - - if ((ret = mpc_streaminfo_read(&info, &reader)) != ERROR_CODE_OK) { - closeInputStream(inStream); - if (!dc->stop) { - ERROR("Not a valid musepack stream"); - return -1; - } else { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } - return 0; - } - - mpc_decoder_setup(&decoder, &reader); - - if (!mpc_decoder_initialize(&decoder, &info)) { - closeInputStream(inStream); - if (!dc->stop) { - ERROR("Not a valid musepack stream"); - } else { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } - } - - dc->totalTime = mpc_streaminfo_get_length(&info); - - dc->audioFormat.bits = 16; - dc->audioFormat.channels = info.channels; - dc->audioFormat.sampleRate = info.sample_freq; - - getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat)); - - replayGainInfo = newReplayGainInfo(); - replayGainInfo->albumGain = info.gain_album * 0.01; - replayGainInfo->albumPeak = info.peak_album / 32767.0; - replayGainInfo->trackGain = info.gain_title * 0.01; - replayGainInfo->trackPeak = info.peak_title / 32767.0; - - dc->state = DECODE_STATE_DECODE; - - while (!eof) { - if (dc->seek) { - samplePos = dc->seekWhere * dc->audioFormat.sampleRate; - if (mpc_decoder_seek_sample(&decoder, samplePos)) { - clearOutputBuffer(cb); - s16 = (mpd_sint16 *) chunk; - chunkpos = 0; - } else - dc->seekError = 1; - dc->seek = 0; - } - - vbrUpdateAcc = 0; - vbrUpdateBits = 0; - ret = mpc_decoder_decode(&decoder, sample_buffer, - &vbrUpdateAcc, &vbrUpdateBits); - - if (ret <= 0 || dc->stop) { - eof = 1; - break; - } - - samplePos += ret; - - /* ret is in samples, and we have stereo */ - ret *= 2; - - for (i = 0; i < ret; i++) { - /* 16 bit audio again */ - *s16 = convertSample(sample_buffer[i]); - chunkpos += 2; - s16++; - - if (chunkpos >= MPC_CHUNK_SIZE) { - time = ((float)samplePos) / - dc->audioFormat.sampleRate; - - bitRate = vbrUpdateBits * - dc->audioFormat.sampleRate / 1152 / 1000; - - sendDataToOutputBuffer(cb, inStream, dc, - inStream->seekable, - chunk, chunkpos, - time, - bitRate, replayGainInfo); - - chunkpos = 0; - s16 = (mpd_sint16 *) chunk; - if (dc->stop) { - eof = 1; - break; - } - } - } - } - - if (!dc->stop && chunkpos > 0) { - time = ((float)samplePos) / dc->audioFormat.sampleRate; - - bitRate = - vbrUpdateBits * dc->audioFormat.sampleRate / 1152 / 1000; - - sendDataToOutputBuffer(cb, NULL, dc, inStream->seekable, - chunk, chunkpos, time, bitRate, - replayGainInfo); - } - - closeInputStream(inStream); - - flushOutputBuffer(cb); - - freeReplayGainInfo(replayGainInfo); - - if (dc->stop) { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } else { - dc->state = DECODE_STATE_STOP; - } - - return 0; -} - -static float mpcGetTime(char *file) -{ - InputStream inStream; - float time = -1; - - mpc_reader reader; - mpc_streaminfo info; - MpcCallbackData data; - - data.inStream = &inStream; - data.dc = NULL; - - reader.read = mpc_read_cb; - reader.seek = mpc_seek_cb; - reader.tell = mpc_tell_cb; - reader.get_size = mpc_getsize_cb; - reader.canseek = mpc_canseek_cb; - reader.data = &data; - - mpc_streaminfo_init(&info); - - if (openInputStream(&inStream, file) < 0) { - DEBUG("mpcGetTime: Failed to open file: %s\n", file); - return -1; - } - - if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) { - closeInputStream(&inStream); - return -1; - } - - time = mpc_streaminfo_get_length(&info); - - closeInputStream(&inStream); - - return time; -} - -static MpdTag *mpcTagDup(char *file) -{ - MpdTag *ret = NULL; - float time = mpcGetTime(file); - - if (time < 0) { - DEBUG("mpcTagDup: Failed to get Songlength of file: %s\n", - file); - return NULL; - } - - ret = apeDup(file); - if (!ret) - ret = id3Dup(file); - if (!ret) - ret = newMpdTag(); - ret->time = time; - - return ret; -} - -static char *mpcSuffixes[] = { "mpc", NULL }; - -InputPlugin mpcPlugin = { - "mpc", - NULL, - NULL, - NULL, - mpc_decode, - NULL, - mpcTagDup, - INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE, - mpcSuffixes, - NULL -}; - -#else - -InputPlugin mpcPlugin; - -#endif /* HAVE_MPCDEC */ diff --git a/trunk/src/inputPlugins/oggflac_plugin.c b/trunk/src/inputPlugins/oggflac_plugin.c deleted file mode 100644 index 58eb0a5f7..000000000 --- a/trunk/src/inputPlugins/oggflac_plugin.c +++ /dev/null @@ -1,423 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * OggFLAC support (half-stolen from flac_plugin.c :)) - * (c) 2005 by Eric Wong <normalperson@yhbt.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "_flac_common.h" - -#ifdef HAVE_OGGFLAC - -#include "_ogg_common.h" - -#include "../utils.h" -#include "../log.h" -#include "../pcm_utils.h" -#include "../inputStream.h" -#include "../outputBuffer.h" -#include "../replayGain.h" -#include "../audio.h" - -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -static void oggflac_cleanup(InputStream * inStream, - FlacData * data, - OggFLAC__SeekableStreamDecoder * decoder) -{ - if (data->replayGainInfo) - freeReplayGainInfo(data->replayGainInfo); - if (decoder) - OggFLAC__seekable_stream_decoder_delete(decoder); - closeInputStream(inStream); -} - -static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb(const - OggFLAC__SeekableStreamDecoder - * decoder, - FLAC__byte buf[], - unsigned *bytes, - void *fdata) -{ - FlacData *data = (FlacData *) fdata; - size_t r; - - while (1) { - r = readFromInputStream(data->inStream, (void *)buf, 1, *bytes); - if (r == 0 && !inputStreamAtEOF(data->inStream) && - !data->dc->stop) - my_usleep(10000); - else - break; - } - *bytes = r; - - if (r == 0 && !inputStreamAtEOF(data->inStream) && !data->dc->stop) - return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; - - return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; -} - -static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb(const - OggFLAC__SeekableStreamDecoder - * decoder, - FLAC__uint64 offset, - void *fdata) -{ - FlacData *data = (FlacData *) fdata; - - if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) { - return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; - } - - return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; -} - -static OggFLAC__SeekableStreamDecoderTellStatus of_tell_cb(const - OggFLAC__SeekableStreamDecoder - * decoder, - FLAC__uint64 * - offset, void *fdata) -{ - FlacData *data = (FlacData *) fdata; - - *offset = (long)(data->inStream->offset); - - return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; -} - -static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(const - OggFLAC__SeekableStreamDecoder - * decoder, - FLAC__uint64 * - length, - void *fdata) -{ - FlacData *data = (FlacData *) fdata; - - *length = (size_t) (data->inStream->size); - - return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; -} - -static FLAC__bool of_EOF_cb(const OggFLAC__SeekableStreamDecoder * decoder, - void *fdata) -{ - FlacData *data = (FlacData *) fdata; - - if (inputStreamAtEOF(data->inStream) == 1) - return true; - return false; -} - -static void of_error_cb(const OggFLAC__SeekableStreamDecoder * decoder, - FLAC__StreamDecoderErrorStatus status, void *fdata) -{ - flac_error_common_cb("oggflac", status, (FlacData *) fdata); -} - -static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state) -{ - switch (state) { - case OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR: - ERROR("oggflac allocation error\n"); - break; - case OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR: - ERROR("oggflac read error\n"); - break; - case OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR: - ERROR("oggflac seek error\n"); - break; - case OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR: - ERROR("oggflac seekable stream error\n"); - break; - case OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED: - ERROR("oggflac decoder already initialized\n"); - break; - case OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK: - ERROR("invalid oggflac callback\n"); - break; - case OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED: - ERROR("oggflac decoder uninitialized\n"); - break; - case OggFLAC__SEEKABLE_STREAM_DECODER_OK: - case OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING: - case OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM: - break; - } -} - -static FLAC__StreamDecoderWriteStatus oggflacWrite(const - OggFLAC__SeekableStreamDecoder - * decoder, - const FLAC__Frame * frame, - const FLAC__int32 * - const buf[], void *vdata) -{ - FlacData *data = (FlacData *) vdata; - FLAC__uint32 samples = frame->header.blocksize; - FLAC__uint16 u16; - unsigned char *uc; - int c_samp, c_chan, d_samp; - int i; - float timeChange; - - timeChange = ((float)samples) / frame->header.sample_rate; - data->time += timeChange; - - /* ogg123 uses a complicated method of calculating bitrate - * with averaging which I'm not too fond of. - * (waste of memory/CPU cycles, especially given this is _lossless_) - * a get_decode_position() is not available in OggFLAC, either - * - * this does not give an accurate bitrate: - * (bytes_last_read was set in the read callback) - data->bitRate = ((8.0 * data->bytes_last_read * - frame->header.sample_rate) - /((float)samples * 1000)) + 0.5; - */ - - for (c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) { - for (c_chan = 0; c_chan < frame->header.channels; - c_chan++, d_samp++) { - u16 = buf[c_chan][c_samp]; - uc = (unsigned char *)&u16; - for (i = 0; i < (data->dc->audioFormat.bits / 8); i++) { - if (data->chunk_length >= FLAC_CHUNK_SIZE) { - if (flacSendChunk(data) < 0) { - return - FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; - } - data->chunk_length = 0; - if (data->dc->seek) { - return - FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; - } - } - data->chunk[data->chunk_length++] = *(uc++); - } - } - } - - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; -} - -/* used by TagDup */ -static void of_metadata_dup_cb(const OggFLAC__SeekableStreamDecoder * decoder, - const FLAC__StreamMetadata * block, void *vdata) -{ - FlacData *data = (FlacData *) vdata; - - switch (block->type) { - case FLAC__METADATA_TYPE_STREAMINFO: - if (!data->tag) - data->tag = newMpdTag(); - data->tag->time = ((float)block->data.stream_info. - total_samples) / - block->data.stream_info.sample_rate + 0.5; - return; - case FLAC__METADATA_TYPE_VORBIS_COMMENT: - copyVorbisCommentBlockToMpdTag(block, data->tag); - default: - break; - } -} - -/* used by decode */ -static void of_metadata_decode_cb(const OggFLAC__SeekableStreamDecoder * dec, - const FLAC__StreamMetadata * block, - void *vdata) -{ - flac_metadata_common_cb(block, (FlacData *) vdata); -} - -static OggFLAC__SeekableStreamDecoder - * full_decoder_init_and_read_metadata(FlacData * data, - unsigned int metadata_only) -{ - OggFLAC__SeekableStreamDecoder *decoder = NULL; - unsigned int s = 1; - - if (!(decoder = OggFLAC__seekable_stream_decoder_new())) - return NULL; - - if (metadata_only) { - s &= OggFLAC__seekable_stream_decoder_set_metadata_callback - (decoder, of_metadata_dup_cb); - s &= OggFLAC__seekable_stream_decoder_set_metadata_respond - (decoder, FLAC__METADATA_TYPE_STREAMINFO); - } else { - s &= OggFLAC__seekable_stream_decoder_set_metadata_callback - (decoder, of_metadata_decode_cb); - } - - s &= OggFLAC__seekable_stream_decoder_set_read_callback(decoder, - of_read_cb); - s &= OggFLAC__seekable_stream_decoder_set_seek_callback(decoder, - of_seek_cb); - s &= OggFLAC__seekable_stream_decoder_set_tell_callback(decoder, - of_tell_cb); - s &= OggFLAC__seekable_stream_decoder_set_length_callback(decoder, - of_length_cb); - s &= OggFLAC__seekable_stream_decoder_set_eof_callback(decoder, - of_EOF_cb); - s &= OggFLAC__seekable_stream_decoder_set_write_callback(decoder, - oggflacWrite); - s &= OggFLAC__seekable_stream_decoder_set_metadata_respond(decoder, - FLAC__METADATA_TYPE_VORBIS_COMMENT); - s &= OggFLAC__seekable_stream_decoder_set_error_callback(decoder, - of_error_cb); - s &= OggFLAC__seekable_stream_decoder_set_client_data(decoder, - (void *)data); - - if (!s) { - ERROR("oggflac problem before init()\n"); - goto fail; - } - if (OggFLAC__seekable_stream_decoder_init(decoder) != - OggFLAC__SEEKABLE_STREAM_DECODER_OK) { - ERROR("oggflac problem doing init()\n"); - goto fail; - } - if (!OggFLAC__seekable_stream_decoder_process_until_end_of_metadata - (decoder)) { - ERROR("oggflac problem reading metadata\n"); - goto fail; - } - - return decoder; - -fail: - oggflacPrintErroredState(OggFLAC__seekable_stream_decoder_get_state - (decoder)); - OggFLAC__seekable_stream_decoder_delete(decoder); - return NULL; -} - -/* public functions: */ -static MpdTag *oggflac_TagDup(char *file) -{ - InputStream inStream; - OggFLAC__SeekableStreamDecoder *decoder; - FlacData data; - - if (openInputStream(&inStream, file) < 0) - return NULL; - if (ogg_stream_type_detect(&inStream) != FLAC) { - closeInputStream(&inStream); - return NULL; - } - - init_FlacData(&data, NULL, NULL, &inStream); - - /* errors here won't matter, - * data.tag will be set or unset, that's all we care about */ - decoder = full_decoder_init_and_read_metadata(&data, 1); - - oggflac_cleanup(&inStream, &data, decoder); - - return data.tag; -} - -static unsigned int oggflac_try_decode(InputStream * inStream) -{ - return (ogg_stream_type_detect(inStream) == FLAC) ? 1 : 0; -} - -static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc, - InputStream * inStream) -{ - OggFLAC__SeekableStreamDecoder *decoder = NULL; - FlacData data; - int ret = 0; - - init_FlacData(&data, cb, dc, inStream); - - if (!(decoder = full_decoder_init_and_read_metadata(&data, 0))) { - ret = -1; - goto fail; - } - - dc->state = DECODE_STATE_DECODE; - - while (1) { - OggFLAC__seekable_stream_decoder_process_single(decoder); - if (OggFLAC__seekable_stream_decoder_get_state(decoder) != - OggFLAC__SEEKABLE_STREAM_DECODER_OK) { - break; - } - if (dc->seek) { - FLAC__uint64 sampleToSeek = dc->seekWhere * - dc->audioFormat.sampleRate + 0.5; - if (OggFLAC__seekable_stream_decoder_seek_absolute - (decoder, sampleToSeek)) { - clearOutputBuffer(cb); - data.time = ((float)sampleToSeek) / - dc->audioFormat.sampleRate; - data.position = 0; - } else - dc->seekError = 1; - dc->seek = 0; - } - } - - if (!dc->stop) { - oggflacPrintErroredState - (OggFLAC__seekable_stream_decoder_get_state(decoder)); - OggFLAC__seekable_stream_decoder_finish(decoder); - } - /* send last little bit */ - if (data.chunk_length > 0 && !dc->stop) { - flacSendChunk(&data); - flushOutputBuffer(data.cb); - } - - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - -fail: - oggflac_cleanup(inStream, &data, decoder); - - return ret; -} - -static char *oggflac_Suffixes[] = { "ogg", NULL }; -static char *oggflac_mime_types[] = { "audio/x-flac+ogg", - "application/ogg", - "application/x-ogg", - NULL }; - -InputPlugin oggflacPlugin = { - "oggflac", - NULL, - NULL, - oggflac_try_decode, - oggflac_decode, - NULL, - oggflac_TagDup, - INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE, - oggflac_Suffixes, - oggflac_mime_types -}; - -#else /* !HAVE_FLAC */ - -InputPlugin oggflacPlugin; - -#endif /* HAVE_OGGFLAC */ diff --git a/trunk/src/inputPlugins/oggvorbis_plugin.c b/trunk/src/inputPlugins/oggvorbis_plugin.c deleted file mode 100644 index 4b4b87c8a..000000000 --- a/trunk/src/inputPlugins/oggvorbis_plugin.c +++ /dev/null @@ -1,434 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* TODO 'ogg' should probably be replaced with 'oggvorbis' in all instances */ - -#include "../inputPlugin.h" - -#ifdef HAVE_OGGVORBIS - -#include "_ogg_common.h" - -#include "../utils.h" -#include "../audio.h" -#include "../log.h" -#include "../pcm_utils.h" -#include "../inputStream.h" -#include "../outputBuffer.h" -#include "../replayGain.h" - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> - -#ifndef HAVE_TREMOR -#include <vorbis/vorbisfile.h> -#else -#include <tremor/ivorbisfile.h> -/* Macros to make Tremor's API look like libogg. Tremor always - returns host-byte-order 16-bit signed data, and uses integer - milliseconds where libogg uses double seconds. -*/ -#define ov_read(VF, BUFFER, LENGTH, BIGENDIANP, WORD, SGNED, BITSTREAM) \ - ov_read(VF, BUFFER, LENGTH, BITSTREAM) -#define ov_time_total(VF, I) ((double)ov_time_total(VF, I)/1000) -#define ov_time_tell(VF) ((double)ov_time_tell(VF)/1000) -#define ov_time_seek_page(VF, S) (ov_time_seek_page(VF, (S)*1000)) -#endif /* HAVE_TREMOR */ - -#include <errno.h> - -#ifdef WORDS_BIGENDIAN -#define OGG_DECODE_USE_BIGENDIAN 1 -#else -#define OGG_DECODE_USE_BIGENDIAN 0 -#endif - -typedef struct _OggCallbackData { - InputStream *inStream; - DecoderControl *dc; -} OggCallbackData; - -static size_t ogg_read_cb(void *ptr, size_t size, size_t nmemb, void *vdata) -{ - size_t ret = 0; - OggCallbackData *data = (OggCallbackData *) vdata; - - while (1) { - ret = readFromInputStream(data->inStream, ptr, size, nmemb); - if (ret == 0 && !inputStreamAtEOF(data->inStream) && - !data->dc->stop) { - my_usleep(10000); - } else - break; - } - errno = 0; - /*if(ret<0) errno = ((InputStream *)inStream)->error; */ - - return ret; -} - -static int ogg_seek_cb(void *vdata, ogg_int64_t offset, int whence) -{ - OggCallbackData *data = (OggCallbackData *) vdata; - - return seekInputStream(data->inStream, offset, whence); -} - -static int ogg_close_cb(void *vdata) -{ - OggCallbackData *data = (OggCallbackData *) vdata; - - return closeInputStream(data->inStream); -} - -static long ogg_tell_cb(void *vdata) -{ - OggCallbackData *data = (OggCallbackData *) vdata; - - return (long)(data->inStream->offset); -} - -static char *ogg_parseComment(char *comment, char *needle) -{ - int len = strlen(needle); - - if (strncasecmp(comment, needle, len) == 0 && *(comment + len) == '=') { - return comment + len + 1; - } - - return NULL; -} - -static void ogg_getReplayGainInfo(char **comments, ReplayGainInfo ** infoPtr) -{ - char *temp; - int found = 0; - - if (*infoPtr) - freeReplayGainInfo(*infoPtr); - *infoPtr = newReplayGainInfo(); - - while (*comments) { - if ((temp = - ogg_parseComment(*comments, "replaygain_track_gain"))) { - (*infoPtr)->trackGain = atof(temp); - found = 1; - } else if ((temp = ogg_parseComment(*comments, - "replaygain_album_gain"))) { - (*infoPtr)->albumGain = atof(temp); - found = 1; - } else if ((temp = ogg_parseComment(*comments, - "replaygain_track_peak"))) { - (*infoPtr)->trackPeak = atof(temp); - found = 1; - } else if ((temp = ogg_parseComment(*comments, - "replaygain_album_peak"))) { - (*infoPtr)->albumPeak = atof(temp); - found = 1; - } - - comments++; - } - - if (!found) { - freeReplayGainInfo(*infoPtr); - *infoPtr = NULL; - } -} - -static const char *VORBIS_COMMENT_TRACK_KEY = "tracknumber"; -static const char *VORBIS_COMMENT_DISC_KEY = "discnumber"; - -static unsigned int ogg_parseCommentAddToTag(char *comment, - unsigned int itemType, - MpdTag ** tag) -{ - const char *needle; - unsigned int len; - switch (itemType) { - case TAG_ITEM_TRACK: - needle = VORBIS_COMMENT_TRACK_KEY; - break; - case TAG_ITEM_DISC: - needle = VORBIS_COMMENT_DISC_KEY; - break; - default: - needle = mpdTagItemKeys[itemType]; - } - len = strlen(needle); - - if (strncasecmp(comment, needle, len) == 0 && *(comment + len) == '=') { - if (!*tag) - *tag = newMpdTag(); - - addItemToMpdTag(*tag, itemType, comment + len + 1); - - return 1; - } - - return 0; -} - -static MpdTag *oggCommentsParse(char **comments) -{ - MpdTag *tag = NULL; - - while (*comments) { - int j; - for (j = TAG_NUM_OF_ITEM_TYPES; --j >= 0;) { - if (ogg_parseCommentAddToTag(*comments, j, &tag)) - break; - } - comments++; - } - - return tag; -} - -static void putOggCommentsIntoOutputBuffer(OutputBuffer * cb, char *streamName, - char **comments) -{ - MpdTag *tag; - - tag = oggCommentsParse(comments); - if (!tag && streamName) { - tag = newMpdTag(); - } - if (!tag) - return; - - /*if(tag->artist) printf("Artist: %s\n", tag->artist); - if(tag->album) printf("Album: %s\n", tag->album); - if(tag->track) printf("Track: %s\n", tag->track); - if(tag->title) printf("Title: %s\n", tag->title); */ - - if (streamName) { - clearItemsFromMpdTag(tag, TAG_ITEM_NAME); - addItemToMpdTag(tag, TAG_ITEM_NAME, streamName); - } - - copyMpdTagToOutputBuffer(cb, tag); - - freeMpdTag(tag); -} - -/* public */ -static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc, - InputStream * inStream) -{ - OggVorbis_File vf; - ov_callbacks callbacks; - OggCallbackData data; - int current_section; - int prev_section = -1; - int eof = 0; - long ret; -#define OGG_CHUNK_SIZE 4096 - char chunk[OGG_CHUNK_SIZE]; - int chunkpos = 0; - long bitRate = 0; - long test; - ReplayGainInfo *replayGainInfo = NULL; - char **comments; - char *errorStr; - - data.inStream = inStream; - data.dc = dc; - - callbacks.read_func = ogg_read_cb; - callbacks.seek_func = ogg_seek_cb; - callbacks.close_func = ogg_close_cb; - callbacks.tell_func = ogg_tell_cb; - - if ((ret = ov_open_callbacks(&data, &vf, NULL, 0, callbacks)) < 0) { - closeInputStream(inStream); - if (!dc->stop) { - switch (ret) { - case OV_EREAD: - errorStr = "read error"; - break; - case OV_ENOTVORBIS: - errorStr = "not vorbis stream"; - break; - case OV_EVERSION: - errorStr = "vorbis version mismatch"; - break; - case OV_EBADHEADER: - errorStr = "invalid vorbis header"; - break; - case OV_EFAULT: - errorStr = "internal logic error"; - break; - default: - errorStr = "unknown error"; - break; - } - ERROR("Error decoding Ogg Vorbis stream: %s\n", - errorStr); - return -1; - } else { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } - return 0; - } - - dc->totalTime = ov_time_total(&vf, -1); - if (dc->totalTime < 0) - dc->totalTime = 0; - - dc->audioFormat.bits = 16; - - while (!eof) { - if (dc->seek) { - if (0 == ov_time_seek_page(&vf, dc->seekWhere)) { - clearOutputBuffer(cb); - chunkpos = 0; - } else - dc->seekError = 1; - dc->seek = 0; - } - ret = ov_read(&vf, chunk + chunkpos, - OGG_CHUNK_SIZE - chunkpos, - OGG_DECODE_USE_BIGENDIAN, 2, 1, ¤t_section); - - if (current_section != prev_section) { - /*printf("new song!\n"); */ - vorbis_info *vi = ov_info(&vf, -1); - dc->audioFormat.channels = vi->channels; - dc->audioFormat.sampleRate = vi->rate; - if (dc->state == DECODE_STATE_START) { - getOutputAudioFormat(&(dc->audioFormat), - &(cb->audioFormat)); - dc->state = DECODE_STATE_DECODE; - } - comments = ov_comment(&vf, -1)->user_comments; - putOggCommentsIntoOutputBuffer(cb, inStream->metaName, - comments); - ogg_getReplayGainInfo(comments, &replayGainInfo); - } - - prev_section = current_section; - - if (ret <= 0 && ret != OV_HOLE) { - eof = 1; - break; - } - if (ret == OV_HOLE) - ret = 0; - - chunkpos += ret; - - if (chunkpos >= OGG_CHUNK_SIZE) { - if ((test = ov_bitrate_instant(&vf)) > 0) { - bitRate = test / 1000; - } - sendDataToOutputBuffer(cb, inStream, dc, - inStream->seekable, - chunk, chunkpos, - ov_pcm_tell(&vf) / - dc->audioFormat.sampleRate, - bitRate, replayGainInfo); - chunkpos = 0; - if (dc->stop) - break; - } - } - - if (!dc->stop && chunkpos > 0) { - sendDataToOutputBuffer(cb, NULL, dc, inStream->seekable, - chunk, chunkpos, - ov_time_tell(&vf), bitRate, - replayGainInfo); - } - - if (replayGainInfo) - freeReplayGainInfo(replayGainInfo); - - ov_clear(&vf); - - flushOutputBuffer(cb); - - if (dc->stop) { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } else - dc->state = DECODE_STATE_STOP; - - return 0; -} - -static MpdTag *oggvorbis_TagDup(char *file) -{ - MpdTag *ret = NULL; - FILE *fp; - OggVorbis_File vf; - - fp = fopen(file, "r"); - if (!fp) { - DEBUG("oggvorbis_TagDup: Failed to open file: '%s', %s\n", - file, strerror(errno)); - return NULL; - } - if (ov_open(fp, &vf, NULL, 0) < 0) { - fclose(fp); - return NULL; - } - - ret = oggCommentsParse(ov_comment(&vf, -1)->user_comments); - - if (!ret) - ret = newMpdTag(); - ret->time = (int)(ov_time_total(&vf, -1) + 0.5); - - ov_clear(&vf); - - return ret; -} - -static unsigned int oggvorbis_try_decode(InputStream * inStream) -{ - return (ogg_stream_type_detect(inStream) == VORBIS) ? 1 : 0; -} - -static char *oggvorbis_Suffixes[] = { "ogg", NULL }; -static char *oggvorbis_MimeTypes[] = { "application/ogg", - "audio/x-vorbis+ogg", - "application/x-ogg", - NULL }; - -InputPlugin oggvorbisPlugin = { - "oggvorbis", - NULL, - NULL, - oggvorbis_try_decode, - oggvorbis_decode, - NULL, - oggvorbis_TagDup, - INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE, - oggvorbis_Suffixes, - oggvorbis_MimeTypes -}; - -#else /* !HAVE_OGGVORBIS */ - -InputPlugin oggvorbisPlugin; - -#endif /* HAVE_OGGVORBIS */ diff --git a/trunk/src/inputStream.c b/trunk/src/inputStream.c deleted file mode 100644 index 013d75f17..000000000 --- a/trunk/src/inputStream.c +++ /dev/null @@ -1,83 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "inputStream.h" - -#include "inputStream_file.h" -#include "inputStream_http.h" - -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> - -void initInputStream(void) -{ - inputStream_initFile(); - inputStream_initHttp(); -} - -int openInputStream(InputStream * inStream, char *url) -{ - inStream->offset = 0; - inStream->size = 0; - inStream->error = 0; - inStream->mime = NULL; - inStream->seekable = 0; - inStream->metaName = NULL; - inStream->metaTitle = NULL; - - if (inputStream_fileOpen(inStream, url) == 0) - return 0; - if (inputStream_httpOpen(inStream, url) == 0) - return 0; - - return -1; -} - -int seekInputStream(InputStream * inStream, long offset, int whence) -{ - return inStream->seekFunc(inStream, offset, whence); -} - -size_t readFromInputStream(InputStream * inStream, void *ptr, size_t size, - size_t nmemb) -{ - return inStream->readFunc(inStream, ptr, size, nmemb); -} - -int closeInputStream(InputStream * inStream) -{ - if (inStream->mime) - free(inStream->mime); - if (inStream->metaName) - free(inStream->metaName); - if (inStream->metaTitle) - free(inStream->metaTitle); - - return inStream->closeFunc(inStream); -} - -int inputStreamAtEOF(InputStream * inStream) -{ - return inStream->atEOFFunc(inStream); -} - -int bufferInputStream(InputStream * inStream) -{ - return inStream->bufferFunc(inStream); -} diff --git a/trunk/src/inputStream.h b/trunk/src/inputStream.h deleted file mode 100644 index 74397f07f..000000000 --- a/trunk/src/inputStream.h +++ /dev/null @@ -1,70 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef INPUT_STREAM_H -#define INPUT_STREAM_H - -#include <stdlib.h> - -typedef struct _InputStream InputStream; - -typedef int (*InputStreamSeekFunc) (InputStream * inStream, long offset, - int whence); -typedef size_t(*InputStreamReadFunc) (InputStream * inStream, void *ptr, - size_t size, size_t nmemb); -typedef int (*InputStreamCloseFunc) (InputStream * inStream); -typedef int (*InputStreamAtEOFFunc) (InputStream * inStream); -typedef int (*InputStreamBufferFunc) (InputStream * inStream); - -struct _InputStream { - int error; - long offset; - size_t size; - char *mime; - int seekable; - - /* don't touc this stuff */ - InputStreamSeekFunc seekFunc; - InputStreamReadFunc readFunc; - InputStreamCloseFunc closeFunc; - InputStreamAtEOFFunc atEOFFunc; - InputStreamBufferFunc bufferFunc; - void *data; - char *metaName; - char *metaTitle; -}; - -void initInputStream(void); - -int isUrlSaneForInputStream(char *url); - -/* if an error occurs for these 3 functions, then -1 is returned and errno - for the input stream is set */ -int openInputStream(InputStream * inStream, char *url); -int seekInputStream(InputStream * inStream, long offset, int whence); -int closeInputStream(InputStream * inStream); -int inputStreamAtEOF(InputStream * inStream); - -/* return value: -1 is error, 1 inidicates stuff was buffered, 0 means nothing - was buffered */ -int bufferInputStream(InputStream * inStream); - -size_t readFromInputStream(InputStream * inStream, void *ptr, size_t size, - size_t nmemb); - -#endif diff --git a/trunk/src/inputStream_file.c b/trunk/src/inputStream_file.c deleted file mode 100644 index 389aaad01..000000000 --- a/trunk/src/inputStream_file.c +++ /dev/null @@ -1,119 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "inputStream_file.h" - -#include "log.h" - -#include <stdio.h> -#include <string.h> -#include <sys/types.h> -#include <unistd.h> -#include <errno.h> -#define _XOPEN_SOURCE 600 -#include <fcntl.h> - -void inputStream_initFile(void) -{ -} - -int inputStream_fileOpen(InputStream * inStream, char *filename) -{ - FILE *fp; - - fp = fopen(filename, "r"); - if (!fp) { - inStream->error = errno; - return -1; - } - - inStream->seekable = 1; - - fseek(fp, 0, SEEK_END); - inStream->size = ftell(fp); - fseek(fp, 0, SEEK_SET); - -#ifdef POSIX_FADV_SEQUENTIAL - posix_fadvise(fileno(fp), (off_t)0, inStream->size, POSIX_FADV_SEQUENTIAL); -#endif - - inStream->data = fp; - inStream->seekFunc = inputStream_fileSeek; - inStream->closeFunc = inputStream_fileClose; - inStream->readFunc = inputStream_fileRead; - inStream->atEOFFunc = inputStream_fileAtEOF; - inStream->bufferFunc = inputStream_fileBuffer; - - return 0; -} - -int inputStream_fileSeek(InputStream * inStream, long offset, int whence) -{ - if (fseek((FILE *) inStream->data, offset, whence) == 0) { - inStream->offset = ftell((FILE *) inStream->data); - } else { - inStream->error = errno; - return -1; - } - - return 0; -} - -size_t inputStream_fileRead(InputStream * inStream, void *ptr, size_t size, - size_t nmemb) -{ - size_t readSize; - - readSize = fread(ptr, size, nmemb, (FILE *) inStream->data); - if (readSize <= 0 && ferror((FILE *) inStream->data)) { - inStream->error = errno; - DEBUG("inputStream_fileRead: error reading: %s\n", - strerror(inStream->error)); - } - - inStream->offset = ftell((FILE *) inStream->data); - - return readSize; -} - -int inputStream_fileClose(InputStream * inStream) -{ - if (fclose((FILE *) inStream->data) < 0) { - inStream->error = errno; - return -1; - } - - return 0; -} - -int inputStream_fileAtEOF(InputStream * inStream) -{ - if (feof((FILE *) inStream->data)) - return 1; - - if (ferror((FILE *) inStream->data) && inStream->error != EINTR) { - return 1; - } - - return 0; -} - -int inputStream_fileBuffer(InputStream * inStream) -{ - return 0; -} diff --git a/trunk/src/inputStream_file.h b/trunk/src/inputStream_file.h deleted file mode 100644 index fad7ac26e..000000000 --- a/trunk/src/inputStream_file.h +++ /dev/null @@ -1,39 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef INPUT_STREAM_FILE_H -#define INPUT_STREAM_FILE_H - -#include "inputStream.h" - -void inputStream_initFile(void); - -int inputStream_fileOpen(InputStream * inStream, char *filename); - -int inputStream_fileSeek(InputStream * inStream, long offset, int whence); - -size_t inputStream_fileRead(InputStream * inStream, void *ptr, size_t size, - size_t nmemb); - -int inputStream_fileClose(InputStream * inStream); - -int inputStream_fileAtEOF(InputStream * inStream); - -int inputStream_fileBuffer(InputStream * inStream); - -#endif diff --git a/trunk/src/inputStream_http.c b/trunk/src/inputStream_http.c deleted file mode 100644 index 3f18575dd..000000000 --- a/trunk/src/inputStream_http.c +++ /dev/null @@ -1,912 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "inputStream_http.h" - -#include "utils.h" -#include "log.h" -#include "conf.h" - -#include <stdio.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netdb.h> -#include <sys/param.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <unistd.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> - -#define HTTP_CONN_STATE_CLOSED 0 -#define HTTP_CONN_STATE_INIT 1 -#define HTTP_CONN_STATE_HELLO 2 -#define HTTP_CONN_STATE_OPEN 3 -#define HTTP_CONN_STATE_REOPEN 4 - -#define HTTP_BUFFER_SIZE_DEFAULT 131072 -#define HTTP_PREBUFFER_SIZE_DEFAULT (HTTP_BUFFER_SIZE_DEFAULT >> 2) - -#define HTTP_REDIRECT_MAX 10 - -static char *proxyHost; -static char *proxyPort; -static char *proxyUser; -static char *proxyPassword; -static int bufferSize = HTTP_BUFFER_SIZE_DEFAULT; -static int prebufferSize = HTTP_PREBUFFER_SIZE_DEFAULT; - -typedef struct _InputStreemHTTPData { - char *host; - char *path; - char *port; - int sock; - int connState; - char *buffer; - size_t buflen; - int timesRedirected; - int icyMetaint; - int prebuffer; - int icyOffset; - char *proxyAuth; - char *httpAuth; -} InputStreamHTTPData; - -void inputStream_initHttp(void) -{ - ConfigParam *param = getConfigParam(CONF_HTTP_PROXY_HOST); - char *test; - - if (param) { - proxyHost = param->value; - - param = getConfigParam(CONF_HTTP_PROXY_PORT); - - if (!param) { - FATAL("%s specified but not %s", CONF_HTTP_PROXY_HOST, - CONF_HTTP_PROXY_PORT); - } - proxyPort = param->value; - - param = getConfigParam(CONF_HTTP_PROXY_USER); - - if (param) { - proxyUser = param->value; - - param = getConfigParam(CONF_HTTP_PROXY_PASSWORD); - - if (!param) { - FATAL("%s specified but not %s\n", - CONF_HTTP_PROXY_USER, - CONF_HTTP_PROXY_PASSWORD); - } - - proxyPassword = param->value; - } else { - param = getConfigParam(CONF_HTTP_PROXY_PASSWORD); - - if (param) { - FATAL("%s specified but not %s\n", - CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_USER); - } - } - } else if ((param = getConfigParam(CONF_HTTP_PROXY_PORT))) { - FATAL("%s specified but not %s, line %i\n", - CONF_HTTP_PROXY_PORT, CONF_HTTP_PROXY_HOST, param->line); - } else if ((param = getConfigParam(CONF_HTTP_PROXY_USER))) { - FATAL("%s specified but not %s, line %i\n", - CONF_HTTP_PROXY_USER, CONF_HTTP_PROXY_HOST, param->line); - } else if ((param = getConfigParam(CONF_HTTP_PROXY_PASSWORD))) { - FATAL("%s specified but not %s, line %i\n", - CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_HOST, - param->line); - } - - param = getConfigParam(CONF_HTTP_BUFFER_SIZE); - - if (param) { - bufferSize = strtol(param->value, &test, 10); - - if (bufferSize <= 0 || *test != '\0') { - FATAL("\"%s\" specified for %s at line %i is not a " - "positive integer\n", - param->value, CONF_HTTP_BUFFER_SIZE, param->line); - } - - bufferSize *= 1024; - - if (prebufferSize > bufferSize) - prebufferSize = bufferSize; - } - - param = getConfigParam(CONF_HTTP_PREBUFFER_SIZE); - - if (param) { - prebufferSize = strtol(param->value, &test, 10); - - if (prebufferSize <= 0 || *test != '\0') { - FATAL("\"%s\" specified for %s at line %i is not a " - "positive integer\n", - param->value, CONF_HTTP_PREBUFFER_SIZE, - param->line); - } - - prebufferSize *= 1024; - } - - if (prebufferSize > bufferSize) - prebufferSize = bufferSize; -} - -/* base64 code taken from xmms */ - -#define BASE64_LENGTH(len) (4 * (((len) + 2) / 3)) - -static char *base64Dup(char *s) -{ - int i; - int len = strlen(s); - char *ret = xcalloc(BASE64_LENGTH(len) + 1, 1); - unsigned char *p = (unsigned char *)ret; - - char tbl[64] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '+', '/' - }; - - /* Transform the 3x8 bits to 4x6 bits, as required by base64. */ - for (i = 0; i < len; i += 3) { - *p++ = tbl[s[0] >> 2]; - *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)]; - *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)]; - *p++ = tbl[s[2] & 0x3f]; - s += 3; - } - /* Pad the result if necessary... */ - if (i == len + 1) - *(p - 1) = '='; - else if (i == len + 2) - *(p - 1) = *(p - 2) = '='; - /* ...and zero-terminate it. */ - *p = '\0'; - - return ret; -} - -static char *authString(char *header, char *user, char *password) -{ - char *ret = NULL; - int templen; - char *temp; - char *temp64; - - if (!user || !password) - return NULL; - - templen = strlen(user) + strlen(password) + 2; - temp = xmalloc(templen); - strcpy(temp, user); - strcat(temp, ":"); - strcat(temp, password); - temp64 = base64Dup(temp); - free(temp); - - ret = xmalloc(strlen(temp64) + strlen(header) + 3); - strcpy(ret, header); - strcat(ret, temp64); - strcat(ret, "\r\n"); - free(temp64); - - return ret; -} - -#define PROXY_AUTH_HEADER "Proxy-Authorization: Basic " -#define HTTP_AUTH_HEADER "Authorization: Basic " - -#define proxyAuthString(x, y) authString(PROXY_AUTH_HEADER, x, y) -#define httpAuthString(x, y) authString(HTTP_AUTH_HEADER, x, y) - -static InputStreamHTTPData *newInputStreamHTTPData(void) -{ - InputStreamHTTPData *ret = xmalloc(sizeof(InputStreamHTTPData)); - - if (proxyHost) { - ret->proxyAuth = proxyAuthString(proxyUser, proxyPassword); - } else - ret->proxyAuth = NULL; - - ret->httpAuth = NULL; - ret->host = NULL; - ret->path = NULL; - ret->port = NULL; - ret->connState = HTTP_CONN_STATE_CLOSED; - ret->timesRedirected = 0; - ret->icyMetaint = 0; - ret->prebuffer = 0; - ret->icyOffset = 0; - ret->buffer = xmalloc(bufferSize); - - return ret; -} - -static void freeInputStreamHTTPData(InputStreamHTTPData * data) -{ - if (data->host) - free(data->host); - if (data->path) - free(data->path); - if (data->port) - free(data->port); - if (data->proxyAuth) - free(data->proxyAuth); - if (data->httpAuth) - free(data->httpAuth); - - free(data->buffer); - - free(data); -} - -static int parseUrl(InputStreamHTTPData * data, char *url) -{ - char *temp; - char *colon; - char *slash; - char *at; - int len; - - if (strncmp("http://", url, strlen("http://")) != 0) - return -1; - - temp = url + strlen("http://"); - - colon = strchr(temp, ':'); - at = strchr(temp, '@'); - - if (data->httpAuth) { - free(data->httpAuth); - data->httpAuth = NULL; - } - - if (at) { - char *user; - char *passwd; - - if (colon && colon < at) { - user = xmalloc(colon - temp + 1); - memcpy(user, temp, colon - temp); - user[colon - temp] = '\0'; - - passwd = xmalloc(at - colon); - memcpy(passwd, colon + 1, at - colon - 1); - passwd[at - colon - 1] = '\0'; - } else { - user = xmalloc(at - temp + 1); - memcpy(user, temp, at - temp); - user[at - temp] = '\0'; - - passwd = xstrdup(""); - } - - data->httpAuth = httpAuthString(user, passwd); - - free(user); - free(passwd); - - temp = at + 1; - colon = strchr(temp, ':'); - } - - slash = strchr(temp, '/'); - - if (slash && colon && slash <= colon) - return -1; - - /* fetch the host portion */ - if (colon) - len = colon - temp + 1; - else if (slash) - len = slash - temp + 1; - else - len = strlen(temp) + 1; - - if (len <= 1) - return -1; - - data->host = xmalloc(len); - memcpy(data->host, temp, len - 1); - data->host[len - 1] = '\0'; - /* fetch the port */ - if (colon && (!slash || slash != colon + 1)) { - len = strlen(colon) - 1; - if (slash) - len -= strlen(slash); - data->port = xmalloc(len + 1); - memcpy(data->port, colon + 1, len); - data->port[len] = '\0'; - DEBUG(__FILE__ ": Port: %s\n", data->port); - } else { - data->port = xstrdup("80"); - } - - /* fetch the path */ - if (proxyHost) - data->path = xstrdup(url); - else - data->path = xstrdup(slash ? slash : "/"); - - return 0; -} - -static int initHTTPConnection(InputStream * inStream) -{ - char *connHost; - char *connPort; - struct addrinfo *ans = NULL; - struct addrinfo *ap = NULL; - struct addrinfo hints; - int error, flags; - InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data; - /** - * Setup hints - */ - hints.ai_flags = 0; - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_addrlen = 0; - hints.ai_addr = NULL; - hints.ai_canonname = NULL; - hints.ai_next = NULL; - - if (proxyHost) { - connHost = proxyHost; - connPort = proxyPort; - } else { - connHost = data->host; - connPort = data->port; - } - - error = getaddrinfo(connHost, connPort, &hints, &ans); - if (error) { - DEBUG(__FILE__ ": Error getting address info: %s\n", - gai_strerror(error)); - return -1; - } - - /* loop through possible addresses */ - for (ap = ans; ap != NULL; ap = ap->ai_next) { - if ((data->sock = socket(ap->ai_family, ap->ai_socktype, - ap->ai_protocol)) < 0) { - DEBUG(__FILE__ ": unable to connect: %s\n", - strerror(errno)); - freeaddrinfo(ans); - return -1; - } - - flags = fcntl(data->sock, F_GETFL, 0); - fcntl(data->sock, F_SETFL, flags | O_NONBLOCK); - - if (connect(data->sock, ap->ai_addr, ap->ai_addrlen) >= 0 - || errno == EINPROGRESS) { - data->connState = HTTP_CONN_STATE_INIT; - data->buflen = 0; - freeaddrinfo(ans); - return 0; /* success */ - } - - /* failed, get the next one */ - - DEBUG(__FILE__ ": unable to connect: %s\n", strerror(errno)); - close(data->sock); - } - - freeaddrinfo(ans); - return -1; /* failed */ -} - -static int finishHTTPInit(InputStream * inStream) -{ - InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data; - struct timeval tv; - fd_set writeSet; - fd_set errorSet; - int error; - socklen_t error_len = sizeof(int); - int ret; - int length; - char request[2048]; - - tv.tv_sec = 0; - tv.tv_usec = 0; - - FD_ZERO(&writeSet); - FD_ZERO(&errorSet); - FD_SET(data->sock, &writeSet); - FD_SET(data->sock, &errorSet); - - ret = select(data->sock + 1, NULL, &writeSet, &errorSet, &tv); - - if (ret == 0 || (ret < 0 && errno == EINTR)) - return 0; - - if (ret < 0) { - DEBUG(__FILE__ ": problem select'ing: %s\n", strerror(errno)); - goto close_err; - } - - getsockopt(data->sock, SOL_SOCKET, SO_ERROR, &error, &error_len); - if (error) - goto close_err; - - /* deal with ICY metadata later, for now its fucking up stuff! */ - length = snprintf(request, sizeof(request), - "GET %s HTTP/1.1\r\n" "Host: %s\r\n" - /*"Connection: close\r\n" */ - "User-Agent: %s/%s\r\n" - "Range: bytes=%ld-\r\n" - "%s" /* authorization */ - "Icy-Metadata:1\r\n" - "\r\n", - data->path, data->host, - PACKAGE_NAME, PACKAGE_VERSION, - inStream->offset, - data->proxyAuth ? data->proxyAuth : - (data->httpAuth ? data->httpAuth : "")); - - if (length >= sizeof(request)) - goto close_err; - ret = write(data->sock, request, length); - if (ret != length) - goto close_err; - - data->connState = HTTP_CONN_STATE_HELLO; - return 0; - -close_err: - close(data->sock); - data->connState = HTTP_CONN_STATE_CLOSED; - return -1; -} - -static int getHTTPHello(InputStream * inStream) -{ - InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data; - fd_set readSet; - struct timeval tv; - int ret; - char *needle; - char *cur = data->buffer; - int rc; - long readed; - - FD_ZERO(&readSet); - FD_SET(data->sock, &readSet); - - tv.tv_sec = 0; - tv.tv_usec = 0; - - ret = select(data->sock + 1, &readSet, NULL, NULL, &tv); - - if (ret == 0 || (ret < 0 && errno == EINTR)) - return 0; - - if (ret < 0) { - data->connState = HTTP_CONN_STATE_CLOSED; - close(data->sock); - data->buflen = 0; - return -1; - } - - if (data->buflen >= bufferSize - 1) { - data->connState = HTTP_CONN_STATE_CLOSED; - close(data->sock); - return -1; - } - - readed = recv(data->sock, data->buffer + data->buflen, - bufferSize - 1 - data->buflen, 0); - - if (readed < 0 && (errno == EAGAIN || errno == EINTR)) - return 0; - - if (readed <= 0) { - data->connState = HTTP_CONN_STATE_CLOSED; - close(data->sock); - data->buflen = 0; - return -1; - } - - data->buffer[data->buflen + readed] = '\0'; - data->buflen += readed; - - needle = strstr(data->buffer, "\r\n\r\n"); - - if (!needle) - return 0; - - if (0 == strncmp(cur, "HTTP/1.0 ", 9)) { - inStream->seekable = 0; - rc = atoi(cur + 9); - } else if (0 == strncmp(cur, "HTTP/1.1 ", 9)) { - inStream->seekable = 1; - rc = atoi(cur + 9); - } else if (0 == strncmp(cur, "ICY 200 OK", 10)) { - inStream->seekable = 0; - rc = 200; - } else if (0 == strncmp(cur, "ICY 400 Server Full", 19)) - rc = 400; - else if (0 == strncmp(cur, "ICY 404", 7)) - rc = 404; - else { - close(data->sock); - data->connState = HTTP_CONN_STATE_CLOSED; - return -1; - } - - switch (rc) { - case 200: - case 206: - break; - case 301: - case 302: - cur = strstr(cur, "Location: "); - if (cur) { - char *url; - int curlen = 0; - cur += strlen("Location: "); - while (*(cur + curlen) != '\0' - && *(cur + curlen) != '\r') { - curlen++; - } - url = xmalloc(curlen + 1); - memcpy(url, cur, curlen); - url[curlen] = '\0'; - ret = parseUrl(data, url); - free(url); - if (ret == 0 && data->timesRedirected < - HTTP_REDIRECT_MAX) { - data->timesRedirected++; - close(data->sock); - data->connState = HTTP_CONN_STATE_REOPEN; - data->buflen = 0; - return 0; - } - } - case 400: - case 401: - case 403: - case 404: - default: - close(data->sock); - data->connState = HTTP_CONN_STATE_CLOSED; - data->buflen = 0; - return -1; - } - - cur = strstr(data->buffer, "\r\n"); - while (cur && cur != needle) { - if (0 == strncmp(cur, "\r\nContent-Length: ", 18)) { - if (!inStream->size) - inStream->size = atol(cur + 18); - } else if (0 == strncmp(cur, "\r\nicy-metaint:", 14)) { - data->icyMetaint = atoi(cur + 14); - } else if (0 == strncmp(cur, "\r\nicy-name:", 11) || - 0 == strncmp(cur, "\r\nice-name:", 11)) { - int incr = 11; - char *temp = strstr(cur + incr, "\r\n"); - if (!temp) - break; - *temp = '\0'; - if (inStream->metaName) - free(inStream->metaName); - while (*(incr + cur) == ' ') - incr++; - inStream->metaName = xstrdup(cur + incr); - *temp = '\r'; - DEBUG("inputStream_http: metaName: %s\n", - inStream->metaName); - } else if (0 == strncmp(cur, "\r\nx-audiocast-name:", 19)) { - int incr = 19; - char *temp = strstr(cur + incr, "\r\n"); - if (!temp) - break; - *temp = '\0'; - if (inStream->metaName) - free(inStream->metaName); - while (*(incr + cur) == ' ') - incr++; - inStream->metaName = xstrdup(cur + incr); - *temp = '\r'; - DEBUG("inputStream_http: metaName: %s\n", - inStream->metaName); - } else if (0 == strncmp(cur, "\r\nContent-Type:", 15)) { - int incr = 15; - char *temp = strstr(cur + incr, "\r\n"); - if (!temp) - break; - *temp = '\0'; - if (inStream->mime) - free(inStream->mime); - while (*(incr + cur) == ' ') - incr++; - inStream->mime = xstrdup(cur + incr); - *temp = '\r'; - } - - cur = strstr(cur + 2, "\r\n"); - } - - if (inStream->size <= 0) - inStream->seekable = 0; - - needle += 4; /* 4 == strlen("\r\n\r\n") */ - data->buflen -= (needle - data->buffer); - /*fwrite(data->buffer, 1, data->buflen, stdout); */ - memmove(data->buffer, needle, data->buflen); - - data->connState = HTTP_CONN_STATE_OPEN; - - data->prebuffer = 1; - - return 0; -} - -int inputStream_httpOpen(InputStream * inStream, char *url) -{ - InputStreamHTTPData *data = newInputStreamHTTPData(); - - inStream->data = data; - - if (parseUrl(data, url) < 0) { - freeInputStreamHTTPData(data); - return -1; - } - - if (initHTTPConnection(inStream) < 0) { - freeInputStreamHTTPData(data); - return -1; - } - - inStream->seekFunc = inputStream_httpSeek; - inStream->closeFunc = inputStream_httpClose; - inStream->readFunc = inputStream_httpRead; - inStream->atEOFFunc = inputStream_httpAtEOF; - inStream->bufferFunc = inputStream_httpBuffer; - - return 0; -} - -int inputStream_httpSeek(InputStream * inStream, long offset, int whence) -{ - InputStreamHTTPData *data; - - if (!inStream->seekable) - return -1; - - switch (whence) { - case SEEK_SET: - inStream->offset = offset; - break; - case SEEK_CUR: - inStream->offset += offset; - break; - case SEEK_END: - inStream->offset = inStream->size + offset; - break; - default: - return -1; - } - - data = (InputStreamHTTPData *)inStream->data; - close(data->sock); - data->connState = HTTP_CONN_STATE_REOPEN; - data->buflen = 0; - - inputStream_httpBuffer(inStream); - - return 0; -} - -static void parseIcyMetadata(InputStream * inStream, char *metadata, int size) -{ - char *r; - char *s; - char *temp = xmalloc(size + 1); - memcpy(temp, metadata, size); - temp[size] = '\0'; - s = strtok_r(temp, ";", &r); - while (s) { - if (0 == strncmp(s, "StreamTitle=", 12)) { - int cur = 12; - if (inStream->metaTitle) - free(inStream->metaTitle); - if (*(s + cur) == '\'') - cur++; - if (s[strlen(s) - 1] == '\'') { - s[strlen(s) - 1] = '\0'; - } - inStream->metaTitle = xstrdup(s + cur); - DEBUG("inputStream_http: metaTitle: %s\n", - inStream->metaTitle); - } - s = strtok_r(NULL, ";", &r); - } - free(temp); -} - -size_t inputStream_httpRead(InputStream * inStream, void *ptr, size_t size, - size_t nmemb) -{ - InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data; - long tosend = 0; - long inlen = size * nmemb; - long maxToSend = data->buflen; - - inputStream_httpBuffer(inStream); - - switch (data->connState) { - case HTTP_CONN_STATE_OPEN: - if (data->prebuffer || data->buflen < data->icyMetaint) - return 0; - - break; - case HTTP_CONN_STATE_CLOSED: - if (data->buflen) - break; - default: - return 0; - } - - if (data->icyMetaint > 0) { - if (data->icyOffset >= data->icyMetaint) { - int metalen = *(data->buffer); - metalen <<= 4; - if (metalen < 0) - metalen = 0; - if (metalen + 1 > data->buflen) { - /* damn that's some fucking big metadata! */ - if (bufferSize < metalen + 1) { - data->connState = - HTTP_CONN_STATE_CLOSED; - close(data->sock); - data->buflen = 0; - } - return 0; - } - if (metalen > 0) { - parseIcyMetadata(inStream, data->buffer + 1, - metalen); - } - data->buflen -= metalen + 1; - memmove(data->buffer, data->buffer + metalen + 1, - data->buflen); - data->icyOffset = 0; - } - maxToSend = data->icyMetaint - data->icyOffset; - maxToSend = maxToSend > data->buflen ? data->buflen : maxToSend; - } - - if (data->buflen > 0) { - tosend = inlen > maxToSend ? maxToSend : inlen; - tosend = (tosend / size) * size; - - memcpy(ptr, data->buffer, tosend); - /*fwrite(ptr,1,readed,stdout); */ - data->buflen -= tosend; - data->icyOffset += tosend; - /*fwrite(data->buffer,1,readed,stdout); */ - memmove(data->buffer, data->buffer + tosend, data->buflen); - - inStream->offset += tosend; - } - - return tosend / size; -} - -int inputStream_httpClose(InputStream * inStream) -{ - InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data; - - switch (data->connState) { - case HTTP_CONN_STATE_CLOSED: - break; - default: - close(data->sock); - } - - freeInputStreamHTTPData(data); - - return 0; -} - -int inputStream_httpAtEOF(InputStream * inStream) -{ - InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data; - switch (data->connState) { - case HTTP_CONN_STATE_CLOSED: - if (data->buflen == 0) - return 1; - default: - return 0; - } -} - -int inputStream_httpBuffer(InputStream * inStream) -{ - InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data; - ssize_t readed = 0; - - if (data->connState == HTTP_CONN_STATE_REOPEN) { - if (initHTTPConnection(inStream) < 0) - return -1; - } - - if (data->connState == HTTP_CONN_STATE_INIT) { - if (finishHTTPInit(inStream) < 0) - return -1; - } - - if (data->connState == HTTP_CONN_STATE_HELLO) { - if (getHTTPHello(inStream) < 0) - return -1; - } - - switch (data->connState) { - case HTTP_CONN_STATE_OPEN: - case HTTP_CONN_STATE_CLOSED: - break; - default: - return -1; - } - - if (data->buflen == 0 || data->buflen < data->icyMetaint) { - data->prebuffer = 1; - } else if (data->buflen > prebufferSize) - data->prebuffer = 0; - - if (data->connState == HTTP_CONN_STATE_OPEN && - data->buflen < bufferSize - 1) { - readed = read(data->sock, data->buffer + data->buflen, - (size_t) (bufferSize - 1 - data->buflen)); - - if (readed < 0 && (errno == EAGAIN || errno == EINTR)) { - readed = 0; - } else if (readed <= 0) { - close(data->sock); - data->connState = HTTP_CONN_STATE_CLOSED; - readed = 0; - } - /*fwrite(data->buffer+data->buflen,1,readed,stdout); */ - data->buflen += readed; - } - - if (data->buflen > prebufferSize) - data->prebuffer = 0; - - return (readed ? 1 : 0); -} diff --git a/trunk/src/inputStream_http.h b/trunk/src/inputStream_http.h deleted file mode 100644 index 7ab23a5de..000000000 --- a/trunk/src/inputStream_http.h +++ /dev/null @@ -1,39 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef INPUT_STREAM_HTTP_H -#define INPUT_STREAM_HTTP_H - -#include "inputStream.h" - -void inputStream_initHttp(void); - -int inputStream_httpOpen(InputStream * inStream, char *filename); - -int inputStream_httpSeek(InputStream * inStream, long offset, int whence); - -size_t inputStream_httpRead(InputStream * inStream, void *ptr, size_t size, - size_t nmemb); - -int inputStream_httpClose(InputStream * inStream); - -int inputStream_httpAtEOF(InputStream * inStream); - -int inputStream_httpBuffer(InputStream * inStream); - -#endif diff --git a/trunk/src/interface.c b/trunk/src/interface.c deleted file mode 100644 index 22660432f..000000000 --- a/trunk/src/interface.c +++ /dev/null @@ -1,851 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "interface.h" -#include "command.h" -#include "conf.h" -#include "list.h" -#include "log.h" -#include "listen.h" -#include "playlist.h" -#include "permission.h" -#include "sllist.h" -#include "utils.h" -#include "ioops.h" - -#include <stdio.h> -#include <stdlib.h> -#include <assert.h> -#include <sys/select.h> -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#include <sys/param.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <signal.h> - -#define GREETING "OK MPD " PROTOCOL_VERSION "\n" - -#define INTERFACE_MAX_BUFFER_LENGTH (40960) -#define INTERFACE_LIST_MODE_BEGIN "command_list_begin" -#define INTERFACE_LIST_OK_MODE_BEGIN "command_list_ok_begin" -#define INTERFACE_LIST_MODE_END "command_list_end" -#define INTERFACE_DEFAULT_OUT_BUFFER_SIZE (4096) -#define INTERFACE_TIMEOUT_DEFAULT (60) -#define INTERFACE_MAX_CONNECTIONS_DEFAULT (10) -#define INTERFACE_MAX_COMMAND_LIST_DEFAULT (2048*1024) -#define INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT (8192*1024) - -/* set this to zero to indicate we have no possible interfaces */ -static int interface_max_connections; /*INTERFACE_MAX_CONNECTIONS_DEFAULT; */ -static int interface_timeout = INTERFACE_TIMEOUT_DEFAULT; -static size_t interface_max_command_list_size = - INTERFACE_MAX_COMMAND_LIST_DEFAULT; -static size_t interface_max_output_buffer_size = - INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT; - -/* List of registered external IO handlers */ -static struct ioOps *ioList; - -/* maybe make conf option for this, or... 32 might be good enough */ -static long int interface_list_cache_size = 32; - -/* shared globally between all interfaces: */ -static struct strnode *list_cache; -static struct strnode *list_cache_head; -static struct strnode *list_cache_tail; - -typedef struct _Interface { - char buffer[INTERFACE_MAX_BUFFER_LENGTH]; - int bufferLength; - int bufferPos; - int fd; /* file descriptor */ - int permission; - time_t lastTime; - struct strnode *cmd_list; /* for when in list mode */ - struct strnode *cmd_list_tail; /* for when in list mode */ - int cmd_list_OK; /* print OK after each command execution */ - int cmd_list_size; /* mem cmd_list consumes */ - int cmd_list_dup; /* has the cmd_list been copied to private space? */ - struct sllnode *deferred_send; /* for output if client is slow */ - int deferred_bytes; /* mem deferred_send consumes */ - int expired; /* set whether this interface should be closed on next - check of old interfaces */ - int num; /* interface number */ - - char *send_buf; - int send_buf_used; /* bytes used this instance */ - int send_buf_size; /* bytes usable this instance */ - int send_buf_alloc; /* bytes actually allocated */ -} Interface; - -static Interface *interfaces; - -static void flushInterfaceBuffer(Interface * interface); - -static void printInterfaceOutBuffer(Interface * interface); - -#ifdef SO_SNDBUF -static int get_default_snd_buf_size(Interface * interface) -{ - int new_size; - socklen_t sockOptLen = sizeof(int); - - if (getsockopt(interface->fd, SOL_SOCKET, SO_SNDBUF, - (char *)&new_size, &sockOptLen) < 0) { - DEBUG("problem getting sockets send buffer size\n"); - return INTERFACE_DEFAULT_OUT_BUFFER_SIZE; - } - if (new_size > 0) - return new_size; - DEBUG("sockets send buffer size is not positive\n"); - return INTERFACE_DEFAULT_OUT_BUFFER_SIZE; -} -#else /* !SO_SNDBUF */ -static int get_default_snd_buf_size(Interface * interface) -{ - return INTERFACE_DEFAULT_OUT_BUFFER_SIZE; -} -#endif /* !SO_SNDBUF */ - -static void set_send_buf_size(Interface * interface) -{ - int new_size = get_default_snd_buf_size(interface); - if (interface->send_buf_size != new_size) { - interface->send_buf_size = new_size; - /* don't resize to get smaller, only bigger */ - if (interface->send_buf_alloc < new_size) { - if (interface->send_buf) - free(interface->send_buf); - interface->send_buf = xmalloc(new_size); - interface->send_buf_alloc = new_size; - } - } -} - -static void openInterface(Interface * interface, int fd) -{ - int flags; - - assert(interface->fd < 0); - - interface->cmd_list_size = 0; - interface->cmd_list_dup = 0; - interface->cmd_list_OK = -1; - interface->bufferLength = 0; - interface->bufferPos = 0; - interface->fd = fd; - while ((flags = fcntl(fd, F_GETFL)) < 0 && errno == EINTR) ; - while (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0 && errno == EINTR) ; - interface->lastTime = time(NULL); - interface->cmd_list = NULL; - interface->cmd_list_tail = NULL; - interface->deferred_send = NULL; - interface->expired = 0; - interface->deferred_bytes = 0; - interface->send_buf_used = 0; - - interface->permission = getDefaultPermissions(); - set_send_buf_size(interface); - - xwrite(fd, GREETING, strlen(GREETING)); -} - -static void free_cmd_list(struct strnode *list) -{ - struct strnode *tmp = list; - - while (tmp) { - struct strnode *next = tmp->next; - if (tmp >= list_cache_head && tmp <= list_cache_tail) { - /* inside list_cache[] array */ - tmp->data = NULL; - tmp->next = NULL; - } else - free(tmp); - tmp = next; - } -} - -static void cmd_list_clone(Interface * interface) -{ - struct strnode *new = dup_strlist(interface->cmd_list); - free_cmd_list(interface->cmd_list); - interface->cmd_list = new; - interface->cmd_list_dup = 1; - - /* new tail */ - while (new && new->next) - new = new->next; - interface->cmd_list_tail = new; -} - -static void new_cmd_list_ptr(Interface * interface, char *s, const int size) -{ - int i; - struct strnode *new; - - if (!interface->cmd_list_dup) { - for (i = interface_list_cache_size - 1; i >= 0; --i) { - if (list_cache[i].data) - continue; - new = &(list_cache[i]); - new->data = s; - /* implied in free_cmd_list() and init: */ - /* last->next->next = NULL; */ - goto out; - } - } - - /* allocate from the heap */ - new = interface->cmd_list_dup ? new_strnode_dup(s, size) - : new_strnode(s); -out: - if (interface->cmd_list) { - interface->cmd_list_tail->next = new; - interface->cmd_list_tail = new; - } else - interface->cmd_list = interface->cmd_list_tail = new; -} - -static void closeInterface(Interface * interface) -{ - struct sllnode *buf; - if (interface->fd < 0) - return; - xclose(interface->fd); - interface->fd = -1; - - if (interface->cmd_list) { - free_cmd_list(interface->cmd_list); - interface->cmd_list = NULL; - } - - if ((buf = interface->deferred_send)) { - do { - struct sllnode *prev = buf; - buf = buf->next; - free(prev); - } while (buf); - interface->deferred_send = NULL; - } - - SECURE("interface %i: closed\n", interface->num); -} - -void openAInterface(int fd, struct sockaddr *addr) -{ - int i; - - for (i = 0; i < interface_max_connections - && interfaces[i].fd >= 0; i++) /* nothing */ ; - - if (i == interface_max_connections) { - ERROR("Max Connections Reached!\n"); - xclose(fd); - } else { - SECURE("interface %i: opened from ", i); - switch (addr->sa_family) { - case AF_INET: - { - char *host = inet_ntoa(((struct sockaddr_in *) - addr)->sin_addr); - if (host) { - SECURE("%s\n", host); - } else { - SECURE("error getting ipv4 address\n"); - } - } - break; -#ifdef HAVE_IPV6 - case AF_INET6: - { - char host[INET6_ADDRSTRLEN + 1]; - memset(host, 0, INET6_ADDRSTRLEN + 1); - if (inet_ntop(AF_INET6, (void *) - &(((struct sockaddr_in6 *)addr)-> - sin6_addr), host, - INET6_ADDRSTRLEN)) { - SECURE("%s\n", host); - } else { - SECURE("error getting ipv6 address\n"); - } - } - break; -#endif - case AF_UNIX: - SECURE("local connection\n"); - break; - default: - SECURE("unknown\n"); - } - openInterface(&(interfaces[i]), fd); - } -} - -static int processLineOfInput(Interface * interface) -{ - int ret = 1; - char *line = interface->buffer + interface->bufferPos; - - if (interface->cmd_list_OK >= 0) { - if (strcmp(line, INTERFACE_LIST_MODE_END) == 0) { - DEBUG("interface %i: process command " - "list\n", interface->num); - ret = processListOfCommands(interface->fd, - &(interface->permission), - &(interface->expired), - interface->cmd_list_OK, - interface->cmd_list); - DEBUG("interface %i: process command " - "list returned %i\n", interface->num, ret); - if (ret == 0) - commandSuccess(interface->fd); - else if (ret == COMMAND_RETURN_CLOSE - || interface->expired) - closeInterface(interface); - - printInterfaceOutBuffer(interface); - free_cmd_list(interface->cmd_list); - interface->cmd_list = NULL; - interface->cmd_list_OK = -1; - } else { - size_t len = strlen(line) + 1; - interface->cmd_list_size += len; - if (interface->cmd_list_size > - interface_max_command_list_size) { - ERROR("interface %i: command " - "list size (%i) is " - "larger than the max " - "(%li)\n", - interface->num, - interface->cmd_list_size, - (long)interface_max_command_list_size); - closeInterface(interface); - ret = COMMAND_RETURN_CLOSE; - } else - new_cmd_list_ptr(interface, line, len); - } - } else { - if (strcmp(line, INTERFACE_LIST_MODE_BEGIN) == 0) { - interface->cmd_list_OK = 0; - ret = 1; - } else if (strcmp(line, INTERFACE_LIST_OK_MODE_BEGIN) == 0) { - interface->cmd_list_OK = 1; - ret = 1; - } else { - DEBUG("interface %i: process command \"%s\"\n", - interface->num, line); - ret = processCommand(interface->fd, - &(interface->permission), line); - DEBUG("interface %i: command returned %i\n", - interface->num, ret); - if (ret == 0) - commandSuccess(interface->fd); - else if (ret == COMMAND_RETURN_CLOSE - || interface->expired) { - closeInterface(interface); - } - printInterfaceOutBuffer(interface); - } - } - - return ret; -} - -static int processBytesRead(Interface * interface, int bytesRead) -{ - int ret = 0; - char *buf_tail = &(interface->buffer[interface->bufferLength - 1]); - - while (bytesRead > 0) { - interface->bufferLength++; - bytesRead--; - buf_tail++; - if (*buf_tail == '\n') { - *buf_tail = '\0'; - if (interface->bufferLength - interface->bufferPos > 1) { - if (*(buf_tail - 1) == '\r') - *(buf_tail - 1) = '\0'; - } - ret = processLineOfInput(interface); - interface->bufferPos = interface->bufferLength; - } - if (interface->bufferLength == INTERFACE_MAX_BUFFER_LENGTH) { - if (interface->bufferPos == 0) { - ERROR("interface %i: buffer overflow\n", - interface->num); - closeInterface(interface); - return 1; - } - if (interface->cmd_list_OK >= 0 && - interface->cmd_list && - !interface->cmd_list_dup) - cmd_list_clone(interface); - interface->bufferLength -= interface->bufferPos; - memmove(interface->buffer, - interface->buffer + interface->bufferPos, - interface->bufferLength); - interface->bufferPos = 0; - } - if (ret == COMMAND_RETURN_KILL || ret == COMMAND_RETURN_CLOSE) { - return ret; - } - - } - - return ret; -} - -static int interfaceReadInput(Interface * interface) -{ - int bytesRead; - - bytesRead = read(interface->fd, - interface->buffer + interface->bufferLength, - INTERFACE_MAX_BUFFER_LENGTH - interface->bufferLength); - - if (bytesRead > 0) - return processBytesRead(interface, bytesRead); - else if (bytesRead == 0 || (bytesRead < 0 && errno != EINTR)) { - closeInterface(interface); - } else - return 0; - - return 1; -} - -static void addInterfacesReadyToReadAndListenSocketToFdSet(fd_set * fds, - int *fdmax) -{ - int i; - - FD_ZERO(fds); - addListenSocketsToFdSet(fds, fdmax); - - for (i = 0; i < interface_max_connections; i++) { - if (interfaces[i].fd >= 0 && !interfaces[i].expired - && !interfaces[i].deferred_send) { - FD_SET(interfaces[i].fd, fds); - if (*fdmax < interfaces[i].fd) - *fdmax = interfaces[i].fd; - } - } -} - -static void addInterfacesForBufferFlushToFdSet(fd_set * fds, int *fdmax) -{ - int i; - - FD_ZERO(fds); - - for (i = 0; i < interface_max_connections; i++) { - if (interfaces[i].fd >= 0 && !interfaces[i].expired - && interfaces[i].deferred_send) { - FD_SET(interfaces[i].fd, fds); - if (*fdmax < interfaces[i].fd) - *fdmax = interfaces[i].fd; - } - } -} - -static void closeNextErroredInterface(void) -{ - fd_set fds; - struct timeval tv; - int i; - - tv.tv_sec = 0; - tv.tv_usec = 0; - - for (i = 0; i < interface_max_connections; i++) { - if (interfaces[i].fd >= 0) { - FD_ZERO(&fds); - FD_SET(interfaces[i].fd, &fds); - if (select(FD_SETSIZE, &fds, NULL, NULL, &tv) < 0) { - closeInterface(&interfaces[i]); - return; - } - } - } -} - -int doIOForInterfaces(void) -{ - fd_set rfds; - fd_set wfds; - fd_set efds; - struct timeval tv; - int i; - int selret; - int fdmax; - - tv.tv_sec = 1; - tv.tv_usec = 0; - - while (1) { - fdmax = 0; - - FD_ZERO( &rfds ); - FD_ZERO( &wfds ); - FD_ZERO( &efds ); - addInterfacesReadyToReadAndListenSocketToFdSet(&rfds, &fdmax); - addInterfacesForBufferFlushToFdSet(&wfds, &fdmax); - - /* Add fds for all registered IO handlers */ - if( ioList ) { - struct ioOps *o = ioList; - while( o ) { - struct ioOps *current = o; - int fdnum; - assert( current->fdset ); - fdnum = current->fdset( &rfds, &wfds, &efds ); - if( fdmax < fdnum ) - fdmax = fdnum; - o = o->next; - } - } - - selret = select(fdmax + 1, &rfds, &wfds, &efds, &tv); - - if (selret < 0 && errno == EINTR) - break; - - /* Consume fds for all registered IO handlers */ - if( ioList ) { - struct ioOps *o = ioList; - while( o ) { - struct ioOps *current = o; - assert( current->consume ); - selret = current->consume( selret, &rfds, &wfds, &efds ); - o = o->next; - } - } - - if (selret == 0) - break; - - if (selret < 0) { - closeNextErroredInterface(); - continue; - } - - getConnections(&rfds); - - for (i = 0; i < interface_max_connections; i++) { - if (interfaces[i].fd >= 0 - && FD_ISSET(interfaces[i].fd, &rfds)) { - if (COMMAND_RETURN_KILL == - interfaceReadInput(&(interfaces[i]))) { - return COMMAND_RETURN_KILL; - } - interfaces[i].lastTime = time(NULL); - } - if (interfaces[i].fd >= 0 - && FD_ISSET(interfaces[i].fd, &wfds)) { - flushInterfaceBuffer(&interfaces[i]); - interfaces[i].lastTime = time(NULL); - } - } - - tv.tv_sec = 0; - tv.tv_usec = 0; - } - - return 1; -} - -void initInterfaces(void) -{ - int i; - char *test; - ConfigParam *param; - - param = getConfigParam(CONF_CONN_TIMEOUT); - - if (param) { - interface_timeout = strtol(param->value, &test, 10); - if (*test != '\0' || interface_timeout <= 0) { - FATAL("connection timeout \"%s\" is not a positive " - "integer, line %i\n", CONF_CONN_TIMEOUT, - param->line); - } - } - - param = getConfigParam(CONF_MAX_CONN); - - if (param) { - interface_max_connections = strtol(param->value, &test, 10); - if (*test != '\0' || interface_max_connections <= 0) { - FATAL("max connections \"%s\" is not a positive integer" - ", line %i\n", param->value, param->line); - } - } else - interface_max_connections = INTERFACE_MAX_CONNECTIONS_DEFAULT; - - param = getConfigParam(CONF_MAX_COMMAND_LIST_SIZE); - - if (param) { - interface_max_command_list_size = strtol(param->value, - &test, 10); - if (*test != '\0' || interface_max_command_list_size <= 0) { - FATAL("max command list size \"%s\" is not a positive " - "integer, line %i\n", param->value, param->line); - } - interface_max_command_list_size *= 1024; - } - - param = getConfigParam(CONF_MAX_OUTPUT_BUFFER_SIZE); - - if (param) { - interface_max_output_buffer_size = strtol(param->value, - &test, 10); - if (*test != '\0' || interface_max_output_buffer_size <= 0) { - FATAL("max output buffer size \"%s\" is not a positive " - "integer, line %i\n", param->value, param->line); - } - interface_max_output_buffer_size *= 1024; - } - - interfaces = xmalloc(sizeof(Interface) * interface_max_connections); - - list_cache = xcalloc(interface_list_cache_size, sizeof(struct strnode)); - list_cache_head = &(list_cache[0]); - list_cache_tail = &(list_cache[interface_list_cache_size - 1]); - - for (i = 0; i < interface_max_connections; i++) { - interfaces[i].fd = -1; - interfaces[i].send_buf = NULL; - interfaces[i].send_buf_size = 0; - interfaces[i].send_buf_alloc = 0; - interfaces[i].num = i; - } -} - -static void closeAllInterfaces(void) -{ - int i; - - for (i = 0; i < interface_max_connections; i++) { - if (interfaces[i].fd > 0) - closeInterface(&(interfaces[i])); - if (interfaces[i].send_buf) - free(interfaces[i].send_buf); - } - free(list_cache); -} - -void freeAllInterfaces(void) -{ - closeAllInterfaces(); - - free(interfaces); - - interface_max_connections = 0; -} - -void closeOldInterfaces(void) -{ - int i; - - for (i = 0; i < interface_max_connections; i++) { - if (interfaces[i].fd > 0) { - if (interfaces[i].expired) { - DEBUG("interface %i: expired\n", i); - closeInterface(&(interfaces[i])); - } else if (time(NULL) - interfaces[i].lastTime > - interface_timeout) { - DEBUG("interface %i: timeout\n", i); - closeInterface(&(interfaces[i])); - } - } - } -} - -static void flushInterfaceBuffer(Interface * interface) -{ - struct sllnode *buf; - int ret = 0; - - buf = interface->deferred_send; - while (buf) { - ret = write(interface->fd, buf->data, buf->size); - if (ret < 0) - break; - else if (ret < buf->size) { - interface->deferred_bytes -= ret; - buf->data = (char *)buf->data + ret; - buf->size -= ret; - } else { - struct sllnode *tmp = buf; - interface->deferred_bytes -= (buf->size + - sizeof(struct sllnode)); - buf = buf->next; - free(tmp); - interface->deferred_send = buf; - } - interface->lastTime = time(NULL); - } - - if (!interface->deferred_send) { - DEBUG("interface %i: buffer empty %i\n", interface->num, - interface->deferred_bytes); - assert(interface->deferred_bytes == 0); - } else if (ret < 0 && errno != EAGAIN && errno != EINTR) { - /* cause interface to close */ - DEBUG("interface %i: problems flushing buffer\n", - interface->num); - buf = interface->deferred_send; - do { - struct sllnode *prev = buf; - buf = buf->next; - free(prev); - } while (buf); - interface->deferred_send = NULL; - interface->deferred_bytes = 0; - interface->expired = 1; - } -} - -int interfacePrintWithFD(int fd, char *buffer, int buflen) -{ - static int i; - int copylen; - Interface *interface; - - assert(fd > 0); - - if (i >= interface_max_connections || - interfaces[i].fd < 0 || interfaces[i].fd != fd) { - for (i = 0; i < interface_max_connections; i++) { - if (interfaces[i].fd == fd) - break; - } - if (i == interface_max_connections) - return -1; - } - - /* if fd isn't found or interfaces is going to be closed, do nothing */ - if (interfaces[i].expired) - return 0; - - interface = interfaces + i; - - while (buflen > 0 && !interface->expired) { - int left = interface->send_buf_size - interface->send_buf_used; - copylen = buflen > left ? left : buflen; - memcpy(interface->send_buf + interface->send_buf_used, buffer, - copylen); - buflen -= copylen; - interface->send_buf_used += copylen; - buffer += copylen; - if (interface->send_buf_used >= interface->send_buf_size) - printInterfaceOutBuffer(interface); - } - - return 0; -} - -static void printInterfaceOutBuffer(Interface * interface) -{ - int ret; - struct sllnode *buf; - - if (interface->fd < 0 || interface->expired || - !interface->send_buf_used) - return; - - if ((buf = interface->deferred_send)) { - interface->deferred_bytes += sizeof(struct sllnode) - + interface->send_buf_used; - if (interface->deferred_bytes > - interface_max_output_buffer_size) { - ERROR("interface %i: output buffer size (%li) is " - "larger than the max (%li)\n", - interface->num, - (long)interface->deferred_bytes, - (long)interface_max_output_buffer_size); - /* cause interface to close */ - interface->expired = 1; - do { - struct sllnode *prev = buf; - buf = buf->next; - free(prev); - } while (buf); - interface->deferred_send = NULL; - interface->deferred_bytes = 0; - } else { - while (buf->next) - buf = buf->next; - buf->next = new_sllnode(interface->send_buf, - interface->send_buf_used); - } - } else { - if ((ret = write(interface->fd, interface->send_buf, - interface->send_buf_used)) < 0) { - if (errno == EAGAIN || errno == EINTR) { - interface->deferred_send = - new_sllnode(interface->send_buf, - interface->send_buf_used); - } else { - DEBUG("interface %i: problems writing\n", - interface->num); - interface->expired = 1; - return; - } - } else if (ret < interface->send_buf_used) { - interface->deferred_send = - new_sllnode(interface->send_buf + ret, - interface->send_buf_used - ret); - } - if (interface->deferred_send) { - DEBUG("interface %i: buffer created\n", interface->num); - interface->deferred_bytes = - interface->deferred_send->size - + sizeof(struct sllnode); - } - } - - interface->send_buf_used = 0; -} - -/* From ioops.h: */ -void registerIO( struct ioOps *ops ) -{ - assert( ops != NULL ); - - ops->next = ioList; - ioList = ops; - ops->prev = NULL; - if( ops->next ) - ops->next->prev = ops; -} - -void deregisterIO( struct ioOps *ops ) -{ - assert( ops != NULL ); - - if( ioList == ops ) - ioList = ops->next; - else if( ops->prev != NULL ) - ops->prev->next = ops->next; -} diff --git a/trunk/src/interface.h b/trunk/src/interface.h deleted file mode 100644 index 6f3c2c070..000000000 --- a/trunk/src/interface.h +++ /dev/null @@ -1,37 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef INTERFACE_H -#define INTERFACE_H - -#include "../config.h" - -#include <stdio.h> -#include <time.h> -#include <sys/types.h> -#include <sys/socket.h> - -void initInterfaces(void); -void openAInterface(int fd, struct sockaddr *addr); -void freeAllInterfaces(void); -void closeOldInterfaces(void); -int interfacePrintWithFD(int fd, char *buffer, int len); - -int doIOForInterfaces(void); - -#endif diff --git a/trunk/src/ioops.h b/trunk/src/ioops.h deleted file mode 100644 index e797a7153..000000000 --- a/trunk/src/ioops.h +++ /dev/null @@ -1,51 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IOOPS_H -#define IOOPS_H - -#include <sys/select.h> - -struct ioOps { - struct ioOps *prev, *next; - - /* - * Called before each 'select' statement. - * To register for IO, call FD_SET for each required queue - * Return the highest fd number you registered - */ - int (*fdset) ( fd_set *rfds, fd_set *wfds, fd_set *efds ); - - /* - * Called after each 'select' statement. - * fdCount is the number of fds total in all sets. It may be 0. - * For each fd you registered for in (fdset), you should FD_CLR it from the - * appropriate queue(s). - * Return the total number of fds left in all sets (Ie, return fdCount - * minus the number of times you called FD_CLR). - */ - int (*consume) ( int fdCount, fd_set *rfds, fd_set *wfds, fd_set *efds ); -}; - -/* Call this to register your io operation handler struct */ -void registerIO( struct ioOps *ops ); - -/* Call this to deregister your io operation handler struct */ -void deregisterIO( struct ioOps *ops ); - -#endif diff --git a/trunk/src/list.c b/trunk/src/list.c deleted file mode 100644 index 71c30f7b6..000000000 --- a/trunk/src/list.c +++ /dev/null @@ -1,519 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "list.h" -#include "utils.h" - -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <time.h> -#include <stdio.h> - -static void makeListNodesArray(List * list) -{ - ListNode *node = list->firstNode; - long i; - - if (!list->numberOfNodes) - return; - - list->nodesArray = xrealloc(list->nodesArray, - sizeof(ListNode *) * list->numberOfNodes); - - for (i = 0; i < list->numberOfNodes; i++) { - list->nodesArray[i] = node; - node = node->nextNode; - } -} - -static void freeListNodesArray(List * list) -{ - if (!list->nodesArray) - return; - free(list->nodesArray); - list->nodesArray = NULL; -} - -List *makeList(ListFreeDataFunc * freeDataFunc, int strdupKeys) -{ - List *list = xmalloc(sizeof(List)); - - assert(list != NULL); - - list->sorted = 0; - list->firstNode = NULL; - list->lastNode = NULL; - list->freeDataFunc = freeDataFunc; - list->numberOfNodes = 0; - list->nodesArray = NULL; - list->strdupKeys = strdupKeys; - - return list; -} - -ListNode *insertInListBeforeNode(List * list, ListNode * beforeNode, int pos, - char *key, void *data) -{ - ListNode *node; - - assert(list != NULL); - assert(key != NULL); - /*assert(data!=NULL); */ - - node = xmalloc(sizeof(ListNode)); - assert(node != NULL); - - node->nextNode = beforeNode; - if (beforeNode == list->firstNode) { - if (list->firstNode == NULL) { - assert(list->lastNode == NULL); - list->lastNode = node; - } else { - assert(list->lastNode != NULL); - assert(list->lastNode->nextNode == NULL); - list->firstNode->prevNode = node; - } - node->prevNode = NULL; - list->firstNode = node; - } else { - if (beforeNode) { - node->prevNode = beforeNode->prevNode; - beforeNode->prevNode = node; - } else { - node->prevNode = list->lastNode; - list->lastNode = node; - } - node->prevNode->nextNode = node; - } - - if (list->strdupKeys) - node->key = xstrdup(key); - else - node->key = key; - - node->data = data; - - list->numberOfNodes++; - - if (list->sorted) { - list->nodesArray = xrealloc(list->nodesArray, - list->numberOfNodes * - sizeof(ListNode *)); - if (node == list->lastNode) { - list->nodesArray[list->numberOfNodes - 1] = node; - } else if (pos < 0) - makeListNodesArray(list); - else { - memmove(list->nodesArray + pos + 1, - list->nodesArray + pos, - sizeof(ListNode *) * (list->numberOfNodes - - pos - 1)); - list->nodesArray[pos] = node; - } - } - - return node; -} - -ListNode *insertInList(List * list, char *key, void *data) -{ - ListNode *node; - - assert(list != NULL); - assert(key != NULL); - /*assert(data!=NULL); */ - - node = xmalloc(sizeof(ListNode)); - assert(node != NULL); - - if (list->nodesArray) - freeListNodesArray(list); - - if (list->firstNode == NULL) { - assert(list->lastNode == NULL); - list->firstNode = node; - } else { - assert(list->lastNode != NULL); - assert(list->lastNode->nextNode == NULL); - list->lastNode->nextNode = node; - } - - if (list->strdupKeys) - node->key = xstrdup(key); - else - node->key = key; - - node->data = data; - node->nextNode = NULL; - node->prevNode = list->lastNode; - - list->lastNode = node; - - list->numberOfNodes++; - - return node; -} - -int insertInListWithoutKey(List * list, void *data) -{ - ListNode *node; - - assert(list != NULL); - assert(data != NULL); - - node = xmalloc(sizeof(ListNode)); - assert(node != NULL); - - if (list->nodesArray) - freeListNodesArray(list); - - if (list->firstNode == NULL) { - assert(list->lastNode == NULL); - list->firstNode = node; - } else { - assert(list->lastNode != NULL); - assert(list->lastNode->nextNode == NULL); - list->lastNode->nextNode = node; - } - - node->key = NULL; - node->data = data; - node->nextNode = NULL; - node->prevNode = list->lastNode; - - list->lastNode = node; - - list->numberOfNodes++; - - return 1; -} - -/* if _key_ is not found, *_node_ is assigned to the node before which - the info would be found */ -int findNodeInList(List * list, char *key, ListNode ** node, int *pos) -{ - long high; - long low; - long cur; - ListNode *tmpNode; - int cmp; - - assert(list != NULL); - - if (list->sorted && list->nodesArray) { - high = list->numberOfNodes - 1; - low = 0; - cur = high; - - while (high > low) { - cur = (high + low) / 2; - tmpNode = list->nodesArray[cur]; - cmp = strcmp(tmpNode->key, key); - if (cmp == 0) { - *node = tmpNode; - *pos = cur; - return 1; - } else if (cmp > 0) - high = cur; - else { - if (low == cur) - break; - low = cur; - } - } - - cur = high; - if (cur >= 0) { - tmpNode = list->nodesArray[cur]; - *node = tmpNode; - *pos = high; - cmp = tmpNode ? strcmp(tmpNode->key, key) : -1; - if (0 == cmp) - return 1; - else if (cmp > 0) - return 0; - else { - *pos = -1; - *node = NULL; - return 0; - } - } else { - *pos = 0; - *node = list->firstNode; - return 0; - } - } else { - tmpNode = list->firstNode; - - while (tmpNode != NULL && strcmp(tmpNode->key, key) != 0) { - tmpNode = tmpNode->nextNode; - } - - *node = tmpNode; - if (tmpNode) - return 1; - } - - 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 0; -} - -int deleteFromList(List * list, char *key) -{ - ListNode *tmpNode; - - assert(list != NULL); - - tmpNode = list->firstNode; - - while (tmpNode != NULL && strcmp(tmpNode->key, key) != 0) { - tmpNode = tmpNode->nextNode; - } - - if (tmpNode != NULL) - deleteNodeFromList(list, tmpNode); - else - return 0; - - return 1; -} - -void deleteNodeFromList(List * list, ListNode * node) -{ - assert(list != NULL); - assert(node != NULL); - - if (node->prevNode == NULL) { - list->firstNode = node->nextNode; - } else { - node->prevNode->nextNode = node->nextNode; - } - if (node->nextNode == NULL) { - list->lastNode = node->prevNode; - } else { - node->nextNode->prevNode = node->prevNode; - } - if (list->freeDataFunc) { - list->freeDataFunc(node->data); - } - - if (list->strdupKeys) - free(node->key); - free(node); - list->numberOfNodes--; - - if (list->nodesArray) { - freeListNodesArray(list); - if (list->sorted) - makeListNodesArray(list); - } - -} - -void freeList(void *list) -{ - ListNode *tmpNode; - ListNode *tmpNode2; - - assert(list != NULL); - - tmpNode = ((List *) list)->firstNode; - - if (((List *) list)->nodesArray) - free(((List *) list)->nodesArray); - - while (tmpNode != NULL) { - tmpNode2 = tmpNode->nextNode; - if (((List *) list)->strdupKeys) - free(tmpNode->key); - if (((List *) list)->freeDataFunc) { - ((List *) list)->freeDataFunc(tmpNode->data); - } - free(tmpNode); - tmpNode = tmpNode2; - } - - free(list); -} - -static void swapNodes(ListNode * nodeA, ListNode * nodeB) -{ - char *key; - void *data; - - assert(nodeA != NULL); - assert(nodeB != NULL); - - key = nodeB->key; - data = nodeB->data; - - nodeB->key = nodeA->key; - nodeB->data = nodeA->data; - - nodeA->key = key; - nodeA->data = data; -} - -static void bubbleSort(ListNode ** nodesArray, long start, long end) -{ - long i; - long j; - ListNode *node; - - if (start >= end) - return; - - for (j = start; j < end; j++) { - for (i = end - 1; i >= start; i--) { - node = nodesArray[i]; - if (strcmp(node->key, node->nextNode->key) > 0) { - swapNodes(node, node->nextNode); - } - } - } -} - -static void quickSort(ListNode ** nodesArray, long start, long end) -{ - if (start >= end) - return; - else if (end - start < 5) - bubbleSort(nodesArray, start, end); - else { - long i; - ListNode *node; - long pivot; - ListNode *pivotNode; - char *pivotKey; - - List *startList = makeList(free, 0); - List *endList = makeList(free, 0); - long *startPtr = xmalloc(sizeof(long)); - long *endPtr = xmalloc(sizeof(long)); - *startPtr = start; - *endPtr = end; - insertInListWithoutKey(startList, (void *)startPtr); - insertInListWithoutKey(endList, (void *)endPtr); - - while (startList->numberOfNodes) { - start = *((long *)startList->lastNode->data); - end = *((long *)endList->lastNode->data); - - if (end - start < 5) { - bubbleSort(nodesArray, start, end); - deleteNodeFromList(startList, - startList->lastNode); - deleteNodeFromList(endList, endList->lastNode); - } else { - pivot = (start + end) / 2; - pivotNode = nodesArray[pivot]; - pivotKey = pivotNode->key; - - for (i = pivot - 1; i >= start; i--) { - node = nodesArray[i]; - if (strcmp(node->key, pivotKey) > 0) { - pivot--; - if (pivot > i) { - swapNodes(node, - nodesArray - [pivot]); - } - swapNodes(pivotNode, - nodesArray[pivot]); - pivotNode = nodesArray[pivot]; - } - } - for (i = pivot + 1; i <= end; i++) { - node = nodesArray[i]; - if (strcmp(pivotKey, node->key) > 0) { - pivot++; - if (pivot < i) { - swapNodes(node, - nodesArray - [pivot]); - } - swapNodes(pivotNode, - nodesArray[pivot]); - pivotNode = nodesArray[pivot]; - } - } - - deleteNodeFromList(startList, - startList->lastNode); - deleteNodeFromList(endList, endList->lastNode); - - if (pivot - 1 - start > 0) { - startPtr = xmalloc(sizeof(long)); - endPtr = xmalloc(sizeof(long)); - *startPtr = start; - *endPtr = pivot - 1; - insertInListWithoutKey(startList, - (void *) - startPtr); - insertInListWithoutKey(endList, - (void *)endPtr); - } - - if (end - pivot - 1 > 0) { - startPtr = xmalloc(sizeof(long)); - endPtr = xmalloc(sizeof(long)); - *startPtr = pivot + 1; - *endPtr = end; - insertInListWithoutKey(startList, - (void *) - startPtr); - insertInListWithoutKey(endList, - (void *)endPtr); - } - } - } - - freeList(startList); - freeList(endList); - } -} - -void sortList(List * list) -{ - assert(list != NULL); - - list->sorted = 1; - - if (list->numberOfNodes < 2) - return; - - if (list->nodesArray) - freeListNodesArray(list); - makeListNodesArray(list); - - quickSort(list->nodesArray, 0, list->numberOfNodes - 1); -} diff --git a/trunk/src/list.h b/trunk/src/list.h deleted file mode 100644 index 5938934ff..000000000 --- a/trunk/src/list.h +++ /dev/null @@ -1,110 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef LIST_H -#define LIST_H - -#include "../config.h" - -#include <stdlib.h> - -/* used to make a list where free() will be used to free data in list */ -#define DEFAULT_FREE_DATA_FUNC free - -/* typedef for function to free data stored in the list nodes */ -typedef void ListFreeDataFunc(void *); - -typedef struct _ListNode { - /* used to identify node (ie. when using findInList) */ - char *key; - /* data store in node */ - void *data; - /* next node in list */ - struct _ListNode *nextNode; - /* previous node in list */ - struct _ListNode *prevNode; -} ListNode; - -typedef struct _List { - /* first node in list */ - ListNode *firstNode; - /* last node in list */ - ListNode *lastNode; - /* function used to free data stored in nodes of the list */ - ListFreeDataFunc *freeDataFunc; - /* number of nodes */ - long numberOfNodes; - /* array for searching when list is sorted */ - ListNode **nodesArray; - /* sorted */ - int sorted; - /* whether to strdup() key's on insertion */ - int strdupKeys; -} List; - -/* allocates memory for a new list and initializes it - * _freeDataFunc_ -> pointer to function used to free data, use - * DEFAULT_FREE_DATAFUNC to use free() - * returns pointer to new list if successful, NULL otherwise - */ -List *makeList(ListFreeDataFunc * freeDataFunc, int strdupKeys); - -/* inserts a node into _list_ with _key_ and _data_ - * _list_ -> list the data will be inserted in - * _key_ -> identifier for node/data to be inserted into list - * _data_ -> data to be inserted in list - * returns 1 if successful, 0 otherwise - */ -ListNode *insertInList(List * list, char *key, void *data); - -ListNode *insertInListBeforeNode(List * list, ListNode * beforeNode, - int pos, char *key, void *data); - -int insertInListWithoutKey(List * list, void *data); - -/* deletes the first node in the list with the key _key_ - * _list_ -> list the node will be deleted from - * _key_ -> key used to identify node to delete - * returns 1 if node is found and deleted, 0 otherwise - */ -int deleteFromList(List * list, char *key); - -void deleteNodeFromList(List * list, ListNode * node); - -/* finds data in a list based on key - * _list_ -> list to search for _key_ in - * _key_ -> which node is being searched for - * _data_ -> a pointer to where data will be placed, - * _data_ memory should not by allocated or freed - * _data_ can be NULL - * returns 1 if successful, 0 otherwise - */ -int findInList(List * list, char *key, void **data); - -/* if _key_ is not found, *_node_ is assigned to the node before which - the info would be found */ -int findNodeInList(List * list, char *key, ListNode ** node, int *pos); - -/* frees memory malloc'd for list and its nodes - * _list_ -> List to be free'd - */ -void freeList(void *list); - -void sortList(List * list); - -#endif diff --git a/trunk/src/listen.c b/trunk/src/listen.c deleted file mode 100644 index 323bf430f..000000000 --- a/trunk/src/listen.c +++ /dev/null @@ -1,258 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "listen.h" -#include "interface.h" -#include "conf.h" -#include "log.h" -#include "utils.h" - -#include <stdio.h> -#include <stdlib.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <netinet/in.h> -#include <netdb.h> -#include <string.h> -#include <errno.h> -#include <resolv.h> -#include <fcntl.h> - -#define MAXHOSTNAME 1024 - -#define ALLOW_REUSE 1 - -#define DEFAULT_PORT 6600 - -#define BINDERROR() do { \ - FATAL("unable to bind port %u: %s\n" \ - "maybe MPD is still running?\n", \ - port, strerror(errno)); \ -} while (0); - -static int *listenSockets; -static int numberOfListenSockets; -static int boundPort; - -static int establishListen(unsigned int port, - struct sockaddr *addrp, socklen_t addrlen) -{ - int pf = 0; - int sock; - int allowReuse = ALLOW_REUSE; - - switch (addrp->sa_family) { - case AF_INET: - pf = PF_INET; - break; -#ifdef HAVE_IPV6 - case AF_INET6: - pf = PF_INET6; - break; -#endif - case AF_UNIX: - pf = PF_UNIX; - break; - default: - FATAL("unknown address family: %i\n", addrp->sa_family); - } - - if ((sock = socket(pf, SOCK_STREAM, 0)) < 0) - FATAL("socket < 0\n"); - - if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) < 0) { - FATAL("problems setting nonblocking on listen socket: %s\n", - strerror(errno)); - } - - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&allowReuse, - sizeof(allowReuse)) < 0) { - FATAL("problems setsockopt'ing: %s\n", strerror(errno)); - } - - if (bind(sock, addrp, addrlen) < 0) { - close(sock); - return -1; - } - - if (listen(sock, 5) < 0) - FATAL("problems listen'ing: %s\n", strerror(errno)); - - numberOfListenSockets++; - listenSockets = - xrealloc(listenSockets, sizeof(int) * numberOfListenSockets); - - listenSockets[numberOfListenSockets - 1] = sock; - - return 0; -} - -static void parseListenConfigParam(unsigned int port, ConfigParam * param) -{ - struct sockaddr *addrp = NULL; - socklen_t addrlen = 0; - struct sockaddr_in sin; -#ifdef HAVE_IPV6 - struct sockaddr_in6 sin6; - int useIpv6 = ipv6Supported(); - - memset(&sin6, 0, sizeof(struct sockaddr_in6)); - sin6.sin6_port = htons(port); - sin6.sin6_family = AF_INET6; -#endif - memset(&sin, 0, sizeof(struct sockaddr_in)); - sin.sin_port = htons(port); - sin.sin_family = AF_INET; - - if (!param || 0 == strcmp(param->value, "any")) { - DEBUG("binding to any address\n"); -#ifdef HAVE_IPV6 - if (useIpv6) { - sin6.sin6_addr = in6addr_any; - addrp = (struct sockaddr *)&sin6; - addrlen = sizeof(struct sockaddr_in6); - if (establishListen(port, addrp, addrlen) < 0) - BINDERROR(); - } -#endif - sin.sin_addr.s_addr = INADDR_ANY; - addrp = (struct sockaddr *)&sin; - addrlen = sizeof(struct sockaddr_in); -#ifdef HAVE_IPV6 - if ((establishListen(port, addrp, addrlen) < 0) && !useIpv6) { -#else - if (establishListen(port, addrp, addrlen) < 0) { -#endif - BINDERROR(); - } - } else { - struct hostent *he; - DEBUG("binding to address for %s\n", param->value); - if (!(he = gethostbyname(param->value))) { - FATAL("can't lookup host \"%s\" at line %i\n", - param->value, param->line); - } - switch (he->h_addrtype) { -#ifdef HAVE_IPV6 - case AF_INET6: - if (!useIpv6) { - FATAL("no IPv6 support, but a IPv6 address " - "found for \"%s\" at line %i\n", - param->value, param->line); - } - memcpy((char *)&sin6.sin6_addr.s6_addr, - (char *)he->h_addr, he->h_length); - addrp = (struct sockaddr *)&sin6; - addrlen = sizeof(struct sockaddr_in6); - break; -#endif - case AF_INET: - memcpy((char *)&sin.sin_addr.s_addr, - (char *)he->h_addr, he->h_length); - addrp = (struct sockaddr *)&sin; - addrlen = sizeof(struct sockaddr_in); - break; - default: - FATAL("address type for \"%s\" is not IPv4 or IPv6 " - "at line %i\n", param->value, param->line); - } - - if (establishListen(port, addrp, addrlen) < 0) - BINDERROR(); - } -} - -void listenOnPort(void) -{ - int port = DEFAULT_PORT; - ConfigParam *param = getNextConfigParam(CONF_BIND_TO_ADDRESS, NULL); - ConfigParam *portParam = getConfigParam(CONF_PORT); - - if (portParam) { - char *test; - port = strtol(portParam->value, &test, 10); - if (port <= 0 || *test != '\0') { - FATAL("%s \"%s\" specified at line %i is not a " - "positive integer", CONF_PORT, - portParam->value, portParam->line); - } - } - - boundPort = port; - - do { - parseListenConfigParam(port, param); - } while ((param = getNextConfigParam(CONF_BIND_TO_ADDRESS, param))); -} - -void addListenSocketsToFdSet(fd_set * fds, int *fdmax) -{ - int i; - - for (i = 0; i < numberOfListenSockets; i++) { - FD_SET(listenSockets[i], fds); - if (listenSockets[i] > *fdmax) - *fdmax = listenSockets[i]; - } -} - -void closeAllListenSockets(void) -{ - int i; - - DEBUG("closeAllListenSockets called\n"); - - for (i = 0; i < numberOfListenSockets; i++) { - DEBUG("closing listen socket %i\n", i); - while (close(listenSockets[i]) < 0 && errno == EINTR) ; - } - freeAllListenSockets(); -} - -void freeAllListenSockets(void) -{ - numberOfListenSockets = 0; - free(listenSockets); - listenSockets = NULL; -} - -void getConnections(fd_set * fds) -{ - int i; - int fd = 0; - struct sockaddr sockAddr; - socklen_t socklen = sizeof(sockAddr); - - for (i = 0; i < numberOfListenSockets; i++) { - if (FD_ISSET(listenSockets[i], fds)) { - if ((fd = accept(listenSockets[i], &sockAddr, &socklen)) - >= 0) { - openAInterface(fd, &sockAddr); - } else if (fd < 0 - && (errno != EAGAIN && errno != EINTR)) { - ERROR("Problems accept()'ing\n"); - } - } - } -} - -int getBoundPort(void) -{ - return boundPort; -} diff --git a/trunk/src/listen.h b/trunk/src/listen.h deleted file mode 100644 index 638214003..000000000 --- a/trunk/src/listen.h +++ /dev/null @@ -1,41 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef LISTEN_H -#define LISTEN_H - -#include "../config.h" - -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#include <sys/select.h> - -void listenOnPort(void); - -void getConnections(fd_set * fds); - -void closeAllListenSockets(void); -void freeAllListenSockets(void); - -/* fdmax should be initialized to something */ -void addListenSocketsToFdSet(fd_set * fds, int *fdmax); - -int getBoundPort(void); - -#endif diff --git a/trunk/src/locate.c b/trunk/src/locate.c deleted file mode 100644 index 7c3bab899..000000000 --- a/trunk/src/locate.c +++ /dev/null @@ -1,211 +0,0 @@ -/* the Music Player Daemon (MPD) - * (c)2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "locate.h" - -#include "utils.h" - -#define LOCATE_TAG_FILE_KEY "file" -#define LOCATE_TAG_FILE_KEY_OLD "filename" -#define LOCATE_TAG_ANY_KEY "any" - -int getLocateTagItemType(char *str) -{ - int i; - - if (0 == strcasecmp(str, LOCATE_TAG_FILE_KEY) || - 0 == strcasecmp(str, LOCATE_TAG_FILE_KEY_OLD)) - { - return LOCATE_TAG_FILE_TYPE; - } - - if (0 == strcasecmp(str, LOCATE_TAG_ANY_KEY)) - { - return LOCATE_TAG_ANY_TYPE; - } - - for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) - { - if (0 == strcasecmp(str, mpdTagItemKeys[i])) - return i; - } - - return -1; -} - -static int initLocateTagItem(LocateTagItem * item, char *typeStr, char *needle) -{ - item->tagType = getLocateTagItemType(typeStr); - - if (item->tagType < 0) - return -1; - - item->needle = xstrdup(needle); - - return 0; -} - -LocateTagItem *newLocateTagItem(char *typeStr, char *needle) -{ - LocateTagItem *ret = xmalloc(sizeof(LocateTagItem)); - - if (initLocateTagItem(ret, typeStr, needle) < 0) { - free(ret); - ret = NULL; - } - - return ret; -} - -void freeLocateTagItemArray(int count, LocateTagItem * array) -{ - int i; - - for (i = 0; i < count; i++) - free(array[i].needle); - - free(array); -} - -int newLocateTagItemArrayFromArgArray(char *argArray[], - int numArgs, LocateTagItem ** arrayRet) -{ - int i, j; - LocateTagItem *item; - - if (numArgs == 0) - return 0; - - if (numArgs % 2 != 0) - return -1; - - *arrayRet = xmalloc(sizeof(LocateTagItem) * numArgs / 2); - - for (i = 0, item = *arrayRet; i < numArgs / 2; i++, item++) { - if (initLocateTagItem - (item, argArray[i * 2], argArray[i * 2 + 1]) < 0) - goto fail; - } - - return numArgs / 2; - -fail: - for (j = 0; j < i; j++) { - free((*arrayRet)[j].needle); - } - - free(*arrayRet); - *arrayRet = NULL; - return -1; -} - -void freeLocateTagItem(LocateTagItem * item) -{ - free(item->needle); - free(item); -} - -static int strstrSearchTag(Song * song, int type, char *str) -{ - int i; - char *dup; - int ret = 0; - - if (type == LOCATE_TAG_FILE_TYPE || type == LOCATE_TAG_ANY_TYPE) { - dup = strDupToUpper(getSongUrl(song)); - if (strstr(dup, str)) - ret = 1; - free(dup); - if (ret == 1 || type == LOCATE_TAG_FILE_TYPE) { - return ret; - } - } - - if (!song->tag) - return 0; - - for (i = 0; i < song->tag->numOfItems && !ret; i++) { - if (type != LOCATE_TAG_ANY_TYPE && - song->tag->items[i].type != type) { - continue; - } - - dup = strDupToUpper(song->tag->items[i].value); - if (strstr(dup, str)) - ret = 1; - free(dup); - } - - return ret; -} - -int strstrSearchTags(Song * song, int numItems, LocateTagItem * items) -{ - int i; - - for (i = 0; i < numItems; i++) { - if (!strstrSearchTag(song, items[i].tagType, - items[i].needle)) { - return 0; - } - } - - return 1; -} - -static int tagItemFoundAndMatches(Song * song, int type, char *str) -{ - int i; - - if (type == LOCATE_TAG_FILE_TYPE || type == LOCATE_TAG_ANY_TYPE) { - if (0 == strcmp(str, getSongUrl(song))) - return 1; - if (type == LOCATE_TAG_FILE_TYPE) - return 0; - } - - if (!song->tag) - return 0; - - for (i = 0; i < song->tag->numOfItems; i++) { - if (type != LOCATE_TAG_ANY_TYPE && - song->tag->items[i].type != type) { - continue; - } - - if (0 == strcmp(str, song->tag->items[i].value)) - return 1; - } - - return 0; -} - - -int tagItemsFoundAndMatches(Song * song, int numItems, LocateTagItem * items) -{ - int i; - - for (i = 0; i < numItems; i++) { - if (!tagItemFoundAndMatches(song, items[i].tagType, - items[i].needle)) { - return 0; - } - } - - return 1; -} diff --git a/trunk/src/locate.h b/trunk/src/locate.h deleted file mode 100644 index c165a310a..000000000 --- a/trunk/src/locate.h +++ /dev/null @@ -1,46 +0,0 @@ -/* the Music Player Daemon (MPD) - * (c)2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "song.h" - -#define LOCATE_TAG_FILE_TYPE TAG_NUM_OF_ITEM_TYPES+10 -#define LOCATE_TAG_ANY_TYPE TAG_NUM_OF_ITEM_TYPES+20 - -/* struct used for search, find, list queries */ -typedef struct _LocateTagItem { - mpd_sint8 tagType; - /* what we are looking for */ - char *needle; -} LocateTagItem; - -int getLocateTagItemType(char *str); - -/* returns NULL if not a known type */ -LocateTagItem *newLocateTagItem(char *typeString, char *needle); - -/* return number of items or -1 on error */ -int newLocateTagItemArrayFromArgArray(char *argArray[], int numArgs, - LocateTagItem ** arrayRet); - -void freeLocateTagItemArray(int count, LocateTagItem * array); - -void freeLocateTagItem(LocateTagItem * item); - -int strstrSearchTags(Song * song, int numItems, LocateTagItem * items); - -int tagItemsFoundAndMatches(Song * song, int numItems, LocateTagItem * items); diff --git a/trunk/src/log.c b/trunk/src/log.c deleted file mode 100644 index fa4ae64f0..000000000 --- a/trunk/src/log.c +++ /dev/null @@ -1,262 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "log.h" - -#include "conf.h" -#include "myfprintf.h" -#include "utils.h" - -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <time.h> - -static unsigned int logLevel = LOG_LEVEL_LOW; -static int warningFlushed; -static int stdout_mode = 1; -static char *warningBuffer; -static int out_fd = -1; -static int err_fd = -1; -static const char *out_filename; -static const char *err_filename; - -/* redirect stdin to /dev/null to work around a libao bug */ -static void redirect_stdin(void) -{ - int fd; - if ((fd = open("/dev/null", O_RDONLY)) < 0) - FATAL("failed to open /dev/null %s\n", strerror(errno)); - if (dup2(fd, STDIN_FILENO) < 0) - FATAL("dup2 stdin: %s\n", strerror(errno)); -} - -static void redirect_logs(void) -{ - assert(out_fd > 0); - assert(err_fd > 0); - if (dup2(out_fd, STDOUT_FILENO) < 0) - FATAL("problems dup2 stdout : %s\n", strerror(errno)); - if (dup2(err_fd, STDERR_FILENO) < 0) - FATAL("problems dup2 stderr : %s\n", strerror(errno)); -} - -static const char *log_date(void) -{ - static char buf[16]; - time_t t = time(NULL); - strftime(buf, 16, "%b %d %H:%M : ", localtime(&t)); - return buf; -} - -#define BUFFER_LENGTH 4096 -static void buffer_warning(const char *fmt, va_list args) -{ - char buffer[BUFFER_LENGTH]; - char *tmp = buffer; - size_t len = BUFFER_LENGTH; - - if (!stdout_mode) { - memcpy(buffer, log_date(), 15); - tmp += 15; - len -= 15; - } - - vsnprintf(tmp, len, fmt, args); - warningBuffer = appendToString(warningBuffer, buffer); - - va_end(args); -} - -static void do_log(FILE *fp, const char *fmt, va_list args) -{ - if (!stdout_mode) - fwrite(log_date(), 15, 1, fp); - vfprintf(fp, fmt, args); -} - -void flushWarningLog(void) -{ - char *s = warningBuffer; - - DEBUG("flushing warning messages\n"); - - if (warningBuffer != NULL) - { - while (s != NULL) { - char *next = strchr(s, '\n'); - if (next == NULL) break; - *next = '\0'; - next++; - fprintf(stderr, "%s\n", s); - s = next; - } - - warningBuffer = NULL; - } - - warningFlushed = 1; - - DEBUG("done flushing warning messages\n"); -} - -void initLog(const int verbose) -{ - ConfigParam *param; - - /* unbuffer stdout, stderr is unbuffered by default, leave it */ - setvbuf(stdout, (char *)NULL, _IONBF, 0); - - if (verbose) { - logLevel = LOG_LEVEL_DEBUG; - return; - } - if (!(param = getConfigParam(CONF_LOG_LEVEL))) - return; - if (0 == strcmp(param->value, "default")) { - logLevel = LOG_LEVEL_LOW; - } else if (0 == strcmp(param->value, "secure")) { - logLevel = LOG_LEVEL_SECURE; - } else if (0 == strcmp(param->value, "verbose")) { - logLevel = LOG_LEVEL_DEBUG; - } else { - FATAL("unknown log level \"%s\" at line %i\n", - param->value, param->line); - } -} - -void open_log_files(const int use_stdout) -{ - mode_t prev; - ConfigParam *param; - - if (use_stdout) { - flushWarningLog(); - return; - } - - prev = umask(0066); - param = parseConfigFilePath(CONF_LOG_FILE, 1); - out_filename = param->value; - out_fd = open(out_filename, O_CREAT | O_WRONLY | O_APPEND, 0666); - if (out_fd < 0) - FATAL("problem opening log file \"%s\" (config line %i) for " - "writing\n", param->value, param->line); - - param = parseConfigFilePath(CONF_ERROR_FILE, 1); - err_filename = param->value; - err_fd = open(err_filename, O_CREAT | O_WRONLY | O_APPEND, 0666); - if (err_fd < 0) - FATAL("problem opening error file \"%s\" (config line %i) for " - "writing\n", param->value, param->line); - - umask(prev); -} - -void setup_log_output(const int use_stdout) -{ - fflush(NULL); - if (!use_stdout) { - redirect_logs(); - stdout_mode = 0; - } - redirect_stdin(); -} - -#define log_func(func,level,fp) \ -mpd_printf void func(const char *fmt, ...) \ -{ \ - if (logLevel >= level) { \ - va_list args; \ - va_start(args, fmt); \ - do_log(fp, fmt, args); \ - va_end(args); \ - } \ -} - -log_func(ERROR, 0, stderr) -log_func(LOG, 0, stdout) -log_func(SECURE, LOG_LEVEL_SECURE, stdout) -log_func(DEBUG, LOG_LEVEL_DEBUG, stdout) - -#undef log_func - -void WARNING(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - if (warningFlushed) { - do_log(stderr, fmt, args); - } else - buffer_warning(fmt, args); - va_end(args); -} - -mpd_printf mpd_noreturn void FATAL(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - do_log(stderr, fmt, args); - va_end(args); - exit(EXIT_FAILURE); -} - -int cycle_log_files(void) -{ - mode_t prev; - - if (stdout_mode) - return 0; - assert(out_filename); - assert(err_filename); - - DEBUG("Cycling log files...\n"); - close_log_files(); - - prev = umask(0066); - - out_fd = open(out_filename, O_CREAT | O_WRONLY | O_APPEND, 0666); - if (out_fd < 0) { - ERROR("error re-opening log file: %s\n", out_filename); - return -1; - } - - err_fd = open(err_filename, O_CREAT | O_WRONLY | O_APPEND, 0666); - if (err_fd < 0) { - ERROR("error re-opening error file: %s\n", err_filename); - return -1; - } - - umask(prev); - - redirect_logs(); - DEBUG("Done cycling log files\n"); - return 0; -} - -void close_log_files(void) -{ - if (stdout_mode) - return; - assert(out_fd > 0); - assert(err_fd > 0); - xclose(out_fd); - xclose(err_fd); -} - diff --git a/trunk/src/log.h b/trunk/src/log.h deleted file mode 100644 index 34f6ac00e..000000000 --- a/trunk/src/log.h +++ /dev/null @@ -1,50 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef LOG_H -#define LOG_H - -#include "../config.h" -#include "gcc.h" - -#include <unistd.h> - -#define LOG_LEVEL_LOW 0 -#define LOG_LEVEL_SECURE 1 -#define LOG_LEVEL_DEBUG 2 - -mpd_printf void ERROR(const char *fmt, ...); -mpd_printf void LOG(const char *fmt, ...); -mpd_printf void SECURE(const char *fmt, ...); -mpd_printf void DEBUG(const char *fmt, ...); -mpd_printf void WARNING(const char *fmt, ...); -mpd_printf void FATAL(const char *fmt, ...); - -void initLog(const int verbose); - -void setup_log_output(const int use_stdout); - -void open_log_files(const int use_stdout); - -int cycle_log_files(void); - -void close_log_files(void); - -void flushWarningLog(void); - -#endif /* LOG_H */ diff --git a/trunk/src/ls.c b/trunk/src/ls.c deleted file mode 100644 index 0b3f7f354..000000000 --- a/trunk/src/ls.c +++ /dev/null @@ -1,281 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ls.h" -#include "playlist.h" -#include "path.h" -#include "myfprintf.h" -#include "log.h" -#include "utf8.h" -#include "utils.h" - -#include <dirent.h> -#include <stdio.h> -#include <errno.h> - -static char *remoteUrlPrefixes[] = { - "http://", - NULL -}; - -int printRemoteUrlHandlers(int fd) -{ - char **prefixes = remoteUrlPrefixes; - - while (*prefixes) { - fdprintf(fd, "handler: %s\n", *prefixes); - prefixes++; - } - - return 0; -} - -int isValidRemoteUtf8Url(char *utf8url) -{ - int ret = 0; - char *temp; - - switch (isRemoteUrl(utf8url)) { - case 1: - ret = 1; - temp = utf8url; - while (*temp) { - if ((*temp >= 'a' && *temp <= 'z') || - (*temp >= 'A' && *temp <= 'Z') || - (*temp >= '0' && *temp <= '9') || - *temp == '$' || - *temp == '-' || - *temp == '.' || - *temp == '+' || - *temp == '!' || - *temp == '*' || - *temp == '\'' || - *temp == '(' || - *temp == ')' || - *temp == ',' || - *temp == '%' || - *temp == '/' || - *temp == ':' || - *temp == '?' || - *temp == ';' || *temp == '&' || *temp == '=') { - } else { - ret = 1; - break; - } - temp++; - } - break; - } - - return ret; -} - -int isRemoteUrl(char *url) -{ - int count = 0; - char **urlPrefixes = remoteUrlPrefixes; - - while (*urlPrefixes) { - count++; - if (strncmp(*urlPrefixes, url, strlen(*urlPrefixes)) == 0) { - return count; - } - urlPrefixes++; - } - - return 0; -} - -int lsPlaylists(int fd, char *utf8path) -{ - DIR *dir; - struct stat st; - struct dirent *ent; - char *dup; - char *utf8; - char s[MAXPATHLEN + 1]; - List *list = NULL; - ListNode *node = NULL; - char *path = utf8ToFsCharset(utf8path); - char *actualPath = rpp2app(path); - int actlen = strlen(actualPath) + 1; - int maxlen = MAXPATHLEN - actlen; - int suflen = strlen(PLAYLIST_FILE_SUFFIX) + 1; - int suff; - - if (actlen > MAXPATHLEN - 1 || (dir = opendir(actualPath)) == NULL) { - return 0; - } - - s[MAXPATHLEN] = '\0'; - /* this is safe, notice actlen > MAXPATHLEN-1 above */ - strcpy(s, actualPath); - strcat(s, "/"); - - while ((ent = readdir(dir))) { - size_t len = strlen(ent->d_name) + 1; - dup = ent->d_name; - if (mpd_likely(len <= maxlen) && - dup[0] != '.' && - (suff = strlen(dup) - suflen) > 0 && - dup[suff] == '.' && - strcmp(dup + suff + 1, PLAYLIST_FILE_SUFFIX) == 0) { - memcpy(s + actlen, ent->d_name, len); - if (stat(s, &st) == 0) { - if (S_ISREG(st.st_mode)) { - if (list == NULL) - list = makeList(NULL, 1); - dup[suff] = '\0'; - if ((utf8 = fsCharsetToUtf8(dup))) { - insertInList(list, utf8, NULL); - } - } - } - } - } - - closedir(dir); - - if (list) { - int i; - sortList(list); - - dup = xmalloc(strlen(utf8path) + 2); - strcpy(dup, utf8path); - for (i = strlen(dup) - 1; i >= 0 && dup[i] == '/'; i--) { - dup[i] = '\0'; - } - if (strlen(dup)) - strcat(dup, "/"); - - node = list->firstNode; - while (node != NULL) { - if (!strchr(node->key, '\n')) { - fdprintf(fd, "playlist: %s%s\n", dup, - node->key); - } - node = node->nextNode; - } - - freeList(list); - free(dup); - } - - return 0; -} - -int myStat(char *utf8file, struct stat *st) -{ - char *file = utf8ToFsCharset(utf8file); - char *actualFile = file; - - if (actualFile[0] != '/') - actualFile = rmp2amp(file); - - return stat(actualFile, st); -} - -static int isFile(char *utf8file, time_t * mtime) -{ - struct stat st; - - if (myStat(utf8file, &st) == 0) { - if (S_ISREG(st.st_mode)) { - if (mtime) - *mtime = st.st_mtime; - return 1; - } else { - DEBUG("isFile: %s is not a regular file\n", utf8file); - return 0; - } - } else { - DEBUG("isFile: failed to stat: %s: %s\n", utf8file, - strerror(errno)); - } - - return 0; -} - -/* suffixes should be ascii only characters */ -char *getSuffix(char *utf8file) -{ - char *ret = NULL; - - while (*utf8file) { - if (*utf8file == '.') - ret = utf8file + 1; - utf8file++; - } - - return ret; -} - -static int hasSuffix(char *utf8file, char *suffix) -{ - char *s = getSuffix(utf8file); - if (s && 0 == strcmp(s, suffix)) - return 1; - return 0; -} - -int isPlaylist(char *utf8file) -{ - if (isFile(utf8file, NULL)) { - return hasSuffix(utf8file, PLAYLIST_FILE_SUFFIX); - } - return 0; -} - -int isDir(char *utf8name) -{ - struct stat st; - - if (myStat(utf8name, &st) == 0) { - if (S_ISDIR(st.st_mode)) { - return 1; - } - } - - return 0; -} - -InputPlugin *hasMusicSuffix(char *utf8file, unsigned int next) -{ - InputPlugin *ret = NULL; - - char *s = getSuffix(utf8file); - if (s) { - ret = getInputPluginFromSuffix(s, next); - } else { - DEBUG("hasMusicSuffix: The file: %s has no valid suffix\n", - utf8file); - } - - return ret; -} - -InputPlugin *isMusic(char *utf8file, time_t * mtime, unsigned int next) -{ - if (isFile(utf8file, mtime)) { - InputPlugin *plugin = hasMusicSuffix(utf8file, next); - if (plugin != NULL) - return plugin; - } - DEBUG("isMusic: %s is not a valid file\n", utf8file); - return NULL; -} diff --git a/trunk/src/ls.h b/trunk/src/ls.h deleted file mode 100644 index 20f668bd9..000000000 --- a/trunk/src/ls.h +++ /dev/null @@ -1,52 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef LS_H -#define LS_H - -#include "../config.h" - -#include "inputPlugin.h" - -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <time.h> - -int lsPlaylists(int fd, char *utf8path); - -char *getSuffix(char *utf8file); - -int isValidRemoteUtf8Url(char *utf8url); - -int isRemoteUrl(char *url); - -int myStat(char *utf8file, struct stat *st); - -int isDir(char *utf8name); - -int isPlaylist(char *utf8file); - -InputPlugin *hasMusicSuffix(char *utf8file, unsigned int next); - -InputPlugin *isMusic(char *utf8file, time_t * mtime, unsigned int next); - -int printRemoteUrlHandlers(int fd); - -#endif diff --git a/trunk/src/main.c b/trunk/src/main.c deleted file mode 100644 index 4c537eb1d..000000000 --- a/trunk/src/main.c +++ /dev/null @@ -1,482 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "interface.h" -#include "command.h" -#include "playlist.h" -#include "directory.h" -#include "player.h" -#include "listen.h" -#include "conf.h" -#include "path.h" -#include "playerData.h" -#include "stats.h" -#include "sig_handlers.h" -#include "audio.h" -#include "volume.h" -#include "log.h" -#include "permission.h" -#include "replayGain.h" -#include "inputPlugin.h" -#include "audioOutput.h" -#include "inputStream.h" -#include "state_file.h" -#include "tag.h" -#include "tagTracker.h" -#include "dbUtils.h" -#include "../config.h" -#include "utils.h" -#include "normalize.h" -#include "zeroconf.h" - -#include <stdio.h> -#include <sys/select.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> -#include <pwd.h> -#include <grp.h> -#include <time.h> -#include <unistd.h> - -#define SYSTEM_CONFIG_FILE_LOCATION "/etc/mpd.conf" -#define USER_CONFIG_FILE_LOCATION "/.mpdconf" - -typedef struct _Options { - int kill; - int daemon; - int stdOutput; - int createDB; - int verbose; -} Options; - -/* - * from git-1.3.0, needed for solaris - */ -#ifndef HAVE_SETENV -static int setenv(const char *name, const char *value, int replace) -{ - int out; - size_t namelen, valuelen; - char *envstr; - - if (!name || !value) - return -1; - if (!replace) { - char *oldval = NULL; - oldval = getenv(name); - if (oldval) - return 0; - } - - namelen = strlen(name); - valuelen = strlen(value); - envstr = xmalloc((namelen + valuelen + 2)); - if (!envstr) - return -1; - - memcpy(envstr, name, namelen); - envstr[namelen] = '='; - memcpy(envstr + namelen + 1, value, valuelen); - envstr[namelen + valuelen + 1] = 0; - - out = putenv(envstr); - /* putenv(3) makes the argument string part of the environment, - * and changing that string modifies the environment --- which - * means we do not own that storage anymore. Do not free - * envstr. - */ - - return out; -} -#endif /* HAVE_SETENV */ - -static void usage(char *argv[]) -{ - ERROR("usage:\n"); - ERROR(" %s [options] <conf file>\n", argv[0]); - ERROR(" %s [options] (searches for ~%s then %s)\n", - argv[0], USER_CONFIG_FILE_LOCATION, SYSTEM_CONFIG_FILE_LOCATION); - ERROR("\n"); - ERROR("options:\n"); - ERROR(" --help this usage statement\n"); - ERROR(" --kill kill the currently running mpd session\n"); - ERROR - (" --create-db force (re)creation of database and exit\n"); - ERROR - (" --no-create-db don't create database, even if it doesn't exist\n"); - ERROR(" --no-daemon don't detach from console\n"); - ERROR(" --stdout print messages to stdout and stderr\n"); - ERROR(" --verbose verbose logging\n"); - ERROR(" --version prints version information\n"); -} - -static void version(void) -{ - LOG("mpd (MPD: Music Player Daemon) %s\n", VERSION); - LOG("\n"); - LOG("Copyright (C) 2003-2007 Warren Dukes <warren.dukes@gmail.com>\n"); - LOG("This is free software; see the source for copying conditions. There is NO\n"); - LOG("warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); - LOG("\n"); - LOG("Supported formats:\n"); - - initInputPlugins(); - printAllInputPluginSuffixes(stdout); - - LOG("\n"); - LOG("Supported outputs:\n"); - loadAudioDrivers(); - printAllOutputPluginTypes(stdout); -} - -static void parseOptions(int argc, char **argv, Options * options) -{ - int argcLeft = argc; - - options->verbose = 0; - options->daemon = 1; - options->stdOutput = 0; - options->createDB = 0; - options->kill = 0; - - if (argc > 1) { - int i = 1; - while (i < argc) { - if (strncmp(argv[i], "--", 2) == 0) { - if (strcmp(argv[i], "--help") == 0) { - usage(argv); - exit(EXIT_SUCCESS); - } else if (strcmp(argv[i], "--kill") == 0) { - options->kill++; - argcLeft--; - } else if (strcmp(argv[i], "--no-daemon") == 0) { - options->daemon = 0; - argcLeft--; - } else if (strcmp(argv[i], "--stdout") == 0) { - options->stdOutput = 1; - argcLeft--; - } else if (strcmp(argv[i], "--create-db") == 0) { - options->stdOutput = 1; - options->createDB = 1; - argcLeft--; - } else if (strcmp(argv[i], "--no-create-db") == - 0) { - options->createDB = -1; - argcLeft--; - } else if (strcmp(argv[i], "--verbose") == 0) { - options->verbose = 1; - argcLeft--; - } else if (strcmp(argv[i], "--version") == 0) { - version(); - exit(EXIT_SUCCESS); - } else { - fprintf(stderr, - "unknown command line option: %s\n", - argv[i]); - exit(EXIT_FAILURE); - } - } else - break; - i++; - } - } - - if (argcLeft <= 2) { - if (argcLeft == 2) { - readConf(argv[argc - 1]); - return; - } else if (argcLeft == 1) { - struct stat st; - char *homedir = getenv("HOME"); - char userfile[MAXPATHLEN + 1] = ""; - if (homedir && (strlen(homedir) + - strlen(USER_CONFIG_FILE_LOCATION)) < - MAXPATHLEN) { - strcpy(userfile, homedir); - strcat(userfile, USER_CONFIG_FILE_LOCATION); - } - if (strlen(userfile) && (0 == stat(userfile, &st))) { - readConf(userfile); - return; - } else if (0 == stat(SYSTEM_CONFIG_FILE_LOCATION, &st)) { - readConf(SYSTEM_CONFIG_FILE_LOCATION); - return; - } - } - } - - usage(argv); - exit(EXIT_FAILURE); -} - -static void closeAllFDs(void) -{ - int i; - int fds = getdtablesize(); - - for (i = 3; i < fds; i++) - close(i); -} - -static void changeToUser(void) -{ - ConfigParam *param = getConfigParam(CONF_USER); - - if (param && strlen(param->value)) { - /* get uid */ - struct passwd *userpwd; - if ((userpwd = getpwnam(param->value)) == NULL) { - FATAL("no such user \"%s\" at line %i\n", param->value, - param->line); - } - - if (setgid(userpwd->pw_gid) == -1) { - FATAL("cannot setgid for user \"%s\" at line %i: %s\n", - param->value, param->line, strerror(errno)); - } -#ifdef _BSD_SOURCE - /* init suplementary groups - * (must be done before we change our uid) - */ - if (initgroups(param->value, userpwd->pw_gid) == -1) { - WARNING("cannot init supplementary groups " - "of user \"%s\" at line %i: %s\n", - param->value, param->line, strerror(errno)); - } -#endif - - /* set uid */ - if (setuid(userpwd->pw_uid) == -1) { - FATAL("cannot change to uid of user " - "\"%s\" at line %i: %s\n", - param->value, param->line, strerror(errno)); - } - - /* this is needed by libs such as arts */ - if (userpwd->pw_dir) { - setenv("HOME", userpwd->pw_dir, 1); - } - } -} - -static void openDB(Options * options, char *argv0) -{ - if (options->createDB > 0 || readDirectoryDB() < 0) { - if (options->createDB < 0) { - FATAL("can't open db file and using " - "\"--no-create-db\" command line option\n" - "try running \"%s --create-db\"\n", argv0); - } - flushWarningLog(); - if (checkDirectoryDB() < 0) - exit(EXIT_FAILURE); - initMp3Directory(); - if (writeDirectoryDB() < 0) - exit(EXIT_FAILURE); - if (options->createDB) - exit(EXIT_SUCCESS); - } -} - -static void daemonize(Options * options) -{ - FILE *fp = NULL; - ConfigParam *pidFileParam = parseConfigFilePath(CONF_PID_FILE, 0); - - if (pidFileParam) { - /* do this before daemon'izing so we can fail gracefully if we can't - * write to the pid file */ - DEBUG("opening pid file\n"); - fp = fopen(pidFileParam->value, "w+"); - if (!fp) { - FATAL("could not open %s \"%s\" (at line %i) for writing: %s\n", - CONF_PID_FILE, pidFileParam->value, - pidFileParam->line, strerror(errno)); - } - } - - if (options->daemon) { - int pid; - - fflush(NULL); - pid = fork(); - if (pid > 0) - _exit(EXIT_SUCCESS); - else if (pid < 0) { - FATAL("problems fork'ing for daemon!\n"); - } - - if (chdir("/") < 0) { - FATAL("problems changing to root directory\n"); - } - - if (setsid() < 0) { - FATAL("problems setsid'ing\n"); - } - - fflush(NULL); - pid = fork(); - if (pid > 0) - _exit(EXIT_SUCCESS); - else if (pid < 0) { - FATAL("problems fork'ing for daemon!\n"); - } - - DEBUG("daemonized!\n"); - } - - if (pidFileParam) { - DEBUG("writing pid file\n"); - fprintf(fp, "%lu\n", (unsigned long)getpid()); - fclose(fp); - } -} - -static void cleanUpPidFile(void) -{ - ConfigParam *pidFileParam = parseConfigFilePath(CONF_PID_FILE, 0); - - if (!pidFileParam) - return; - - DEBUG("cleaning up pid file\n"); - - unlink(pidFileParam->value); -} - -static void killFromPidFile(char *cmd, int killOption) -{ - FILE *fp; - ConfigParam *pidFileParam = parseConfigFilePath(CONF_PID_FILE, 0); - int pid; - - if (!pidFileParam) { - FATAL("no pid_file specified in the config file\n"); - } - - fp = fopen(pidFileParam->value, "r"); - if (!fp) { - FATAL("unable to open %s \"%s\": %s\n", - CONF_PID_FILE, pidFileParam->value, strerror(errno)); - } - if (fscanf(fp, "%i", &pid) != 1) { - FATAL("unable to read the pid from file \"%s\"\n", - pidFileParam->value); - } - fclose(fp); - - if (kill(pid, SIGTERM)) { - FATAL("unable to kill proccess %i: %s\n", pid, strerror(errno)); - } - exit(EXIT_SUCCESS); -} - -int main(int argc, char *argv[]) -{ - Options options; - clock_t start; - - closeAllFDs(); - - initConf(); - - parseOptions(argc, argv, &options); - - if (options.kill) - killFromPidFile(argv[0], options.kill); - - initStats(); - initTagConfig(); - initLog(options.verbose); - - if (options.createDB <= 0) - listenOnPort(); - - changeToUser(); - - open_log_files(options.stdOutput); - - initPaths(); - initPermissions(); - initPlaylist(); - initInputPlugins(); - - openDB(&options, argv[0]); - - initCommands(); - initPlayerData(); - initAudioConfig(); - initAudioDriver(); - initVolume(); - initInterfaces(); - initZeroconf(); - initReplayGainState(); - initNormalization(); - initInputStream(); - - daemonize(&options); - - setup_log_output(options.stdOutput); - - - - initSigHandlers(); - - openVolumeDevice(); - read_state_file(); - - while (COMMAND_RETURN_KILL != doIOForInterfaces()) { - if (COMMAND_RETURN_KILL == handlePendingSignals()) - break; - syncPlayerAndPlaylist(); - closeOldInterfaces(); - readDirectoryDBIfUpdateIsFinished(); - } - - write_state_file(); - playerKill(); - finishZeroconf(); - freeAllInterfaces(); - closeAllListenSockets(); - finishPlaylist(); - - start = clock(); - closeMp3Directory(); - DEBUG("closeMp3Directory took %f seconds\n", - ((float)(clock()-start))/CLOCKS_PER_SEC); - - finishNormalization(); - finishAudioDriver(); - finishAudioConfig(); - finishVolume(); - finishPaths(); - finishPermissions(); - finishCommands(); - finishInputPlugins(); - cleanUpPidFile(); - finishConf(); - freePlayerData(); - - close_log_files(); - return EXIT_SUCCESS; -} diff --git a/trunk/src/metadataChunk.c b/trunk/src/metadataChunk.c deleted file mode 100644 index bc5118fd0..000000000 --- a/trunk/src/metadataChunk.c +++ /dev/null @@ -1,94 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "metadataChunk.h" -#include "gcc.h" - -#include <string.h> - -static void initMetadataChunk(MetadataChunk * chunk) -{ - chunk->name = -1; - chunk->artist = -1; - chunk->album = -1; - chunk->title = -1; -} - -#define dupElementToTag(item, element) { \ - if(element >= 0 && element < METADATA_BUFFER_LENGTH) { \ - addItemToMpdTag(ret, item, chunk->buffer+element); \ - } \ -} - -MpdTag *metadataChunkToMpdTagDup(MetadataChunk * chunk) -{ - MpdTag *ret = newMpdTag(); - - chunk->buffer[METADATA_BUFFER_LENGTH - 1] = '\0'; - - dupElementToTag(TAG_ITEM_NAME, chunk->name); - dupElementToTag(TAG_ITEM_TITLE, chunk->title); - dupElementToTag(TAG_ITEM_ARTIST, chunk->artist); - dupElementToTag(TAG_ITEM_ALBUM, chunk->album); - - return ret; -} - -#define copyStringToChunk(string, element) { \ - if(element < 0 && string && (slen = strlen(string)) && \ - pos < METADATA_BUFFER_LENGTH-1) \ - { \ - size_t len = slen; \ - size_t max = METADATA_BUFFER_LENGTH - 1 - pos; \ - if (mpd_unlikely(len > max)) \ - len = max; \ - memcpy(chunk->buffer+pos, string, len); \ - *(chunk->buffer+pos+len) = '\0'; \ - element = pos; \ - pos += slen+1; \ - } \ -} - -void copyMpdTagToMetadataChunk(MpdTag * tag, MetadataChunk * chunk) -{ - int pos = 0; - int slen; - int i; - - initMetadataChunk(chunk); - - if (!tag) - return; - - for (i = 0; i < tag->numOfItems; i++) { - switch (tag->items[i].type) { - case TAG_ITEM_NAME: - copyStringToChunk(tag->items[i].value, chunk->name); - break; - case TAG_ITEM_TITLE: - copyStringToChunk(tag->items[i].value, chunk->title); - break; - case TAG_ITEM_ARTIST: - copyStringToChunk(tag->items[i].value, chunk->artist); - break; - case TAG_ITEM_ALBUM: - copyStringToChunk(tag->items[i].value, chunk->album); - break; - } - } -} diff --git a/trunk/src/metadataChunk.h b/trunk/src/metadataChunk.h deleted file mode 100644 index c1da8b320..000000000 --- a/trunk/src/metadataChunk.h +++ /dev/null @@ -1,38 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef METADATA_CHUNK_H -#define METADATA_CHUNK_H - -#define METADATA_BUFFER_LENGTH 1024 - -#include "tag.h" - -typedef struct _MetadataChunk { - int name; - int title; - int artist; - int album; - char buffer[METADATA_BUFFER_LENGTH]; -} MetadataChunk; - -MpdTag *metadataChunkToMpdTagDup(MetadataChunk * chunk); - -void copyMpdTagToMetadataChunk(MpdTag * tag, MetadataChunk * chunk); - -#endif diff --git a/trunk/src/mp4ff/Makefile.am b/trunk/src/mp4ff/Makefile.am deleted file mode 100644 index d1258e7b8..000000000 --- a/trunk/src/mp4ff/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -noinst_LTLIBRARIES = libmp4ff.la - -noinst_HEADERS = mp4ff.h - -libmp4ff_la_SOURCES = mp4ff.c mp4atom.c mp4meta.c mp4sample.c mp4util.c \ - mp4tagupdate.c mp4ff.h mp4ffint.h mp4ff_int_types.h \ - drms.h drms.c drmstables.h - -AM_CFLAGS = -DUSE_TAGGING=1 diff --git a/trunk/src/mp4ff/drms.c b/trunk/src/mp4ff/drms.c deleted file mode 100644 index 368b88110..000000000 --- a/trunk/src/mp4ff/drms.c +++ /dev/null @@ -1,1043 +0,0 @@ -/***************************************************************************** - * drms.c : DRMS - ***************************************************************************** - * Copyright (C) 2004 VideoLAN - * $Id: drms.c,v 1.3 2004/01/11 15:52:18 menno Exp $ - * - * Author: Jon Lech Johansen <jon-vl@nanocrew.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - *****************************************************************************/ - -#include <stdlib.h> /* malloc(), free() */ - -#include "mp4ffint.h" - -#ifdef ITUNES_DRM - -#ifdef _WIN32 -#include <tchar.h> -#include <shlobj.h> -#include <windows.h> -#endif - -#include "drms.h" -#include "drmstables.h" - -static __inline uint32_t U32_AT( void * _p ) -{ - uint8_t * p = (uint8_t *)_p; - return ( ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) - | ((uint32_t)p[2] << 8) | p[3] ); -} - -#define TAOS_INIT( tmp, i ) \ - memset( tmp, 0, sizeof(tmp) ); \ - tmp[ i + 0 ] = 0x67452301; \ - tmp[ i + 1 ] = 0xEFCDAB89; \ - tmp[ i + 2 ] = 0x98BADCFE; \ - tmp[ i + 3 ] = 0x10325476; - -#define ROR( x, n ) (((x) << (32-(n))) | ((x) >> (n))) - -static void init_ctx( uint32_t *p_ctx, uint32_t *p_input ) -{ - uint32_t i; - uint32_t p_tmp[ 6 ]; - - p_ctx[ 0 ] = sizeof(*p_input); - - memset( &p_ctx[ 1 + 4 ], 0, sizeof(*p_input) * 4 ); - memcpy( &p_ctx[ 1 + 0 ], p_input, sizeof(*p_input) * 4 ); - - p_tmp[ 0 ] = p_ctx[ 1 + 3 ]; - - for( i = 0; i < sizeof(p_drms_tab1)/sizeof(p_drms_tab1[ 0 ]); i++ ) - { - p_tmp[ 0 ] = ROR( p_tmp[ 0 ], 8 ); - - p_tmp[ 5 ] = p_drms_tab2[ (p_tmp[ 0 ] >> 24) & 0xFF ] - ^ ROR( p_drms_tab2[ (p_tmp[ 0 ] >> 16) & 0xFF ], 8 ) - ^ ROR( p_drms_tab2[ (p_tmp[ 0 ] >> 8) & 0xFF ], 16 ) - ^ ROR( p_drms_tab2[ p_tmp[ 0 ] & 0xFF ], 24 ) - ^ p_drms_tab1[ i ] - ^ p_ctx[ 1 + ((i + 1) * 4) - 4 ]; - - p_ctx[ 1 + ((i + 1) * 4) + 0 ] = p_tmp[ 5 ]; - p_tmp[ 5 ] ^= p_ctx[ 1 + ((i + 1) * 4) - 3 ]; - p_ctx[ 1 + ((i + 1) * 4) + 1 ] = p_tmp[ 5 ]; - p_tmp[ 5 ] ^= p_ctx[ 1 + ((i + 1) * 4) - 2 ]; - p_ctx[ 1 + ((i + 1) * 4) + 2 ] = p_tmp[ 5 ]; - p_tmp[ 5 ] ^= p_ctx[ 1 + ((i + 1) * 4) - 1 ]; - p_ctx[ 1 + ((i + 1) * 4) + 3 ] = p_tmp[ 5 ]; - - p_tmp[ 0 ] = p_tmp[ 5 ]; - } - - memcpy( &p_ctx[ 1 + 64 ], &p_ctx[ 1 ], sizeof(*p_ctx) * 4 ); - - for( i = 4; i < sizeof(p_drms_tab1); i++ ) - { - p_tmp[ 2 ] = p_ctx[ 1 + 4 + (i - 4) ]; - - p_tmp[ 0 ] = (((p_tmp[ 2 ] >> 7) & 0x01010101) * 27) - ^ ((p_tmp[ 2 ] & 0xFF7F7F7F) << 1); - p_tmp[ 1 ] = (((p_tmp[ 0 ] >> 7) & 0x01010101) * 27) - ^ ((p_tmp[ 0 ] & 0xFF7F7F7F) << 1); - p_tmp[ 4 ] = (((p_tmp[ 1 ] >> 7) & 0x01010101) * 27) - ^ ((p_tmp[ 1 ] & 0xFF7F7F7F) << 1); - - p_tmp[ 2 ] ^= p_tmp[ 4 ]; - - p_tmp[ 3 ] = ROR( p_tmp[ 1 ] ^ p_tmp[ 2 ], 16 ) - ^ ROR( p_tmp[ 0 ] ^ p_tmp[ 2 ], 8 ) - ^ ROR( p_tmp[ 2 ], 24 ); - - p_ctx[ 1 + 4 + 64 + (i - 4) ] = p_tmp[ 3 ] ^ p_tmp[ 4 ] - ^ p_tmp[ 1 ] ^ p_tmp[ 0 ]; - } -} - -static void ctx_xor( uint32_t *p_ctx, uint32_t *p_in, uint32_t *p_out, - uint32_t p_table1[ 256 ], uint32_t p_table2[ 256 ] ) -{ - uint32_t i, x, y; - uint32_t p_tmp1[ 4 ]; - uint32_t p_tmp2[ 4 ]; - - i = p_ctx[ 0 ] * 4; - - p_tmp1[ 0 ] = p_ctx[ 1 + i + 24 ] ^ p_in[ 0 ]; - p_tmp1[ 1 ] = p_ctx[ 1 + i + 25 ] ^ p_in[ 1 ]; - p_tmp1[ 2 ] = p_ctx[ 1 + i + 26 ] ^ p_in[ 2 ]; - p_tmp1[ 3 ] = p_ctx[ 1 + i + 27 ] ^ p_in[ 3 ]; - - i += 84; - -#define XOR_ROR( p_table, p_tmp, i_ctx ) \ - p_table[ (p_tmp[ y > 2 ? y - 3 : y + 1 ] >> 24) & 0xFF ] \ - ^ ROR( p_table[ (p_tmp[ y > 1 ? y - 2 : y + 2 ] >> 16) & 0xFF ], 8 ) \ - ^ ROR( p_table[ (p_tmp[ y > 0 ? y - 1 : y + 3 ] >> 8) & 0xFF ], 16 ) \ - ^ ROR( p_table[ p_tmp[ y ] & 0xFF ], 24 ) \ - ^ p_ctx[ i_ctx ] - - for( x = 0; x < 1; x++ ) - { - memcpy( p_tmp2, p_tmp1, sizeof(p_tmp1) ); - - for( y = 0; y < 4; y++ ) - { - p_tmp1[ y ] = XOR_ROR( p_table1, p_tmp2, 1 + i - x + y ); - } - } - - for( ; x < 9; x++ ) - { - memcpy( p_tmp2, p_tmp1, sizeof(p_tmp1) ); - - for( y = 0; y < 4; y++ ) - { - p_tmp1[ y ] = XOR_ROR( p_table1, p_tmp2, - 1 + i - x - ((x * 3) - y) ); - } - } - - for( y = 0; y < 4; y++ ) - { - p_out[ y ] = XOR_ROR( p_table2, p_tmp1, - 1 + i - x - ((x * 3) - y) ); - } - -#undef XOR_ROR -} - -static void taos( uint32_t *p_buffer, uint32_t *p_input ) -{ - uint32_t i; - uint32_t x = 0; - uint32_t p_tmp1[ 4 ]; - uint32_t p_tmp2[ 4 ]; - - memcpy( p_tmp1, p_buffer, sizeof(p_tmp1) ); - - p_tmp2[ 0 ] = ((~p_tmp1[ 1 ] & p_tmp1[ 3 ]) - | (p_tmp1[ 2 ] & p_tmp1[ 1 ])) + p_input[ x ]; - p_tmp1[ 0 ] = p_tmp2[ 0 ] + p_tmp1[ 0 ] + p_drms_tab_taos[ x++ ]; - - for( i = 0; i < 4; i++ ) - { - p_tmp2[ 0 ] = ((p_tmp1[ 0 ] >> 0x19) - | (p_tmp1[ 0 ] << 0x7)) + p_tmp1[ 1 ]; - p_tmp2[ 1 ] = ((~p_tmp2[ 0 ] & p_tmp1[ 2 ]) - | (p_tmp1[ 1 ] & p_tmp2[ 0 ])) + p_input[ x ]; - p_tmp2[ 1 ] += p_tmp1[ 3 ] + p_drms_tab_taos[ x++ ]; - - p_tmp1[ 3 ] = ((p_tmp2[ 1 ] >> 0x14) - | (p_tmp2[ 1 ] << 0xC)) + p_tmp2[ 0 ]; - p_tmp2[ 1 ] = ((~p_tmp1[ 3 ] & p_tmp1[ 1 ]) - | (p_tmp1[ 3 ] & p_tmp2[ 0 ])) + p_input[ x ]; - p_tmp2[ 1 ] += p_tmp1[ 2 ] + p_drms_tab_taos[ x++ ]; - - p_tmp1[ 2 ] = ((p_tmp2[ 1 ] >> 0xF) - | (p_tmp2[ 1 ] << 0x11)) + p_tmp1[ 3 ]; - p_tmp2[ 1 ] = ((~p_tmp1[ 2 ] & p_tmp2[ 0 ]) - | (p_tmp1[ 3 ] & p_tmp1[ 2 ])) + p_input[ x ]; - p_tmp2[ 2 ] = p_tmp2[ 1 ] + p_tmp1[ 1 ] + p_drms_tab_taos[ x++ ]; - - p_tmp1[ 1 ] = ((p_tmp2[ 2 ] << 0x16) - | (p_tmp2[ 2 ] >> 0xA)) + p_tmp1[ 2 ]; - if( i == 3 ) - { - p_tmp2[ 1 ] = ((~p_tmp1[ 3 ] & p_tmp1[ 2 ]) - | (p_tmp1[ 3 ] & p_tmp1[ 1 ])) + p_input[ 1 ]; - } - else - { - p_tmp2[ 1 ] = ((~p_tmp1[ 1 ] & p_tmp1[ 3 ]) - | (p_tmp1[ 2 ] & p_tmp1[ 1 ])) + p_input[ x ]; - } - p_tmp1[ 0 ] = p_tmp2[ 0 ] + p_tmp2[ 1 ] + p_drms_tab_taos[ x++ ]; - } - - for( i = 0; i < 4; i++ ) - { - uint8_t p_table[ 4 ][ 4 ] = - { - { 6, 11, 0, 5 }, - { 10, 15, 4, 9 }, - { 14, 3, 8, 13 }, - { 2, 7, 12, 5 } - }; - - p_tmp2[ 0 ] = ((p_tmp1[ 0 ] >> 0x1B) - | (p_tmp1[ 0 ] << 0x5)) + p_tmp1[ 1 ]; - p_tmp2[ 1 ] = ((~p_tmp1[ 2 ] & p_tmp1[ 1 ]) - | (p_tmp1[ 2 ] & p_tmp2[ 0 ])) - + p_input[ p_table[ i ][ 0 ] ]; - p_tmp2[ 1 ] += p_tmp1[ 3 ] + p_drms_tab_taos[ x++ ]; - - p_tmp1[ 3 ] = ((p_tmp2[ 1 ] >> 0x17) - | (p_tmp2[ 1 ] << 0x9)) + p_tmp2[ 0 ]; - p_tmp2[ 1 ] = ((~p_tmp1[ 1 ] & p_tmp2[ 0 ]) - | (p_tmp1[ 3 ] & p_tmp1[ 1 ])) - + p_input[ p_table[ i ][ 1 ] ]; - p_tmp2[ 1 ] += p_tmp1[ 2 ] + p_drms_tab_taos[ x++ ]; - - p_tmp1[ 2 ] = ((p_tmp2[ 1 ] >> 0x12) - | (p_tmp2[ 1 ] << 0xE)) + p_tmp1[ 3 ]; - p_tmp2[ 1 ] = ((~p_tmp2[ 0 ] & p_tmp1[ 3 ]) - | (p_tmp1[ 2 ] & p_tmp2[ 0 ])) - + p_input[ p_table[ i ][ 2 ] ]; - p_tmp2[ 1 ] += p_tmp1[ 1 ] + p_drms_tab_taos[ x++ ]; - - p_tmp1[ 1 ] = ((p_tmp2[ 1 ] << 0x14) - | (p_tmp2[ 1 ] >> 0xC)) + p_tmp1[ 2 ]; - if( i == 3 ) - { - p_tmp2[ 1 ] = (p_tmp1[ 3 ] ^ p_tmp1[ 2 ] ^ p_tmp1[ 1 ]) - + p_input[ p_table[ i ][ 3 ] ]; - } - else - { - p_tmp2[ 1 ] = ((~p_tmp1[ 3 ] & p_tmp1[ 2 ]) - | (p_tmp1[ 3 ] & p_tmp1[ 1 ])) - + p_input[ p_table[ i ][ 3 ] ]; - } - p_tmp1[ 0 ] = p_tmp2[ 0 ] + p_tmp2[ 1 ] + p_drms_tab_taos[ x++ ]; - } - - for( i = 0; i < 4; i++ ) - { - uint8_t p_table[ 4 ][ 4 ] = - { - { 8, 11, 14, 1 }, - { 4, 7, 10, 13 }, - { 0, 3, 6, 9 }, - { 12, 15, 2, 0 } - }; - - p_tmp2[ 0 ] = ((p_tmp1[ 0 ] >> 0x1C) - | (p_tmp1[ 0 ] << 0x4)) + p_tmp1[ 1 ]; - p_tmp2[ 1 ] = (p_tmp1[ 2 ] ^ p_tmp1[ 1 ] ^ p_tmp2[ 0 ]) - + p_input[ p_table[ i ][ 0 ] ]; - p_tmp2[ 1 ] += p_tmp1[ 3 ] + p_drms_tab_taos[ x++ ]; - - p_tmp1[ 3 ] = ((p_tmp2[ 1 ] >> 0x15) - | (p_tmp2[ 1 ] << 0xB)) + p_tmp2[ 0 ]; - p_tmp2[ 1 ] = (p_tmp1[ 3 ] ^ p_tmp1[ 1 ] ^ p_tmp2[ 0 ]) - + p_input[ p_table[ i ][ 1 ] ]; - p_tmp2[ 1 ] += p_tmp1[ 2 ] + p_drms_tab_taos[ x++ ]; - - p_tmp1[ 2 ] = ((p_tmp2[ 1 ] >> 0x10) - | (p_tmp2[ 1 ] << 0x10)) + p_tmp1[ 3 ]; - p_tmp2[ 1 ] = (p_tmp1[ 3 ] ^ p_tmp1[ 2 ] ^ p_tmp2[ 0 ]) - + p_input[ p_table[ i ][ 2 ] ]; - p_tmp2[ 1 ] += p_tmp1[ 1 ] + p_drms_tab_taos[ x++ ]; - - p_tmp1[ 1 ] = ((p_tmp2[ 1 ] << 0x17) - | (p_tmp2[ 1 ] >> 0x9)) + p_tmp1[ 2 ]; - if( i == 3 ) - { - p_tmp2[ 1 ] = ((~p_tmp1[ 3 ] | p_tmp1[ 1 ]) ^ p_tmp1[ 2 ]) - + p_input[ p_table[ i ][ 3 ] ]; - } - else - { - p_tmp2[ 1 ] = (p_tmp1[ 3 ] ^ p_tmp1[ 2 ] ^ p_tmp1[ 1 ]) - + p_input[ p_table[ i ][ 3 ] ]; - } - p_tmp1[ 0 ] = p_tmp2[ 0 ] + p_tmp2[ 1 ] + p_drms_tab_taos[ x++ ]; - } - - for( i = 0; i < 4; i++ ) - { - uint8_t p_table[ 4 ][ 4 ] = - { - { 7, 14, 5, 12 }, - { 3, 10, 1, 8 }, - { 15, 6, 13, 4 }, - { 11, 2, 9, 0 } - }; - - p_tmp2[ 0 ] = ((p_tmp1[ 0 ] >> 0x1A) - | (p_tmp1[ 0 ] << 0x6)) + p_tmp1[ 1 ]; - p_tmp2[ 1 ] = ((~p_tmp1[ 2 ] | p_tmp2[ 0 ]) ^ p_tmp1[ 1 ]) - + p_input[ p_table[ i ][ 0 ] ]; - p_tmp2[ 1 ] += p_tmp1[ 3 ] + p_drms_tab_taos[ x++ ]; - - p_tmp1[ 3 ] = ((p_tmp2[ 1 ] >> 0x16) - | (p_tmp2[ 1 ] << 0xA)) + p_tmp2[ 0 ]; - p_tmp2[ 1 ] = ((~p_tmp1[ 1 ] | p_tmp1[ 3 ]) ^ p_tmp2[ 0 ]) - + p_input[ p_table[ i ][ 1 ] ]; - p_tmp2[ 1 ] += p_tmp1[ 2 ] + p_drms_tab_taos[ x++ ]; - - p_tmp1[ 2 ] = ((p_tmp2[ 1 ] >> 0x11) - | (p_tmp2[ 1 ] << 0xF)) + p_tmp1[ 3 ]; - p_tmp2[ 1 ] = ((~p_tmp2[ 0 ] | p_tmp1[ 2 ]) ^ p_tmp1[ 3 ]) - + p_input[ p_table[ i ][ 2 ] ]; - p_tmp2[ 1 ] += p_tmp1[ 1 ] + p_drms_tab_taos[ x++ ]; - - p_tmp1[ 1 ] = ((p_tmp2[ 1 ] << 0x15) - | (p_tmp2[ 1 ] >> 0xB)) + p_tmp1[ 2 ]; - - if( i < 3 ) - { - p_tmp2[ 1 ] = ((~p_tmp1[ 3 ] | p_tmp1[ 1 ]) ^ p_tmp1[ 2 ]) - + p_input[ p_table[ i ][ 3 ] ]; - p_tmp1[ 0 ] = p_tmp2[ 0 ] + p_tmp2[ 1 ] + p_drms_tab_taos[ x++ ]; - } - } - - p_buffer[ 0 ] += p_tmp2[ 0 ]; - p_buffer[ 1 ] += p_tmp1[ 1 ]; - p_buffer[ 2 ] += p_tmp1[ 2 ]; - p_buffer[ 3 ] += p_tmp1[ 3 ]; -} - -static void taos_add1( uint32_t *p_buffer, - uint8_t *p_in, uint32_t i_len ) -{ - uint32_t i; - uint32_t x, y; - uint32_t p_tmp[ 16 ]; - uint32_t i_offset = 0; - - x = p_buffer[ 6 ] & 63; - y = 64 - x; - - p_buffer[ 6 ] += i_len; - - if( i_len < y ) - { - memcpy( &((uint8_t *)p_buffer)[ 48 + x ], p_in, i_len ); - } - else - { - if( x ) - { - memcpy( &((uint8_t *)p_buffer)[ 48 + x ], p_in, y ); - taos( &p_buffer[ 8 ], &p_buffer[ 12 ] ); - i_offset = y; - i_len -= y; - } - - if( i_len >= 64 ) - { - for( i = 0; i < i_len / 64; i++ ) - { - memcpy( p_tmp, &p_in[ i_offset ], sizeof(p_tmp) ); - taos( &p_buffer[ 8 ], p_tmp ); - i_offset += 64; - i_len -= 64; - } - } - - if( i_len ) - { - memcpy( &p_buffer[ 12 ], &p_in[ i_offset ], i_len ); - } - } -} - -static void taos_end1( uint32_t *p_buffer, uint32_t *p_out ) -{ - uint32_t x, y; - - x = p_buffer[ 6 ] & 63; - y = 63 - x; - - ((uint8_t *)p_buffer)[ 48 + x++ ] = 128; - - if( y < 8 ) - { - memset( &((uint8_t *)p_buffer)[ 48 + x ], 0, y ); - taos( &p_buffer[ 8 ], &p_buffer[ 12 ] ); - y = 64; - x = 0; - } - - memset( &((uint8_t *)p_buffer)[ 48 + x ], 0, y ); - - p_buffer[ 26 ] = p_buffer[ 6 ] * 8; - p_buffer[ 27 ] = p_buffer[ 6 ] >> 29; - taos( &p_buffer[ 8 ], &p_buffer[ 12 ] ); - - memcpy( p_out, &p_buffer[ 8 ], sizeof(*p_out) * 4 ); -} - -static void taos_add2( uint32_t *p_buffer, uint8_t *p_in, uint32_t i_len ) -{ - uint32_t i, x; - uint32_t p_tmp[ 16 ]; - - x = (p_buffer[ 0 ] / 8) & 63; - i = p_buffer[ 0 ] + i_len * 8; - - if( i < p_buffer[ 0 ] ) - { - p_buffer[ 1 ] += 1; - } - - p_buffer[ 0 ] = i; - p_buffer[ 1 ] += i_len >> 29; - - for( i = 0; i < i_len; i++ ) - { - ((uint8_t *)p_buffer)[ 24 + x++ ] = p_in[ i ]; - - if( x != 64 ) - continue; - - memcpy( p_tmp, &p_buffer[ 6 ], sizeof(p_tmp) ); - taos( &p_buffer[ 2 ], p_tmp ); - } -} - -static void taos_add2e( uint32_t *p_buffer, uint32_t *p_in, uint32_t i_len ) -{ - uint32_t i, x, y; - uint32_t p_tmp[ 32 ]; - - if( i_len ) - { - for( x = i_len; x; x -= y ) - { - y = x > 32 ? 32 : x; - - for( i = 0; i < y; i++ ) - { - p_tmp[ i ] = U32_AT(&p_in[ i ]); - } - } - } - - taos_add2( p_buffer, (uint8_t *)p_tmp, i_len * sizeof(p_tmp[ 0 ]) ); -} - -static void taos_end2( uint32_t *p_buffer ) -{ - uint32_t x; - uint32_t p_tmp[ 16 ]; - - p_tmp[ 14 ] = p_buffer[ 0 ]; - p_tmp[ 15 ] = p_buffer[ 1 ]; - - x = (p_buffer[ 0 ] / 8) & 63; - - taos_add2( p_buffer, p_drms_tab_tend, 56 - x ); - memcpy( p_tmp, &p_buffer[ 6 ], 56 ); - taos( &p_buffer[ 2 ], p_tmp ); - memcpy( &p_buffer[ 22 ], &p_buffer[ 2 ], sizeof(*p_buffer) * 4 ); -} - -static void taos_add3( uint32_t *p_buffer, uint8_t *p_key, uint32_t i_len ) -{ - uint32_t x, y; - uint32_t i = 0; - - x = (p_buffer[ 4 ] / 8) & 63; - p_buffer[ 4 ] += i_len * 8; - - if( p_buffer[ 4 ] < i_len * 8 ) - p_buffer[ 5 ] += 1; - - p_buffer[ 5 ] += i_len >> 29; - - y = 64 - x; - - if( i_len >= y ) - { - memcpy( &((uint8_t *)p_buffer)[ 24 + x ], p_key, y ); - taos( p_buffer, &p_buffer[ 6 ] ); - - i = y; - y += 63; - - if( y < i_len ) - { - for( ; y < i_len; y += 64, i += 64 ) - { - taos( p_buffer, (uint32_t *)&p_key[y - 63] ); - } - } - else - { - x = 0; - } - } - - memcpy( &((uint8_t *)p_buffer)[ 24 + x ], &p_key[ i ], i_len - i ); -} - -static int taos_osi( uint32_t *p_buffer ) -{ - int i_ret = 0; - -#ifdef _WIN32 - HKEY i_key; - uint32_t i; - DWORD i_size; - DWORD i_serial; - LPBYTE p_reg_buf; - - static LPCTSTR p_reg_keys[ 3 ][ 2 ] = - { - { - _T("HARDWARE\\DESCRIPTION\\System"), - _T("SystemBiosVersion") - }, - - { - _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), - _T("ProcessorNameString") - }, - - { - _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"), - _T("ProductId") - } - }; - - taos_add1( p_buffer, "cache-control", 13 ); - taos_add1( p_buffer, "Ethernet", 8 ); - - GetVolumeInformation( _T("C:\\"), NULL, 0, &i_serial, - NULL, NULL, NULL, 0 ); - taos_add1( p_buffer, (uint8_t *)&i_serial, 4 ); - - for( i = 0; i < sizeof(p_reg_keys)/sizeof(p_reg_keys[ 0 ]); i++ ) - { - if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, p_reg_keys[ i ][ 0 ], - 0, KEY_READ, &i_key ) == ERROR_SUCCESS ) - { - if( RegQueryValueEx( i_key, p_reg_keys[ i ][ 1 ], - NULL, NULL, NULL, - &i_size ) == ERROR_SUCCESS ) - { - p_reg_buf = malloc( i_size ); - - if( p_reg_buf != NULL ) - { - if( RegQueryValueEx( i_key, p_reg_keys[ i ][ 1 ], - NULL, NULL, p_reg_buf, - &i_size ) == ERROR_SUCCESS ) - { - taos_add1( p_buffer, (uint8_t *)p_reg_buf, - i_size ); - } - - free( p_reg_buf ); - } - } - - RegCloseKey( i_key ); - } - } - -#else - i_ret = -1; -#endif - - return( i_ret ); -} - -static int get_sci_data( uint32_t p_sci[ 11 ][ 4 ] ) -{ - int i_ret = -1; - -#ifdef _WIN32 - HANDLE i_file; - DWORD i_size, i_read; - TCHAR p_path[ MAX_PATH ]; - TCHAR *p_filename = _T("\\Apple Computer\\iTunes\\SC Info\\SC Info.sidb"); - - typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD, - LPTSTR ); - - HINSTANCE shfolder_dll = NULL; - SHGETFOLDERPATH dSHGetFolderPath = NULL; - - if( ( shfolder_dll = LoadLibrary( _T("SHFolder.dll") ) ) != NULL ) - { - dSHGetFolderPath = - (SHGETFOLDERPATH)GetProcAddress( shfolder_dll, -#ifdef _UNICODE - _T("SHGetFolderPathW") ); -#else - _T("SHGetFolderPathA") ); -#endif - } - - if( dSHGetFolderPath != NULL && - SUCCEEDED( dSHGetFolderPath( NULL, /*CSIDL_COMMON_APPDATA*/ 0x0023, - NULL, 0, p_path ) ) ) - { - _tcsncat( p_path, p_filename, min( _tcslen( p_filename ), - (MAX_PATH-1) - _tcslen( p_path ) ) ); - - i_file = CreateFile( p_path, GENERIC_READ, 0, NULL, - OPEN_EXISTING, 0, NULL ); - if( i_file != INVALID_HANDLE_VALUE ) - { - i_read = sizeof(p_sci[ 0 ]) * 11; - i_size = GetFileSize( i_file, NULL ); - if( i_size != INVALID_FILE_SIZE && i_size >= i_read ) - { - i_size = SetFilePointer( i_file, 4, NULL, FILE_BEGIN ); - if( i_size != /*INVALID_SET_FILE_POINTER*/ ((DWORD)-1)) - { - if( ReadFile( i_file, p_sci, i_read, &i_size, NULL ) && - i_size == i_read ) - { - i_ret = 0; - } - } - } - - CloseHandle( i_file ); - } - } -#endif - - return( i_ret ); -} - -static void acei_taxs( uint32_t *p_acei, uint32_t i_val ) -{ - uint32_t i, x; - - i = (i_val / 16) & 15; - x = (~(i_val & 15)) & 15; - - if( (i_val & 768) == 768 ) - { - x = (~i) & 15; - i = i_val & 15; - - p_acei[ 25 + i ] = p_acei[ 25 + ((16 - x) & 15) ] - + p_acei[ 25 + (15 - x) ]; - } - else if( (i_val & 512) == 512 ) - { - p_acei[ 25 + i ] ^= p_drms_tab_xor[ 15 - i ][ x ]; - } - else if( (i_val & 256) == 256 ) - { - p_acei[ 25 + i ] -= p_drms_tab_sub[ 15 - i ][ x ]; - } - else - { - p_acei[ 25 + i ] += p_drms_tab_add[ 15 - i ][ x ]; - } -} - -static void acei( uint32_t *p_acei, uint8_t *p_buffer, uint32_t i_len ) -{ - uint32_t i, x; - uint32_t p_tmp[ 26 ]; - - for( i = 5; i < 25; i++ ) - { - if( p_acei[ i ] ) - { - acei_taxs( p_acei, p_acei[ i ] ); - } - } - - TAOS_INIT( p_tmp, 2 ); - taos_add2e( p_tmp, &p_acei[ 25 ], sizeof(*p_acei) * 4 ); - taos_end2( p_tmp ); - - x = i_len < 16 ? i_len : 16; - - if( x > 0 ) - { - for( i = 0; i < x; i++ ) - { - p_buffer[ i ] ^= ((uint8_t *)&p_tmp)[ 88 + i ]; - } - } -} - -static uint32_t ttov_calc( uint32_t *p_acei ) -{ - int32_t i_val; - uint32_t p_tmp[ 26 ]; - - TAOS_INIT( p_tmp, 2 ); - taos_add2e( p_tmp, &p_acei[ 0 ], 4 ); - taos_add2e( p_tmp, &p_acei[ 4 ], 1 ); - taos_end2( p_tmp ); - - p_acei[ 4 ]++; - - i_val = ((int32_t)U32_AT(&p_tmp[ 22 ])) % 1024; - - return( i_val < 0 ? i_val * -1 : i_val ); -} - -static void acei_init( uint32_t *p_acei, uint32_t *p_sys_key ) -{ - uint32_t i; - - for( i = 0; i < 4; i++ ) - { - p_acei[ i ] = U32_AT(&p_sys_key[ i ]); - } - - p_acei[ 4 ] = 0x5476212A; - - for( i = 5; i < 25; i++ ) - { - p_acei[ i ] = ttov_calc( p_acei ); - } - - p_acei[ 25 + 0 ] = p_acei[ 0 ]; - p_acei[ 25 + 1 ] = 0x68723876; - p_acei[ 25 + 2 ] = 0x41617376; - p_acei[ 25 + 3 ] = 0x4D4B4F76; - - p_acei[ 25 + 4 ] = p_acei[ 1 ]; - p_acei[ 25 + 5 ] = 0x48556646; - p_acei[ 25 + 6 ] = 0x38393725; - p_acei[ 25 + 7 ] = 0x2E3B5B3D; - - p_acei[ 25 + 8 ] = p_acei[ 2 ]; - p_acei[ 25 + 9 ] = 0x37363866; - p_acei[ 25 + 10 ] = 0x30383637; - p_acei[ 25 + 11 ] = 0x34333661; - - p_acei[ 25 + 12 ] = p_acei[ 3 ]; - p_acei[ 25 + 13 ] = 0x37386162; - p_acei[ 25 + 14 ] = 0x494F6E66; - p_acei[ 25 + 15 ] = 0x2A282966; -} - -static __inline void block_xor( uint32_t *p_in, uint32_t *p_key, - uint32_t *p_out ) -{ - uint32_t i; - - for( i = 0; i < 4; i++ ) - { - p_out[ i ] = p_key[ i ] ^ p_in[ i ]; - } -} - -int drms_get_sys_key( uint32_t *p_sys_key ) -{ - uint32_t p_tmp[ 128 ]; - uint32_t p_tmp_key[ 4 ]; - - TAOS_INIT( p_tmp, 8 ); - if( taos_osi( p_tmp ) ) - { - return( -1 ); - } - taos_end1( p_tmp, p_tmp_key ); - - TAOS_INIT( p_tmp, 2 ); - taos_add2( p_tmp, "YuaFlafu", 8 ); - taos_add2( p_tmp, (uint8_t *)p_tmp_key, 6 ); - taos_add2( p_tmp, (uint8_t *)p_tmp_key, 6 ); - taos_add2( p_tmp, (uint8_t *)p_tmp_key, 6 ); - taos_add2( p_tmp, "zPif98ga", 8 ); - taos_end2( p_tmp ); - - memcpy( p_sys_key, &p_tmp[ 2 ], sizeof(*p_sys_key) * 4 ); - - return( 0 ); -} - -int drms_get_user_key( uint32_t *p_sys_key, uint32_t *p_user_key ) -{ - uint32_t i; - uint32_t p_tmp[ 4 ]; - uint32_t *p_cur_key; - uint32_t p_acei[ 41 ]; - uint32_t p_ctx[ 128 ]; - uint32_t p_sci[ 2 ][ 11 ][ 4 ]; - - uint32_t p_sci_key[ 4 ] = - { - 0x6E66556D, 0x6E676F70, 0x67666461, 0x33373866 - }; - - if( p_sys_key == NULL ) - { - if( drms_get_sys_key( p_tmp ) ) - { - return( -1 ); - } - - p_sys_key = p_tmp; - } - - if( get_sci_data( p_sci[ 0 ] ) ) - { - return( -1 ); - } - - init_ctx( p_ctx, p_sys_key ); - - for( i = 0, p_cur_key = p_sci_key; - i < sizeof(p_sci[ 0 ])/sizeof(p_sci[ 0 ][ 0 ]); i++ ) - { - ctx_xor( p_ctx, &p_sci[ 0 ][ i ][ 0 ], &p_sci[ 1 ][ i ][ 0 ], - p_drms_tab3, p_drms_tab4 ); - block_xor( &p_sci[ 1 ][ i ][ 0 ], p_cur_key, &p_sci[ 1 ][ i ][ 0 ] ); - - p_cur_key = &p_sci[ 0 ][ i ][ 0 ]; - } - - acei_init( p_acei, p_sys_key ); - - for( i = 0; i < sizeof(p_sci[ 1 ])/sizeof(p_sci[ 1 ][ 0 ]); i++ ) - { - acei( p_acei, (uint8_t *)&p_sci[ 1 ][ i ][ 0 ], - sizeof(p_sci[ 1 ][ i ]) ); - } - - memcpy( p_user_key, &p_sci[ 1 ][ 10 ][ 0 ], sizeof(p_sci[ 1 ][ i ]) ); - - return( 0 ); -} - -struct drms_s -{ - uint8_t *p_iviv; - uint32_t i_iviv_len; - uint8_t *p_name; - uint32_t i_name_len; - - uint32_t *p_tmp; - uint32_t i_tmp_len; - - uint32_t p_key[ 4 ]; - uint32_t p_ctx[ 128 ]; -}; - -#define P_DRMS ((struct drms_s *)p_drms) - -void *drms_alloc() -{ - struct drms_s *p_drms; - - p_drms = malloc( sizeof(struct drms_s) ); - - if( p_drms != NULL ) - { - memset( p_drms, 0, sizeof(struct drms_s) ); - - p_drms->i_tmp_len = 1024; - p_drms->p_tmp = malloc( p_drms->i_tmp_len ); - if( p_drms->p_tmp == NULL ) - { - free( (void *)p_drms ); - p_drms = NULL; - } - } - - return( (void *)p_drms ); -} - -void drms_free( void *p_drms ) -{ - if( P_DRMS->p_name != NULL ) - { - free( (void *)P_DRMS->p_name ); - } - - if( P_DRMS->p_iviv != NULL ) - { - free( (void *)P_DRMS->p_iviv ); - } - - if( P_DRMS->p_tmp != NULL ) - { - free( (void *)P_DRMS->p_tmp ); - } - - free( p_drms ); -} - -void drms_decrypt( void *p_drms, uint32_t *p_buffer, uint32_t i_len ) -{ - uint32_t i, x, y; - uint32_t *p_cur_key = P_DRMS->p_key; - - x = (i_len / sizeof(P_DRMS->p_key)) * sizeof(P_DRMS->p_key); - - if( P_DRMS->i_tmp_len < x ) - { - free( (void *)P_DRMS->p_tmp ); - - P_DRMS->i_tmp_len = x; - P_DRMS->p_tmp = malloc( P_DRMS->i_tmp_len ); - } - - if( P_DRMS->p_tmp != NULL ) - { - memcpy( P_DRMS->p_tmp, p_buffer, x ); - - for( i = 0, x /= sizeof(P_DRMS->p_key); i < x; i++ ) - { - y = i * sizeof(*p_buffer); - - ctx_xor( P_DRMS->p_ctx, P_DRMS->p_tmp + y, p_buffer + y, - p_drms_tab3, p_drms_tab4 ); - block_xor( p_buffer + y, p_cur_key, p_buffer + y ); - - p_cur_key = P_DRMS->p_tmp + y; - } - } -} - -int drms_init( void *p_drms, uint32_t i_type, - uint8_t *p_info, uint32_t i_len ) -{ - int i_ret = 0; - - switch( i_type ) - { - case DRMS_INIT_UKEY: - { - if( i_len != sizeof(P_DRMS->p_key) ) - { - i_ret = -1; - break; - } - - init_ctx( P_DRMS->p_ctx, (uint32_t *)p_info ); - } - break; - - case DRMS_INIT_IVIV: - { - if( i_len != sizeof(P_DRMS->p_key) ) - { - i_ret = -1; - break; - } - - P_DRMS->p_iviv = malloc( i_len ); - if( P_DRMS->p_iviv == NULL ) - { - i_ret = -1; - break; - } - - memcpy( P_DRMS->p_iviv, p_info, i_len ); - P_DRMS->i_iviv_len = i_len; - } - break; - - case DRMS_INIT_NAME: - { - P_DRMS->p_name = malloc( i_len ); - if( P_DRMS->p_name == NULL ) - { - i_ret = -1; - break; - } - - memcpy( P_DRMS->p_name, p_info, i_len ); - P_DRMS->i_name_len = i_len; - } - break; - - case DRMS_INIT_PRIV: - { - uint32_t i; - uint32_t p_priv[ 64 ]; - uint32_t p_tmp[ 128 ]; - - if( i_len < 64 ) - { - i_ret = -1; - break; - } - - TAOS_INIT( p_tmp, 0 ); - taos_add3( p_tmp, P_DRMS->p_name, P_DRMS->i_name_len ); - taos_add3( p_tmp, P_DRMS->p_iviv, P_DRMS->i_iviv_len ); - memcpy( p_priv, &p_tmp[ 4 ], sizeof(p_priv[ 0 ]) * 2 ); - i = (p_tmp[ 4 ] / 8) & 63; - i = i >= 56 ? 120 - i : 56 - i; - taos_add3( p_tmp, p_drms_tab_tend, i ); - taos_add3( p_tmp, (uint8_t *)p_priv, sizeof(p_priv[ 0 ]) * 2 ); - - memcpy( p_priv, p_info, 64 ); - memcpy( P_DRMS->p_key, p_tmp, sizeof(P_DRMS->p_key) ); - drms_decrypt( p_drms, p_priv, sizeof(p_priv) ); - - init_ctx( P_DRMS->p_ctx, &p_priv[ 6 ] ); - memcpy( P_DRMS->p_key, &p_priv[ 12 ], sizeof(P_DRMS->p_key) ); - - free( (void *)P_DRMS->p_name ); - P_DRMS->p_name = NULL; - free( (void *)P_DRMS->p_iviv ); - P_DRMS->p_iviv = NULL; - } - break; - } - - return( i_ret ); -} - -#undef P_DRMS - -#endif - diff --git a/trunk/src/mp4ff/drms.h b/trunk/src/mp4ff/drms.h deleted file mode 100644 index 42d957400..000000000 --- a/trunk/src/mp4ff/drms.h +++ /dev/null @@ -1,40 +0,0 @@ -/***************************************************************************** - * drms.h : DRMS - ***************************************************************************** - * Copyright (C) 2004 VideoLAN - * $Id: drms.h,v 1.3 2004/01/11 15:52:18 menno Exp $ - * - * Author: Jon Lech Johansen <jon-vl@nanocrew.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - *****************************************************************************/ - - -#define DRMS_INIT_UKEY 0 -#define DRMS_INIT_IVIV 1 -#define DRMS_INIT_NAME 2 -#define DRMS_INIT_PRIV 3 - -extern int drms_get_sys_key( uint32_t *p_sys_key ); -extern int drms_get_user_key( uint32_t *p_sys_key, - uint32_t *p_user_key ); - -extern void *drms_alloc(); -extern void drms_free( void *p_drms ); -extern int drms_init( void *p_drms, uint32_t i_type, - uint8_t *p_info, uint32_t i_len ); -extern void drms_decrypt( void *p_drms, uint32_t *p_buffer, - uint32_t i_len ); - diff --git a/trunk/src/mp4ff/drmstables.h b/trunk/src/mp4ff/drmstables.h deleted file mode 100644 index e38c1f762..000000000 --- a/trunk/src/mp4ff/drmstables.h +++ /dev/null @@ -1,449 +0,0 @@ -/***************************************************************************** - * drmstables.h : DRMS tables - ***************************************************************************** - * Copyright (C) 2004 VideoLAN - * $Id: drmstables.h,v 1.2 2004/01/11 15:52:18 menno Exp $ - * - * Author: Jon Lech Johansen <jon-vl@nanocrew.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - *****************************************************************************/ - - -static uint32_t p_drms_tab1[ 10 ] = -{ - 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, - 0x00000040, 0x00000080, 0x0000001B, 0x00000036 -}; - -static uint32_t p_drms_tab2[ 256 ] = -{ - 0x63000000, 0x7C000000, 0x77000000, 0x7B000000, 0xF2000000, 0x6B000000, - 0x6F000000, 0xC5000000, 0x30000000, 0x01000000, 0x67000000, 0x2B000000, - 0xFE000000, 0xD7000000, 0xAB000000, 0x76000000, 0xCA000000, 0x82000000, - 0xC9000000, 0x7D000000, 0xFA000000, 0x59000000, 0x47000000, 0xF0000000, - 0xAD000000, 0xD4000000, 0xA2000000, 0xAF000000, 0x9C000000, 0xA4000000, - 0x72000000, 0xC0000000, 0xB7000000, 0xFD000000, 0x93000000, 0x26000000, - 0x36000000, 0x3F000000, 0xF7000000, 0xCC000000, 0x34000000, 0xA5000000, - 0xE5000000, 0xF1000000, 0x71000000, 0xD8000000, 0x31000000, 0x15000000, - 0x04000000, 0xC7000000, 0x23000000, 0xC3000000, 0x18000000, 0x96000000, - 0x05000000, 0x9A000000, 0x07000000, 0x12000000, 0x80000000, 0xE2000000, - 0xEB000000, 0x27000000, 0xB2000000, 0x75000000, 0x09000000, 0x83000000, - 0x2C000000, 0x1A000000, 0x1B000000, 0x6E000000, 0x5A000000, 0xA0000000, - 0x52000000, 0x3B000000, 0xD6000000, 0xB3000000, 0x29000000, 0xE3000000, - 0x2F000000, 0x84000000, 0x53000000, 0xD1000000, 0x00000000, 0xED000000, - 0x20000000, 0xFC000000, 0xB1000000, 0x5B000000, 0x6A000000, 0xCB000000, - 0xBE000000, 0x39000000, 0x4A000000, 0x4C000000, 0x58000000, 0xCF000000, - 0xD0000000, 0xEF000000, 0xAA000000, 0xFB000000, 0x43000000, 0x4D000000, - 0x33000000, 0x85000000, 0x45000000, 0xF9000000, 0x02000000, 0x7F000000, - 0x50000000, 0x3C000000, 0x9F000000, 0xA8000000, 0x51000000, 0xA3000000, - 0x40000000, 0x8F000000, 0x92000000, 0x9D000000, 0x38000000, 0xF5000000, - 0xBC000000, 0xB6000000, 0xDA000000, 0x21000000, 0x10000000, 0xFF000000, - 0xF3000000, 0xD2000000, 0xCD000000, 0x0C000000, 0x13000000, 0xEC000000, - 0x5F000000, 0x97000000, 0x44000000, 0x17000000, 0xC4000000, 0xA7000000, - 0x7E000000, 0x3D000000, 0x64000000, 0x5D000000, 0x19000000, 0x73000000, - 0x60000000, 0x81000000, 0x4F000000, 0xDC000000, 0x22000000, 0x2A000000, - 0x90000000, 0x88000000, 0x46000000, 0xEE000000, 0xB8000000, 0x14000000, - 0xDE000000, 0x5E000000, 0x0B000000, 0xDB000000, 0xE0000000, 0x32000000, - 0x3A000000, 0x0A000000, 0x49000000, 0x06000000, 0x24000000, 0x5C000000, - 0xC2000000, 0xD3000000, 0xAC000000, 0x62000000, 0x91000000, 0x95000000, - 0xE4000000, 0x79000000, 0xE7000000, 0xC8000000, 0x37000000, 0x6D000000, - 0x8D000000, 0xD5000000, 0x4E000000, 0xA9000000, 0x6C000000, 0x56000000, - 0xF4000000, 0xEA000000, 0x65000000, 0x7A000000, 0xAE000000, 0x08000000, - 0xBA000000, 0x78000000, 0x25000000, 0x2E000000, 0x1C000000, 0xA6000000, - 0xB4000000, 0xC6000000, 0xE8000000, 0xDD000000, 0x74000000, 0x1F000000, - 0x4B000000, 0xBD000000, 0x8B000000, 0x8A000000, 0x70000000, 0x3E000000, - 0xB5000000, 0x66000000, 0x48000000, 0x03000000, 0xF6000000, 0x0E000000, - 0x61000000, 0x35000000, 0x57000000, 0xB9000000, 0x86000000, 0xC1000000, - 0x1D000000, 0x9E000000, 0xE1000000, 0xF8000000, 0x98000000, 0x11000000, - 0x69000000, 0xD9000000, 0x8E000000, 0x94000000, 0x9B000000, 0x1E000000, - 0x87000000, 0xE9000000, 0xCE000000, 0x55000000, 0x28000000, 0xDF000000, - 0x8C000000, 0xA1000000, 0x89000000, 0x0D000000, 0xBF000000, 0xE6000000, - 0x42000000, 0x68000000, 0x41000000, 0x99000000, 0x2D000000, 0x0F000000, - 0xB0000000, 0x54000000, 0xBB000000, 0x16000000 -}; - -static uint32_t p_drms_tab3[ 256 ] = -{ - 0x5150A7F4, 0x7E536541, 0x1AC3A417, 0x3A965E27, 0x3BCB6BAB, 0x1FF1459D, - 0xACAB58FA, 0x4B9303E3, 0x2055FA30, 0xADF66D76, 0x889176CC, 0xF5254C02, - 0x4FFCD7E5, 0xC5D7CB2A, 0x26804435, 0xB58FA362, 0xDE495AB1, 0x25671BBA, - 0x45980EEA, 0x5DE1C0FE, 0xC302752F, 0x8112F04C, 0x8DA39746, 0x6BC6F9D3, - 0x03E75F8F, 0x15959C92, 0xBFEB7A6D, 0x95DA5952, 0xD42D83BE, 0x58D32174, - 0x492969E0, 0x8E44C8C9, 0x756A89C2, 0xF478798E, 0x996B3E58, 0x27DD71B9, - 0xBEB64FE1, 0xF017AD88, 0xC966AC20, 0x7DB43ACE, 0x63184ADF, 0xE582311A, - 0x97603351, 0x62457F53, 0xB1E07764, 0xBB84AE6B, 0xFE1CA081, 0xF9942B08, - 0x70586848, 0x8F19FD45, 0x94876CDE, 0x52B7F87B, 0xAB23D373, 0x72E2024B, - 0xE3578F1F, 0x662AAB55, 0xB20728EB, 0x2F03C2B5, 0x869A7BC5, 0xD3A50837, - 0x30F28728, 0x23B2A5BF, 0x02BA6A03, 0xED5C8216, 0x8A2B1CCF, 0xA792B479, - 0xF3F0F207, 0x4EA1E269, 0x65CDF4DA, 0x06D5BE05, 0xD11F6234, 0xC48AFEA6, - 0x349D532E, 0xA2A055F3, 0x0532E18A, 0xA475EBF6, 0x0B39EC83, 0x40AAEF60, - 0x5E069F71, 0xBD51106E, 0x3EF98A21, 0x963D06DD, 0xDDAE053E, 0x4D46BDE6, - 0x91B58D54, 0x71055DC4, 0x046FD406, 0x60FF1550, 0x1924FB98, 0xD697E9BD, - 0x89CC4340, 0x67779ED9, 0xB0BD42E8, 0x07888B89, 0xE7385B19, 0x79DBEEC8, - 0xA1470A7C, 0x7CE90F42, 0xF8C91E84, 0x00000000, 0x09838680, 0x3248ED2B, - 0x1EAC7011, 0x6C4E725A, 0xFDFBFF0E, 0x0F563885, 0x3D1ED5AE, 0x3627392D, - 0x0A64D90F, 0x6821A65C, 0x9BD1545B, 0x243A2E36, 0x0CB1670A, 0x930FE757, - 0xB4D296EE, 0x1B9E919B, 0x804FC5C0, 0x61A220DC, 0x5A694B77, 0x1C161A12, - 0xE20ABA93, 0xC0E52AA0, 0x3C43E022, 0x121D171B, 0x0E0B0D09, 0xF2ADC78B, - 0x2DB9A8B6, 0x14C8A91E, 0x578519F1, 0xAF4C0775, 0xEEBBDD99, 0xA3FD607F, - 0xF79F2601, 0x5CBCF572, 0x44C53B66, 0x5B347EFB, 0x8B762943, 0xCBDCC623, - 0xB668FCED, 0xB863F1E4, 0xD7CADC31, 0x42108563, 0x13402297, 0x842011C6, - 0x857D244A, 0xD2F83DBB, 0xAE1132F9, 0xC76DA129, 0x1D4B2F9E, 0xDCF330B2, - 0x0DEC5286, 0x77D0E3C1, 0x2B6C16B3, 0xA999B970, 0x11FA4894, 0x472264E9, - 0xA8C48CFC, 0xA01A3FF0, 0x56D82C7D, 0x22EF9033, 0x87C74E49, 0xD9C1D138, - 0x8CFEA2CA, 0x98360BD4, 0xA6CF81F5, 0xA528DE7A, 0xDA268EB7, 0x3FA4BFAD, - 0x2CE49D3A, 0x500D9278, 0x6A9BCC5F, 0x5462467E, 0xF6C2138D, 0x90E8B8D8, - 0x2E5EF739, 0x82F5AFC3, 0x9FBE805D, 0x697C93D0, 0x6FA92DD5, 0xCFB31225, - 0xC83B99AC, 0x10A77D18, 0xE86E639C, 0xDB7BBB3B, 0xCD097826, 0x6EF41859, - 0xEC01B79A, 0x83A89A4F, 0xE6656E95, 0xAA7EE6FF, 0x2108CFBC, 0xEFE6E815, - 0xBAD99BE7, 0x4ACE366F, 0xEAD4099F, 0x29D67CB0, 0x31AFB2A4, 0x2A31233F, - 0xC63094A5, 0x35C066A2, 0x7437BC4E, 0xFCA6CA82, 0xE0B0D090, 0x3315D8A7, - 0xF14A9804, 0x41F7DAEC, 0x7F0E50CD, 0x172FF691, 0x768DD64D, 0x434DB0EF, - 0xCC544DAA, 0xE4DF0496, 0x9EE3B5D1, 0x4C1B886A, 0xC1B81F2C, 0x467F5165, - 0x9D04EA5E, 0x015D358C, 0xFA737487, 0xFB2E410B, 0xB35A1D67, 0x9252D2DB, - 0xE9335610, 0x6D1347D6, 0x9A8C61D7, 0x377A0CA1, 0x598E14F8, 0xEB893C13, - 0xCEEE27A9, 0xB735C961, 0xE1EDE51C, 0x7A3CB147, 0x9C59DFD2, 0x553F73F2, - 0x1879CE14, 0x73BF37C7, 0x53EACDF7, 0x5F5BAAFD, 0xDF146F3D, 0x7886DB44, - 0xCA81F3AF, 0xB93EC468, 0x382C3424, 0xC25F40A3, 0x1672C31D, 0xBC0C25E2, - 0x288B493C, 0xFF41950D, 0x397101A8, 0x08DEB30C, 0xD89CE4B4, 0x6490C156, - 0x7B6184CB, 0xD570B632, 0x48745C6C, 0xD04257B8 -}; - -static uint32_t p_drms_tab4[ 256 ] = -{ - 0x52000000, 0x09000000, 0x6A000000, 0xD5000000, 0x30000000, 0x36000000, - 0xA5000000, 0x38000000, 0xBF000000, 0x40000000, 0xA3000000, 0x9E000000, - 0x81000000, 0xF3000000, 0xD7000000, 0xFB000000, 0x7C000000, 0xE3000000, - 0x39000000, 0x82000000, 0x9B000000, 0x2F000000, 0xFF000000, 0x87000000, - 0x34000000, 0x8E000000, 0x43000000, 0x44000000, 0xC4000000, 0xDE000000, - 0xE9000000, 0xCB000000, 0x54000000, 0x7B000000, 0x94000000, 0x32000000, - 0xA6000000, 0xC2000000, 0x23000000, 0x3D000000, 0xEE000000, 0x4C000000, - 0x95000000, 0x0B000000, 0x42000000, 0xFA000000, 0xC3000000, 0x4E000000, - 0x08000000, 0x2E000000, 0xA1000000, 0x66000000, 0x28000000, 0xD9000000, - 0x24000000, 0xB2000000, 0x76000000, 0x5B000000, 0xA2000000, 0x49000000, - 0x6D000000, 0x8B000000, 0xD1000000, 0x25000000, 0x72000000, 0xF8000000, - 0xF6000000, 0x64000000, 0x86000000, 0x68000000, 0x98000000, 0x16000000, - 0xD4000000, 0xA4000000, 0x5C000000, 0xCC000000, 0x5D000000, 0x65000000, - 0xB6000000, 0x92000000, 0x6C000000, 0x70000000, 0x48000000, 0x50000000, - 0xFD000000, 0xED000000, 0xB9000000, 0xDA000000, 0x5E000000, 0x15000000, - 0x46000000, 0x57000000, 0xA7000000, 0x8D000000, 0x9D000000, 0x84000000, - 0x90000000, 0xD8000000, 0xAB000000, 0x00000000, 0x8C000000, 0xBC000000, - 0xD3000000, 0x0A000000, 0xF7000000, 0xE4000000, 0x58000000, 0x05000000, - 0xB8000000, 0xB3000000, 0x45000000, 0x06000000, 0xD0000000, 0x2C000000, - 0x1E000000, 0x8F000000, 0xCA000000, 0x3F000000, 0x0F000000, 0x02000000, - 0xC1000000, 0xAF000000, 0xBD000000, 0x03000000, 0x01000000, 0x13000000, - 0x8A000000, 0x6B000000, 0x3A000000, 0x91000000, 0x11000000, 0x41000000, - 0x4F000000, 0x67000000, 0xDC000000, 0xEA000000, 0x97000000, 0xF2000000, - 0xCF000000, 0xCE000000, 0xF0000000, 0xB4000000, 0xE6000000, 0x73000000, - 0x96000000, 0xAC000000, 0x74000000, 0x22000000, 0xE7000000, 0xAD000000, - 0x35000000, 0x85000000, 0xE2000000, 0xF9000000, 0x37000000, 0xE8000000, - 0x1C000000, 0x75000000, 0xDF000000, 0x6E000000, 0x47000000, 0xF1000000, - 0x1A000000, 0x71000000, 0x1D000000, 0x29000000, 0xC5000000, 0x89000000, - 0x6F000000, 0xB7000000, 0x62000000, 0x0E000000, 0xAA000000, 0x18000000, - 0xBE000000, 0x1B000000, 0xFC000000, 0x56000000, 0x3E000000, 0x4B000000, - 0xC6000000, 0xD2000000, 0x79000000, 0x20000000, 0x9A000000, 0xDB000000, - 0xC0000000, 0xFE000000, 0x78000000, 0xCD000000, 0x5A000000, 0xF4000000, - 0x1F000000, 0xDD000000, 0xA8000000, 0x33000000, 0x88000000, 0x07000000, - 0xC7000000, 0x31000000, 0xB1000000, 0x12000000, 0x10000000, 0x59000000, - 0x27000000, 0x80000000, 0xEC000000, 0x5F000000, 0x60000000, 0x51000000, - 0x7F000000, 0xA9000000, 0x19000000, 0xB5000000, 0x4A000000, 0x0D000000, - 0x2D000000, 0xE5000000, 0x7A000000, 0x9F000000, 0x93000000, 0xC9000000, - 0x9C000000, 0xEF000000, 0xA0000000, 0xE0000000, 0x3B000000, 0x4D000000, - 0xAE000000, 0x2A000000, 0xF5000000, 0xB0000000, 0xC8000000, 0xEB000000, - 0xBB000000, 0x3C000000, 0x83000000, 0x53000000, 0x99000000, 0x61000000, - 0x17000000, 0x2B000000, 0x04000000, 0x7E000000, 0xBA000000, 0x77000000, - 0xD6000000, 0x26000000, 0xE1000000, 0x69000000, 0x14000000, 0x63000000, - 0x55000000, 0x21000000, 0x0C000000, 0x7D000000 -}; - -static int32_t p_drms_tab_taos[ 64 ] = -{ - -0x28955B88, -0x173848AA, +0x242070DB, -0x3E423112, -0x0A83F051, - +0x4787C62A, -0x57CFB9ED, -0x02B96AFF, +0x698098D8, -0x74BB0851, - -0x0000A44F, -0x76A32842, +0x6B901122, -0x02678E6D, -0x5986BC72, - +0x49B40821, -0x09E1DA9E, -0x3FBF4CC0, +0x265E5A51, -0x16493856, - -0x29D0EFA3, +0x02441453, -0x275E197F, -0x182C0438, +0x21E1CDE6, - -0x3CC8F82A, -0x0B2AF279, +0x455A14ED, -0x561C16FB, -0x03105C08, - +0x676F02D9, -0x72D5B376, -0x0005C6BE, -0x788E097F, +0x6D9D6122, - -0x021AC7F4, -0x5B4115BC, +0x4BDECFA9, -0x0944B4A0, -0x41404390, - +0x289B7EC6, -0x155ED806, -0x2B10CF7B, +0x04881D05, -0x262B2FC7, - -0x1924661B, +0x1FA27CF8, -0x3B53A99B, -0x0BD6DDBC, +0x432AFF97, - -0x546BDC59, -0x036C5FC7, +0x655B59C3, -0x70F3336E, -0x00100B83, - -0x7A7BA22F, +0x6FA87E4F, -0x01D31920, -0x5CFEBCEC, +0x4E0811A1, - -0x08AC817E, -0x42C50DCB, +0x2AD7D2BB, -0x14792C6F -}; - -static uint8_t p_drms_tab_tend[ 64 ] = -{ - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static uint16_t p_drms_tab_xor[ 16 ][ 16 ] = -{ - { - 0x00D1, 0x0315, 0x1A32, 0x19EC, 0x1BBB, 0x1D6F, 0x14FE, 0x0E9E, - 0x029E, 0x1B8F, 0x0B70, 0x033A, 0x188E, 0x1D18, 0x0BD8, 0x0EDB - }, - - { - 0x0C64, 0x1C2B, 0x149C, 0x047B, 0x1064, 0x1C7C, 0x118D, 0x1355, - 0x0AE5, 0x0F18, 0x016F, 0x17D6, 0x1595, 0x0084, 0x0616, 0x1CCD - }, - - { - 0x1D94, 0x0618, 0x182C, 0x195B, 0x196D, 0x0394, 0x07DB, 0x0287, - 0x1636, 0x0B81, 0x1519, 0x0DF9, 0x1BA3, 0x1CC3, 0x0EE2, 0x1434 - }, - - { - 0x1457, 0x0CED, 0x0F7D, 0x0D7B, 0x0B9E, 0x0D13, 0x13D7, 0x18D0, - 0x1259, 0x1977, 0x0606, 0x1E80, 0x05F2, 0x06B8, 0x1F07, 0x1365 - }, - - { - 0x0334, 0x0E30, 0x195F, 0x15F1, 0x058E, 0x0AA8, 0x045A, 0x0465, - 0x0B3E, 0x071E, 0x0A36, 0x105C, 0x01AC, 0x1A1E, 0x04E4, 0x056B - }, - - { - 0x12BF, 0x0DA2, 0x0B41, 0x0EAF, 0x034F, 0x0181, 0x04E2, 0x002B, - 0x12E6, 0x01BE, 0x10E8, 0x128F, 0x0EB2, 0x1369, 0x05BE, 0x1A59 - }, - - { - 0x117E, 0x047C, 0x1E86, 0x056A, 0x0DA7, 0x0D61, 0x03FC, 0x1E6E, - 0x1D0C, 0x1E6D, 0x14BF, 0x0C50, 0x063A, 0x1B47, 0x17AE, 0x1321 - }, - - { - 0x041B, 0x0A24, 0x0D4D, 0x1F2B, 0x1CB6, 0x1BED, 0x1549, 0x03A7, - 0x0254, 0x006C, 0x0C9E, 0x0F73, 0x006C, 0x0008, 0x11F9, 0x0DD5 - }, - - { - 0x0BCF, 0x0AF9, 0x1DFE, 0x0341, 0x0E49, 0x0D38, 0x17CB, 0x1513, - 0x0E96, 0x00ED, 0x0556, 0x1B28, 0x100C, 0x19D8, 0x14FA, 0x028C - }, - - { - 0x1C60, 0x1232, 0x13D3, 0x0D00, 0x1534, 0x192C, 0x14B5, 0x1CF2, - 0x0504, 0x0B5B, 0x1ECF, 0x0423, 0x183B, 0x06B0, 0x169E, 0x1066 - }, - - { - 0x04CB, 0x08A2, 0x1B4A, 0x1254, 0x198D, 0x1044, 0x0236, 0x1BD8, - 0x18A1, 0x03FF, 0x1A0D, 0x0277, 0x0C2D, 0x17C9, 0x007C, 0x116E - }, - - { - 0x048A, 0x1EAF, 0x0922, 0x0C45, 0x0766, 0x1E5F, 0x1A28, 0x0120, - 0x1C15, 0x034C, 0x0508, 0x0E73, 0x0879, 0x0441, 0x09AE, 0x132F - }, - - { - 0x14FE, 0x0413, 0x0A9D, 0x1727, 0x01D7, 0x1A2B, 0x0474, 0x18F0, - 0x1F3B, 0x14F5, 0x1071, 0x0895, 0x1071, 0x18FF, 0x18E3, 0x0EB9 - }, - - { - 0x0BA9, 0x0961, 0x1599, 0x019E, 0x1D12, 0x1BAA, 0x1E94, 0x1921, - 0x14DC, 0x124E, 0x0A25, 0x03AB, 0x1CC0, 0x1EBB, 0x0B4B, 0x16E5 - }, - - { - 0x11EA, 0x0D78, 0x1BB3, 0x1BA7, 0x1510, 0x1B7B, 0x0C64, 0x1995, - 0x1A58, 0x1651, 0x1964, 0x147A, 0x15F2, 0x11BB, 0x1654, 0x166E - }, - - { - 0x0EA9, 0x1DE1, 0x1443, 0x13C5, 0x00E1, 0x0B2F, 0x0B6F, 0x0A37, - 0x18AC, 0x08E6, 0x06F0, 0x136E, 0x0853, 0x0B2E, 0x0813, 0x10D6 - } -}; - -static uint16_t p_drms_tab_sub[ 16 ][ 16 ] = -{ - { - 0x067A, 0x0C7D, 0x0B4F, 0x127D, 0x0BD6, 0x04AC, 0x16E0, 0x1730, - 0x0587, 0x0AFB, 0x1AC3, 0x0120, 0x14B5, 0x0F67, 0x11DE, 0x0961 - }, - - { - 0x1127, 0x1A68, 0x07F0, 0x17D0, 0x1A6F, 0x1F3B, 0x01EF, 0x0919, - 0x131E, 0x0F90, 0x19E9, 0x18A8, 0x0CB2, 0x1AD0, 0x0C66, 0x0378 - }, - - { - 0x03B0, 0x01BE, 0x1866, 0x1159, 0x197C, 0x1105, 0x010B, 0x0353, - 0x1ABB, 0x09A6, 0x028A, 0x1BAD, 0x1B20, 0x0455, 0x0F57, 0x0588 - }, - - { - 0x1491, 0x0A1D, 0x0F04, 0x0650, 0x191E, 0x1E0E, 0x174B, 0x016B, - 0x051F, 0x0532, 0x00DF, 0x1AEA, 0x0005, 0x0E1B, 0x0FF6, 0x08D8 - }, - - { - 0x14B4, 0x086A, 0x0C20, 0x0149, 0x1971, 0x0F26, 0x1852, 0x017D, - 0x1228, 0x0352, 0x0A44, 0x1330, 0x18DF, 0x1E38, 0x01BC, 0x0BAC - }, - - { - 0x1A48, 0x021F, 0x02F7, 0x0C31, 0x0BC4, 0x1E75, 0x105C, 0x13E3, - 0x0B20, 0x03A1, 0x1AF3, 0x1A36, 0x0E34, 0x181F, 0x09BD, 0x122B - }, - - { - 0x0EE0, 0x163B, 0x0BE7, 0x103D, 0x1075, 0x1E9D, 0x02AF, 0x0BA2, - 0x1DAA, 0x0CF1, 0x04B6, 0x0598, 0x06A1, 0x0D33, 0x1CFE, 0x04EE - }, - - { - 0x1BAD, 0x07C8, 0x1A48, 0x05E6, 0x031F, 0x0E0A, 0x0326, 0x1650, - 0x0526, 0x0B4E, 0x08FC, 0x0E4D, 0x0832, 0x06EA, 0x09BF, 0x0993 - }, - - { - 0x09EB, 0x0F31, 0x071B, 0x14D5, 0x11CA, 0x0722, 0x120D, 0x014C, - 0x1993, 0x0AE4, 0x1CCB, 0x04E9, 0x0AEE, 0x1708, 0x0C3D, 0x12F2 - }, - - { - 0x1A19, 0x07C1, 0x05A7, 0x0744, 0x1606, 0x1A9B, 0x042D, 0x1BFC, - 0x1841, 0x0C3C, 0x0FFE, 0x1AB1, 0x1416, 0x18A9, 0x0320, 0x1EC2 - }, - - { - 0x0AE7, 0x11C6, 0x124A, 0x11DF, 0x0F81, 0x06CF, 0x0ED9, 0x0253, - 0x1D2B, 0x0349, 0x0805, 0x08B3, 0x1052, 0x12CF, 0x0A44, 0x0EA6 - }, - - { - 0x03BF, 0x1D90, 0x0EF8, 0x0657, 0x156D, 0x0405, 0x10BE, 0x091F, - 0x1C82, 0x1725, 0x19EF, 0x0B8C, 0x04D9, 0x02C7, 0x025A, 0x1B89 - }, - - { - 0x0F5C, 0x013D, 0x02F7, 0x12E3, 0x0BC5, 0x1B56, 0x0848, 0x0239, - 0x0FCF, 0x03A4, 0x092D, 0x1354, 0x1D83, 0x01BD, 0x071A, 0x0AF1 - }, - - { - 0x0875, 0x0793, 0x1B41, 0x1782, 0x0DEF, 0x1D20, 0x13BE, 0x0095, - 0x1650, 0x19D4, 0x0DE3, 0x0980, 0x18F2, 0x0CA3, 0x0098, 0x149A - }, - - { - 0x0B81, 0x0AD2, 0x1BBA, 0x1A02, 0x027B, 0x1906, 0x07F5, 0x1CAE, - 0x0C3F, 0x02F6, 0x1298, 0x175E, 0x15B2, 0x13D8, 0x14CC, 0x161A - }, - - { - 0x0A42, 0x15F3, 0x0870, 0x1C1D, 0x1203, 0x18B1, 0x1738, 0x1954, - 0x1143, 0x1AE8, 0x1D9D, 0x155B, 0x11E8, 0x0ED9, 0x06F7, 0x04CA - } -}; - -static uint16_t p_drms_tab_add[ 16 ][ 16 ] = -{ - { - 0x0706, 0x175A, 0x0DEF, 0x1E72, 0x0297, 0x1B0E, 0x1D5A, 0x15B8, - 0x13E2, 0x1347, 0x10C6, 0x0B4F, 0x0629, 0x0A75, 0x0A9B, 0x0F55 - }, - - { - 0x1A69, 0x09BF, 0x0BA6, 0x1582, 0x1086, 0x1921, 0x01CB, 0x1C6A, - 0x0FF5, 0x00F7, 0x0A67, 0x0A1E, 0x1838, 0x0196, 0x10D6, 0x0C7A - }, - - { - 0x180E, 0x038D, 0x1ADD, 0x0684, 0x154A, 0x0AB0, 0x18A4, 0x0D73, - 0x1641, 0x0EC6, 0x09F1, 0x1A62, 0x0414, 0x162A, 0x194E, 0x1EC9 - }, - - { - 0x022F, 0x0296, 0x1104, 0x14FC, 0x096C, 0x1D02, 0x09BD, 0x027C, - 0x080E, 0x1324, 0x128C, 0x0DC1, 0x00B9, 0x17F2, 0x0CBC, 0x0F97 - }, - - { - 0x1B93, 0x1C3C, 0x0415, 0x0395, 0x0C7A, 0x06CC, 0x0D4B, 0x16E2, - 0x04A2, 0x0DAB, 0x1228, 0x012B, 0x0896, 0x0012, 0x1CD6, 0x1DAC - }, - - { - 0x080D, 0x0446, 0x047A, 0x00AD, 0x029E, 0x0686, 0x17C3, 0x1466, - 0x0D16, 0x1896, 0x076E, 0x00CD, 0x17DC, 0x1E9F, 0x1A7C, 0x02BB - }, - - { - 0x0D06, 0x112B, 0x14CB, 0x0A03, 0x1541, 0x1290, 0x0F6D, 0x1503, - 0x084B, 0x0382, 0x1A3F, 0x0371, 0x1977, 0x0B67, 0x0CAD, 0x1DF8 - }, - - { - 0x1CE3, 0x1306, 0x13F8, 0x1163, 0x1B0B, 0x00BD, 0x0BF0, 0x1A4F, - 0x16F7, 0x0B4F, 0x0CF8, 0x1254, 0x0541, 0x100D, 0x0296, 0x0410 - }, - - { - 0x1A2B, 0x1169, 0x17D9, 0x0819, 0x03D6, 0x0D03, 0x194D, 0x184A, - 0x07CA, 0x1989, 0x0FAD, 0x011C, 0x1C71, 0x0EF6, 0x0DC8, 0x0F2F - }, - - { - 0x0FA5, 0x11BE, 0x0F3B, 0x1D52, 0x0DE2, 0x016E, 0x1AD1, 0x0C4A, - 0x1BC2, 0x0AC9, 0x1485, 0x1BEE, 0x0949, 0x1A79, 0x1894, 0x12BB - }, - - { - 0x17B6, 0x14F5, 0x16B1, 0x142C, 0x1301, 0x03EF, 0x16FF, 0x0D37, - 0x0D78, 0x01FF, 0x00D6, 0x1053, 0x1A2A, 0x0F61, 0x1352, 0x0C7F - }, - - { - 0x137F, 0x09C4, 0x1D96, 0x021D, 0x1037, 0x1B19, 0x10EF, 0x14E4, - 0x02A0, 0x0236, 0x0A5D, 0x1519, 0x141C, 0x1399, 0x007E, 0x1E74 - }, - - { - 0x0941, 0x1B3C, 0x0062, 0x0371, 0x09AD, 0x08E8, 0x0A24, 0x0B97, - 0x1ED2, 0x0889, 0x136B, 0x0006, 0x1C4C, 0x0444, 0x06F8, 0x0DFB - }, - - { - 0x1D0F, 0x198D, 0x0700, 0x0AFC, 0x1781, 0x12F3, 0x10DA, 0x1F19, - 0x1055, 0x0DC9, 0x1860, 0x012B, 0x05BF, 0x082D, 0x0C17, 0x1941 - }, - - { - 0x0359, 0x1232, 0x104C, 0x0762, 0x0897, 0x1D6C, 0x030F, 0x1A36, - 0x16B0, 0x094D, 0x1782, 0x036F, 0x0EEA, 0x06E6, 0x0D00, 0x0187 - }, - - { - 0x17E2, 0x05E5, 0x19FA, 0x1950, 0x146A, 0x0B2A, 0x0512, 0x0EE0, - 0x1E27, 0x112D, 0x1DF0, 0x0B13, 0x0378, 0x1DD0, 0x00C1, 0x01E6 - } -}; - diff --git a/trunk/src/mp4ff/mp4atom.c b/trunk/src/mp4ff/mp4atom.c deleted file mode 100644 index b75a3da7f..000000000 --- a/trunk/src/mp4ff/mp4atom.c +++ /dev/null @@ -1,781 +0,0 @@ -/* -** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -** -** Any non-GPL usage of this software or parts of this software is strictly -** forbidden. -** -** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. -** -** $Id: mp4atom.c,v 1.17 2004/01/11 15:52:18 menno Exp $ -**/ - -#include <stdlib.h> -#include "mp4ffint.h" - -#include "drms.h" - -/* parse atom header size */ -static int32_t mp4ff_atom_get_size(const int8_t *data) -{ - uint32_t result; - uint32_t a, b, c, d; - - a = (uint8_t)data[0]; - b = (uint8_t)data[1]; - c = (uint8_t)data[2]; - d = (uint8_t)data[3]; - - result = (a<<24) | (b<<16) | (c<<8) | d; - //if (result > 0 && result < 8) result = 8; - - return (int32_t)result; -} - -/* comnapre 2 atom names, returns 1 for equal, 0 for unequal */ -static int32_t mp4ff_atom_compare(const int8_t a1, const int8_t b1, const int8_t c1, const int8_t d1, - const int8_t a2, const int8_t b2, const int8_t c2, const int8_t d2) -{ - if (a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2) - return 1; - else - return 0; -} - -static uint8_t mp4ff_atom_name_to_type(const int8_t a, const int8_t b, - const int8_t c, const int8_t d) -{ - if (a == 'm') - { - if (mp4ff_atom_compare(a,b,c,d, 'm','o','o','v')) - return ATOM_MOOV; - else if (mp4ff_atom_compare(a,b,c,d, 'm','i','n','f')) - return ATOM_MINF; - else if (mp4ff_atom_compare(a,b,c,d, 'm','d','i','a')) - return ATOM_MDIA; - else if (mp4ff_atom_compare(a,b,c,d, 'm','d','a','t')) - return ATOM_MDAT; - else if (mp4ff_atom_compare(a,b,c,d, 'm','d','h','d')) - return ATOM_MDHD; - else if (mp4ff_atom_compare(a,b,c,d, 'm','v','h','d')) - return ATOM_MVHD; - else if (mp4ff_atom_compare(a,b,c,d, 'm','p','4','a')) - return ATOM_MP4A; - else if (mp4ff_atom_compare(a,b,c,d, 'm','p','4','v')) - return ATOM_MP4V; - else if (mp4ff_atom_compare(a,b,c,d, 'm','p','4','s')) - return ATOM_MP4S; - else if (mp4ff_atom_compare(a,b,c,d, 'm','e','t','a')) - return ATOM_META; - } else if (a == 't') { - if (mp4ff_atom_compare(a,b,c,d, 't','r','a','k')) - return ATOM_TRAK; - else if (mp4ff_atom_compare(a,b,c,d, 't','k','h','d')) - return ATOM_TKHD; - else if (mp4ff_atom_compare(a,b,c,d, 't','r','e','f')) - return ATOM_TREF; - else if (mp4ff_atom_compare(a,b,c,d, 't','r','k','n')) - return ATOM_TRACK; - else if (mp4ff_atom_compare(a,b,c,d, 't','m','p','o')) - return ATOM_TEMPO; - } else if (a == 's') { - if (mp4ff_atom_compare(a,b,c,d, 's','t','b','l')) - return ATOM_STBL; - else if (mp4ff_atom_compare(a,b,c,d, 's','m','h','d')) - return ATOM_SMHD; - else if (mp4ff_atom_compare(a,b,c,d, 's','t','s','d')) - return ATOM_STSD; - else if (mp4ff_atom_compare(a,b,c,d, 's','t','t','s')) - return ATOM_STTS; - else if (mp4ff_atom_compare(a,b,c,d, 's','t','c','o')) - return ATOM_STCO; - else if (mp4ff_atom_compare(a,b,c,d, 's','t','s','c')) - return ATOM_STSC; - else if (mp4ff_atom_compare(a,b,c,d, 's','t','s','z')) - return ATOM_STSZ; - else if (mp4ff_atom_compare(a,b,c,d, 's','t','z','2')) - return ATOM_STZ2; - else if (mp4ff_atom_compare(a,b,c,d, 's','k','i','p')) - return ATOM_SKIP; - else if (mp4ff_atom_compare(a,b,c,d, 's','i','n','f')) - return ATOM_SINF; - else if (mp4ff_atom_compare(a,b,c,d, 's','c','h','i')) - return ATOM_SCHI; - } else if (a == '©') { - if (mp4ff_atom_compare(a,b,c,d, '©','n','a','m')) - return ATOM_TITLE; - else if (mp4ff_atom_compare(a,b,c,d, '©','A','R','T')) - return ATOM_ARTIST; - else if (mp4ff_atom_compare(a,b,c,d, '©','w','r','t')) - return ATOM_WRITER; - else if (mp4ff_atom_compare(a,b,c,d, '©','a','l','b')) - return ATOM_ALBUM; - else if (mp4ff_atom_compare(a,b,c,d, '©','d','a','y')) - return ATOM_DATE; - else if (mp4ff_atom_compare(a,b,c,d, '©','t','o','o')) - return ATOM_TOOL; - else if (mp4ff_atom_compare(a,b,c,d, '©','c','m','t')) - return ATOM_COMMENT; - else if (mp4ff_atom_compare(a,b,c,d, '©','g','e','n')) - return ATOM_GENRE1; - } - - if (mp4ff_atom_compare(a,b,c,d, 'e','d','t','s')) - return ATOM_EDTS; - else if (mp4ff_atom_compare(a,b,c,d, 'e','s','d','s')) - return ATOM_ESDS; - else if (mp4ff_atom_compare(a,b,c,d, 'f','t','y','p')) - return ATOM_FTYP; - else if (mp4ff_atom_compare(a,b,c,d, 'f','r','e','e')) - return ATOM_FREE; - else if (mp4ff_atom_compare(a,b,c,d, 'h','m','h','d')) - return ATOM_HMHD; - else if (mp4ff_atom_compare(a,b,c,d, 'v','m','h','d')) - return ATOM_VMHD; - else if (mp4ff_atom_compare(a,b,c,d, 'u','d','t','a')) - return ATOM_UDTA; - else if (mp4ff_atom_compare(a,b,c,d, 'i','l','s','t')) - return ATOM_ILST; - else if (mp4ff_atom_compare(a,b,c,d, 'n','a','m','e')) - return ATOM_NAME; - else if (mp4ff_atom_compare(a,b,c,d, 'd','a','t','a')) - return ATOM_DATA; - else if (mp4ff_atom_compare(a,b,c,d, 'd','i','s','k')) - return ATOM_DISC; - else if (mp4ff_atom_compare(a,b,c,d, 'g','n','r','e')) - return ATOM_GENRE2; - else if (mp4ff_atom_compare(a,b,c,d, 'c','o','v','r')) - return ATOM_COVER; - else if (mp4ff_atom_compare(a,b,c,d, 'c','p','i','l')) - return ATOM_COMPILATION; - else if (mp4ff_atom_compare(a,b,c,d, 'c','t','t','s')) - return ATOM_CTTS; - else if (mp4ff_atom_compare(a,b,c,d, 'd','r','m','s')) - return ATOM_DRMS; - else if (mp4ff_atom_compare(a,b,c,d, 'f','r','m','a')) - return ATOM_FRMA; - else if (mp4ff_atom_compare(a,b,c,d, 'p','r','i','v')) - return ATOM_PRIV; - else if (mp4ff_atom_compare(a,b,c,d, 'i','v','i','v')) - return ATOM_IVIV; - else - return ATOM_UNKNOWN; -} - -/* read atom header, return atom size, atom size is with header included */ -uint64_t mp4ff_atom_read_header(mp4ff_t *f, uint8_t *atom_type, uint8_t *header_size) -{ - uint64_t size; - int32_t ret; - int8_t atom_header[8]; - - ret = mp4ff_read_data(f, atom_header, 8); - if (ret != 8) - return 0; - - size = mp4ff_atom_get_size(atom_header); - *header_size = 8; - - /* check for 64 bit atom size */ - if (size == 1) - { - *header_size = 16; - size = mp4ff_read_int64(f); - } - - //printf("%c%c%c%c\n", atom_header[4], atom_header[5], atom_header[6], atom_header[7]); - - *atom_type = mp4ff_atom_name_to_type(atom_header[4], atom_header[5], atom_header[6], atom_header[7]); - - return size; -} - -static int32_t mp4ff_read_stsz(mp4ff_t *f) -{ - mp4ff_read_char(f); /* version */ - mp4ff_read_int24(f); /* flags */ - f->track[f->total_tracks - 1]->stsz_sample_size = mp4ff_read_int32(f); - f->track[f->total_tracks - 1]->stsz_sample_count = mp4ff_read_int32(f); - - if (f->track[f->total_tracks - 1]->stsz_sample_size == 0) - { - int32_t i; - f->track[f->total_tracks - 1]->stsz_table = - (int32_t*)malloc(f->track[f->total_tracks - 1]->stsz_sample_count*sizeof(int32_t)); - - for (i = 0; i < f->track[f->total_tracks - 1]->stsz_sample_count; i++) - { - f->track[f->total_tracks - 1]->stsz_table[i] = mp4ff_read_int32(f); - } - } - - return 0; -} - -static int32_t mp4ff_read_esds(mp4ff_t *f) -{ - uint8_t tag; - uint32_t temp; - - mp4ff_read_char(f); /* version */ - mp4ff_read_int24(f); /* flags */ - - /* get and verify ES_DescrTag */ - tag = mp4ff_read_char(f); - if (tag == 0x03) - { - /* read length */ - if (mp4ff_read_mp4_descr_length(f) < 5 + 15) - { - return 1; - } - /* skip 3 bytes */ - mp4ff_read_int24(f); - } else { - /* skip 2 bytes */ - mp4ff_read_int16(f); - } - - /* get and verify DecoderConfigDescrTab */ - if (mp4ff_read_char(f) != 0x04) - { - return 1; - } - - /* read length */ - temp = mp4ff_read_mp4_descr_length(f); - if (temp < 13) return 1; - - f->track[f->total_tracks - 1]->audioType = mp4ff_read_char(f); - mp4ff_read_int32(f);//0x15000414 ???? - f->track[f->total_tracks - 1]->maxBitrate = mp4ff_read_int32(f); - f->track[f->total_tracks - 1]->avgBitrate = mp4ff_read_int32(f); - - /* get and verify DecSpecificInfoTag */ - if (mp4ff_read_char(f) != 0x05) - { - return 1; - } - - /* read length */ - f->track[f->total_tracks - 1]->decoderConfigLen = mp4ff_read_mp4_descr_length(f); - - if (f->track[f->total_tracks - 1]->decoderConfig) - free(f->track[f->total_tracks - 1]->decoderConfig); - f->track[f->total_tracks - 1]->decoderConfig = malloc(f->track[f->total_tracks - 1]->decoderConfigLen); - if (f->track[f->total_tracks - 1]->decoderConfig) - { - mp4ff_read_data(f, f->track[f->total_tracks - 1]->decoderConfig, f->track[f->total_tracks - 1]->decoderConfigLen); - } else { - f->track[f->total_tracks - 1]->decoderConfigLen = 0; - } - - /* will skip the remainder of the atom */ - return 0; -} - -static int32_t mp4ff_read_mp4a(mp4ff_t *f) -{ - uint64_t size; - int32_t i; - uint8_t atom_type = 0; - uint8_t header_size = 0; - - for (i = 0; i < 6; i++) - { - mp4ff_read_char(f); /* reserved */ - } - /* data_reference_index */ mp4ff_read_int16(f); - - mp4ff_read_int32(f); /* reserved */ - mp4ff_read_int32(f); /* reserved */ - - f->track[f->total_tracks - 1]->channelCount = mp4ff_read_int16(f); - f->track[f->total_tracks - 1]->sampleSize = mp4ff_read_int16(f); - - mp4ff_read_int16(f); - mp4ff_read_int16(f); - - f->track[f->total_tracks - 1]->sampleRate = mp4ff_read_int16(f); - - mp4ff_read_int16(f); - - size = mp4ff_atom_read_header(f, &atom_type, &header_size); - if (atom_type == ATOM_ESDS) - { - mp4ff_read_esds(f); - } - - return 0; -} - -#ifdef ITUNES_DRM -static int32_t mp4ff_read_drms(mp4ff_t *f, uint64_t skip) -{ - uint64_t size; - int32_t i; - uint8_t atom_type = 0; - uint8_t header_size = 0; - uint32_t drms_user_key[4]; - - if (drms_get_user_key(NULL, drms_user_key) == 0) - { - f->track[f->total_tracks - 1]->p_drms = drms_alloc(); - - drms_init( f->track[f->total_tracks - 1]->p_drms, - DRMS_INIT_UKEY, (uint8_t *)drms_user_key, - sizeof(drms_user_key) ); - } - - for (i = 0; i < 6; i++) - { - mp4ff_read_char(f); /* reserved */ - } - /* data_reference_index */ mp4ff_read_int16(f); - - mp4ff_read_int32(f); /* reserved */ - mp4ff_read_int32(f); /* reserved */ - - f->track[f->total_tracks - 1]->channelCount = mp4ff_read_int16(f); - f->track[f->total_tracks - 1]->sampleSize = mp4ff_read_int16(f); - - mp4ff_read_int16(f); - mp4ff_read_int16(f); - - f->track[f->total_tracks - 1]->sampleRate = mp4ff_read_int16(f); - - mp4ff_read_int16(f); - - size = mp4ff_atom_read_header(f, &atom_type, &header_size); - if (atom_type == ATOM_ESDS) - { - mp4ff_read_esds(f); - } - mp4ff_set_position(f, skip+size+28); - - size = mp4ff_atom_read_header(f, &atom_type, &header_size); - if (atom_type == ATOM_SINF) - { - parse_sub_atoms(f, size-header_size); - } - - return 0; -} - -static int32_t mp4ff_read_frma(mp4ff_t *f) -{ - uint8_t atom_type; - int8_t type[4]; - - mp4ff_read_data(f, type, 4); - - atom_type = mp4ff_atom_name_to_type(type[0], type[1], type[2], type[3]); - - if (atom_type == ATOM_MP4A) - { - f->track[f->total_tracks - 1]->type = TRACK_AUDIO; - } else if (atom_type == ATOM_MP4V) { - f->track[f->total_tracks - 1]->type = TRACK_VIDEO; - } else if (atom_type == ATOM_MP4S) { - f->track[f->total_tracks - 1]->type = TRACK_SYSTEM; - } else { - f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN; - } - - return 0; -} - -static int32_t mp4ff_read_name(mp4ff_t *f, uint64_t size) -{ - uint8_t *data = malloc(size); - mp4ff_read_data(f, data, size); - - if (f->track[f->total_tracks - 1]->p_drms != NULL) - { - drms_init(f->track[f->total_tracks - 1]->p_drms, - DRMS_INIT_NAME, data, strlen(data) ); - } - - if (data) - free(data); - - return 0; -} - -static int32_t mp4ff_read_priv(mp4ff_t *f, uint64_t size) -{ - uint8_t *data = malloc(size); - mp4ff_read_data(f, data, size); - - if (f->track[f->total_tracks - 1]->p_drms != 0) - { - drms_init(f->track[f->total_tracks - 1]->p_drms, - DRMS_INIT_PRIV, data, size ); - } - - if (data) - free(data); - - return 0; -} - -static int32_t mp4ff_read_iviv(mp4ff_t *f, uint64_t size) -{ - uint8_t *data = malloc(size); - mp4ff_read_data(f, data, size); - - if (f->track[f->total_tracks - 1]->p_drms != 0) - { - drms_init(f->track[f->total_tracks - 1]->p_drms, - DRMS_INIT_IVIV, data, sizeof(uint32_t) * 4 ); - } - - if (data) - free(data); - - return 0; -} -#endif - -static int32_t mp4ff_read_stsd(mp4ff_t *f) -{ - int32_t i; - uint8_t header_size = 0; - - mp4ff_read_char(f); /* version */ - mp4ff_read_int24(f); /* flags */ - - f->track[f->total_tracks - 1]->stsd_entry_count = mp4ff_read_int32(f); - - for (i = 0; i < f->track[f->total_tracks - 1]->stsd_entry_count; i++) - { - uint64_t skip = mp4ff_position(f); - uint64_t size; - uint8_t atom_type = 0; - size = mp4ff_atom_read_header(f, &atom_type, &header_size); - skip += size; - - if (atom_type == ATOM_MP4A) - { - f->track[f->total_tracks - 1]->type = TRACK_AUDIO; - mp4ff_read_mp4a(f); - } else if (atom_type == ATOM_MP4V) { - f->track[f->total_tracks - 1]->type = TRACK_VIDEO; - } else if (atom_type == ATOM_MP4S) { - f->track[f->total_tracks - 1]->type = TRACK_SYSTEM; -#ifdef ITUNES_DRM - } else if (atom_type == ATOM_DRMS) { - // track type is read from the "frma" atom - f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN; - mp4ff_read_drms(f, skip-size+header_size); -#endif - } else { - f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN; - } - - mp4ff_set_position(f, skip); - } - - return 0; -} - -static int32_t mp4ff_read_stsc(mp4ff_t *f) -{ - int32_t i; - - mp4ff_read_char(f); /* version */ - mp4ff_read_int24(f); /* flags */ - f->track[f->total_tracks - 1]->stsc_entry_count = mp4ff_read_int32(f); - - f->track[f->total_tracks - 1]->stsc_first_chunk = - (int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t)); - f->track[f->total_tracks - 1]->stsc_samples_per_chunk = - (int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t)); - f->track[f->total_tracks - 1]->stsc_sample_desc_index = - (int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t)); - - for (i = 0; i < f->track[f->total_tracks - 1]->stsc_entry_count; i++) - { - f->track[f->total_tracks - 1]->stsc_first_chunk[i] = mp4ff_read_int32(f); - f->track[f->total_tracks - 1]->stsc_samples_per_chunk[i] = mp4ff_read_int32(f); - f->track[f->total_tracks - 1]->stsc_sample_desc_index[i] = mp4ff_read_int32(f); - } - - return 0; -} - -static int32_t mp4ff_read_stco(mp4ff_t *f) -{ - int32_t i; - - mp4ff_read_char(f); /* version */ - mp4ff_read_int24(f); /* flags */ - f->track[f->total_tracks - 1]->stco_entry_count = mp4ff_read_int32(f); - - f->track[f->total_tracks - 1]->stco_chunk_offset = - (int32_t*)malloc(f->track[f->total_tracks - 1]->stco_entry_count*sizeof(int32_t)); - - for (i = 0; i < f->track[f->total_tracks - 1]->stco_entry_count; i++) - { - f->track[f->total_tracks - 1]->stco_chunk_offset[i] = mp4ff_read_int32(f); - } - - return 0; -} - -static int32_t mp4ff_read_ctts(mp4ff_t *f) -{ - int32_t i; - mp4ff_track_t * p_track = f->track[f->total_tracks - 1]; - - if (p_track->ctts_entry_count) return 0; - - mp4ff_read_char(f); /* version */ - mp4ff_read_int24(f); /* flags */ - p_track->ctts_entry_count = mp4ff_read_int32(f); - - p_track->ctts_sample_count = (int32_t*)malloc(p_track->ctts_entry_count * sizeof(int32_t)); - p_track->ctts_sample_offset = (int32_t*)malloc(p_track->ctts_entry_count * sizeof(int32_t)); - - if (p_track->ctts_sample_count == 0 || p_track->ctts_sample_offset == 0) - { - if (p_track->ctts_sample_count) {free(p_track->ctts_sample_count);p_track->ctts_sample_count=0;} - if (p_track->ctts_sample_offset) {free(p_track->ctts_sample_offset);p_track->ctts_sample_offset=0;} - p_track->ctts_entry_count = 0; - return 0; - } - else - { - for (i = 0; i < f->track[f->total_tracks - 1]->ctts_entry_count; i++) - { - p_track->ctts_sample_count[i] = mp4ff_read_int32(f); - p_track->ctts_sample_offset[i] = mp4ff_read_int32(f); - } - return 1; - } -} - -static int32_t mp4ff_read_stts(mp4ff_t *f) -{ - int32_t i; - mp4ff_track_t * p_track = f->track[f->total_tracks - 1]; - - if (p_track->stts_entry_count) return 0; - - mp4ff_read_char(f); /* version */ - mp4ff_read_int24(f); /* flags */ - p_track->stts_entry_count = mp4ff_read_int32(f); - - p_track->stts_sample_count = (int32_t*)malloc(p_track->stts_entry_count * sizeof(int32_t)); - p_track->stts_sample_delta = (int32_t*)malloc(p_track->stts_entry_count * sizeof(int32_t)); - - if (p_track->stts_sample_count == 0 || p_track->stts_sample_delta == 0) - { - if (p_track->stts_sample_count) {free(p_track->stts_sample_count);p_track->stts_sample_count=0;} - if (p_track->stts_sample_delta) {free(p_track->stts_sample_delta);p_track->stts_sample_delta=0;} - p_track->stts_entry_count = 0; - return 0; - } - else - { - for (i = 0; i < f->track[f->total_tracks - 1]->stts_entry_count; i++) - { - p_track->stts_sample_count[i] = mp4ff_read_int32(f); - p_track->stts_sample_delta[i] = mp4ff_read_int32(f); - } - return 1; - } -} - -static int32_t mp4ff_read_mvhd(mp4ff_t *f) -{ - int32_t i; - - mp4ff_read_char(f); /* version */ - mp4ff_read_int24(f); /* flags */ - /* creation_time */ mp4ff_read_int32(f); - /* modification_time */ mp4ff_read_int32(f); - f->time_scale = mp4ff_read_int32(f); - f->duration = mp4ff_read_int32(f); - /* preferred_rate */ mp4ff_read_int32(f); /*mp4ff_read_fixed32(f);*/ - /* preferred_volume */ mp4ff_read_int16(f); /*mp4ff_read_fixed16(f);*/ - for (i = 0; i < 10; i++) - { - /* reserved */ mp4ff_read_char(f); - } - for (i = 0; i < 9; i++) - { - mp4ff_read_int32(f); /* matrix */ - } - /* preview_time */ mp4ff_read_int32(f); - /* preview_duration */ mp4ff_read_int32(f); - /* poster_time */ mp4ff_read_int32(f); - /* selection_time */ mp4ff_read_int32(f); - /* selection_duration */ mp4ff_read_int32(f); - /* current_time */ mp4ff_read_int32(f); - /* next_track_id */ mp4ff_read_int32(f); - - return 0; -} - -#if 0 -static int32_t mp4ff_read_tkhd(mp4ff_t *f) -{ - uint8_t version; - uint32_t flags; - version = mp4ff_read_char(f); /* version */ - flags = mp4ff_read_int24(f); /* flags */ - if (version==1) - { - mp4ff_read_int64(f);//creation-time - mp4ff_read_int64(f);//modification-time - mp4ff_read_int32(f);//track-id - mp4ff_read_int32(f);//reserved - f->track[f->total_tracks - 1]->duration = mp4ff_read_int64(f);//duration - } - else //version == 0 - { - mp4ff_read_int32(f);//creation-time - mp4ff_read_int32(f);//modification-time - mp4ff_read_int32(f);//track-id - mp4ff_read_int32(f);//reserved - f->track[f->total_tracks - 1]->duration = mp4ff_read_int32(f);//duration - if (f->track[f->total_tracks - 1]->duration == 0xFFFFFFFF) - f->track[f->total_tracks - 1]->duration = 0xFFFFFFFFFFFFFFFF; - - } - mp4ff_read_int32(f);//reserved - mp4ff_read_int32(f);//reserved - mp4ff_read_int16(f);//layer - mp4ff_read_int16(f);//pre-defined - mp4ff_read_int16(f);//volume - mp4ff_read_int16(f);//reserved - - //matrix - mp4ff_read_int32(f); mp4ff_read_int32(f); mp4ff_read_int32(f); - mp4ff_read_int32(f); mp4ff_read_int32(f); mp4ff_read_int32(f); - mp4ff_read_int32(f); mp4ff_read_int32(f); mp4ff_read_int32(f); - mp4ff_read_int32(f);//width - mp4ff_read_int32(f);//height - return 1; -} -#endif - -static int32_t mp4ff_read_mdhd(mp4ff_t *f) -{ - uint32_t version; - - version = mp4ff_read_int32(f); - if (version==1) - { - mp4ff_read_int64(f);//creation-time - mp4ff_read_int64(f);//modification-time - f->track[f->total_tracks - 1]->timeScale = mp4ff_read_int32(f);//timescale - f->track[f->total_tracks - 1]->duration = mp4ff_read_int64(f);//duration - } - else //version == 0 - { - uint32_t temp; - - mp4ff_read_int32(f);//creation-time - mp4ff_read_int32(f);//modification-time - f->track[f->total_tracks - 1]->timeScale = mp4ff_read_int32(f);//timescale - temp = mp4ff_read_int32(f); - f->track[f->total_tracks - 1]->duration = (temp == (uint32_t)(-1)) ? (uint64_t)(-1) : (uint64_t)(temp); - } - mp4ff_read_int16(f); - mp4ff_read_int16(f); - return 1; -} -#ifdef USE_TAGGING -static int32_t mp4ff_read_meta(mp4ff_t *f, const uint64_t size) -{ - uint64_t subsize, sumsize = 0; - uint8_t atom_type; - uint8_t header_size = 0; - - mp4ff_read_char(f); /* version */ - mp4ff_read_int24(f); /* flags */ - - while (sumsize < (size-12)) - { - subsize = mp4ff_atom_read_header(f, &atom_type, &header_size); - if (atom_type == ATOM_ILST) - { - mp4ff_parse_metadata(f, (uint32_t)(subsize-(header_size+4))); - } else { - mp4ff_set_position(f, mp4ff_position(f)+subsize-header_size); - } - sumsize += subsize; - } - - return 0; -} -#endif - -int32_t mp4ff_atom_read(mp4ff_t *f, const int32_t size, const uint8_t atom_type) -{ - uint64_t dest_position = mp4ff_position(f)+size-8; - if (atom_type == ATOM_STSZ) - { - /* sample size box */ - mp4ff_read_stsz(f); - } else if (atom_type == ATOM_STTS) { - /* time to sample box */ - mp4ff_read_stts(f); - } else if (atom_type == ATOM_CTTS) { - /* composition offset box */ - mp4ff_read_ctts(f); - } else if (atom_type == ATOM_STSC) { - /* sample to chunk box */ - mp4ff_read_stsc(f); - } else if (atom_type == ATOM_STCO) { - /* chunk offset box */ - mp4ff_read_stco(f); - } else if (atom_type == ATOM_STSD) { - /* sample description box */ - mp4ff_read_stsd(f); - } else if (atom_type == ATOM_MVHD) { - /* movie header box */ - mp4ff_read_mvhd(f); - } else if (atom_type == ATOM_MDHD) { - /* track header */ - mp4ff_read_mdhd(f); -#ifdef ITUNES_DRM - } else if (atom_type == ATOM_FRMA) { - /* DRM track format */ - mp4ff_read_frma(f); - } else if (atom_type == ATOM_IVIV) { - mp4ff_read_iviv(f, size-8); - } else if (atom_type == ATOM_NAME) { - mp4ff_read_name(f, size-8); - } else if (atom_type == ATOM_PRIV) { - mp4ff_read_priv(f, size-8); -#endif -#ifdef USE_TAGGING - } else if (atom_type == ATOM_META) { - /* iTunes Metadata box */ - mp4ff_read_meta(f, size); -#endif - } - - mp4ff_set_position(f, dest_position); - - - return 0; -} diff --git a/trunk/src/mp4ff/mp4ff.c b/trunk/src/mp4ff/mp4ff.c deleted file mode 100644 index e0bb781e8..000000000 --- a/trunk/src/mp4ff/mp4ff.c +++ /dev/null @@ -1,430 +0,0 @@ -/* -** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -** -** Any non-GPL usage of this software or parts of this software is strictly -** forbidden. -** -** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. -** -** $Id: mp4ff.c,v 1.15 2004/01/11 15:52:18 menno Exp $ -**/ - -#include <stdlib.h> -#include <string.h> -#include "mp4ffint.h" - -#include "drms.h" - -int64_t mp4ff_get_track_duration_use_offsets(const mp4ff_t *f, const int32_t track); - -mp4ff_t *mp4ff_open_read(mp4ff_callback_t *f) -{ - mp4ff_t *ff = malloc(sizeof(mp4ff_t)); - - memset(ff, 0, sizeof(mp4ff_t)); - - ff->stream = f; - - parse_atoms(ff); - - return ff; -} - -void mp4ff_close(mp4ff_t *ff) -{ - int32_t i; - - for (i = 0; i < ff->total_tracks; i++) - { - if (ff->track[i]) - { - if (ff->track[i]->stsz_table) - free(ff->track[i]->stsz_table); - if (ff->track[i]->stts_sample_count) - free(ff->track[i]->stts_sample_count); - if (ff->track[i]->stts_sample_delta) - free(ff->track[i]->stts_sample_delta); - if (ff->track[i]->stsc_first_chunk) - free(ff->track[i]->stsc_first_chunk); - if (ff->track[i]->stsc_samples_per_chunk) - free(ff->track[i]->stsc_samples_per_chunk); - if (ff->track[i]->stsc_sample_desc_index) - free(ff->track[i]->stsc_sample_desc_index); - if (ff->track[i]->stco_chunk_offset) - free(ff->track[i]->stco_chunk_offset); - if (ff->track[i]->decoderConfig) - free(ff->track[i]->decoderConfig); - if (ff->track[i]->ctts_sample_count) - free(ff->track[i]->ctts_sample_count); - if (ff->track[i]->ctts_sample_offset) - free(ff->track[i]->ctts_sample_offset); -#ifdef ITUNES_DRM - if (ff->track[i]->p_drms) - drms_free(ff->track[i]->p_drms); -#endif - free(ff->track[i]); - } - } - -#ifdef USE_TAGGING - mp4ff_tag_delete(&(ff->tags)); -#endif - - if (ff) free(ff); -} - -static void mp4ff_track_add(mp4ff_t *f) -{ - f->total_tracks++; - - f->track[f->total_tracks - 1] = malloc(sizeof(mp4ff_track_t)); - - memset(f->track[f->total_tracks - 1], 0, sizeof(mp4ff_track_t)); -} - -/* parse atoms that are sub atoms of other atoms */ -int32_t parse_sub_atoms(mp4ff_t *f, const uint64_t total_size) -{ - uint64_t size; - uint8_t atom_type = 0; - uint64_t counted_size = 0; - uint8_t header_size = 0; - - while (counted_size < total_size) - { - size = mp4ff_atom_read_header(f, &atom_type, &header_size); - counted_size += size; - - /* check for end of file */ - if (size == 0) - break; - - /* we're starting to read a new track, update index, - * so that all data and tables get written in the right place - */ - if (atom_type == ATOM_TRAK) - { - mp4ff_track_add(f); - } - - /* parse subatoms */ - if (atom_type < SUBATOMIC) - { - parse_sub_atoms(f, size-header_size); - } else { - mp4ff_atom_read(f, (uint32_t)size, atom_type); - } - } - - return 0; -} - -/* parse root atoms */ -int32_t parse_atoms(mp4ff_t *f) -{ - uint64_t size; - uint8_t atom_type = 0; - uint8_t header_size = 0; - - f->file_size = 0; - - while ((size = mp4ff_atom_read_header(f, &atom_type, &header_size)) != 0) - { - f->file_size += size; - f->last_atom = atom_type; - - if (atom_type == ATOM_MDAT && f->moov_read) - { - /* moov atom is before mdat, we can stop reading when mdat is encountered */ - /* file position will stay at beginning of mdat data */ -// break; - } - - if (atom_type == ATOM_MOOV && size > header_size) - { - f->moov_read = 1; - f->moov_offset = mp4ff_position(f)-header_size; - f->moov_size = size; - } - - /* parse subatoms */ - if (atom_type < SUBATOMIC) - { - parse_sub_atoms(f, size-header_size); - } else { - /* skip this atom */ - mp4ff_set_position(f, mp4ff_position(f)+size-header_size); - } - } - - return 0; -} - -int32_t mp4ff_get_decoder_config(const mp4ff_t *f, const int32_t track, - uint8_t** ppBuf, uint32_t* pBufSize) -{ - if (track >= f->total_tracks) - { - *ppBuf = NULL; - *pBufSize = 0; - return 1; - } - - if (f->track[track]->decoderConfig == NULL || f->track[track]->decoderConfigLen == 0) - { - *ppBuf = NULL; - *pBufSize = 0; - } else { - *ppBuf = malloc(f->track[track]->decoderConfigLen); - if (*ppBuf == NULL) - { - *pBufSize = 0; - return 1; - } - memcpy(*ppBuf, f->track[track]->decoderConfig, f->track[track]->decoderConfigLen); - *pBufSize = f->track[track]->decoderConfigLen; - } - - return 0; -} - -static int32_t mp4ff_get_track_type(const mp4ff_t *f, const int track) -{ - return f->track[track]->type; -} - -int32_t mp4ff_total_tracks(const mp4ff_t *f) -{ - return f->total_tracks; -} - -int32_t mp4ff_time_scale(const mp4ff_t *f, const int32_t track) -{ - return f->track[track]->timeScale; -} - -static uint32_t mp4ff_get_avg_bitrate(const mp4ff_t *f, const int32_t track) -{ - return f->track[track]->avgBitrate; -} - -static uint32_t mp4ff_get_max_bitrate(const mp4ff_t *f, const int32_t track) -{ - return f->track[track]->maxBitrate; -} - -static int64_t mp4ff_get_track_duration(const mp4ff_t *f, const int32_t track) -{ - return f->track[track]->duration; -} - -int64_t mp4ff_get_track_duration_use_offsets(const mp4ff_t *f, const int32_t track) -{ - int64_t duration = mp4ff_get_track_duration(f,track); - if (duration!=-1) - { - int64_t offset = mp4ff_get_sample_offset(f,track,0); - if (offset > duration) duration = 0; - else duration -= offset; - } - return duration; -} - - -int32_t mp4ff_num_samples(const mp4ff_t *f, const int32_t track) -{ - int32_t i; - int32_t total = 0; - - for (i = 0; i < f->track[track]->stts_entry_count; i++) - { - total += f->track[track]->stts_sample_count[i]; - } - return total; -} - - - - -static uint32_t mp4ff_get_sample_rate(const mp4ff_t *f, const int32_t track) -{ - return f->track[track]->sampleRate; -} - -static uint32_t mp4ff_get_channel_count(const mp4ff_t * f,const int32_t track) -{ - return f->track[track]->channelCount; -} - -static uint32_t mp4ff_get_audio_type(const mp4ff_t * f,const int32_t track) -{ - return f->track[track]->audioType; -} - -static int32_t mp4ff_get_sample_duration_use_offsets(const mp4ff_t *f, const int32_t track, const int32_t sample) -{ - int32_t d,o; - d = mp4ff_get_sample_duration(f,track,sample); - if (d!=-1) - { - o = mp4ff_get_sample_offset(f,track,sample); - if (o>d) d = 0; - else d -= o; - } - return d; -} - -int32_t mp4ff_get_sample_duration(const mp4ff_t *f, const int32_t track, const int32_t sample) -{ - int32_t i, co = 0; - - for (i = 0; i < f->track[track]->stts_entry_count; i++) - { - int32_t delta = f->track[track]->stts_sample_count[i]; - if (sample < co + delta) - return f->track[track]->stts_sample_delta[i]; - co += delta; - } - return (int32_t)(-1); -} - -int64_t mp4ff_get_sample_position(const mp4ff_t *f, const int32_t track, const int32_t sample) -{ - int32_t i, co = 0; - int64_t acc = 0; - - for (i = 0; i < f->track[track]->stts_entry_count; i++) - { - int32_t delta = f->track[track]->stts_sample_count[i]; - if (sample < co + delta) - { - acc += f->track[track]->stts_sample_delta[i] * (sample - co); - return acc; - } - else - { - acc += f->track[track]->stts_sample_delta[i] * delta; - } - co += delta; - } - return (int64_t)(-1); -} - -int32_t mp4ff_get_sample_offset(const mp4ff_t *f, const int32_t track, const int32_t sample) -{ - int32_t i, co = 0; - - for (i = 0; i < f->track[track]->ctts_entry_count; i++) - { - int32_t delta = f->track[track]->ctts_sample_count[i]; - if (sample < co + delta) - return f->track[track]->ctts_sample_offset[i]; - co += delta; - } - return 0; -} - -int32_t mp4ff_find_sample(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip) -{ - int32_t i, co = 0; - int64_t offset_total = 0; - mp4ff_track_t * p_track = f->track[track]; - - for (i = 0; i < p_track->stts_entry_count; i++) - { - int32_t sample_count = p_track->stts_sample_count[i]; - int32_t sample_delta = p_track->stts_sample_delta[i]; - int64_t offset_delta = (int64_t)sample_delta * (int64_t)sample_count; - if (offset < offset_total + offset_delta) - { - int64_t offset_fromstts = offset - offset_total; - if (toskip) *toskip = (int32_t)(offset_fromstts % sample_delta); - return co + (int32_t)(offset_fromstts / sample_delta); - } - else - { - offset_total += offset_delta; - } - co += sample_count; - } - return (int32_t)(-1); -} - -static int32_t mp4ff_find_sample_use_offsets(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip) -{ - return mp4ff_find_sample(f,track,offset + mp4ff_get_sample_offset(f,track,0),toskip); -} - -int32_t mp4ff_read_sample(mp4ff_t *f, const int32_t track, const int32_t sample, - uint8_t **audio_buffer, uint32_t *bytes) -{ - int32_t result = 0; - - *bytes = mp4ff_audio_frame_size(f, track, sample); - - if (*bytes==0) return 0; - - *audio_buffer = (uint8_t*)malloc(*bytes); - - mp4ff_set_sample_position(f, track, sample); - - result = mp4ff_read_data(f, *audio_buffer, *bytes); - - if (!result) - { - free(*audio_buffer); - *audio_buffer = 0; - return 0; - } - -#ifdef ITUNES_DRM - if (f->track[track]->p_drms != NULL) - { - drms_decrypt(f->track[track]->p_drms, (uint32_t*)*audio_buffer, *bytes); - } -#endif - - return *bytes; -} - - -static int32_t mp4ff_read_sample_v2(mp4ff_t *f, const int track, const int sample,unsigned char *buffer) -{ - int32_t result = 0; - int32_t size = mp4ff_audio_frame_size(f,track,sample); - if (size<=0) return 0; - mp4ff_set_sample_position(f, track, sample); - result = mp4ff_read_data(f,buffer,size); - -#ifdef ITUNES_DRM - if (f->track[track]->p_drms != NULL) - { - drms_decrypt(f->track[track]->p_drms, (uint32_t*)buffer, size); - } -#endif - - return result; -} - -static int32_t mp4ff_read_sample_getsize(mp4ff_t *f, const int track, const int sample) -{ - int32_t temp = mp4ff_audio_frame_size(f, track, sample); - if (temp<0) temp = 0; - return temp; -} diff --git a/trunk/src/mp4ff/mp4ff.dsp b/trunk/src/mp4ff/mp4ff.dsp deleted file mode 100644 index e3a2d0899..000000000 --- a/trunk/src/mp4ff/mp4ff.dsp +++ /dev/null @@ -1,144 +0,0 @@ -# Microsoft Developer Studio Project File - Name="mp4ff" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=mp4ff - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "mp4ff.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "mp4ff.mak" CFG="mp4ff - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "mp4ff - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "mp4ff - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=xicl6.exe -RSC=rc.exe - -!IF "$(CFG)" == "mp4ff - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -F90=df.exe -MTL=midl.exe -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_TAGGING" /YX /FD /c -# ADD BASE RSC /l 0x413 /d "NDEBUG" -# ADD RSC /l 0x413 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=xilink6.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ELSEIF "$(CFG)" == "mp4ff - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -F90=df.exe -MTL=midl.exe -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_TAGGING" /YX /FD /GZ /c -# ADD BASE RSC /l 0x413 /d "_DEBUG" -# ADD RSC /l 0x413 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=xilink6.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ENDIF - -# Begin Target - -# Name "mp4ff - Win32 Release" -# Name "mp4ff - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\drms.c -# End Source File -# Begin Source File - -SOURCE=.\mp4atom.c -# End Source File -# Begin Source File - -SOURCE=.\mp4ff.c -# End Source File -# Begin Source File - -SOURCE=.\mp4meta.c -# End Source File -# Begin Source File - -SOURCE=.\mp4sample.c -# End Source File -# Begin Source File - -SOURCE=.\mp4tagupdate.c -# End Source File -# Begin Source File - -SOURCE=.\mp4util.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\drms.h -# End Source File -# Begin Source File - -SOURCE=.\drmstables.h -# End Source File -# Begin Source File - -SOURCE=.\mp4ff.h -# End Source File -# Begin Source File - -SOURCE=.\mp4ff_int_types.h -# End Source File -# Begin Source File - -SOURCE=.\mp4ffint.h -# End Source File -# End Group -# End Target -# End Project diff --git a/trunk/src/mp4ff/mp4ff.h b/trunk/src/mp4ff/mp4ff.h deleted file mode 100644 index 5fb485d77..000000000 --- a/trunk/src/mp4ff/mp4ff.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -** -** Any non-GPL usage of this software or parts of this software is strictly -** forbidden. -** -** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. -** -** $Id: mp4ff.h,v 1.19 2004/01/11 15:52:18 menno Exp $ -**/ - -#ifndef MP4FF_H -#define MP4FF_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "mp4ff_int_types.h" - -/* file callback structure */ -typedef struct -{ - uint32_t (*read)(void *user_data, void *buffer, uint32_t length); - uint32_t (*write)(void *udata, void *buffer, uint32_t length); - uint32_t (*seek)(void *user_data, uint64_t position); - uint32_t (*truncate)(void *user_data); - void *user_data; -} mp4ff_callback_t; - -/* mp4 main file structure */ -typedef void* mp4ff_t; - - -/* API */ - -mp4ff_t *mp4ff_open_read(mp4ff_callback_t *f); -void mp4ff_close(mp4ff_t *f); -int32_t mp4ff_get_sample_duration(const mp4ff_t *f, const int32_t track, const int32_t sample); -int32_t mp4ff_get_sample_duration_use_offsets(const mp4ff_t *f, const int32_t track, const int32_t sample); -int64_t mp4ff_get_sample_position(const mp4ff_t *f, const int32_t track, const int32_t sample); -int32_t mp4ff_get_sample_offset(const mp4ff_t *f, const int32_t track, const int32_t sample); -int32_t mp4ff_find_sample(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip); -int32_t mp4ff_find_sample_use_offsets(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip); - -int32_t mp4ff_read_sample(mp4ff_t *f, const int track, const int sample, - unsigned char **audio_buffer, unsigned int *bytes); - -int32_t mp4ff_read_sample_v2(mp4ff_t *f, const int track, const int sample,unsigned char *buffer);//returns 0 on error, number of bytes read on success, use mp4ff_read_sample_getsize() to check buffer size needed -int32_t mp4ff_read_sample_getsize(mp4ff_t *f, const int track, const int sample);//returns 0 on error, buffer size needed for mp4ff_read_sample_v2() on success - - - -int32_t mp4ff_get_decoder_config(const mp4ff_t *f, const int track, - unsigned char** ppBuf, unsigned int* pBufSize); -int32_t mp4ff_get_track_type(const mp4ff_t *f, const int track); -int32_t mp4ff_total_tracks(const mp4ff_t *f); -int32_t mp4ff_num_samples(const mp4ff_t *f, const int track); -int32_t mp4ff_time_scale(const mp4ff_t *f, const int track); - -uint32_t mp4ff_get_avg_bitrate(const mp4ff_t *f, const int32_t track); -uint32_t mp4ff_get_max_bitrate(const mp4ff_t *f, const int32_t track); -int64_t mp4ff_get_track_duration(const mp4ff_t *f, const int32_t track); //returns (-1) if unknown -int64_t mp4ff_get_track_duration_use_offsets(const mp4ff_t *f, const int32_t track); //returns (-1) if unknown -uint32_t mp4ff_get_sample_rate(const mp4ff_t *f, const int32_t track); -uint32_t mp4ff_get_channel_count(const mp4ff_t * f,const int32_t track); -uint32_t mp4ff_get_audio_type(const mp4ff_t * f,const int32_t track); - - -/* metadata */ -int mp4ff_meta_get_num_items(const mp4ff_t *f); -int mp4ff_meta_get_by_index(const mp4ff_t *f, unsigned int index, - char **item, char **value); -int mp4ff_meta_get_title(const mp4ff_t *f, char **value); -int mp4ff_meta_get_artist(const mp4ff_t *f, char **value); -int mp4ff_meta_get_writer(const mp4ff_t *f, char **value); -int mp4ff_meta_get_album(const mp4ff_t *f, char **value); -int mp4ff_meta_get_date(const mp4ff_t *f, char **value); -int mp4ff_meta_get_tool(const mp4ff_t *f, char **value); -int mp4ff_meta_get_comment(const mp4ff_t *f, char **value); -int mp4ff_meta_get_genre(const mp4ff_t *f, char **value); -int mp4ff_meta_get_track(const mp4ff_t *f, char **value); -int mp4ff_meta_get_disc(const mp4ff_t *f, char **value); -int mp4ff_meta_get_compilation(const mp4ff_t *f, char **value); -int mp4ff_meta_get_tempo(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_coverart(const mp4ff_t *f, char **value); -#ifdef USE_TAGGING - -/* metadata tag structure */ -typedef struct -{ - char *item; - char *value; -} mp4ff_tag_t; - -/* metadata list structure */ -typedef struct -{ - mp4ff_tag_t *tags; - uint32_t count; -} mp4ff_metadata_t; - -int32_t mp4ff_meta_update(mp4ff_callback_t *f,const mp4ff_metadata_t * data); - -#endif - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif diff --git a/trunk/src/mp4ff/mp4ff_int_types.h b/trunk/src/mp4ff/mp4ff_int_types.h deleted file mode 100644 index 2da8fee6e..000000000 --- a/trunk/src/mp4ff/mp4ff_int_types.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _MP4FF_INT_TYPES_H_ -#define _MP4FF_INT_TYPES_H_ - -#ifdef _WIN32 - -typedef char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef long int32_t; -typedef unsigned long uint32_t; - -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; - -#else - -#include "config.h" - -#if defined(HAVE_STDINT_H) -#include <stdint.h> -#elif defined(HAVE_INTTYPES_H) -#include <inttypes.h> -#elif defined(HAVE_SYS_INTTYPES_H) -#include <sys/inttypes.h> -#elif defined(HAVE_SYS_TYPES_H) -#include <sys/types.h> -#endif - -#endif - -#endif diff --git a/trunk/src/mp4ff/mp4ffint.h b/trunk/src/mp4ff/mp4ffint.h deleted file mode 100644 index fc13f469d..000000000 --- a/trunk/src/mp4ff/mp4ffint.h +++ /dev/null @@ -1,329 +0,0 @@ -/* -** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -** -** Any non-GPL usage of this software or parts of this software is strictly -** forbidden. -** -** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. -** -** $Id: mp4ffint.h,v 1.15 2004/01/14 20:50:22 menno Exp $ -**/ - -#ifndef MP4FF_INTERNAL_H -#define MP4FF_INTERNAL_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "mp4ff_int_types.h" - - -#ifdef _WIN32 -#define ITUNES_DRM -#endif - - -#define MAX_TRACKS 1024 -#define TRACK_UNKNOWN 0 -#define TRACK_AUDIO 1 -#define TRACK_VIDEO 2 -#define TRACK_SYSTEM 3 - - -#define SUBATOMIC 128 - -/* atoms without subatoms */ -#define ATOM_FTYP 129 -#define ATOM_MDAT 130 -#define ATOM_MVHD 131 -#define ATOM_TKHD 132 -#define ATOM_TREF 133 -#define ATOM_MDHD 134 -#define ATOM_VMHD 135 -#define ATOM_SMHD 136 -#define ATOM_HMHD 137 -#define ATOM_STSD 138 -#define ATOM_STTS 139 -#define ATOM_STSZ 140 -#define ATOM_STZ2 141 -#define ATOM_STCO 142 -#define ATOM_STSC 143 -#define ATOM_MP4A 144 -#define ATOM_MP4V 145 -#define ATOM_MP4S 146 -#define ATOM_ESDS 147 -#define ATOM_META 148 /* iTunes Metadata box */ -#define ATOM_NAME 149 /* iTunes Metadata name box */ -#define ATOM_DATA 150 /* iTunes Metadata data box */ -#define ATOM_CTTS 151 -#define ATOM_FRMA 152 -#define ATOM_IVIV 153 -#define ATOM_PRIV 154 - -#define ATOM_UNKNOWN 255 -#define ATOM_FREE ATOM_UNKNOWN -#define ATOM_SKIP ATOM_UNKNOWN - -/* atoms with subatoms */ -#define ATOM_MOOV 1 -#define ATOM_TRAK 2 -#define ATOM_EDTS 3 -#define ATOM_MDIA 4 -#define ATOM_MINF 5 -#define ATOM_STBL 6 -#define ATOM_UDTA 7 -#define ATOM_ILST 8 /* iTunes Metadata list */ -#define ATOM_TITLE 9 -#define ATOM_ARTIST 10 -#define ATOM_WRITER 11 -#define ATOM_ALBUM 12 -#define ATOM_DATE 13 -#define ATOM_TOOL 14 -#define ATOM_COMMENT 15 -#define ATOM_GENRE1 16 -#define ATOM_TRACK 17 -#define ATOM_DISC 18 -#define ATOM_COMPILATION 19 -#define ATOM_GENRE2 20 -#define ATOM_TEMPO 21 -#define ATOM_COVER 22 -#define ATOM_DRMS 23 -#define ATOM_SINF 24 -#define ATOM_SCHI 25 - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifndef _WIN32 -#define stricmp strcasecmp -#endif - -/* file callback structure */ -typedef struct -{ - uint32_t (*read)(void *user_data, void *buffer, uint32_t length); - uint32_t (*write)(void *udata, void *buffer, uint32_t length); - uint32_t (*seek)(void *user_data, uint64_t position); - uint32_t (*truncate)(void *user_data); - void *user_data; -} mp4ff_callback_t; - - -/* metadata tag structure */ -typedef struct -{ - char *item; - char *value; -} mp4ff_tag_t; - -/* metadata list structure */ -typedef struct -{ - mp4ff_tag_t *tags; - uint32_t count; -} mp4ff_metadata_t; - - -typedef struct -{ - int32_t type; - int32_t channelCount; - int32_t sampleSize; - uint16_t sampleRate; - int32_t audioType; - - /* stsd */ - int32_t stsd_entry_count; - - /* stsz */ - int32_t stsz_sample_size; - int32_t stsz_sample_count; - int32_t *stsz_table; - - /* stts */ - int32_t stts_entry_count; - int32_t *stts_sample_count; - int32_t *stts_sample_delta; - - /* stsc */ - int32_t stsc_entry_count; - int32_t *stsc_first_chunk; - int32_t *stsc_samples_per_chunk; - int32_t *stsc_sample_desc_index; - - /* stsc */ - int32_t stco_entry_count; - int32_t *stco_chunk_offset; - - /* ctts */ - int32_t ctts_entry_count; - int32_t *ctts_sample_count; - int32_t *ctts_sample_offset; - - /* esde */ - uint8_t *decoderConfig; - int32_t decoderConfigLen; - - uint32_t maxBitrate; - uint32_t avgBitrate; - - uint32_t timeScale; - uint64_t duration; - -#ifdef ITUNES_DRM - /* drms */ - void *p_drms; -#endif - -} mp4ff_track_t; - -/* mp4 main file structure */ -typedef struct -{ - /* stream to read from */ - mp4ff_callback_t *stream; - int64_t current_position; - - int32_t moov_read; - uint64_t moov_offset; - uint64_t moov_size; - uint8_t last_atom; - uint64_t file_size; - - /* mvhd */ - int32_t time_scale; - int32_t duration; - - /* incremental track index while reading the file */ - int32_t total_tracks; - - /* track data */ - mp4ff_track_t *track[MAX_TRACKS]; - - /* metadata */ - mp4ff_metadata_t tags; -} mp4ff_t; - - - - -/* mp4util.c */ -int32_t mp4ff_read_data(mp4ff_t *f, int8_t *data, uint32_t size); -int32_t mp4ff_write_data(mp4ff_t *f, int8_t *data, uint32_t size); -uint64_t mp4ff_read_int64(mp4ff_t *f); -uint32_t mp4ff_read_int32(mp4ff_t *f); -uint32_t mp4ff_read_int24(mp4ff_t *f); -uint16_t mp4ff_read_int16(mp4ff_t *f); -uint8_t mp4ff_read_char(mp4ff_t *f); -int32_t mp4ff_write_int32(mp4ff_t *f,const uint32_t data); -uint32_t mp4ff_read_mp4_descr_length(mp4ff_t *f); -int64_t mp4ff_position(const mp4ff_t *f); -int32_t mp4ff_set_position(mp4ff_t *f, const int64_t position); -int32_t mp4ff_truncate(mp4ff_t * f); -char * mp4ff_read_string(mp4ff_t * f,uint32_t length); - -/* mp4atom.c */ -static int32_t mp4ff_atom_get_size(const int8_t *data); -static int32_t mp4ff_atom_compare(const int8_t a1, const int8_t b1, const int8_t c1, const int8_t d1, - const int8_t a2, const int8_t b2, const int8_t c2, const int8_t d2); -static uint8_t mp4ff_atom_name_to_type(const int8_t a, const int8_t b, const int8_t c, const int8_t d); -uint64_t mp4ff_atom_read_header(mp4ff_t *f, uint8_t *atom_type, uint8_t *header_size); -static int32_t mp4ff_read_stsz(mp4ff_t *f); -static int32_t mp4ff_read_esds(mp4ff_t *f); -static int32_t mp4ff_read_mp4a(mp4ff_t *f); -static int32_t mp4ff_read_stsd(mp4ff_t *f); -static int32_t mp4ff_read_stsc(mp4ff_t *f); -static int32_t mp4ff_read_stco(mp4ff_t *f); -static int32_t mp4ff_read_stts(mp4ff_t *f); -#ifdef USE_TAGGING -static int32_t mp4ff_read_meta(mp4ff_t *f, const uint64_t size); -#endif -int32_t mp4ff_atom_read(mp4ff_t *f, const int32_t size, const uint8_t atom_type); - -/* mp4sample.c */ -static int32_t mp4ff_chunk_of_sample(const mp4ff_t *f, const int32_t track, const int32_t sample, - int32_t *chunk_sample, int32_t *chunk); -static int32_t mp4ff_chunk_to_offset(const mp4ff_t *f, const int32_t track, const int32_t chunk); -static int32_t mp4ff_sample_range_size(const mp4ff_t *f, const int32_t track, - const int32_t chunk_sample, const int32_t sample); -static int32_t mp4ff_sample_to_offset(const mp4ff_t *f, const int32_t track, const int32_t sample); -int32_t mp4ff_audio_frame_size(const mp4ff_t *f, const int32_t track, const int32_t sample); -int32_t mp4ff_set_sample_position(mp4ff_t *f, const int32_t track, const int32_t sample); - -#ifdef USE_TAGGING -/* mp4meta.c */ -static int32_t mp4ff_tag_add_field(mp4ff_metadata_t *tags, const char *item, const char *value); -static int32_t mp4ff_tag_set_field(mp4ff_metadata_t *tags, const char *item, const char *value); -static int32_t mp4ff_set_metadata_name(mp4ff_t *f, const uint8_t atom_type, char **name); -static int32_t mp4ff_parse_tag(mp4ff_t *f, const uint8_t parent_atom_type, const int32_t size); -static int32_t mp4ff_meta_find_by_name(const mp4ff_t *f, const char *item, char **value); -int32_t mp4ff_parse_metadata(mp4ff_t *f, const int32_t size); -int32_t mp4ff_tag_delete(mp4ff_metadata_t *tags); -int32_t mp4ff_meta_get_num_items(const mp4ff_t *f); -int32_t mp4ff_meta_get_by_index(const mp4ff_t *f, uint32_t index, - char **item, char **value); -int32_t mp4ff_meta_get_title(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_artist(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_writer(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_album(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_date(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_tool(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_comment(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_genre(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_track(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_disc(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_compilation(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_tempo(const mp4ff_t *f, char **value); -int32_t mp4ff_meta_get_coverart(const mp4ff_t *f, char **value); -#endif - -/* mp4ff.c */ -mp4ff_t *mp4ff_open_read(mp4ff_callback_t *f); -#ifdef USE_TAGGING -mp4ff_t *mp4ff_open_edit(mp4ff_callback_t *f); -#endif -void mp4ff_close(mp4ff_t *ff); -/*void mp4ff_track_add(mp4ff_t *f);*/ -int32_t parse_sub_atoms(mp4ff_t *f, const uint64_t total_size); -int32_t parse_atoms(mp4ff_t *f); - -int32_t mp4ff_get_sample_duration(const mp4ff_t *f, const int32_t track, const int32_t sample); -int64_t mp4ff_get_sample_position(const mp4ff_t *f, const int32_t track, const int32_t sample); -int32_t mp4ff_get_sample_offset(const mp4ff_t *f, const int32_t track, const int32_t sample); -int32_t mp4ff_find_sample(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip); - -int32_t mp4ff_read_sample(mp4ff_t *f, const int32_t track, const int32_t sample, - uint8_t **audio_buffer, uint32_t *bytes); -int32_t mp4ff_get_decoder_config(const mp4ff_t *f, const int32_t track, - uint8_t** ppBuf, uint32_t* pBufSize); -int32_t mp4ff_total_tracks(const mp4ff_t *f); -int32_t mp4ff_time_scale(const mp4ff_t *f, const int32_t track); -int32_t mp4ff_num_samples(const mp4ff_t *f, const int32_t track); - -uint32_t mp4ff_meta_genre_to_index(const char * genrestr);//returns 1-based index, 0 if not found -const char * mp4ff_meta_index_to_genre(uint32_t idx);//returns pointer to static string - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif diff --git a/trunk/src/mp4ff/mp4meta.c b/trunk/src/mp4ff/mp4meta.c deleted file mode 100644 index 762f5dee7..000000000 --- a/trunk/src/mp4ff/mp4meta.c +++ /dev/null @@ -1,414 +0,0 @@ -/* -** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -** -** Any non-GPL usage of this software or parts of this software is strictly -** forbidden. -** -** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. -** -** $Id: mp4meta.c,v 1.13 2004/01/11 15:52:18 menno Exp $ -**/ - -#ifdef USE_TAGGING - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "mp4ffint.h" - -static int32_t mp4ff_tag_add_field(mp4ff_metadata_t *tags, const char *item, const char *value) -{ - void *backup = (void *)tags->tags; - - if (!item || (item && !*item) || !value) return 0; - - tags->tags = (mp4ff_tag_t*)realloc(tags->tags, (tags->count+1) * sizeof(mp4ff_tag_t)); - if (!tags->tags) - { - if (backup) free(backup); - return 0; - } else { - tags->tags[tags->count].item = strdup(item); - tags->tags[tags->count].value = strdup(value); - - if (!tags->tags[tags->count].item || !tags->tags[tags->count].value) - { - if (!tags->tags[tags->count].item) free (tags->tags[tags->count].item); - if (!tags->tags[tags->count].value) free (tags->tags[tags->count].value); - tags->tags[tags->count].item = NULL; - tags->tags[tags->count].value = NULL; - return 0; - } - - tags->count++; - return 1; - } -} - -static int32_t mp4ff_tag_set_field(mp4ff_metadata_t *tags, const char *item, const char *value) -{ - unsigned int i; - - if (!item || (item && !*item) || !value) return 0; - - for (i = 0; i < tags->count; i++) - { - if (!stricmp(tags->tags[i].item, item)) - { - free(tags->tags[i].value); - tags->tags[i].value = strdup(value); - return 1; - } - } - - return mp4ff_tag_add_field(tags, item, value); -} - -int32_t mp4ff_tag_delete(mp4ff_metadata_t *tags) -{ - uint32_t i; - - for (i = 0; i < tags->count; i++) - { - if (tags->tags[i].item) free(tags->tags[i].item); - if (tags->tags[i].value) free(tags->tags[i].value); - } - - if (tags->tags) free(tags->tags); - - tags->tags = NULL; - tags->count = 0; - - return 0; -} - -static const char* ID3v1GenreList[] = { - "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", - "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", - "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", - "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", - "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", - "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House", - "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", - "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", - "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", - "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta", - "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret", - "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", - "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", - "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing", - "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", - "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band", - "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", - "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", - "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", - "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", - "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall", - "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror", - "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat", - "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover", "Contemporary C", - "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", - "SynthPop", -}; - -uint32_t mp4ff_meta_genre_to_index(const char * genrestr) -{ - unsigned n; - for(n=0;n<sizeof(ID3v1GenreList)/sizeof(ID3v1GenreList[0]);n++) - { - if (!stricmp(genrestr,ID3v1GenreList[n])) return n+1; - } - return 0; -} - -const char * mp4ff_meta_index_to_genre(uint32_t idx) -{ - if (idx>0 && idx<=sizeof(ID3v1GenreList)/sizeof(ID3v1GenreList[0])) - { - return ID3v1GenreList[idx-1]; - } - else - { - return 0; - } -} - - -static int32_t TrackToString(char** str, const uint16_t track, const uint16_t totalTracks) -{ - char temp[32]; - sprintf(temp, "%.5u of %.5u", track, totalTracks); - *str = strdup(temp); - return 0; -} - -static int32_t mp4ff_set_metadata_name(mp4ff_t *f, const uint8_t atom_type, char **name) -{ - static char *tag_names[] = { - "unknown", "title", "artist", "writer", "album", - "date", "tool", "comment", "genre", "track", - "disc", "compilation", "genre", "tempo", "cover" - }; - uint8_t tag_idx = 0; - - switch (atom_type) - { - case ATOM_TITLE: tag_idx = 1; break; - case ATOM_ARTIST: tag_idx = 2; break; - case ATOM_WRITER: tag_idx = 3; break; - case ATOM_ALBUM: tag_idx = 4; break; - case ATOM_DATE: tag_idx = 5; break; - case ATOM_TOOL: tag_idx = 6; break; - case ATOM_COMMENT: tag_idx = 7; break; - case ATOM_GENRE1: tag_idx = 8; break; - case ATOM_TRACK: tag_idx = 9; break; - case ATOM_DISC: tag_idx = 10; break; - case ATOM_COMPILATION: tag_idx = 11; break; - case ATOM_GENRE2: tag_idx = 12; break; - case ATOM_TEMPO: tag_idx = 13; break; - case ATOM_COVER: tag_idx = 14; break; - default: tag_idx = 0; break; - } - - *name = strdup(tag_names[tag_idx]); - - return 0; -} - -static int32_t mp4ff_parse_tag(mp4ff_t *f, const uint8_t parent_atom_type, const int32_t size) -{ - uint8_t atom_type; - uint8_t header_size = 0; - uint64_t subsize, sumsize = 0; - char * name = NULL; - char * data = NULL; - uint32_t done = 0; - - - while (sumsize < size) - { - uint64_t destpos; - subsize = mp4ff_atom_read_header(f, &atom_type, &header_size); - destpos = mp4ff_position(f)+subsize-header_size; - if (!done) - { - if (atom_type == ATOM_DATA) - { - mp4ff_read_char(f); /* version */ - mp4ff_read_int24(f); /* flags */ - mp4ff_read_int32(f); /* reserved */ - - /* some need special attention */ - if (parent_atom_type == ATOM_GENRE2 || parent_atom_type == ATOM_TEMPO) - { - if (subsize - header_size >= 8 + 2) - { - uint16_t val = mp4ff_read_int16(f); - - if (parent_atom_type == ATOM_TEMPO) - { - char temp[16]; - sprintf(temp, "%.5u BPM", val); - mp4ff_tag_add_field(&(f->tags), "tempo", temp); - } - else - { - const char * temp = mp4ff_meta_index_to_genre(val); - if (temp) - { - mp4ff_tag_add_field(&(f->tags), "genre", temp); - } - } - done = 1; - } - } else if (parent_atom_type == ATOM_TRACK || parent_atom_type == ATOM_DISC) { - if (!done && subsize - header_size >= 8 + 8) - { - uint16_t index,total; - char temp[32]; - mp4ff_read_int16(f); - index = mp4ff_read_int16(f); - total = mp4ff_read_int16(f); - mp4ff_read_int16(f); - - sprintf(temp,"%d",index); - mp4ff_tag_add_field(&(f->tags), parent_atom_type == ATOM_TRACK ? "track" : "disc", temp); - if (total>0) - { - sprintf(temp,"%d",total); - mp4ff_tag_add_field(&(f->tags), parent_atom_type == ATOM_TRACK ? "totaltracks" : "totaldiscs", temp); - } - done = 1; - } - } else - { - if (data) {free(data);data = NULL;} - data = mp4ff_read_string(f,(uint32_t)(subsize-(header_size+8))); - } - } else if (atom_type == ATOM_NAME) { - if (!done) - { - mp4ff_read_char(f); /* version */ - mp4ff_read_int24(f); /* flags */ - if (name) free(name); - name = mp4ff_read_string(f,(uint32_t)(subsize-(header_size+4))); - } - } - mp4ff_set_position(f, destpos); - sumsize += subsize; - } - } - - if (data) - { - if (!done) - { - if (name == NULL) mp4ff_set_metadata_name(f, parent_atom_type, &name); - if (name) mp4ff_tag_add_field(&(f->tags), name, data); - } - - free(data); - } - if (name) free(name); - return 1; -} - -int32_t mp4ff_parse_metadata(mp4ff_t *f, const int32_t size) -{ - uint64_t subsize, sumsize = 0; - uint8_t atom_type; - uint8_t header_size = 0; - - while (sumsize < size) - { - subsize = mp4ff_atom_read_header(f, &atom_type, &header_size); - mp4ff_parse_tag(f, atom_type, (uint32_t)(subsize-header_size)); - sumsize += subsize; - } - - return 0; -} - -/* find a metadata item by name */ -/* returns 0 if item found, 1 if no such item */ -static int32_t mp4ff_meta_find_by_name(const mp4ff_t *f, const char *item, char **value) -{ - uint32_t i; - - for (i = 0; i < f->tags.count; i++) - { - if (!stricmp(f->tags.tags[i].item, item)) - { - *value = strdup(f->tags.tags[i].value); - return 1; - } - } - - *value = NULL; - - /* not found */ - return 0; -} - -int32_t mp4ff_meta_get_num_items(const mp4ff_t *f) -{ - return f->tags.count; -} - -int32_t mp4ff_meta_get_by_index(const mp4ff_t *f, uint32_t index, - char **item, char **value) -{ - if (index >= f->tags.count) - { - *item = NULL; - *value = NULL; - return 0; - } else { - *item = strdup(f->tags.tags[index].item); - *value = strdup(f->tags.tags[index].value); - return 1; - } -} - -int32_t mp4ff_meta_get_title(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "title", value); -} - -int32_t mp4ff_meta_get_artist(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "artist", value); -} - -int32_t mp4ff_meta_get_writer(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "writer", value); -} - -int32_t mp4ff_meta_get_album(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "album", value); -} - -int32_t mp4ff_meta_get_date(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "date", value); -} - -int32_t mp4ff_meta_get_tool(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "tool", value); -} - -int32_t mp4ff_meta_get_comment(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "comment", value); -} - -int32_t mp4ff_meta_get_genre(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "genre", value); -} - -int32_t mp4ff_meta_get_track(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "track", value); -} - -int32_t mp4ff_meta_get_disc(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "disc", value); -} - -int32_t mp4ff_meta_get_compilation(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "compilation", value); -} - -int32_t mp4ff_meta_get_tempo(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "tempo", value); -} - -int32_t mp4ff_meta_get_coverart(const mp4ff_t *f, char **value) -{ - return mp4ff_meta_find_by_name(f, "cover", value); -} - -#endif diff --git a/trunk/src/mp4ff/mp4sample.c b/trunk/src/mp4ff/mp4sample.c deleted file mode 100644 index 5688a3a8f..000000000 --- a/trunk/src/mp4ff/mp4sample.c +++ /dev/null @@ -1,152 +0,0 @@ -/* -** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -** -** Any non-GPL usage of this software or parts of this software is strictly -** forbidden. -** -** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. -** -** $Id: mp4sample.c,v 1.15 2004/01/11 15:52:19 menno Exp $ -**/ - -#include <stdlib.h> -#include "mp4ffint.h" - - -static int32_t mp4ff_chunk_of_sample(const mp4ff_t *f, const int32_t track, const int32_t sample, - int32_t *chunk_sample, int32_t *chunk) -{ - int32_t total_entries = 0; - int32_t chunk2entry; - int32_t chunk1, chunk2, chunk1samples, range_samples, total = 0; - - if (f->track[track] == NULL) - { - return -1; - } - - total_entries = f->track[track]->stsc_entry_count; - - chunk1 = 1; - chunk1samples = 0; - chunk2entry = 0; - - do - { - chunk2 = f->track[track]->stsc_first_chunk[chunk2entry]; - *chunk = chunk2 - chunk1; - range_samples = *chunk * chunk1samples; - - if (sample < total + range_samples) break; - - chunk1samples = f->track[track]->stsc_samples_per_chunk[chunk2entry]; - chunk1 = chunk2; - - if(chunk2entry < total_entries) - { - chunk2entry++; - total += range_samples; - } - } while (chunk2entry < total_entries); - - if (chunk1samples) - *chunk = (sample - total) / chunk1samples + chunk1; - else - *chunk = 1; - - *chunk_sample = total + (*chunk - chunk1) * chunk1samples; - - return 0; -} - -static int32_t mp4ff_chunk_to_offset(const mp4ff_t *f, const int32_t track, const int32_t chunk) -{ - const mp4ff_track_t * p_track = f->track[track]; - - if (p_track->stco_entry_count && (chunk > p_track->stco_entry_count)) - { - return p_track->stco_chunk_offset[p_track->stco_entry_count - 1]; - } else if (p_track->stco_entry_count) { - return p_track->stco_chunk_offset[chunk - 1]; - } else { - return 8; - } - - return 0; -} - -static int32_t mp4ff_sample_range_size(const mp4ff_t *f, const int32_t track, - const int32_t chunk_sample, const int32_t sample) -{ - int32_t i, total; - const mp4ff_track_t * p_track = f->track[track]; - - if (p_track->stsz_sample_size) - { - return (sample - chunk_sample) * p_track->stsz_sample_size; - } - else - { - if (sample>=p_track->stsz_sample_count) return 0;//error - - for(i = chunk_sample, total = 0; i < sample; i++) - { - total += p_track->stsz_table[i]; - } - } - - return total; -} - -static int32_t mp4ff_sample_to_offset(const mp4ff_t *f, const int32_t track, const int32_t sample) -{ - int32_t chunk, chunk_sample, chunk_offset1, chunk_offset2; - - mp4ff_chunk_of_sample(f, track, sample, &chunk_sample, &chunk); - - chunk_offset1 = mp4ff_chunk_to_offset(f, track, chunk); - chunk_offset2 = chunk_offset1 + mp4ff_sample_range_size(f, track, chunk_sample, sample); - - return chunk_offset2; -} - -int32_t mp4ff_audio_frame_size(const mp4ff_t *f, const int32_t track, const int32_t sample) -{ - int32_t bytes; - const mp4ff_track_t * p_track = f->track[track]; - - if (p_track->stsz_sample_size) - { - bytes = p_track->stsz_sample_size; - } else { - bytes = p_track->stsz_table[sample]; - } - - return bytes; -} - -int32_t mp4ff_set_sample_position(mp4ff_t *f, const int32_t track, const int32_t sample) -{ - int32_t offset; - - offset = mp4ff_sample_to_offset(f, track, sample); - mp4ff_set_position(f, offset); - - return 0; -} diff --git a/trunk/src/mp4ff/mp4tagupdate.c b/trunk/src/mp4ff/mp4tagupdate.c deleted file mode 100644 index c999fa5ee..000000000 --- a/trunk/src/mp4ff/mp4tagupdate.c +++ /dev/null @@ -1,645 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#include "mp4ffint.h" - -#ifdef USE_TAGGING - -static uint32_t fix_byte_order_32(uint32_t src) -{ - uint32_t result; - uint32_t a, b, c, d; - int8_t data[4]; - - memcpy(data,&src,sizeof(src)); - a = (uint8_t)data[0]; - b = (uint8_t)data[1]; - c = (uint8_t)data[2]; - d = (uint8_t)data[3]; - - result = (a<<24) | (b<<16) | (c<<8) | d; - return (uint32_t)result; -} - -static uint16_t fix_byte_order_16(uint16_t src) -{ - uint16_t result; - uint16_t a, b; - int8_t data[2]; - - memcpy(data,&src,sizeof(src)); - a = (uint8_t)data[0]; - b = (uint8_t)data[1]; - - result = (a<<8) | b; - return (uint16_t)result; -} - - -typedef struct -{ - void * data; - unsigned written; - unsigned allocated; - unsigned error; -} membuffer; - -static unsigned membuffer_write(membuffer * buf,const void * ptr,unsigned bytes) -{ - unsigned dest_size = buf->written + bytes; - - if (buf->error) return 0; - if (dest_size > buf->allocated) - { - do - { - buf->allocated <<= 1; - } while(dest_size > buf->allocated); - - { - void * newptr = realloc(buf->data,buf->allocated); - if (newptr==0) - { - free(buf->data); - buf->data = 0; - buf->error = 1; - return 0; - } - buf->data = newptr; - } - } - - if (ptr) memcpy((char*)buf->data + buf->written,ptr,bytes); - buf->written += bytes; - return bytes; -} - -#define membuffer_write_data membuffer_write - -static unsigned membuffer_write_int32(membuffer * buf,uint32_t data) -{ - uint8_t temp[4] = {(uint8_t)(data>>24),(uint8_t)(data>>16),(uint8_t)(data>>8),(uint8_t)data}; - return membuffer_write_data(buf,temp,4); -} - -static unsigned membuffer_write_int24(membuffer * buf,uint32_t data) -{ - uint8_t temp[3] = {(uint8_t)(data>>16),(uint8_t)(data>>8),(uint8_t)data}; - return membuffer_write_data(buf,temp,3); -} - -static unsigned membuffer_write_int16(membuffer * buf,uint16_t data) -{ - uint8_t temp[2] = {(uint8_t)(data>>8),(uint8_t)data}; - return membuffer_write_data(buf,temp,2); -} - -static unsigned membuffer_write_atom_name(membuffer * buf,const char * data) -{ - return membuffer_write_data(buf,data,4)==4 ? 1 : 0; -} - -static void membuffer_write_atom(membuffer * buf,const char * name,unsigned size,const void * data) -{ - membuffer_write_int32(buf,size + 8); - membuffer_write_atom_name(buf,name); - membuffer_write_data(buf,data,size); -} - -static unsigned membuffer_write_string(membuffer * buf,const char * data) -{ - return membuffer_write_data(buf,data,strlen(data)); -} - -static unsigned membuffer_write_int8(membuffer * buf,uint8_t data) -{ - return membuffer_write_data(buf,&data,1); -} - -static void * membuffer_get_ptr(const membuffer * buf) -{ - return buf->data; -} - -static unsigned membuffer_get_size(const membuffer * buf) -{ - return buf->written; -} - -static unsigned membuffer_error(const membuffer * buf) -{ - return buf->error; -} - -static void membuffer_set_error(membuffer * buf) {buf->error = 1;} - -static unsigned membuffer_transfer_from_file(membuffer * buf,mp4ff_t * src,unsigned bytes) -{ - unsigned oldsize; - void * bufptr; - - oldsize = membuffer_get_size(buf); - if (membuffer_write_data(buf,0,bytes) != bytes) return 0; - - bufptr = membuffer_get_ptr(buf); - if (bufptr==0) return 0; - - if ((unsigned)mp4ff_read_data(src,(char*)bufptr + oldsize,bytes)!=bytes) - { - membuffer_set_error(buf); - return 0; - } - - return bytes; -} - - -static membuffer * membuffer_create() -{ - const unsigned initial_size = 256; - - membuffer * buf = (membuffer *) malloc(sizeof(membuffer)); - buf->data = malloc(initial_size); - buf->written = 0; - buf->allocated = initial_size; - buf->error = buf->data == 0 ? 1 : 0; - - return buf; -} - -static void membuffer_free(membuffer * buf) -{ - if (buf->data) free(buf->data); - free(buf); -} - -static void * membuffer_detach(membuffer * buf) -{ - void * ret; - - if (buf->error) return 0; - - ret = realloc(buf->data,buf->written); - - if (ret == 0) free(buf->data); - - buf->data = 0; - buf->error = 1; - - return ret; -} - -#if 0 -/* metadata tag structure */ -typedef struct -{ - char *item; - char *value; -} mp4ff_tag_t; - -/* metadata list structure */ -typedef struct -{ - mp4ff_tag_t *tags; - uint32_t count; -} mp4ff_metadata_t; -#endif - -typedef struct -{ - const char * atom; - const char * name; -} stdmeta_entry; - -static stdmeta_entry stdmetas[] = -{ - {"©nam","title"}, - {"©ART","artist"}, - {"©wrt","writer"}, - {"©alb","album"}, - {"©day","date"}, - {"©too","tool"}, - {"©cmt","comment"}, -// {"©gen","genre"}, - {"cpil","compilation"}, -// {"trkn","track"}, -// {"disk","disc"}, -// {"gnre","genre"}, - {"covr","cover"}, -}; - - -static const char* find_standard_meta(const char * name) //returns atom name if found, 0 if not -{ - unsigned n; - for(n=0;n<sizeof(stdmetas)/sizeof(stdmetas[0]);n++) - { - if (!stricmp(name,stdmetas[n].name)) return stdmetas[n].atom; - } - return 0; -} - -static void membuffer_write_track_tag(membuffer * buf,const char * name,uint32_t index,uint32_t total) -{ - membuffer_write_int32(buf,8 /*atom header*/ + 8 /*data atom header*/ + 8 /*flags + reserved*/ + 8 /*actual data*/ ); - membuffer_write_atom_name(buf,name); - membuffer_write_int32(buf,8 /*data atom header*/ + 8 /*flags + reserved*/ + 8 /*actual data*/ ); - membuffer_write_atom_name(buf,"data"); - membuffer_write_int32(buf,0);//flags - membuffer_write_int32(buf,0);//reserved - membuffer_write_int16(buf,0); - membuffer_write_int16(buf,(uint16_t)index);//track number - membuffer_write_int16(buf,(uint16_t)total);//total tracks - membuffer_write_int16(buf,0); -} - -static void membuffer_write_int16_tag(membuffer * buf,const char * name,uint16_t value) -{ - membuffer_write_int32(buf,8 /*atom header*/ + 8 /*data atom header*/ + 8 /*flags + reserved*/ + 2 /*actual data*/ ); - membuffer_write_atom_name(buf,name); - membuffer_write_int32(buf,8 /*data atom header*/ + 8 /*flags + reserved*/ + 2 /*actual data*/ ); - membuffer_write_atom_name(buf,"data"); - membuffer_write_int32(buf,0);//flags - membuffer_write_int32(buf,0);//reserved - membuffer_write_int16(buf,value);//value -} - -static void membuffer_write_std_tag(membuffer * buf,const char * name,const char * value) -{ - membuffer_write_int32(buf,8 /*atom header*/ + 8 /*data atom header*/ + 8 /*flags + reserved*/ + strlen(value) ); - membuffer_write_atom_name(buf,name); - membuffer_write_int32(buf,8 /*data atom header*/ + 8 /*flags + reserved*/ + strlen(value)); - membuffer_write_atom_name(buf,"data"); - membuffer_write_int32(buf,1);//flags - membuffer_write_int32(buf,0);//reserved - membuffer_write_data(buf,value,strlen(value)); -} - -static void membuffer_write_custom_tag(membuffer * buf,const char * name,const char * value) -{ - membuffer_write_int32(buf,8 /*atom header*/ + 0x1C /*weirdo itunes atom*/ + 12 /*name atom header*/ + strlen(name) + 16 /*data atom header + flags*/ + strlen(value) ); - membuffer_write_atom_name(buf,"----"); - membuffer_write_int32(buf,0x1C);//weirdo itunes atom - membuffer_write_atom_name(buf,"mean"); - membuffer_write_int32(buf,0); - membuffer_write_data(buf,"com.apple.iTunes",16); - membuffer_write_int32(buf,12 + strlen(name)); - membuffer_write_atom_name(buf,"name"); - membuffer_write_int32(buf,0); - membuffer_write_data(buf,name,strlen(name)); - membuffer_write_int32(buf,8 /*data atom header*/ + 8 /*flags + reserved*/ + strlen(value)); - membuffer_write_atom_name(buf,"data"); - membuffer_write_int32(buf,1);//flags - membuffer_write_int32(buf,0);//reserved - membuffer_write_data(buf,value,strlen(value)); - -} - -static uint32_t myatoi(const char * param) -{ - return param ? atoi(param) : 0; -} - -static uint32_t create_ilst(const mp4ff_metadata_t * data,void ** out_buffer,uint32_t * out_size) -{ - membuffer * buf = membuffer_create(); - unsigned metaptr; - char * mask = (char*)malloc(data->count); - memset(mask,0,data->count); - - { - const char * tracknumber_ptr = 0, * totaltracks_ptr = 0; - const char * discnumber_ptr = 0, * totaldiscs_ptr = 0; - const char * genre_ptr = 0, * tempo_ptr = 0; - for(metaptr = 0; metaptr < data->count; metaptr++) - { - mp4ff_tag_t * tag = &data->tags[metaptr]; - if (!stricmp(tag->item,"tracknumber") || !stricmp(tag->item,"track")) - { - if (tracknumber_ptr==0) tracknumber_ptr = tag->value; - mask[metaptr] = 1; - } - else if (!stricmp(tag->item,"totaltracks")) - { - if (totaltracks_ptr==0) totaltracks_ptr = tag->value; - mask[metaptr] = 1; - } - else if (!stricmp(tag->item,"discnumber") || !stricmp(tag->item,"disc")) - { - if (discnumber_ptr==0) discnumber_ptr = tag->value; - mask[metaptr] = 1; - } - else if (!stricmp(tag->item,"totaldiscs")) - { - if (totaldiscs_ptr==0) totaldiscs_ptr = tag->value; - mask[metaptr] = 1; - } - else if (!stricmp(tag->item,"genre")) - { - if (genre_ptr==0) genre_ptr = tag->value; - mask[metaptr] = 1; - } - else if (!stricmp(tag->item,"tempo")) - { - if (tempo_ptr==0) tempo_ptr = tag->value; - mask[metaptr] = 1; - } - - } - - if (tracknumber_ptr) membuffer_write_track_tag(buf,"trkn",myatoi(tracknumber_ptr),myatoi(totaltracks_ptr)); - if (discnumber_ptr) membuffer_write_track_tag(buf,"disk",myatoi(discnumber_ptr),myatoi(totaldiscs_ptr)); - if (tempo_ptr) membuffer_write_int16_tag(buf,"tmpo",(uint16_t)myatoi(tempo_ptr)); - - if (genre_ptr) - { - uint32_t index = mp4ff_meta_genre_to_index(genre_ptr); - if (index==0) - membuffer_write_std_tag(buf,"©gen",genre_ptr); - else - membuffer_write_int16_tag(buf,"gnre",(uint16_t)index); - } - } - - for(metaptr = 0; metaptr < data->count; metaptr++) - { - if (!mask[metaptr]) - { - mp4ff_tag_t * tag = &data->tags[metaptr]; - const char * std_meta_atom = find_standard_meta(tag->item); - if (std_meta_atom) - { - membuffer_write_std_tag(buf,std_meta_atom,tag->value); - } - else - { - membuffer_write_custom_tag(buf,tag->item,tag->value); - } - } - } - - free(mask); - - if (membuffer_error(buf)) - { - membuffer_free(buf); - return 0; - } - - *out_size = membuffer_get_size(buf); - *out_buffer = membuffer_detach(buf); - membuffer_free(buf); - - return 1; -} - -static uint32_t find_atom(mp4ff_t * f,uint64_t base,uint32_t size,const char * name) -{ - uint32_t remaining = size; - uint64_t atom_offset = base; - for(;;) - { - char atom_name[4]; - uint32_t atom_size; - - mp4ff_set_position(f,atom_offset); - - if (remaining < 8) break; - atom_size = mp4ff_read_int32(f); - if (atom_size > remaining || atom_size < 8) break; - mp4ff_read_data(f,atom_name,4); - - if (!memcmp(atom_name,name,4)) - { - mp4ff_set_position(f,atom_offset); - return 1; - } - - remaining -= atom_size; - atom_offset += atom_size; - } - return 0; -} - -static uint32_t find_atom_v2(mp4ff_t * f,uint64_t base,uint32_t size,const char * name,uint32_t extraheaders,const char * name_inside) -{ - uint64_t first_base = (uint64_t)(-1); - while(find_atom(f,base,size,name))//try to find atom <name> with atom <name_inside> in it - { - uint64_t mybase = mp4ff_position(f); - uint32_t mysize = mp4ff_read_int32(f); - - if (first_base == (uint64_t)(-1)) first_base = mybase; - - if (mysize < 8 + extraheaders) break; - - if (find_atom(f,mybase+(8+extraheaders),mysize-(8+extraheaders),name_inside)) - { - mp4ff_set_position(f,mybase); - return 2; - } - base += mysize; - if (size<=mysize) {size=0;break;} - size -= mysize; - } - - if (first_base != (uint64_t)(-1))//wanted atom inside not found - { - mp4ff_set_position(f,first_base); - return 1; - } - else return 0; -} - -static uint32_t create_meta(const mp4ff_metadata_t * data,void ** out_buffer,uint32_t * out_size) -{ - membuffer * buf; - uint32_t ilst_size; - void * ilst_buffer; - - if (!create_ilst(data,&ilst_buffer,&ilst_size)) return 0; - - buf = membuffer_create(); - - membuffer_write_int32(buf,0); - membuffer_write_atom(buf,"ilst",ilst_size,ilst_buffer); - free(ilst_buffer); - - *out_size = membuffer_get_size(buf); - *out_buffer = membuffer_detach(buf); - membuffer_free(buf); - return 1; -} - -static uint32_t create_udta(const mp4ff_metadata_t * data,void ** out_buffer,uint32_t * out_size) -{ - membuffer * buf; - uint32_t meta_size; - void * meta_buffer; - - if (!create_meta(data,&meta_buffer,&meta_size)) return 0; - - buf = membuffer_create(); - - membuffer_write_atom(buf,"meta",meta_size,meta_buffer); - - free(meta_buffer); - - *out_size = membuffer_get_size(buf); - *out_buffer = membuffer_detach(buf); - membuffer_free(buf); - return 1; -} - -static uint32_t modify_moov(mp4ff_t * f,const mp4ff_metadata_t * data,void ** out_buffer,uint32_t * out_size) -{ - uint64_t total_base = f->moov_offset + 8; - uint32_t total_size = (uint32_t)(f->moov_size - 8); - - uint64_t udta_offset,meta_offset,ilst_offset; - uint32_t udta_size, meta_size, ilst_size; - - uint32_t new_ilst_size; - void * new_ilst_buffer; - - uint8_t * p_out; - int32_t size_delta; - - - if (!find_atom_v2(f,total_base,total_size,"udta",0,"meta")) - { - membuffer * buf; - void * new_udta_buffer; - uint32_t new_udta_size; - if (!create_udta(data,&new_udta_buffer,&new_udta_size)) return 0; - - buf = membuffer_create(); - mp4ff_set_position(f,total_base); - membuffer_transfer_from_file(buf,f,total_size); - - membuffer_write_atom(buf,"udta",new_udta_size,new_udta_buffer); - - free(new_udta_buffer); - - *out_size = membuffer_get_size(buf); - *out_buffer = membuffer_detach(buf); - membuffer_free(buf); - return 1; - } - else - { - udta_offset = mp4ff_position(f); - udta_size = mp4ff_read_int32(f); - if (find_atom_v2(f,udta_offset+8,udta_size-8,"meta",4,"ilst")<2) - { - membuffer * buf; - void * new_meta_buffer; - uint32_t new_meta_size; - if (!create_meta(data,&new_meta_buffer,&new_meta_size)) return 0; - - buf = membuffer_create(); - mp4ff_set_position(f,total_base); - membuffer_transfer_from_file(buf,f,(uint32_t)(udta_offset - total_base)); - - membuffer_write_int32(buf,udta_size + 8 + new_meta_size); - membuffer_write_atom_name(buf,"udta"); - membuffer_transfer_from_file(buf,f,udta_size); - - membuffer_write_atom(buf,"meta",new_meta_size,new_meta_buffer); - free(new_meta_buffer); - - *out_size = membuffer_get_size(buf); - *out_buffer = membuffer_detach(buf); - membuffer_free(buf); - return 1; - } - meta_offset = mp4ff_position(f); - meta_size = mp4ff_read_int32(f); - if (!find_atom(f,meta_offset+12,meta_size-12,"ilst")) return 0;//shouldn't happen, find_atom_v2 above takes care of it - ilst_offset = mp4ff_position(f); - ilst_size = mp4ff_read_int32(f); - - if (!create_ilst(data,&new_ilst_buffer,&new_ilst_size)) return 0; - - size_delta = new_ilst_size - (ilst_size - 8); - - *out_size = total_size + size_delta; - *out_buffer = malloc(*out_size); - if (*out_buffer == 0) - { - free(new_ilst_buffer); - return 0; - } - - p_out = (uint8_t*)*out_buffer; - - mp4ff_set_position(f,total_base); - mp4ff_read_data(f,p_out,(uint32_t)(udta_offset - total_base )); p_out += (uint32_t)(udta_offset - total_base ); - *(uint32_t*)p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta); p_out += 4; - mp4ff_read_data(f,p_out,4); p_out += 4; - mp4ff_read_data(f,p_out,(uint32_t)(meta_offset - udta_offset - 8)); p_out += (uint32_t)(meta_offset - udta_offset - 8); - *(uint32_t*)p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta); p_out += 4; - mp4ff_read_data(f,p_out,4); p_out += 4; - mp4ff_read_data(f,p_out,(uint32_t)(ilst_offset - meta_offset - 8)); p_out += (uint32_t)(ilst_offset - meta_offset - 8); - *(uint32_t*)p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta); p_out += 4; - mp4ff_read_data(f,p_out,4); p_out += 4; - - memcpy(p_out,new_ilst_buffer,new_ilst_size); - p_out += new_ilst_size; - - mp4ff_set_position(f,ilst_offset + ilst_size); - mp4ff_read_data(f,p_out,(uint32_t)(total_size - (ilst_offset - total_base) - ilst_size)); - - free(new_ilst_buffer); - } - return 1; - -} - -static int32_t mp4ff_meta_update(mp4ff_callback_t *f,const mp4ff_metadata_t * data) -{ - void * new_moov_data; - uint32_t new_moov_size; - - mp4ff_t *ff = malloc(sizeof(mp4ff_t)); - - memset(ff, 0, sizeof(mp4ff_t)); - ff->stream = f; - mp4ff_set_position(ff,0); - - parse_atoms(ff); - - - if (!modify_moov(ff,data,&new_moov_data,&new_moov_size)) - { - mp4ff_close(ff); - return 0; - } - - /* copy moov atom to end of the file */ - if (ff->last_atom != ATOM_MOOV) - { - char *free_data = "free"; - - /* rename old moov to free */ - mp4ff_set_position(ff, ff->moov_offset + 4); - mp4ff_write_data(ff, free_data, 4); - - mp4ff_set_position(ff, ff->file_size); - mp4ff_write_int32(ff,new_moov_size + 8); - mp4ff_write_data(ff,"moov",4); - mp4ff_write_data(ff, new_moov_data, new_moov_size); - } - else - { - mp4ff_set_position(ff, ff->moov_offset); - mp4ff_write_int32(ff,new_moov_size + 8); - mp4ff_write_data(ff,"moov",4); - mp4ff_write_data(ff, new_moov_data, new_moov_size); - } - - mp4ff_truncate(ff); - - mp4ff_close(ff); - return 1; -} -#endif diff --git a/trunk/src/mp4ff/mp4util.c b/trunk/src/mp4ff/mp4util.c deleted file mode 100644 index 1a77c97ae..000000000 --- a/trunk/src/mp4ff/mp4util.c +++ /dev/null @@ -1,188 +0,0 @@ -/* -** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -** -** Any non-GPL usage of this software or parts of this software is strictly -** forbidden. -** -** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. -** -** $Id: mp4util.c,v 1.15 2004/01/11 15:52:19 menno Exp $ -**/ - -#include "mp4ffint.h" -#include <stdlib.h> - -int32_t mp4ff_read_data(mp4ff_t *f, int8_t *data, uint32_t size) -{ - int32_t result = 1; - - result = f->stream->read(f->stream->user_data, data, size); - - f->current_position += size; - - return result; -} - -int32_t mp4ff_truncate(mp4ff_t * f) -{ - return f->stream->truncate(f->stream->user_data); -} - -int32_t mp4ff_write_data(mp4ff_t *f, int8_t *data, uint32_t size) -{ - int32_t result = 1; - - result = f->stream->write(f->stream->user_data, data, size); - - f->current_position += size; - - return result; -} - -int32_t mp4ff_write_int32(mp4ff_t *f,const uint32_t data) -{ - uint32_t result; - uint32_t a, b, c, d; - int8_t temp[4]; - - *(uint32_t*)temp = data; - a = (uint8_t)temp[0]; - b = (uint8_t)temp[1]; - c = (uint8_t)temp[2]; - d = (uint8_t)temp[3]; - - result = (a<<24) | (b<<16) | (c<<8) | d; - - return mp4ff_write_data(f,(uint8_t*)&result,sizeof(result)); -} - -int32_t mp4ff_set_position(mp4ff_t *f, const int64_t position) -{ - f->stream->seek(f->stream->user_data, position); - f->current_position = position; - - return 0; -} - -int64_t mp4ff_position(const mp4ff_t *f) -{ - return f->current_position; -} - -uint64_t mp4ff_read_int64(mp4ff_t *f) -{ - uint8_t data[8]; - uint64_t result = 0; - int8_t i; - - mp4ff_read_data(f, data, 8); - - for (i = 0; i < 8; i++) - { - result |= ((uint64_t)data[i]) << ((7 - i) * 8); - } - - return result; -} - -uint32_t mp4ff_read_int32(mp4ff_t *f) -{ - uint32_t result; - uint32_t a, b, c, d; - int8_t data[4]; - - mp4ff_read_data(f, data, 4); - a = (uint8_t)data[0]; - b = (uint8_t)data[1]; - c = (uint8_t)data[2]; - d = (uint8_t)data[3]; - - result = (a<<24) | (b<<16) | (c<<8) | d; - return (uint32_t)result; -} - -uint32_t mp4ff_read_int24(mp4ff_t *f) -{ - uint32_t result; - uint32_t a, b, c; - int8_t data[4]; - - mp4ff_read_data(f, data, 3); - a = (uint8_t)data[0]; - b = (uint8_t)data[1]; - c = (uint8_t)data[2]; - - result = (a<<16) | (b<<8) | c; - return (uint32_t)result; -} - -uint16_t mp4ff_read_int16(mp4ff_t *f) -{ - uint32_t result; - uint32_t a, b; - int8_t data[2]; - - mp4ff_read_data(f, data, 2); - a = (uint8_t)data[0]; - b = (uint8_t)data[1]; - - result = (a<<8) | b; - return (uint16_t)result; -} - -char * mp4ff_read_string(mp4ff_t * f,uint32_t length) -{ - char * str = (char*)malloc(length + 1); - if (str!=0) - { - if ((uint32_t)mp4ff_read_data(f,str,length)!=length) - { - free(str); - str = 0; - } - else - { - str[length] = 0; - } - } - return str; -} - -uint8_t mp4ff_read_char(mp4ff_t *f) -{ - uint8_t output; - mp4ff_read_data(f, &output, 1); - return output; -} - -uint32_t mp4ff_read_mp4_descr_length(mp4ff_t *f) -{ - uint8_t b; - uint8_t numBytes = 0; - uint32_t length = 0; - - do - { - b = mp4ff_read_char(f); - numBytes++; - length = (length << 7) | (b & 0x7F); - } while ((b & 0x80) && numBytes < 4); - - return length; -} diff --git a/trunk/src/mpd_types.h b/trunk/src/mpd_types.h deleted file mode 100644 index dbdfc6865..000000000 --- a/trunk/src/mpd_types.h +++ /dev/null @@ -1,43 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MPD_TYPES_H -#define MPD_TYPES_H - -#include "../config.h" - -typedef unsigned char mpd_uint8; -typedef signed char mpd_sint8; - -#if SIZEOF_SHORT == 2 -typedef unsigned short mpd_uint16; -typedef signed short mpd_sint16; -#elif SIZEOF_INT == 2 -typedef unsigned int mpd_uint16; -typedef signed int mpd_sint16; -#endif - -#if SIZEOF_INT == 4 -typedef unsigned int mpd_uint32; -typedef signed int mpd_sint32; -#elif SIZEOF_LONG == 4 -typedef unsigned long mpd_uint32; -typedef signed long mpd_sint32; -#endif - -#endif diff --git a/trunk/src/myfprintf.c b/trunk/src/myfprintf.c deleted file mode 100644 index a09ae4324..000000000 --- a/trunk/src/myfprintf.c +++ /dev/null @@ -1,72 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "myfprintf.h" -#include "interface.h" -#include "path.h" -#include "log.h" -#include "conf.h" -#include "utils.h" - -#include <stdarg.h> -#include <sys/param.h> -#include <unistd.h> -#include <sys/select.h> -#include <fcntl.h> -#include <string.h> -#include <errno.h> - -#define BUFFER_LENGTH MAXPATHLEN+1024 - -static void blockingWrite(const int fd, const char *string, size_t len) -{ - while (len) { - ssize_t ret = xwrite(fd, string, len); - if (ret == len) - return; - if (ret >= 0) { - len -= ret; - string += ret; - continue; - } - return; /* error */ - } -} - -void vfdprintf(const int fd, const char *fmt, va_list args) -{ - static char buffer[BUFFER_LENGTH]; - char *buf = buffer; - size_t len; - - vsnprintf(buf, BUFFER_LENGTH, fmt, args); - len = strlen(buf); - if (fd == STDERR_FILENO || - fd == STDOUT_FILENO || - interfacePrintWithFD(fd, buf, len) < 0) - blockingWrite(fd, buf, len); -} - -mpd_fprintf void fdprintf(const int fd, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - vfdprintf(fd, fmt, args); - va_end(args); -} - diff --git a/trunk/src/myfprintf.h b/trunk/src/myfprintf.h deleted file mode 100644 index 287902f9b..000000000 --- a/trunk/src/myfprintf.h +++ /dev/null @@ -1,31 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MYFPRINTF_H -#define MYFPRINTF_H - -#include "../config.h" -#include "gcc.h" - -#include <stdarg.h> -#include <stdio.h> - -mpd_fprintf void fdprintf(const int fd, const char *fmt, ...); -void vfdprintf(const int fd, const char *fmt, va_list arglist); - -#endif diff --git a/trunk/src/normalize.c b/trunk/src/normalize.c deleted file mode 100644 index fb62e7a4e..000000000 --- a/trunk/src/normalize.c +++ /dev/null @@ -1,47 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "compress.h" -#include "conf.h" -#include "normalize.h" - -#include <stdlib.h> - -int normalizationEnabled; - -void initNormalization(void) -{ - normalizationEnabled = getBoolConfigParam(CONF_VOLUME_NORMALIZATION); - if (normalizationEnabled == -1) normalizationEnabled = 0; - else if (normalizationEnabled < 0) exit(EXIT_FAILURE); - - if (normalizationEnabled) - CompressCfg(0, ANTICLIP, TARGET, GAINMAX, GAINSMOOTH, BUCKETS); -} - -void finishNormalization(void) -{ - if (normalizationEnabled) CompressFree(); -} - -void normalizeData(char *buffer, int bufferSize, AudioFormat *format) -{ - if ((format->bits != 16) || (format->channels != 2)) return; - - CompressDo(buffer, bufferSize); -} diff --git a/trunk/src/normalize.h b/trunk/src/normalize.h deleted file mode 100644 index ddbefab08..000000000 --- a/trunk/src/normalize.h +++ /dev/null @@ -1,32 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef NORMALIZE_H -#define NORMALIZE_H - -#include "audio.h" - -extern int normalizationEnabled; - -void initNormalization(void); - -void finishNormalization(void); - -void normalizeData(char *buffer, int bufferSize, AudioFormat *format); - -#endif /* !NORMALIZE_H */ diff --git a/trunk/src/outputBuffer.c b/trunk/src/outputBuffer.c deleted file mode 100644 index c7ff8b479..000000000 --- a/trunk/src/outputBuffer.c +++ /dev/null @@ -1,198 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "outputBuffer.h" - -#include "pcm_utils.h" -#include "playerData.h" -#include "utils.h" -#include "log.h" -#include "normalize.h" -#include "conf.h" - -#include <string.h> - -static mpd_sint16 currentChunk = -1; - -static mpd_sint8 currentMetaChunk = -1; -static mpd_sint8 sendMetaChunk; - -void clearAllMetaChunkSets(OutputBuffer * cb) -{ - memset(cb->metaChunkSet, 0, BUFFERED_METACHUNKS); -} - -void clearOutputBuffer(OutputBuffer * cb) -{ - int currentSet = 1; - - cb->end = cb->begin; - - /* be sure to reset metaChunkSets cause we are skipping over audio - * audio chunks, and thus skipping over metadata */ - if (currentChunk >= 0 && sendMetaChunk == 0 && currentMetaChunk >= 0) { - currentSet = cb->metaChunkSet[currentChunk]; - } - clearAllMetaChunkSets(cb); - if (currentChunk >= 0 && sendMetaChunk == 0 && currentMetaChunk >= 0) { - cb->metaChunkSet[currentChunk] = currentSet; - } - currentChunk = -1; -} - -void flushOutputBuffer(OutputBuffer * cb) -{ - if (currentChunk == cb->end) { - if ((cb->end + 1) >= buffered_chunks) { - cb->end = 0; - } - else cb->end++; - currentChunk = -1; - } -} - -int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream, - DecoderControl * dc, int seekable, void *dataIn, - long dataInLen, float time, mpd_uint16 bitRate, - ReplayGainInfo * replayGainInfo) -{ - mpd_uint16 dataToSend; - mpd_uint16 chunkLeft; - char *data; - size_t datalen; - static char *convBuffer; - static long convBufferLen; - - if (cmpAudioFormat(&(cb->audioFormat), &(dc->audioFormat)) == 0) { - data = dataIn; - datalen = dataInLen; - } else { - datalen = pcm_sizeOfConvBuffer(&(dc->audioFormat), dataInLen, - &(cb->audioFormat)); - if (datalen > convBufferLen) { - convBuffer = xrealloc(convBuffer, datalen); - convBufferLen = datalen; - } - data = convBuffer; - datalen = pcm_convertAudioFormat(&(dc->audioFormat), dataIn, - dataInLen, &(cb->audioFormat), - data, &(cb->convState)); - } - - if (replayGainInfo && (replayGainState != REPLAYGAIN_OFF)) - doReplayGain(replayGainInfo, data, datalen, &cb->audioFormat); - else if (normalizationEnabled) - normalizeData(data, datalen, &cb->audioFormat); - - while (datalen) { - if (currentChunk != cb->end) { - int next = cb->end + 1; - if (next >= buffered_chunks) { - next = 0; - } - while (cb->begin == next && !dc->stop) { - if (dc->seek) { - if (seekable) { - return OUTPUT_BUFFER_DC_SEEK; - } else { - dc->seekError = 1; - dc->seek = 0; - } - } - if (!inStream || - bufferInputStream(inStream) <= 0) { - my_usleep(10000); - } - } - if (dc->stop) - return OUTPUT_BUFFER_DC_STOP; - - currentChunk = cb->end; - cb->chunkSize[currentChunk] = 0; - - if (sendMetaChunk) { - cb->metaChunk[currentChunk] = currentMetaChunk; - } else - cb->metaChunk[currentChunk] = -1; - cb->bitRate[currentChunk] = bitRate; - cb->times[currentChunk] = time; - } - - chunkLeft = CHUNK_SIZE - cb->chunkSize[currentChunk]; - dataToSend = datalen > chunkLeft ? chunkLeft : datalen; - - memcpy(cb->chunks + currentChunk * CHUNK_SIZE + - cb->chunkSize[currentChunk], data, dataToSend); - cb->chunkSize[currentChunk] += dataToSend; - datalen -= dataToSend; - data += dataToSend; - - if (cb->chunkSize[currentChunk] == CHUNK_SIZE) { - flushOutputBuffer(cb); - } - } - - return 0; -} - -int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag) -{ - int nextChunk; - static MpdTag *last; - - if (!cb->acceptMetadata || !tag) { - sendMetaChunk = 0; - if (last) - freeMpdTag(last); - last = NULL; - DEBUG("copyMpdTagToOB: !acceptMetadata || !tag\n"); - return 0; - } - - if (last && mpdTagsAreEqual(last, tag)) { - DEBUG("copyMpdTagToOB: same as last\n"); - return 0; - } - - if (last) - freeMpdTag(last); - last = NULL; - - nextChunk = currentMetaChunk + 1; - if (nextChunk >= BUFFERED_METACHUNKS) - nextChunk = 0; - - if (cb->metaChunkSet[nextChunk]) { - sendMetaChunk = 0; - DEBUG("copyMpdTagToOB: metachunk in use!\n"); - return -1; - } - - sendMetaChunk = 1; - currentMetaChunk = nextChunk; - - last = mpdTagDup(tag); - - copyMpdTagToMetadataChunk(tag, &(cb->metadataChunks[currentMetaChunk])); - - cb->metaChunkSet[nextChunk] = 1; - - DEBUG("copyMpdTagToOB: copiedTag\n"); - - return 0; -} diff --git a/trunk/src/outputBuffer.h b/trunk/src/outputBuffer.h deleted file mode 100644 index f690941d4..000000000 --- a/trunk/src/outputBuffer.h +++ /dev/null @@ -1,69 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef OUTPUT_BUFFER_H -#define OUTPUT_BUFFER_H - -#include "pcm_utils.h" -#include "mpd_types.h" -#include "decode.h" -#include "audio.h" -#include "inputStream.h" -#include "metadataChunk.h" -#include "replayGain.h" - -#define OUTPUT_BUFFER_DC_STOP -1 -#define OUTPUT_BUFFER_DC_SEEK -2 - -#define BUFFERED_METACHUNKS 25 - -typedef struct _OutputBuffer { - char *volatile chunks; - mpd_uint16 *volatile chunkSize; - mpd_uint16 *volatile bitRate; - float *volatile times; - mpd_sint16 volatile begin; - mpd_sint16 volatile end; - AudioFormat audioFormat; - ConvState convState; - MetadataChunk metadataChunks[BUFFERED_METACHUNKS]; - mpd_sint8 metaChunkSet[BUFFERED_METACHUNKS]; - mpd_sint8 *volatile metaChunk; - volatile mpd_sint8 acceptMetadata; -} OutputBuffer; - -void clearOutputBuffer(OutputBuffer * cb); - -void flushOutputBuffer(OutputBuffer * cb); - -/* we send inStream for buffering the inputStream while waiting to - send the next chunk */ -int sendDataToOutputBuffer(OutputBuffer * cb, - InputStream * inStream, - DecoderControl * dc, - int seekable, - void *data, - long datalen, - float time, - mpd_uint16 bitRate, ReplayGainInfo * replayGainInfo); - -int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag); - -void clearAllMetaChunkSets(OutputBuffer * cb); - -#endif diff --git a/trunk/src/path.c b/trunk/src/path.c deleted file mode 100644 index f30eb0793..000000000 --- a/trunk/src/path.c +++ /dev/null @@ -1,310 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "path.h" -#include "log.h" -#include "charConv.h" -#include "conf.h" -#include "utf8.h" -#include "utils.h" - -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <dirent.h> - -#ifdef HAVE_LOCALE -#ifdef HAVE_LANGINFO_CODESET -#include <locale.h> -#include <langinfo.h> -#endif -#endif - -const char *musicDir; -static const char *playlistDir; -static char *fsCharset; - -static char *pathConvCharset(char *to, char *from, char *str, char *ret) -{ - if (ret) - free(ret); - return setCharSetConversion(to, from) ? NULL : convStrDup(str); -} - -char *fsCharsetToUtf8(char *str) -{ - static char *ret; - - ret = pathConvCharset("UTF-8", fsCharset, str, ret); - - if (ret && !validUtf8String(ret)) { - free(ret); - ret = NULL; - } - - return ret; -} - -char *utf8ToFsCharset(char *str) -{ - static char *ret; - - ret = pathConvCharset(fsCharset, "UTF-8", str, ret); - - if (!ret) - ret = xstrdup(str); - - return ret; -} - -void setFsCharset(char *charset) -{ - int error = 0; - - if (fsCharset) - free(fsCharset); - - fsCharset = xstrdup(charset); - - DEBUG("setFsCharset: fs charset is: %s\n", fsCharset); - - if (setCharSetConversion("UTF-8", fsCharset) != 0) { - WARNING("fs charset conversion problem: " - "not able to convert from \"%s\" to \"%s\"\n", - fsCharset, "UTF-8"); - error = 1; - } - if (setCharSetConversion(fsCharset, "UTF-8") != 0) { - WARNING("fs charset conversion problem: " - "not able to convert from \"%s\" to \"%s\"\n", - "UTF-8", fsCharset); - error = 1; - } - - if (error) { - free(fsCharset); - WARNING("setting fs charset to ISO-8859-1!\n"); - fsCharset = xstrdup("ISO-8859-1"); - } -} - -char *getFsCharset(void) -{ - return fsCharset; -} - -static char *appendSlash(char **path) -{ - char *temp = *path; - int len = strlen(temp); - - if (temp[len - 1] != '/') { - temp = xmalloc(len + 2); - memset(temp, 0, len + 2); - memcpy(temp, *path, len); - temp[len] = '/'; - free(*path); - *path = temp; - } - - return temp; -} - -void initPaths(void) -{ - ConfigParam *musicParam = parseConfigFilePath(CONF_MUSIC_DIR, 1); - ConfigParam *playlistParam = parseConfigFilePath(CONF_PLAYLIST_DIR, 1); - ConfigParam *fsCharsetParam = getConfigParam(CONF_FS_CHARSET); - - char *charset = NULL; - char *originalLocale; - DIR *dir; - - musicDir = appendSlash(&(musicParam->value)); - playlistDir = appendSlash(&(playlistParam->value)); - - if ((dir = opendir(playlistDir)) == NULL) { - FATAL("cannot open %s \"%s\" (config line %i): %s\n", - CONF_PLAYLIST_DIR, playlistParam->value, - playlistParam->line, strerror(errno)); - } - closedir(dir); - - if ((dir = opendir(musicDir)) == NULL) { - FATAL("cannot open %s \"%s\" (config line %i): %s\n", - CONF_MUSIC_DIR, musicParam->value, - musicParam->line, strerror(errno)); - } - closedir(dir); - - if (fsCharsetParam) { - charset = xstrdup(fsCharsetParam->value); - } -#ifdef HAVE_LOCALE -#ifdef HAVE_LANGINFO_CODESET - else if ((originalLocale = setlocale(LC_CTYPE, NULL))) { - char *temp; - char *currentLocale; - originalLocale = xstrdup(originalLocale); - - if (!(currentLocale = setlocale(LC_CTYPE, ""))) { - WARNING("problems setting current locale with " - "setlocale()\n"); - } else { - if (strcmp(currentLocale, "C") == 0 || - strcmp(currentLocale, "POSIX") == 0) { - WARNING("current locale is \"%s\"\n", - currentLocale); - } else if ((temp = nl_langinfo(CODESET))) { - charset = xstrdup(temp); - } else - WARNING - ("problems getting charset for locale\n"); - if (!setlocale(LC_CTYPE, originalLocale)) { - WARNING - ("problems resetting locale with setlocale()\n"); - } - } - - free(originalLocale); - } else - WARNING("problems getting locale with setlocale()\n"); -#endif -#endif - - if (charset) { - setFsCharset(charset); - free(charset); - } else { - WARNING("setting filesystem charset to ISO-8859-1\n"); - setFsCharset("ISO-8859-1"); - } -} - -void finishPaths(void) -{ - free(fsCharset); - fsCharset = NULL; -} - -static char *pfx_path(const char *path, const char *pfx, const size_t pfx_len) -{ - static char ret[MAXPATHLEN+1]; - size_t rp_len = strlen(path); - - /* check for the likely condition first: */ - if (mpd_likely((pfx_len + rp_len) < MAXPATHLEN)) { - memcpy(ret, pfx, pfx_len); - memcpy(ret + pfx_len, path, rp_len + 1); - return ret; - } - - /* unlikely, return an empty string because truncating would - * also be wrong... break early and break loudly (the system - * headers are likely screwed, not mpd) */ - ERROR("Cannot prefix '%s' to '%s', max: %d", pfx, path, MAXPATHLEN); - ret[0] = '\0'; - return ret; -} - -char *rmp2amp(char *relativePath) -{ - size_t pfx_len = strlen(musicDir); - return pfx_path(relativePath, musicDir, pfx_len); -} - -char *rpp2app(char *relativePath) -{ - size_t pfx_len = strlen(playlistDir); - return pfx_path(relativePath, playlistDir, pfx_len); -} - -/* this is actually like strlcpy (OpenBSD), but we don't actually want to - * blindly use it everywhere, only for paths that are OK to truncate (for - * error reporting and such */ -void pathcpy_trunc(char *dest, const char *src) -{ - size_t len = strlen(src); - - if (mpd_unlikely(len > MAXPATHLEN)) - len = MAXPATHLEN; - memcpy(dest, src, len); - dest[len] = '\0'; -} - -char *parentPath(char *path) -{ - static char parentPath[MAXPATHLEN+1]; - char *c; - - pathcpy_trunc(parentPath, path); - c = strrchr(parentPath,'/'); - - if (c == NULL) - parentPath[0] = '\0'; - else { - while ((parentPath <= c) && *(--c) == '/') /* nothing */ - ; - c[1] = '\0'; - } - - return parentPath; -} - -char *sanitizePathDup(char *path) -{ - int len = strlen(path) + 1; - char *ret = xmalloc(len); - char *cp = ret; - - memset(ret, 0, len); - - len = 0; - - /* eliminate more than one '/' in a row, like "///" */ - while (*path) { - while (*path == '/') - path++; - if (*path == '.') { - /* we don't want to have hidden directories, or '.' or - ".." in our path */ - free(ret); - return NULL; - } - while (*path && *path != '/') { - *(cp++) = *(path++); - len++; - } - if (*path == '/') { - *(cp++) = *(path++); - len++; - } - } - - if (len && ret[len - 1] == '/') { - len--; - ret[len] = '\0'; - } - - DEBUG("sanitized: %s\n", ret); - - return xrealloc(ret, len + 1); -} diff --git a/trunk/src/path.h b/trunk/src/path.h deleted file mode 100644 index 2357aa25d..000000000 --- a/trunk/src/path.h +++ /dev/null @@ -1,69 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PATH_H -#define PATH_H - -#include "../config.h" - -#include <sys/param.h> - -extern const char *musicDir; - -void initPaths(void); - -void finishPaths(void); - -/* utf8ToFsCharset() and fsCharsetToUtf8() - * Each returns a static pointer to a dynamically allocated buffer - * which means: - * - Do not manually free the return value of these functions, it'll be - * automatically freed the next time it is called. - * - They are not reentrant, xstrdup the return value immediately if - * you expect to call one of these functions again, but still need the - * previous result. - * - The static pointer is unique to each function. - */ -char *utf8ToFsCharset(char *str); -char *fsCharsetToUtf8(char *str); - -void setFsCharset(char *charset); - -char *getFsCharset(void); - -/* relative music path to absolute music path - * char * passed is a static variable, so don't free it - */ -char *rmp2amp(char *file); - -/* static char * returned */ -char *rpp2app(char *file); - -/* static char * returned */ -char *parentPath(char *path); - -/* strips extra "///" and leading "/" and trailing "/" */ -char *sanitizePathDup(char *path); - -/* this is actually like strlcpy (OpenBSD), but we don't actually want to - * blindly use it everywhere, only for paths that are OK to truncate (for - * error reporting and such. - * dest must be MAXPATHLEN+1 bytes large (which is standard in mpd) */ -void pathcpy_trunc(char *dest, const char *src); - -#endif diff --git a/trunk/src/pcm_utils.c b/trunk/src/pcm_utils.c deleted file mode 100644 index 534095620..000000000 --- a/trunk/src/pcm_utils.c +++ /dev/null @@ -1,470 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "pcm_utils.h" - -#include "mpd_types.h" -#include "log.h" -#include "utils.h" -#include "conf.h" - -#include <string.h> -#include <math.h> -#include <assert.h> - -void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format, - int volume) -{ - mpd_sint32 temp32; - mpd_sint8 *buffer8 = (mpd_sint8 *) buffer; - mpd_sint16 *buffer16 = (mpd_sint16 *) buffer; - - if (volume >= 1000) - return; - - if (volume <= 0) { - memset(buffer, 0, bufferSize); - return; - } - - switch (format->bits) { - case 16: - while (bufferSize > 0) { - temp32 = *buffer16; - temp32 *= volume; - temp32 += rand() & 511; - temp32 -= rand() & 511; - temp32 += 500; - temp32 /= 1000; - *buffer16 = temp32 > 32767 ? 32767 : - (temp32 < -32768 ? -32768 : temp32); - buffer16++; - bufferSize -= 2; - } - break; - case 8: - while (bufferSize > 0) { - temp32 = *buffer8; - temp32 *= volume; - temp32 += rand() & 511; - temp32 -= rand() & 511; - temp32 += 500; - temp32 /= 1000; - *buffer8 = temp32 > 127 ? 127 : - (temp32 < -128 ? -128 : temp32); - buffer8++; - bufferSize--; - } - break; - default: - FATAL("%i bits not supported by pcm_volumeChange!\n", - format->bits); - } -} - -static void pcm_add(char *buffer1, char *buffer2, size_t bufferSize1, - size_t bufferSize2, int vol1, int vol2, - AudioFormat * format) -{ - mpd_sint32 temp32; - mpd_sint8 *buffer8_1 = (mpd_sint8 *) buffer1; - mpd_sint8 *buffer8_2 = (mpd_sint8 *) buffer2; - mpd_sint16 *buffer16_1 = (mpd_sint16 *) buffer1; - mpd_sint16 *buffer16_2 = (mpd_sint16 *) buffer2; - - switch (format->bits) { - case 16: - while (bufferSize1 > 0 && bufferSize2 > 0) { - temp32 = - (vol1 * (*buffer16_1) + - vol2 * (*buffer16_2)); - temp32 += rand() & 511; - temp32 -= rand() & 511; - temp32 += 500; - temp32 /= 1000; - *buffer16_1 = - temp32 > 32767 ? 32767 : (temp32 < - -32768 ? -32768 : temp32); - buffer16_1++; - buffer16_2++; - bufferSize1 -= 2; - bufferSize2 -= 2; - } - if (bufferSize2 > 0) - memcpy(buffer16_1, buffer16_2, bufferSize2); - break; - case 8: - while (bufferSize1 > 0 && bufferSize2 > 0) { - temp32 = - (vol1 * (*buffer8_1) + vol2 * (*buffer8_2)); - temp32 += rand() & 511; - temp32 -= rand() & 511; - temp32 += 500; - temp32 /= 1000; - *buffer8_1 = - temp32 > 127 ? 127 : (temp32 < - -128 ? -128 : temp32); - buffer8_1++; - buffer8_2++; - bufferSize1--; - bufferSize2--; - } - if (bufferSize2 > 0) - memcpy(buffer8_1, buffer8_2, bufferSize2); - break; - default: - FATAL("%i bits not supported by pcm_add!\n", format->bits); - } -} - -void pcm_mix(char *buffer1, char *buffer2, size_t bufferSize1, - size_t bufferSize2, AudioFormat * format, float portion1) -{ - int vol1; - float s = sin(M_PI_2 * portion1); - s *= s; - - vol1 = s * 1000 + 0.5; - vol1 = vol1 > 1000 ? 1000 : (vol1 < 0 ? 0 : vol1); - - pcm_add(buffer1, buffer2, bufferSize1, bufferSize2, vol1, 1000 - vol1, - format); -} - -#ifdef HAVE_LIBSAMPLERATE -static int pcm_getSampleRateConverter(void) -{ - const char *conf = getConfigParamValue(CONF_SAMPLERATE_CONVERTER); - long convalgo; - char *test; - size_t len; - - if (!conf) { - convalgo = SRC_SINC_FASTEST; - goto out; - } - - convalgo = strtol(conf, &test, 10); - if (*test == '\0' && src_get_name(convalgo)) - goto out; - - len = strlen(conf); - for (convalgo = 0 ; ; convalgo++) { - test = (char *)src_get_name(convalgo); - if (!test) { - convalgo = SRC_SINC_FASTEST; - break; - } - if (strncasecmp(test, conf, len) == 0) - goto out; - } - - ERROR("unknown samplerate converter \"%s\"\n", conf); -out: - DEBUG("selecting samplerate converter \"%s\"\n", - src_get_name(convalgo)); - - return convalgo; -} -#endif - -#ifdef HAVE_LIBSAMPLERATE -static size_t pcm_convertSampleRate(mpd_sint8 channels, mpd_uint32 inSampleRate, - char *inBuffer, size_t inSize, - mpd_uint32 outSampleRate, char *outBuffer, - size_t outSize, ConvState *convState) -{ - static int convalgo = -1; - SRC_DATA *data = &convState->data; - size_t dataInSize; - size_t dataOutSize; - int error; - - if (convalgo < 0) - convalgo = pcm_getSampleRateConverter(); - - /* (re)set the state/ratio if the in or out format changed */ - if ((channels != convState->lastChannels) || - (inSampleRate != convState->lastInSampleRate) || - (outSampleRate != convState->lastOutSampleRate)) { - convState->error = 0; - convState->lastChannels = channels; - convState->lastInSampleRate = inSampleRate; - convState->lastOutSampleRate = outSampleRate; - - if (convState->state) - convState->state = src_delete(convState->state); - - convState->state = src_new(convalgo, channels, &error); - if (!convState->state) { - ERROR("cannot create new libsamplerate state: %s\n", - src_strerror(error)); - convState->error = 1; - return 0; - } - - data->src_ratio = (double)outSampleRate / (double)inSampleRate; - DEBUG("setting samplerate conversion ratio to %.2lf\n", - data->src_ratio); - src_set_ratio(convState->state, data->src_ratio); - } - - /* there was an error previously, and nothing has changed */ - if (convState->error) - return 0; - - data->input_frames = inSize / 2 / channels; - dataInSize = data->input_frames * sizeof(float) * channels; - if (dataInSize > convState->dataInSize) { - convState->dataInSize = dataInSize; - data->data_in = xrealloc(data->data_in, dataInSize); - } - - data->output_frames = outSize / 2 / channels; - dataOutSize = data->output_frames * sizeof(float) * channels; - if (dataOutSize > convState->dataOutSize) { - convState->dataOutSize = dataOutSize; - data->data_out = xrealloc(data->data_out, dataOutSize); - } - - src_short_to_float_array((short *)inBuffer, data->data_in, - data->input_frames * channels); - - error = src_process(convState->state, data); - if (error) { - ERROR("error processing samples with libsamplerate: %s\n", - src_strerror(error)); - convState->error = 1; - return 0; - } - - src_float_to_short_array(data->data_out, (short *)outBuffer, - data->output_frames_gen * channels); - - return data->output_frames_gen * 2 * channels; -} -#else /* !HAVE_LIBSAMPLERATE */ -/* resampling code blatantly ripped from ESD */ -static size_t pcm_convertSampleRate(mpd_sint8 channels, mpd_uint32 inSampleRate, - char *inBuffer, size_t inSize, - mpd_uint32 outSampleRate, char *outBuffer, - size_t outSize, ConvState *convState) -{ - mpd_uint32 rd_dat = 0; - mpd_uint32 wr_dat = 0; - mpd_sint16 *in = (mpd_sint16 *)inBuffer; - mpd_sint16 *out = (mpd_sint16 *)outBuffer; - mpd_uint32 nlen = outSize / 2; - mpd_sint16 lsample, rsample; - - switch (channels) { - case 1: - while (wr_dat < nlen) { - rd_dat = wr_dat * inSampleRate / outSampleRate; - - lsample = in[rd_dat++]; - - out[wr_dat++] = lsample; - } - break; - case 2: - while (wr_dat < nlen) { - rd_dat = wr_dat * inSampleRate / outSampleRate; - rd_dat &= ~1; - - lsample = in[rd_dat++]; - rsample = in[rd_dat++]; - - out[wr_dat++] = lsample; - out[wr_dat++] = rsample; - } - break; - } - - return outSize; -} -#endif /* !HAVE_LIBSAMPLERATE */ - -static char *pcm_convertChannels(mpd_sint8 channels, char *inBuffer, - size_t inSize, size_t *outSize) -{ - static char *buf; - static size_t len; - char *outBuffer = NULL;; - mpd_sint16 *in; - mpd_sint16 *out; - int inSamples, i; - - switch (channels) { - /* convert from 1 -> 2 channels */ - case 1: - *outSize = (inSize >> 1) << 2; - if (*outSize > len) { - len = *outSize; - buf = xrealloc(buf, len); - } - outBuffer = buf; - - inSamples = inSize >> 1; - in = (mpd_sint16 *)inBuffer; - out = (mpd_sint16 *)outBuffer; - for (i = 0; i < inSamples; i++) { - *out++ = *in; - *out++ = *in++; - } - - break; - /* convert from 2 -> 1 channels */ - case 2: - *outSize = inSize >> 1; - if (*outSize > len) { - len = *outSize; - buf = xrealloc(buf, len); - } - outBuffer = buf; - - inSamples = inSize >> 2; - in = (mpd_sint16 *)inBuffer; - out = (mpd_sint16 *)outBuffer; - for (i = 0; i < inSamples; i++) { - *out = (*in++) / 2; - *out++ += (*in++) / 2; - } - - break; - default: - ERROR("only 1 or 2 channels are supported for conversion!\n"); - } - - return outBuffer; -} - -static char *pcm_convertTo16bit(mpd_sint8 bits, char *inBuffer, size_t inSize, - size_t *outSize) -{ - static char *buf; - static size_t len; - char *outBuffer = NULL; - mpd_sint8 *in; - mpd_sint16 *out; - int i; - - switch (bits) { - case 8: - *outSize = inSize << 1; - if (*outSize > len) { - len = *outSize; - buf = xrealloc(buf, len); - } - outBuffer = buf; - - in = (mpd_sint8 *)inBuffer; - out = (mpd_sint16 *)outBuffer; - for (i = 0; i < inSize; i++) - *out++ = (*in++) << 8; - - break; - case 16: - *outSize = inSize; - outBuffer = inBuffer; - break; - case 24: - /* put dithering code from mp3_decode here */ - default: - ERROR("only 8 or 16 bits are supported for conversion!\n"); - } - - return outBuffer; -} - -/* outFormat bits must be 16 and channels must be 1 or 2! */ -size_t pcm_convertAudioFormat(AudioFormat * inFormat, char *inBuffer, - size_t inSize, AudioFormat * outFormat, - char *outBuffer, ConvState *convState) -{ - char *buf; - size_t len; - size_t outSize = pcm_sizeOfConvBuffer(inFormat, inSize, outFormat); - - assert(outFormat->bits == 16); - assert(outFormat->channels == 2 || outFormat->channels == 1); - - /* everything else supports 16 bit only, so convert to that first */ - buf = pcm_convertTo16bit(inFormat->bits, inBuffer, inSize, &len); - if (!buf) - exit(EXIT_FAILURE); - - if (inFormat->channels != outFormat->channels) { - buf = pcm_convertChannels(inFormat->channels, buf, len, &len); - if (!buf) - exit(EXIT_FAILURE); - } - - if (inFormat->sampleRate == outFormat->sampleRate) { - assert(outSize >= len); - memcpy(outBuffer, buf, len); - } else { - len = pcm_convertSampleRate(outFormat->channels, - inFormat->sampleRate, buf, len, - outFormat->sampleRate, outBuffer, - outSize, convState); - if (len == 0) - exit(EXIT_FAILURE); - } - - return len; -} - -size_t pcm_sizeOfConvBuffer(AudioFormat * inFormat, size_t inSize, - AudioFormat * outFormat) -{ - const double ratio = (double)outFormat->sampleRate / - (double)inFormat->sampleRate; - const int shift = 2 * outFormat->channels; - size_t outSize = inSize; - - switch (inFormat->bits) { - case 8: - outSize <<= 1; - break; - case 16: - break; - default: - FATAL("only 8 or 16 bits are supported for conversion!\n"); - } - - if (inFormat->channels != outFormat->channels) { - switch (inFormat->channels) { - case 1: - outSize = (outSize >> 1) << 2; - break; - case 2: - outSize >>= 1; - break; - default: - FATAL("only 1 or 2 channels are supported " - "for conversion!\n"); - } - } - - outSize /= shift; - outSize = floor(0.5 + (double)outSize * ratio); - outSize *= shift; - - return outSize; -} diff --git a/trunk/src/pcm_utils.h b/trunk/src/pcm_utils.h deleted file mode 100644 index 2c6610a75..000000000 --- a/trunk/src/pcm_utils.h +++ /dev/null @@ -1,57 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PCM_UTILS_H -#define PCM_UTILS_H - -#include "../config.h" - -#include "audio.h" - -#include <stdlib.h> - -#ifdef HAVE_LIBSAMPLERATE -#include <samplerate.h> -#endif - -typedef struct _ConvState { -#ifdef HAVE_LIBSAMPLERATE - SRC_STATE *state; - SRC_DATA data; - size_t dataInSize; - size_t dataOutSize; - mpd_sint8 lastChannels; - mpd_sint32 lastInSampleRate; - mpd_sint32 lastOutSampleRate; - int error; -#endif -} ConvState; - -void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format, - int volume); - -void pcm_mix(char *buffer1, char *buffer2, size_t bufferSize1, - size_t bufferSize2, AudioFormat * format, float portion1); - -size_t pcm_convertAudioFormat(AudioFormat * inFormat, char *inBuffer, - size_t inSize, AudioFormat * outFormat, - char *outBuffer, ConvState *convState); - -size_t pcm_sizeOfConvBuffer(AudioFormat * inFormat, size_t inSize, - AudioFormat * outFormat); -#endif diff --git a/trunk/src/permission.c b/trunk/src/permission.c deleted file mode 100644 index 3d597052c..000000000 --- a/trunk/src/permission.c +++ /dev/null @@ -1,140 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "permission.h" - -#include "conf.h" -#include "list.h" -#include "log.h" -#include "utils.h" - -#include <string.h> - -#define PERMISSION_PASSWORD_CHAR "@" -#define PERMISSION_SEPERATOR "," - -#define PERMISSION_READ_STRING "read" -#define PERMISSION_ADD_STRING "add" -#define PERMISSION_CONTROL_STRING "control" -#define PERMISSION_ADMIN_STRING "admin" - -static List *permission_passwords; - -static int permission_default; - -static int parsePermissions(char *string) -{ - int permission = 0; - char *temp; - char *tok; - - if (!string) - return 0; - - temp = strtok_r(string, PERMISSION_SEPERATOR, &tok); - while (temp) { - if (strcmp(temp, PERMISSION_READ_STRING) == 0) { - permission |= PERMISSION_READ; - } else if (strcmp(temp, PERMISSION_ADD_STRING) == 0) { - permission |= PERMISSION_ADD; - } else if (strcmp(temp, PERMISSION_CONTROL_STRING) == 0) { - permission |= PERMISSION_CONTROL; - } else if (strcmp(temp, PERMISSION_ADMIN_STRING) == 0) { - permission |= PERMISSION_ADMIN; - } else { - FATAL("unknown permission \"%s\"\n", temp); - } - - temp = strtok_r(NULL, PERMISSION_SEPERATOR, &tok); - } - - return permission; -} - -void initPermissions(void) -{ - char *temp; - char *cp2; - char *password; - int *permission; - ConfigParam *param; - - permission_passwords = makeList(free, 1); - - permission_default = PERMISSION_READ | PERMISSION_ADD | - PERMISSION_CONTROL | PERMISSION_ADMIN; - - param = getNextConfigParam(CONF_PASSWORD, NULL); - - if (param) { - permission_default = 0; - - do { - if (!strstr(param->value, PERMISSION_PASSWORD_CHAR)) { - FATAL("\"%s\" not found in password string " - "\"%s\", line %i\n", - PERMISSION_PASSWORD_CHAR, - param->value, param->line); - } - - if (!(temp = strtok_r(param->value, - PERMISSION_PASSWORD_CHAR, - &cp2))) { - FATAL("something weird just happened in permission.c\n"); - } - - password = temp; - - permission = xmalloc(sizeof(int)); - *permission = - parsePermissions(strtok_r(NULL, "", &cp2)); - - insertInList(permission_passwords, password, - permission); - } while ((param = getNextConfigParam(CONF_PASSWORD, param))); - } - - param = getConfigParam(CONF_DEFAULT_PERMS); - - if (param) - permission_default = parsePermissions(param->value); - - sortList(permission_passwords); -} - -int getPermissionFromPassword(char *password, int *permission) -{ - void *foundPermission; - - if (findInList(permission_passwords, password, &foundPermission)) { - *permission = *((int *)foundPermission); - return 0; - } - - return -1; -} - -void finishPermissions(void) -{ - freeList(permission_passwords); -} - -int getDefaultPermissions(void) -{ - return permission_default; -} diff --git a/trunk/src/permission.h b/trunk/src/permission.h deleted file mode 100644 index bd4257080..000000000 --- a/trunk/src/permission.h +++ /dev/null @@ -1,39 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PERMISSION_H -#define PERMISSION_H - -#include "../config.h" - -#define PERMISSION_NONE 0 -#define PERMISSION_READ 1 -#define PERMISSION_ADD 2 -#define PERMISSION_CONTROL 4 -#define PERMISSION_ADMIN 8 - - -int getPermissionFromPassword(char *password, int *permission); - -void finishPermissions(void); - -int getDefaultPermissions(void); - -void initPermissions(void); - -#endif diff --git a/trunk/src/player.c b/trunk/src/player.c deleted file mode 100644 index 7c92d088e..000000000 --- a/trunk/src/player.c +++ /dev/null @@ -1,530 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "player.h" -#include "path.h" -#include "decode.h" -#include "command.h" -#include "interface.h" -#include "playlist.h" -#include "ls.h" -#include "listen.h" -#include "log.h" -#include "utils.h" -#include "directory.h" -#include "volume.h" -#include "playerData.h" -#include "permission.h" -#include "sig_handlers.h" - -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/time.h> -#include <sys/wait.h> -#include <stdlib.h> -#include <signal.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> - -volatile int player_pid = 0; - -void clearPlayerPid(void) -{ - player_pid = 0; -} - -static void resetPlayerMetadata(void) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - if (pc->metadataState == PLAYER_METADATA_STATE_READ) { - pc->metadataState = PLAYER_METADATA_STATE_WRITE; - } -} - -static void resetPlayer(void) -{ - int pid; - - clearPlayerPid(); - getPlayerData()->playerControl.stop = 0; - getPlayerData()->playerControl.play = 0; - getPlayerData()->playerControl.pause = 0; - getPlayerData()->playerControl.lockQueue = 0; - getPlayerData()->playerControl.unlockQueue = 0; - getPlayerData()->playerControl.state = PLAYER_STATE_STOP; - getPlayerData()->playerControl.queueState = PLAYER_QUEUE_UNLOCKED; - getPlayerData()->playerControl.seek = 0; - getPlayerData()->playerControl.metadataState = - PLAYER_METADATA_STATE_WRITE; - pid = getPlayerData()->playerControl.decode_pid; - if (pid > 0) - kill(pid, SIGTERM); - getPlayerData()->playerControl.decode_pid = 0; -} - -void player_sigChldHandler(int pid, int status) -{ - if (player_pid == pid) - { - DEBUG("SIGCHLD caused by player process\n"); - if (WIFSIGNALED(status) && - WTERMSIG(status) != SIGTERM && - WTERMSIG(status) != SIGINT) - { - ERROR("player process died from signal: %i\n", - WTERMSIG(status)); - } - resetPlayer(); - } - else if (pid == getPlayerData()->playerControl.decode_pid && - player_pid <= 0) - { - if (WIFSIGNALED(status) && WTERMSIG(status) != SIGTERM) - { - ERROR("(caught by master parent) " - "decode process died from a " - "non-TERM signal: %i\n", WTERMSIG(status)); - } - getPlayerData()->playerControl.decode_pid = 0; - } -} - -int playerInit(void) -{ - blockSignals(); - player_pid = fork(); - if (player_pid==0) - { - clock_t start = clock(); - - PlayerControl *pc = &(getPlayerData()->playerControl); - - unblockSignals(); - - setSigHandlersForDecoder(); - - closeAllListenSockets(); - freeAllInterfaces(); - finishPlaylist(); - closeMp3Directory(); - finishPermissions(); - finishCommands(); - finishVolume(); - - DEBUG("took %f to init player\n", - (float)(clock()-start)/CLOCKS_PER_SEC); - - while (1) { - if (pc->play) - decode(); - else if (pc->stop) - pc->stop = 0; - else if (pc->seek) - pc->seek = 0; - else if (pc->pause) - pc->pause = 0; - else if (pc->closeAudio) { - closeAudioDevice(); - pc->closeAudio = 0; - kill(getppid(), SIGUSR1); - } else if (pc->lockQueue) { - pc->queueLockState = PLAYER_QUEUE_LOCKED; - pc->lockQueue = 0; - } else if (pc->unlockQueue) { - pc->queueLockState = PLAYER_QUEUE_UNLOCKED; - pc->unlockQueue = 0; - } else if (pc->cycleLogFiles) { - cycle_log_files(); - pc->cycleLogFiles = 0; - } else - my_usleep(10000); - } - - exit(EXIT_SUCCESS); - } - else if (player_pid < 0) - { - unblockSignals(); - ERROR("player Problems fork()'ing\n"); - player_pid = 0; - return -1; - } - - unblockSignals(); - - return 0; -} - -int playerPlay(int fd, Song * song) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - if (playerStop(fd) < 0) - return -1; - - if (song->tag) - pc->fileTime = song->tag->time; - else - pc->fileTime = 0; - - copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk)); - - pathcpy_trunc(pc->utf8url, getSongUrl(song)); - - pc->play = 1; - if (player_pid == 0 && playerInit() < 0) { - pc->play = 0; - return -1; - } - - resetPlayerMetadata(); - while (player_pid > 0 && pc->play) - my_usleep(1000); - - return 0; -} - -int playerStop(int fd) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - if (player_pid > 0 && pc->state != PLAYER_STATE_STOP) { - pc->stop = 1; - while (player_pid > 0 && pc->stop) - my_usleep(1000); - } - - pc->queueState = PLAYER_QUEUE_BLANK; - playerQueueUnlock(); - - return 0; -} - -void playerKill(void) -{ - int pid; - /*PlayerControl * pc = &(getPlayerData()->playerControl); - - playerStop(stderr); - playerCloseAudio(stderr); - if(player_pid>0 && pc->closeAudio) sleep(1); */ - - pid = player_pid; - if (pid > 0) - kill(pid, SIGTERM); -} - -int playerPause(int fd) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - if (player_pid > 0 && pc->state != PLAYER_STATE_STOP) { - pc->pause = 1; - while (player_pid > 0 && pc->pause) - my_usleep(1000); - } - - return 0; -} - -int playerSetPause(int fd, int pause) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - if (player_pid <= 0) - return 0; - - switch (pc->state) { - case PLAYER_STATE_PLAY: - if (pause) - playerPause(fd); - break; - case PLAYER_STATE_PAUSE: - if (!pause) - playerPause(fd); - break; - } - - return 0; -} - -int getPlayerElapsedTime(void) -{ - return (int)(getPlayerData()->playerControl.elapsedTime + 0.5); -} - -unsigned long getPlayerBitRate(void) -{ - return getPlayerData()->playerControl.bitRate; -} - -int getPlayerTotalTime(void) -{ - return (int)(getPlayerData()->playerControl.totalTime + 0.5); -} - -int getPlayerState(void) -{ - return getPlayerData()->playerControl.state; -} - -void clearPlayerError(void) -{ - getPlayerData()->playerControl.error = 0; -} - -int getPlayerError(void) -{ - return getPlayerData()->playerControl.error; -} - -char *getPlayerErrorStr(void) -{ - static char *error; - int errorlen = MAXPATHLEN + 1024; - PlayerControl *pc = &(getPlayerData()->playerControl); - - error = xrealloc(error, errorlen); - error[0] = '\0'; - - switch (pc->error) { - case PLAYER_ERROR_FILENOTFOUND: - snprintf(error, errorlen, - "file \"%s\" does not exist or is inaccessible", - pc->erroredUrl); - break; - case PLAYER_ERROR_FILE: - snprintf(error, errorlen, "problems decoding \"%s\"", - pc->erroredUrl); - break; - case PLAYER_ERROR_AUDIO: - snprintf(error, errorlen, "problems opening audio device"); - break; - case PLAYER_ERROR_SYSTEM: - snprintf(error, errorlen, "system error occured"); - break; - case PLAYER_ERROR_UNKTYPE: - snprintf(error, errorlen, "file type of \"%s\" is unknown", - pc->erroredUrl); - default: - break; - } - - errorlen = strlen(error); - error = xrealloc(error, errorlen + 1); - - if (errorlen) - return error; - - return NULL; -} - -void playerCloseAudio(void) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - if (player_pid > 0) { - if (playerStop(STDERR_FILENO) < 0) - return; - pc->closeAudio = 1; - } -} - -int queueSong(Song * song) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - if (pc->queueState == PLAYER_QUEUE_BLANK) { - pathcpy_trunc(pc->utf8url, getSongUrl(song)); - - if (song->tag) - pc->fileTime = song->tag->time; - else - pc->fileTime = 0; - - copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk)); - - pc->queueState = PLAYER_QUEUE_FULL; - return 0; - } - - return -1; -} - -int getPlayerQueueState(void) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - return pc->queueState; -} - -void setQueueState(int queueState) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - pc->queueState = queueState; -} - -void playerQueueLock(void) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - if (player_pid > 0 && pc->queueLockState == PLAYER_QUEUE_UNLOCKED) { - pc->lockQueue = 1; - while (player_pid > 0 && pc->lockQueue) - my_usleep(1000); - } -} - -void playerQueueUnlock(void) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - if (player_pid > 0 && pc->queueLockState == PLAYER_QUEUE_LOCKED) { - pc->unlockQueue = 1; - while (player_pid > 0 && pc->unlockQueue) - my_usleep(1000); - } -} - -int playerSeek(int fd, Song * song, float time) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - if (pc->state == PLAYER_STATE_STOP) { - commandError(fd, ACK_ERROR_PLAYER_SYNC, - "player not currently playing"); - return -1; - } - - if (strcmp(pc->utf8url, getSongUrl(song)) != 0) { - if (song->tag) - pc->fileTime = song->tag->time; - else - pc->fileTime = 0; - - copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk)); - - pathcpy_trunc(pc->utf8url, getSongUrl(song)); - } - - if (pc->error == PLAYER_ERROR_NOERROR) { - resetPlayerMetadata(); - pc->seekWhere = time; - pc->seek = 1; - while (player_pid > 0 && pc->seek) - my_usleep(1000); - } - - return 0; -} - -float getPlayerCrossFade(void) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - return pc->crossFade; -} - -void setPlayerCrossFade(float crossFadeInSeconds) -{ - PlayerControl *pc; - if (crossFadeInSeconds < 0) - crossFadeInSeconds = 0; - - pc = &(getPlayerData()->playerControl); - - pc->crossFade = crossFadeInSeconds; -} - -void setPlayerSoftwareVolume(int volume) -{ - PlayerControl *pc; - volume = (volume > 1000) ? 1000 : (volume < 0 ? 0 : volume); - - pc = &(getPlayerData()->playerControl); - - pc->softwareVolume = volume; -} - -double getPlayerTotalPlayTime(void) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - return pc->totalPlayTime; -} - -unsigned int getPlayerSampleRate(void) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - return pc->sampleRate; -} - -int getPlayerBits(void) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - return pc->bits; -} - -int getPlayerChannels(void) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - - return pc->channels; -} - -void playerCycleLogFiles(void) -{ - PlayerControl *pc = &(getPlayerData()->playerControl); - DecoderControl *dc = &(getPlayerData()->decoderControl); - - pc->cycleLogFiles = 1; - dc->cycleLogFiles = 1; -} - -/* this actually creates a dupe of the current metadata */ -Song *playerCurrentDecodeSong(void) -{ - static Song *song; - static MetadataChunk *prev; - Song *ret = NULL; - PlayerControl *pc = &(getPlayerData()->playerControl); - - if (pc->metadataState == PLAYER_METADATA_STATE_READ) { - DEBUG("playerCurrentDecodeSong: caught new metadata!\n"); - if (prev) - free(prev); - prev = xmalloc(sizeof(MetadataChunk)); - memcpy(prev, &(pc->metadataChunk), sizeof(MetadataChunk)); - if (song) - freeJustSong(song); - song = newNullSong(); - song->url = xstrdup(pc->currentUrl); - song->tag = metadataChunkToMpdTagDup(prev); - ret = song; - resetPlayerMetadata(); - } - - return ret; -} diff --git a/trunk/src/player.h b/trunk/src/player.h deleted file mode 100644 index b62fab2ea..000000000 --- a/trunk/src/player.h +++ /dev/null @@ -1,154 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PLAYER_H -#define PLAYER_H - -#include "../config.h" - -#include "decode.h" -#include "mpd_types.h" -#include "song.h" -#include "metadataChunk.h" - -#include <stdio.h> -#include <sys/param.h> - -#define PLAYER_STATE_STOP 0 -#define PLAYER_STATE_PAUSE 1 -#define PLAYER_STATE_PLAY 2 - -#define PLAYER_ERROR_NOERROR 0 -#define PLAYER_ERROR_FILE 1 -#define PLAYER_ERROR_AUDIO 2 -#define PLAYER_ERROR_SYSTEM 3 -#define PLAYER_ERROR_UNKTYPE 4 -#define PLAYER_ERROR_FILENOTFOUND 5 - -/* 0->1->2->3->5 regular playback - * ->4->0 don't play queued song - */ -#define PLAYER_QUEUE_BLANK 0 -#define PLAYER_QUEUE_FULL 1 -#define PLAYER_QUEUE_DECODE 2 -#define PLAYER_QUEUE_PLAY 3 -#define PLAYER_QUEUE_STOP 4 -#define PLAYER_QUEUE_EMPTY 5 - -#define PLAYER_QUEUE_UNLOCKED 0 -#define PLAYER_QUEUE_LOCKED 1 - -#define PLAYER_METADATA_STATE_READ 1 -#define PLAYER_METADATA_STATE_WRITE 2 - -typedef struct _PlayerControl { - volatile mpd_sint8 stop; - volatile mpd_sint8 play; - volatile mpd_sint8 pause; - volatile mpd_sint8 state; - volatile mpd_sint8 closeAudio; - volatile mpd_sint8 error; - volatile mpd_uint16 bitRate; - volatile mpd_sint8 bits; - volatile mpd_sint8 channels; - volatile mpd_uint32 sampleRate; - volatile float totalTime; - volatile float elapsedTime; - volatile float fileTime; - char utf8url[MAXPATHLEN + 1]; - char currentUrl[MAXPATHLEN + 1]; - char erroredUrl[MAXPATHLEN + 1]; - volatile mpd_sint8 queueState; - volatile mpd_sint8 queueLockState; - volatile mpd_sint8 lockQueue; - volatile mpd_sint8 unlockQueue; - volatile mpd_sint8 seek; - volatile double seekWhere; - volatile float crossFade; - volatile mpd_uint16 softwareVolume; - volatile double totalPlayTime; - volatile int decode_pid; - volatile mpd_sint8 cycleLogFiles; - volatile mpd_sint8 metadataState; - MetadataChunk metadataChunk; - MetadataChunk fileMetadataChunk; -} PlayerControl; - -void clearPlayerPid(void); - -void player_sigChldHandler(int pid, int status); - -int playerPlay(int fd, Song * song); - -int playerSetPause(int fd, int pause); - -int playerPause(int fd); - -int playerStop(int fd); - -void playerCloseAudio(void); - -void playerKill(void); - -int getPlayerTotalTime(void); - -int getPlayerElapsedTime(void); - -unsigned long getPlayerBitRate(void); - -int getPlayerState(void); - -void clearPlayerError(void); - -char *getPlayerErrorStr(void); - -int getPlayerError(void); - -int playerInit(void); - -int queueSong(Song * song); - -int getPlayerQueueState(void); - -void setQueueState(int queueState); - -void playerQueueLock(void); - -void playerQueueUnlock(void); - -int playerSeek(int fd, Song * song, float time); - -void setPlayerCrossFade(float crossFadeInSeconds); - -float getPlayerCrossFade(void); - -void setPlayerSoftwareVolume(int volume); - -double getPlayerTotalPlayTime(void); - -unsigned int getPlayerSampleRate(void); - -int getPlayerBits(void); - -int getPlayerChannels(void); - -void playerCycleLogFiles(void); - -Song *playerCurrentDecodeSong(void); - -#endif diff --git a/trunk/src/playerData.c b/trunk/src/playerData.c deleted file mode 100644 index 30ff6d6d6..000000000 --- a/trunk/src/playerData.c +++ /dev/null @@ -1,162 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "playerData.h" -#include "conf.h" -#include "log.h" - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/ipc.h> -#include <sys/shm.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -int buffered_before_play; -int buffered_chunks; - -#define DEFAULT_BUFFER_SIZE 2048 -#define DEFAULT_BUFFER_BEFORE_PLAY 10 - -static PlayerData *playerData_pd; - -void initPlayerData(void) -{ - float perc = DEFAULT_BUFFER_BEFORE_PLAY; - char *test; - int shmid; - int crossfade = 0; - size_t bufferSize = DEFAULT_BUFFER_SIZE; - size_t allocationSize; - OutputBuffer *buffer; - ConfigParam *param; - size_t device_array_size = audio_device_count() * sizeof(mpd_sint8); - - param = getConfigParam(CONF_AUDIO_BUFFER_SIZE); - - if (param) { - bufferSize = strtol(param->value, &test, 10); - if (*test != '\0' || bufferSize <= 0) { - FATAL("buffer size \"%s\" is not a positive integer, " - "line %i\n", param->value, param->line); - } - } - - bufferSize *= 1024; - - buffered_chunks = bufferSize / CHUNK_SIZE; - - if (buffered_chunks >= 1 << 15) { - FATAL("buffer size \"%li\" is too big\n", (long)bufferSize); - } - - param = getConfigParam(CONF_BUFFER_BEFORE_PLAY); - - if (param) { - perc = strtod(param->value, &test); - if (*test != '%' || perc < 0 || perc > 100) { - FATAL("buffered before play \"%s\" is not a positive " - "percentage and less than 100 percent, line %i" - "\n", param->value, param->line); - } - } - - buffered_before_play = (perc / 100) * buffered_chunks; - if (buffered_before_play > buffered_chunks) { - buffered_before_play = buffered_chunks; - } else if (buffered_before_play < 0) - buffered_before_play = 0; - - allocationSize = buffered_chunks * CHUNK_SIZE; /*actual buffer */ - allocationSize += buffered_chunks * sizeof(float); /*for times */ - allocationSize += buffered_chunks * sizeof(mpd_sint16); /*for chunkSize */ - allocationSize += buffered_chunks * sizeof(mpd_sint16); /*for bitRate */ - allocationSize += buffered_chunks * sizeof(mpd_sint8); /*for metaChunk */ - allocationSize += sizeof(PlayerData); /*for playerData struct */ - - /* for audioDeviceStates[] */ - allocationSize += device_array_size; - - if ((shmid = shmget(IPC_PRIVATE, allocationSize, IPC_CREAT | 0600)) < 0) - FATAL("problems shmget'ing\n"); - if (!(playerData_pd = shmat(shmid, NULL, 0))) - FATAL("problems shmat'ing\n"); - if (shmctl(shmid, IPC_RMID, NULL) < 0) - FATAL("problems shmctl'ing\n"); - - playerData_pd->audioDeviceStates = (mpd_uint8 *)playerData_pd + - allocationSize - device_array_size; - buffer = &(playerData_pd->buffer); - - memset(&buffer->convState, 0, sizeof(ConvState)); - buffer->chunks = ((char *)playerData_pd) + sizeof(PlayerData); - buffer->chunkSize = (mpd_uint16 *) (((char *)buffer->chunks) + - buffered_chunks * CHUNK_SIZE); - buffer->bitRate = (mpd_uint16 *) (((char *)buffer->chunkSize) + - buffered_chunks * sizeof(mpd_sint16)); - buffer->metaChunk = (mpd_sint8 *) (((char *)buffer->bitRate) + - buffered_chunks * - sizeof(mpd_sint16)); - buffer->times = - (float *)(((char *)buffer->metaChunk) + - buffered_chunks * sizeof(mpd_sint8)); - buffer->acceptMetadata = 0; - - playerData_pd->playerControl.stop = 0; - playerData_pd->playerControl.pause = 0; - playerData_pd->playerControl.play = 0; - playerData_pd->playerControl.error = PLAYER_ERROR_NOERROR; - playerData_pd->playerControl.lockQueue = 0; - playerData_pd->playerControl.unlockQueue = 0; - playerData_pd->playerControl.state = PLAYER_STATE_STOP; - playerData_pd->playerControl.queueState = PLAYER_QUEUE_BLANK; - playerData_pd->playerControl.queueLockState = PLAYER_QUEUE_UNLOCKED; - playerData_pd->playerControl.seek = 0; - playerData_pd->playerControl.closeAudio = 0; - memset(playerData_pd->playerControl.utf8url, 0, MAXPATHLEN + 1); - memset(playerData_pd->playerControl.erroredUrl, 0, MAXPATHLEN + 1); - memset(playerData_pd->playerControl.currentUrl, 0, MAXPATHLEN + 1); - playerData_pd->playerControl.crossFade = crossfade; - playerData_pd->playerControl.softwareVolume = 1000; - playerData_pd->playerControl.totalPlayTime = 0; - playerData_pd->playerControl.decode_pid = 0; - playerData_pd->playerControl.metadataState = - PLAYER_METADATA_STATE_WRITE; - - playerData_pd->decoderControl.stop = 0; - playerData_pd->decoderControl.start = 0; - playerData_pd->decoderControl.state = DECODE_STATE_STOP; - playerData_pd->decoderControl.seek = 0; - playerData_pd->decoderControl.error = DECODE_ERROR_NOERROR; - memset(playerData_pd->decoderControl.utf8url, 0, MAXPATHLEN + 1); -} - -PlayerData *getPlayerData(void) -{ - return playerData_pd; -} - -void freePlayerData(void) -{ - /* We don't want to release this memory until we know our player and - * decoder have exited. Otherwise, their signal handlers will want to - * access playerData_pd and we need to keep it available for them */ - waitpid(-1, NULL, 0); - shmdt(playerData_pd); -} diff --git a/trunk/src/playerData.h b/trunk/src/playerData.h deleted file mode 100644 index 00e4040be..000000000 --- a/trunk/src/playerData.h +++ /dev/null @@ -1,49 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PLAYER_DATA_H -#define PLAYER_DATA_H - -#include "../config.h" - -#include "audio.h" -#include "player.h" -#include "decode.h" -#include "mpd_types.h" -#include "outputBuffer.h" - -/* pick 1020 since its devisible for 8,16,24, and 32-bit audio */ -#define CHUNK_SIZE 1020 - -extern int buffered_before_play; -extern int buffered_chunks; - -typedef struct _PlayerData { - OutputBuffer buffer; - PlayerControl playerControl; - DecoderControl decoderControl; - mpd_uint8 *audioDeviceStates; -} PlayerData; - -void initPlayerData(void); - -PlayerData *getPlayerData(void); - -void freePlayerData(void); - -#endif diff --git a/trunk/src/playlist.c b/trunk/src/playlist.c deleted file mode 100644 index d8f2c6b65..000000000 --- a/trunk/src/playlist.c +++ /dev/null @@ -1,1499 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "playlist.h" -#include "player.h" -#include "command.h" -#include "ls.h" -#include "tag.h" -#include "conf.h" -#include "directory.h" -#include "log.h" -#include "path.h" -#include "utils.h" -#include "sig_handlers.h" -#include "state_file.h" -#include "storedPlaylist.h" - -#include <string.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <errno.h> -#include <unistd.h> -#include <time.h> - -#define PLAYLIST_STATE_STOP 0 -#define PLAYLIST_STATE_PLAY 1 - -#define PLAYLIST_PREV_UNLESS_ELAPSED 10 - -#define PLAYLIST_STATE_FILE_STATE "state: " -#define PLAYLIST_STATE_FILE_RANDOM "random: " -#define PLAYLIST_STATE_FILE_REPEAT "repeat: " -#define PLAYLIST_STATE_FILE_CURRENT "current: " -#define PLAYLIST_STATE_FILE_TIME "time: " -#define PLAYLIST_STATE_FILE_CROSSFADE "crossfade: " -#define PLAYLIST_STATE_FILE_PLAYLIST_BEGIN "playlist_begin" -#define PLAYLIST_STATE_FILE_PLAYLIST_END "playlist_end" - -#define PLAYLIST_STATE_FILE_STATE_PLAY "play" -#define PLAYLIST_STATE_FILE_STATE_PAUSE "pause" -#define PLAYLIST_STATE_FILE_STATE_STOP "stop" - -#define PLAYLIST_BUFFER_SIZE 2*MAXPATHLEN - -#define PLAYLIST_HASH_MULT 4 - -#define DEFAULT_PLAYLIST_MAX_LENGTH (1024*16) -#define DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS 0 - -static Playlist playlist; -static int playlist_state = PLAYLIST_STATE_STOP; -static int playlist_max_length = DEFAULT_PLAYLIST_MAX_LENGTH; -static int playlist_stopOnError; -static int playlist_errorCount; -static int playlist_queueError; -static int playlist_noGoToNext; - -int playlist_saveAbsolutePaths = DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS; - -static void swapOrder(int a, int b); -static int playPlaylistOrderNumber(int fd, int orderNum); -static void randomizeOrder(int start, int end); - -static void incrPlaylistVersion(void) -{ - static unsigned long max = ((mpd_uint32) 1 << 31) - 1; - playlist.version++; - if (playlist.version >= max) { - int i; - - for (i = 0; i < playlist.length; i++) { - playlist.songMod[i] = 0; - } - - playlist.version = 1; - } -} - -void playlistVersionChange(void) -{ - int i = 0; - - for (i = 0; i < playlist.length; i++) { - playlist.songMod[i] = playlist.version; - } - - incrPlaylistVersion(); -} - -static void incrPlaylistCurrent(void) -{ - if (playlist.current < 0) - return; - - if (playlist.current >= playlist.length - 1) { - if (playlist.repeat) - playlist.current = 0; - else - playlist.current = -1; - } else - playlist.current++; -} - -void initPlaylist(void) -{ - char *test; - int i; - ConfigParam *param; - - playlist.length = 0; - playlist.repeat = 0; - playlist.version = 1; - playlist.random = 0; - playlist.queued = -1; - playlist.current = -1; - - param = getConfigParam(CONF_MAX_PLAYLIST_LENGTH); - - if (param) { - playlist_max_length = strtol(param->value, &test, 10); - if (*test != '\0') { - FATAL("max playlist length \"%s\" is not an integer, " - "line %i\n", param->value, param->line); - } - } - - playlist_saveAbsolutePaths = getBoolConfigParam(CONF_SAVE_ABSOLUTE_PATHS); - if (playlist_saveAbsolutePaths == -1) playlist_saveAbsolutePaths = DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS; - else if (playlist_saveAbsolutePaths < 0) exit(EXIT_FAILURE); - - playlist.songs = xmalloc(sizeof(Song *) * playlist_max_length); - playlist.songMod = xmalloc(sizeof(mpd_uint32) * playlist_max_length); - playlist.order = xmalloc(sizeof(int) * playlist_max_length); - playlist.idToPosition = xmalloc(sizeof(int) * playlist_max_length * - PLAYLIST_HASH_MULT); - playlist.positionToId = xmalloc(sizeof(int) * playlist_max_length); - - memset(playlist.songs, 0, sizeof(char *) * playlist_max_length); - - srandom(time(NULL)); - - for (i = 0; i < playlist_max_length * PLAYLIST_HASH_MULT; i++) { - playlist.idToPosition[i] = -1; - } -} - -static int getNextId(void) -{ - static int cur = -1; - - do { - cur++; - if (cur >= playlist_max_length * PLAYLIST_HASH_MULT) { - cur = 0; - } - } while (playlist.idToPosition[cur] != -1); - - return cur; -} - -void finishPlaylist(void) -{ - int i; - for (i = 0; i < playlist.length; i++) { - if (playlist.songs[i]->type == SONG_TYPE_URL) { - freeJustSong(playlist.songs[i]); - } - } - - playlist.length = 0; - - free(playlist.songs); - playlist.songs = NULL; - free(playlist.songMod); - playlist.songMod = NULL; - free(playlist.order); - playlist.order = NULL; - free(playlist.idToPosition); - playlist.idToPosition = NULL; - free(playlist.positionToId); - playlist.positionToId = NULL; -} - -int clearPlaylist(int fd) -{ - int i; - - if (stopPlaylist(fd) < 0) - return -1; - - for (i = 0; i < playlist.length; i++) { - if (playlist.songs[i]->type == SONG_TYPE_URL) { - freeJustSong(playlist.songs[i]); - } - playlist.idToPosition[playlist.positionToId[i]] = -1; - playlist.songs[i] = NULL; - } - playlist.length = 0; - playlist.current = -1; - - incrPlaylistVersion(); - - return 0; -} - -int clearStoredPlaylist(int fd, char *utf8file) -{ - removeAllFromStoredPlaylistByPath(fd, utf8file); - return 0; -} - -int showPlaylist(int fd) -{ - int i; - - for (i = 0; i < playlist.length; i++) { - fdprintf(fd, "%i:%s\n", i, getSongUrl(playlist.songs[i])); - } - - return 0; -} - -void savePlaylistState(FILE *fp) -{ - fprintf(fp, "%s", PLAYLIST_STATE_FILE_STATE); - switch (playlist_state) { - case PLAYLIST_STATE_PLAY: - switch (getPlayerState()) { - case PLAYER_STATE_PAUSE: - fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_STATE_PAUSE); - break; - default: - fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_STATE_PLAY); - } - fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_CURRENT, - playlist.order[playlist.current]); - fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_TIME, - getPlayerElapsedTime()); - break; - default: - fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_STATE_STOP); - break; - } - fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_RANDOM, playlist.random); - fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_REPEAT, playlist.repeat); - fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_CROSSFADE, - (int)(getPlayerCrossFade())); - fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_PLAYLIST_BEGIN); - fflush(fp); - showPlaylist(fileno(fp)); - fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_PLAYLIST_END); -} - -static void loadPlaylistFromStateFile(FILE *fp, char *buffer, - int state, int current, int time) -{ - char *temp; - int song; - - if (!myFgets(buffer, PLAYLIST_BUFFER_SIZE, fp)) - state_file_fatal(); - while (strcmp(buffer, PLAYLIST_STATE_FILE_PLAYLIST_END)) { - song = atoi(strtok(buffer, ":")); - if (!(temp = strtok(NULL, ""))) - state_file_fatal(); - if (!addToPlaylist(STDERR_FILENO, temp, 0) && current == song) { - if (state != PLAYER_STATE_STOP) { - playPlaylist(STDERR_FILENO, - playlist.length - 1, 0); - } - if (state == PLAYER_STATE_PAUSE) { - playerPause(STDERR_FILENO); - } - if (state != PLAYER_STATE_STOP) { - seekSongInPlaylist(STDERR_FILENO, - playlist.length - 1, time); - } - } - if (!myFgets(buffer, PLAYLIST_BUFFER_SIZE, fp)) - state_file_fatal(); - } -} - -void readPlaylistState(FILE *fp) -{ - int current = -1; - int time = 0; - int state = PLAYER_STATE_STOP; - char buffer[PLAYLIST_BUFFER_SIZE]; - - while (myFgets(buffer, PLAYLIST_BUFFER_SIZE, fp)) { - if (strncmp(buffer, PLAYLIST_STATE_FILE_STATE, - strlen(PLAYLIST_STATE_FILE_STATE)) == 0) { - if (strcmp(&(buffer[strlen(PLAYLIST_STATE_FILE_STATE)]), - PLAYLIST_STATE_FILE_STATE_PLAY) == 0) { - state = PLAYER_STATE_PLAY; - } else - if (strcmp - (&(buffer[strlen(PLAYLIST_STATE_FILE_STATE)]), - PLAYLIST_STATE_FILE_STATE_PAUSE) - == 0) { - state = PLAYER_STATE_PAUSE; - } - } else if (strncmp(buffer, PLAYLIST_STATE_FILE_TIME, - strlen(PLAYLIST_STATE_FILE_TIME)) == 0) { - time = - atoi(&(buffer[strlen(PLAYLIST_STATE_FILE_TIME)])); - } else - if (strncmp - (buffer, PLAYLIST_STATE_FILE_REPEAT, - strlen(PLAYLIST_STATE_FILE_REPEAT)) == 0) { - if (strcmp - (&(buffer[strlen(PLAYLIST_STATE_FILE_REPEAT)]), - "1") == 0) { - setPlaylistRepeatStatus(STDERR_FILENO, 1); - } else - setPlaylistRepeatStatus(STDERR_FILENO, 0); - } else - if (strncmp - (buffer, PLAYLIST_STATE_FILE_CROSSFADE, - strlen(PLAYLIST_STATE_FILE_CROSSFADE)) == 0) { - setPlayerCrossFade(atoi - (& - (buffer - [strlen - (PLAYLIST_STATE_FILE_CROSSFADE)]))); - } else - if (strncmp - (buffer, PLAYLIST_STATE_FILE_RANDOM, - strlen(PLAYLIST_STATE_FILE_RANDOM)) == 0) { - if (strcmp - (& - (buffer - [strlen(PLAYLIST_STATE_FILE_RANDOM)]), - "1") == 0) { - setPlaylistRandomStatus(STDERR_FILENO, 1); - } else - setPlaylistRandomStatus(STDERR_FILENO, 0); - } else if (strncmp(buffer, PLAYLIST_STATE_FILE_CURRENT, - strlen(PLAYLIST_STATE_FILE_CURRENT)) - == 0) { - if (strlen(buffer) == - strlen(PLAYLIST_STATE_FILE_CURRENT)) - state_file_fatal(); - current = atoi(&(buffer - [strlen - (PLAYLIST_STATE_FILE_CURRENT)])); - } else - if (strncmp - (buffer, PLAYLIST_STATE_FILE_PLAYLIST_BEGIN, - strlen(PLAYLIST_STATE_FILE_PLAYLIST_BEGIN) - ) == 0) { - if (state == PLAYER_STATE_STOP) - current = -1; - loadPlaylistFromStateFile(fp, buffer, state, - current, time); - } - } -} - -static void printPlaylistSongInfo(int fd, int song) -{ - printSongInfo(fd, playlist.songs[song]); - fdprintf(fd, "Pos: %i\nId: %i\n", song, playlist.positionToId[song]); -} - -int playlistChanges(int fd, mpd_uint32 version) -{ - int i; - - for (i = 0; i < playlist.length; i++) { - if (version > playlist.version || - playlist.songMod[i] >= version || - playlist.songMod[i] == 0) { - printPlaylistSongInfo(fd, i); - } - } - - return 0; -} - -int playlistChangesPosId(int fd, mpd_uint32 version) -{ - int i; - - for (i = 0; i < playlist.length; i++) { - if (version > playlist.version || - playlist.songMod[i] >= version || - playlist.songMod[i] == 0) { - fdprintf(fd, "cpos: %i\nId: %i\n", - i, playlist.positionToId[i]); - } - } - - return 0; -} - -int playlistInfo(int fd, int song) -{ - int i; - int begin = 0; - int end = playlist.length; - - if (song >= 0) { - begin = song; - end = song + 1; - } - if (song >= playlist.length) { - commandError(fd, ACK_ERROR_NO_EXIST, - "song doesn't exist: \"%i\"", song); - return -1; - } - - for (i = begin; i < end; i++) - printPlaylistSongInfo(fd, i); - - return 0; -} - -# define checkSongId(id) { \ - if(id < 0 || id >= PLAYLIST_HASH_MULT*playlist_max_length || \ - playlist.idToPosition[id] == -1 ) \ - { \ - commandError(fd, ACK_ERROR_NO_EXIST, \ - "song id doesn't exist: \"%i\"", id); \ - return -1; \ - } \ -} - -int playlistId(int fd, int id) -{ - int i; - int begin = 0; - int end = playlist.length; - - if (id >= 0) { - checkSongId(id); - begin = playlist.idToPosition[id]; - end = begin + 1; - } - - for (i = begin; i < end; i++) - printPlaylistSongInfo(fd, i); - - return 0; -} - -static void swapSongs(int song1, int song2) -{ - Song *sTemp; - int iTemp; - - sTemp = playlist.songs[song1]; - playlist.songs[song1] = playlist.songs[song2]; - playlist.songs[song2] = sTemp; - - playlist.songMod[song1] = playlist.version; - playlist.songMod[song2] = playlist.version; - - playlist.idToPosition[playlist.positionToId[song1]] = song2; - playlist.idToPosition[playlist.positionToId[song2]] = song1; - - iTemp = playlist.positionToId[song1]; - playlist.positionToId[song1] = playlist.positionToId[song2]; - playlist.positionToId[song2] = iTemp; -} - -static void queueNextSongInPlaylist(void) -{ - if (playlist.current < playlist.length - 1) { - playlist.queued = playlist.current + 1; - DEBUG("playlist: queue song %i:\"%s\"\n", - playlist.queued, - getSongUrl(playlist. - songs[playlist.order[playlist.queued]])); - if (queueSong(playlist.songs[playlist.order[playlist.queued]]) < - 0) { - playlist.queued = -1; - playlist_queueError = 1; - } - } else if (playlist.length && playlist.repeat) { - if (playlist.length > 1 && playlist.random) { - randomizeOrder(0, playlist.length - 1); - } - playlist.queued = 0; - DEBUG("playlist: queue song %i:\"%s\"\n", - playlist.queued, - getSongUrl(playlist. - songs[playlist.order[playlist.queued]])); - if (queueSong(playlist.songs[playlist.order[playlist.queued]]) < - 0) { - playlist.queued = -1; - playlist_queueError = 1; - } - } -} - -static void syncPlaylistWithQueue(int queue) -{ - if (queue && getPlayerQueueState() == PLAYER_QUEUE_BLANK) { - queueNextSongInPlaylist(); - } else if (getPlayerQueueState() == PLAYER_QUEUE_DECODE) { - if (playlist.queued != -1) - setQueueState(PLAYER_QUEUE_PLAY); - else - setQueueState(PLAYER_QUEUE_STOP); - } else if (getPlayerQueueState() == PLAYER_QUEUE_EMPTY) { - setQueueState(PLAYER_QUEUE_BLANK); - if (playlist.queued >= 0) { - DEBUG("playlist: now playing queued song\n"); - playlist.current = playlist.queued; - } - playlist.queued = -1; - if (queue) - queueNextSongInPlaylist(); - } -} - -static void lockPlaylistInteraction(void) -{ - if (getPlayerQueueState() == PLAYER_QUEUE_PLAY || - getPlayerQueueState() == PLAYER_QUEUE_FULL) { - playerQueueLock(); - syncPlaylistWithQueue(0); - } -} - -static void unlockPlaylistInteraction(void) -{ - playerQueueUnlock(); -} - -static void clearPlayerQueue(void) -{ - playlist.queued = -1; - switch (getPlayerQueueState()) { - case PLAYER_QUEUE_FULL: - DEBUG("playlist: dequeue song\n"); - setQueueState(PLAYER_QUEUE_BLANK); - break; - case PLAYER_QUEUE_PLAY: - DEBUG("playlist: stop decoding queued song\n"); - setQueueState(PLAYER_QUEUE_STOP); - break; - } -} - -int addToPlaylist(int fd, char *url, int printId) -{ - Song *song; - - DEBUG("add to playlist: %s\n", url); - - if ((song = getSongFromDB(url))) { - } else if (!(isValidRemoteUtf8Url(url) && - (song = newSong(url, SONG_TYPE_URL, NULL)))) { - commandError(fd, ACK_ERROR_NO_EXIST, - "\"%s\" is not in the music db or is " - "not a valid url", url); - return -1; - } - - return addSongToPlaylist(fd, song, printId); -} - -int addToStoredPlaylist(int fd, char *url, char *utf8file) -{ - Song *song; - - DEBUG("add to stored playlist: %s\n", url); - - song = getSongFromDB(url); - if (song) { - appendSongToStoredPlaylistByPath(fd, utf8file, song); - return 0; - } - - if (!isValidRemoteUtf8Url(url)) - goto fail; - - song = newSong(url, SONG_TYPE_URL, NULL); - if (song) { - appendSongToStoredPlaylistByPath(fd, utf8file, song); - freeJustSong(song); - return 0; - } - -fail: - commandError(fd, ACK_ERROR_NO_EXIST, "\"%s\" is not in the music db" - "or is not a valid url", url); - return -1; -} - -int addSongToPlaylist(int fd, Song * song, int printId) -{ - int id; - - if (playlist.length == playlist_max_length) { - commandError(fd, ACK_ERROR_PLAYLIST_MAX, - "playlist is at the max size"); - return -1; - } - - if (playlist_state == PLAYLIST_STATE_PLAY) { - if (playlist.queued >= 0 - && playlist.current == playlist.length - 1) { - lockPlaylistInteraction(); - clearPlayerQueue(); - unlockPlaylistInteraction(); - } - } - - id = getNextId(); - - playlist.songs[playlist.length] = song; - playlist.songMod[playlist.length] = playlist.version; - playlist.order[playlist.length] = playlist.length; - playlist.positionToId[playlist.length] = id; - playlist.idToPosition[playlist.positionToId[playlist.length]] = - playlist.length; - playlist.length++; - - if (playlist.random) { - int swap; - int start; - /*if(playlist_state==PLAYLIST_STATE_STOP) start = 0; - else */ if (playlist.queued >= 0) - start = playlist.queued + 1; - else - start = playlist.current + 1; - if (start < playlist.length) { - swap = random() % (playlist.length - start); - swap += start; - swapOrder(playlist.length - 1, swap); - } - } - - incrPlaylistVersion(); - - if (printId) - fdprintf(fd, "Id: %i\n", id); - - return 0; -} - -int swapSongsInPlaylist(int fd, int song1, int song2) -{ - int queuedSong = -1; - int currentSong = -1; - - if (song1 < 0 || song1 >= playlist.length) { - commandError(fd, ACK_ERROR_NO_EXIST, - "song doesn't exist: \"%i\"", song1); - return -1; - } - if (song2 < 0 || song2 >= playlist.length) { - commandError(fd, ACK_ERROR_NO_EXIST, - "song doesn't exist: \"%i\"", song2); - return -1; - } - - if (playlist_state == PLAYLIST_STATE_PLAY) { - if (playlist.queued >= 0) { - queuedSong = playlist.order[playlist.queued]; - } - currentSong = playlist.order[playlist.current]; - - if (queuedSong == song1 || queuedSong == song2 - || currentSong == song1 || currentSong == song2) { - lockPlaylistInteraction(); - clearPlayerQueue(); - unlockPlaylistInteraction(); - } - } - - swapSongs(song1, song2); - if (playlist.random) { - int i; - int k; - int j = -1; - for (i = 0; playlist.order[i] != song1; i++) { - if (playlist.order[i] == song2) - j = i; - } - k = i; - for (; j == -1; i++) - if (playlist.order[i] == song2) - j = i; - swapOrder(k, j); - } else { - if (playlist.current == song1) - playlist.current = song2; - else if (playlist.current == song2) - playlist.current = song1; - } - - incrPlaylistVersion(); - - return 0; -} - -int swapSongsInPlaylistById(int fd, int id1, int id2) -{ - checkSongId(id1); - checkSongId(id2); - - return swapSongsInPlaylist(fd, playlist.idToPosition[id1], - playlist.idToPosition[id2]); -} - -#define moveSongFromTo(from, to) { \ - playlist.idToPosition[playlist.positionToId[from]] = to; \ - playlist.positionToId[to] = playlist.positionToId[from]; \ - playlist.songs[to] = playlist.songs[from]; \ - playlist.songMod[to] = playlist.version; \ -} - -int deleteFromPlaylist(int fd, int song) -{ - int i; - int songOrder; - - if (song < 0 || song >= playlist.length) { - commandError(fd, ACK_ERROR_NO_EXIST, - "song doesn't exist: \"%i\"", song); - return -1; - } - - if (playlist_state == PLAYLIST_STATE_PLAY) { - if (playlist.queued >= 0 - && (playlist.order[playlist.queued] == song - || playlist.order[playlist.current] == song)) { - lockPlaylistInteraction(); - clearPlayerQueue(); - unlockPlaylistInteraction(); - } - } - - if (playlist.songs[song]->type == SONG_TYPE_URL) { - freeJustSong(playlist.songs[song]); - } - - playlist.idToPosition[playlist.positionToId[song]] = -1; - - /* delete song from songs array */ - for (i = song; i < playlist.length - 1; i++) { - moveSongFromTo(i + 1, i); - } - /* now find it in the order array */ - for (i = 0; i < playlist.length - 1; i++) { - if (playlist.order[i] == song) - break; - } - songOrder = i; - /* delete the entry from the order array */ - for (; i < playlist.length - 1; i++) - playlist.order[i] = playlist.order[i + 1]; - /* readjust values in the order array */ - for (i = 0; i < playlist.length - 1; i++) { - if (playlist.order[i] > song) - playlist.order[i]--; - } - /* now take care of other misc stuff */ - playlist.songs[playlist.length - 1] = NULL; - playlist.length--; - - incrPlaylistVersion(); - - if (playlist_state != PLAYLIST_STATE_STOP - && playlist.current == songOrder) { - /*if(playlist.current>=playlist.length) return playerStop(fd); - else return playPlaylistOrderNumber(fd,playlist.current); */ - playerStop(STDERR_FILENO); - playlist_noGoToNext = 1; - } - - if (playlist.current > songOrder) { - playlist.current--; - } else if (playlist.current >= playlist.length) { - incrPlaylistCurrent(); - } - - if (playlist.queued > songOrder) { - playlist.queued--; - } - - return 0; -} - -int deleteFromPlaylistById(int fd, int id) -{ - checkSongId(id); - - return deleteFromPlaylist(fd, playlist.idToPosition[id]); -} - -void deleteASongFromPlaylist(Song * song) -{ - int i; - - if (NULL == playlist.songs) - return; - - for (i = 0; i < playlist.length; i++) { - if (song == playlist.songs[i]) { - deleteFromPlaylist(STDERR_FILENO, i); - } - } -} - -int stopPlaylist(int fd) -{ - DEBUG("playlist: stop\n"); - if (playerStop(fd) < 0) - return -1; - playerCloseAudio(); - playlist.queued = -1; - playlist_state = PLAYLIST_STATE_STOP; - playlist_noGoToNext = 0; - if (playlist.random) - randomizeOrder(0, playlist.length - 1); - return 0; -} - -static int playPlaylistOrderNumber(int fd, int orderNum) -{ - - if (playerStop(fd) < 0) - return -1; - - playlist_state = PLAYLIST_STATE_PLAY; - playlist_noGoToNext = 0; - playlist.queued = -1; - playlist_queueError = 0; - - DEBUG("playlist: play %i:\"%s\"\n", orderNum, - getSongUrl(playlist.songs[playlist.order[orderNum]])); - - if (playerPlay(fd, (playlist.songs[playlist.order[orderNum]])) < 0) { - stopPlaylist(fd); - return -1; - } - - playlist.current = orderNum; - - return 0; -} - -int playPlaylist(int fd, int song, int stopOnError) -{ - int i = song; - - clearPlayerError(); - - if (song == -1) { - if (playlist.length == 0) - return 0; - - if (playlist_state == PLAYLIST_STATE_PLAY) { - return playerSetPause(fd, 0); - } - if (playlist.current >= 0 && playlist.current < playlist.length) { - i = playlist.current; - } else { - i = 0; - } - } else if (song < 0 || song >= playlist.length) { - commandError(fd, ACK_ERROR_NO_EXIST, - "song doesn't exist: \"%i\"", song); - return -1; - } - - if (playlist.random) { - if (song == -1 && playlist_state == PLAYLIST_STATE_PLAY) { - randomizeOrder(0, playlist.length - 1); - } else { - if (song >= 0) - for (i = 0; song != playlist.order[i]; i++) ; - if (playlist_state == PLAYLIST_STATE_STOP) { - playlist.current = 0; - } - swapOrder(i, playlist.current); - i = playlist.current; - } - } - - playlist_stopOnError = stopOnError; - playlist_errorCount = 0; - - return playPlaylistOrderNumber(fd, i); -} - -int playPlaylistById(int fd, int id, int stopOnError) -{ - if (id == -1) { - return playPlaylist(fd, id, stopOnError); - } - - checkSongId(id); - - return playPlaylist(fd, playlist.idToPosition[id], stopOnError); -} - -static void syncCurrentPlayerDecodeMetadata(void) -{ - Song *songPlayer = playerCurrentDecodeSong(); - Song *song; - int songNum; - - if (!songPlayer) - return; - - if (playlist_state != PLAYLIST_STATE_PLAY) - return; - - songNum = playlist.order[playlist.current]; - song = playlist.songs[songNum]; - - if (song->type == SONG_TYPE_URL && - 0 == strcmp(getSongUrl(song), songPlayer->url) && - !mpdTagsAreEqual(song->tag, songPlayer->tag)) { - if (song->tag) - freeMpdTag(song->tag); - song->tag = mpdTagDup(songPlayer->tag); - playlist.songMod[songNum] = playlist.version; - incrPlaylistVersion(); - } -} - -void syncPlayerAndPlaylist(void) -{ - if (playlist_state != PLAYLIST_STATE_PLAY) - return; - - if (getPlayerState() == PLAYER_STATE_STOP) - playPlaylistIfPlayerStopped(); - else - syncPlaylistWithQueue(!playlist_queueError); - - syncCurrentPlayerDecodeMetadata(); -} - -static int currentSongInPlaylist(int fd) -{ - if (playlist_state != PLAYLIST_STATE_PLAY) - return 0; - - playlist_stopOnError = 0; - - syncPlaylistWithQueue(0); - - if (playlist.current >= 0 && playlist.current < playlist.length) { - return playPlaylistOrderNumber(fd, playlist.current); - } else - return stopPlaylist(fd); - - return 0; -} - -int nextSongInPlaylist(int fd) -{ - if (playlist_state != PLAYLIST_STATE_PLAY) - return 0; - - syncPlaylistWithQueue(0); - - playlist_stopOnError = 0; - - if (playlist.current < playlist.length - 1) { - return playPlaylistOrderNumber(fd, playlist.current + 1); - } else if (playlist.length && playlist.repeat) { - if (playlist.random) - randomizeOrder(0, playlist.length - 1); - return playPlaylistOrderNumber(fd, 0); - } else { - incrPlaylistCurrent(); - return stopPlaylist(fd); - } - - return 0; -} - -void playPlaylistIfPlayerStopped(void) -{ - if (getPlayerState() == PLAYER_STATE_STOP) { - int error = getPlayerError(); - - if (error == PLAYER_ERROR_NOERROR) - playlist_errorCount = 0; - else - playlist_errorCount++; - - if (playlist_state == PLAYLIST_STATE_PLAY - && ((playlist_stopOnError && error != PLAYER_ERROR_NOERROR) - || error == PLAYER_ERROR_AUDIO - || error == PLAYER_ERROR_SYSTEM - || playlist_errorCount >= playlist.length)) { - stopPlaylist(STDERR_FILENO); - } else if (playlist_noGoToNext) - currentSongInPlaylist(STDERR_FILENO); - else - nextSongInPlaylist(STDERR_FILENO); - } -} - -int getPlaylistRepeatStatus(void) -{ - return playlist.repeat; -} - -int getPlaylistRandomStatus(void) -{ - return playlist.random; -} - -int setPlaylistRepeatStatus(int fd, int status) -{ - if (status != 0 && status != 1) { - commandError(fd, ACK_ERROR_ARG, "\"%i\" is not 0 or 1", status); - return -1; - } - - if (playlist_state == PLAYLIST_STATE_PLAY) { - if (playlist.repeat && !status && playlist.queued == 0) { - lockPlaylistInteraction(); - clearPlayerQueue(); - unlockPlaylistInteraction(); - } - } - - playlist.repeat = status; - - return 0; -} - -int moveSongInPlaylist(int fd, int from, int to) -{ - int i; - Song *tmpSong; - int tmpId; - int queuedSong = -1; - int currentSong = -1; - - if (from < 0 || from >= playlist.length) { - commandError(fd, ACK_ERROR_NO_EXIST, - "song doesn't exist: \"%i\"", from); - return -1; - } - - if (to < 0 || to >= playlist.length) { - commandError(fd, ACK_ERROR_NO_EXIST, - "song doesn't exist: \"%i\"", to); - return -1; - } - - if (playlist_state == PLAYLIST_STATE_PLAY) { - if (playlist.queued >= 0) { - queuedSong = playlist.order[playlist.queued]; - } - currentSong = playlist.order[playlist.current]; - if (queuedSong == from || queuedSong == to - || currentSong == from || currentSong == to) { - lockPlaylistInteraction(); - clearPlayerQueue(); - unlockPlaylistInteraction(); - } - } - - tmpSong = playlist.songs[from]; - tmpId = playlist.positionToId[from]; - /* move songs to one less in from->to */ - for (i = from; i < to; i++) { - moveSongFromTo(i + 1, i); - } - /* move songs to one more in to->from */ - for (i = from; i > to; i--) { - moveSongFromTo(i - 1, i); - } - /* put song at _to_ */ - playlist.idToPosition[tmpId] = to; - playlist.positionToId[to] = tmpId; - playlist.songs[to] = tmpSong; - playlist.songMod[to] = playlist.version; - /* now deal with order */ - if (playlist.random) { - for (i = 0; i < playlist.length; i++) { - if (playlist.order[i] > from && playlist.order[i] <= to) { - playlist.order[i]--; - } else if (playlist.order[i] < from && - playlist.order[i] >= to) { - playlist.order[i]++; - } else if (from == playlist.order[i]) { - playlist.order[i] = to; - } - } - } - else - { - if (playlist.current == from) - playlist.current = to; - else if (playlist.current > from && playlist.current <= to) { - playlist.current--; - } else if (playlist.current >= to && playlist.current < from) { - playlist.current++; - } - - /* this first if statement isn't necessary since the queue - * would have been cleared out if queued == from */ - if (playlist.queued == from) - playlist.queued = to; - else if (playlist.queued > from && playlist.queued <= to) { - playlist.queued--; - } else if (playlist.queued>= to && playlist.queued < from) { - playlist.queued++; - } - } - - incrPlaylistVersion(); - - return 0; -} - -int moveSongInPlaylistById(int fd, int id1, int to) -{ - checkSongId(id1); - - return moveSongInPlaylist(fd, playlist.idToPosition[id1], to); -} - -static void orderPlaylist(void) -{ - int i; - - if (playlist.current >= 0 && playlist.current < playlist.length) { - playlist.current = playlist.order[playlist.current]; - } - - if (playlist_state == PLAYLIST_STATE_PLAY) { - if (playlist.queued >= 0) { - lockPlaylistInteraction(); - clearPlayerQueue(); - unlockPlaylistInteraction(); - } - } - - for (i = 0; i < playlist.length; i++) { - playlist.order[i] = i; - } - -} - -static void swapOrder(int a, int b) -{ - int bak = playlist.order[a]; - playlist.order[a] = playlist.order[b]; - playlist.order[b] = bak; -} - -static void randomizeOrder(int start, int end) -{ - int i; - int ri; - - DEBUG("playlist: randomize from %i to %i\n", start, end); - - if (playlist_state == PLAYLIST_STATE_PLAY) { - if (playlist.queued >= start && playlist.queued <= end) { - lockPlaylistInteraction(); - clearPlayerQueue(); - unlockPlaylistInteraction(); - } - } - - for (i = start; i <= end; i++) { - ri = random() % (end - start + 1) + start; - if (ri == playlist.current) - playlist.current = i; - else if (i == playlist.current) - playlist.current = ri; - swapOrder(i, ri); - } - -} - -int setPlaylistRandomStatus(int fd, int status) -{ - int statusWas = playlist.random; - - if (status != 0 && status != 1) { - commandError(fd, ACK_ERROR_ARG, "\"%i\" is not 0 or 1", status); - return -1; - } - - playlist.random = status; - - if (status != statusWas) { - if (playlist.random) { - /*if(playlist_state==PLAYLIST_STATE_PLAY) { - randomizeOrder(playlist.current+1, - playlist.length-1); - } - else */ randomizeOrder(0, playlist.length - 1); - if (playlist.current >= 0 && - playlist.current < playlist.length) { - swapOrder(playlist.current, 0); - playlist.current = 0; - } - } else - orderPlaylist(); - } - - return 0; -} - -int previousSongInPlaylist(int fd) -{ - static time_t lastTime; - time_t diff = time(NULL) - lastTime; - - lastTime += diff; - - if (playlist_state != PLAYLIST_STATE_PLAY) - return 0; - - syncPlaylistWithQueue(0); - - if (diff && getPlayerElapsedTime() > PLAYLIST_PREV_UNLESS_ELAPSED) { - return playPlaylistOrderNumber(fd, playlist.current); - } else { - if (playlist.current > 0) { - return playPlaylistOrderNumber(fd, - playlist.current - 1); - } else if (playlist.repeat) { - return playPlaylistOrderNumber(fd, playlist.length - 1); - } else { - return playPlaylistOrderNumber(fd, playlist.current); - } - } - - return 0; -} - -int shufflePlaylist(int fd) -{ - int i; - int ri; - - if (playlist.length > 1) { - if (playlist_state == PLAYLIST_STATE_PLAY) { - lockPlaylistInteraction(); - clearPlayerQueue(); - unlockPlaylistInteraction(); - /* put current playing song first */ - swapSongs(0, playlist.order[playlist.current]); - if (playlist.random) { - int j; - for (j = 0; 0 != playlist.order[j]; j++) ; - playlist.current = j; - } else - playlist.current = 0; - i = 1; - } else { - i = 0; - playlist.current = -1; - } - /* shuffle the rest of the list */ - for (; i < playlist.length; i++) { - ri = random() % (playlist.length - 1) + 1; - swapSongs(i, ri); - } - - incrPlaylistVersion(); - } - - return 0; -} - -int deletePlaylist(int fd, char *utf8file) -{ - char *file = utf8ToFsCharset(utf8file); - char *rfile = xmalloc(strlen(file) + strlen(".") + - strlen(PLAYLIST_FILE_SUFFIX) + 1); - char *actualFile; - - strcpy(rfile, file); - strcat(rfile, "."); - strcat(rfile, PLAYLIST_FILE_SUFFIX); - - if ((actualFile = rpp2app(rfile)) && isPlaylist(actualFile)) - free(rfile); - else { - free(rfile); - commandError(fd, ACK_ERROR_NO_EXIST, - "playlist \"%s\" not found", utf8file); - return -1; - } - - if (unlink(actualFile) < 0) { - commandError(fd, ACK_ERROR_SYSTEM, - "problems deleting file"); - return -1; - } - - return 0; -} - -int savePlaylist(int fd, char *utf8file) -{ - StoredPlaylist *sp = newStoredPlaylist(utf8file, fd, 0); - if (!sp) - return -1; - - appendPlaylistToStoredPlaylist(sp, &playlist); - if (writeStoredPlaylist(sp) != 0) { - freeStoredPlaylist(sp); - return -1; - } - - freeStoredPlaylist(sp); - return 0; -} - -int getPlaylistCurrentSong(void) -{ - if (playlist.current >= 0 && playlist.current < playlist.length) { - return playlist.order[playlist.current]; - } - - return -1; -} - -unsigned long getPlaylistVersion(void) -{ - return playlist.version; -} - -int getPlaylistLength(void) -{ - return playlist.length; -} - -int seekSongInPlaylist(int fd, int song, float time) -{ - int i = song; - - if (song < 0 || song >= playlist.length) { - commandError(fd, ACK_ERROR_NO_EXIST, - "song doesn't exist: \"%i\"", song); - return -1; - } - - if (playlist.random) - for (i = 0; song != playlist.order[i]; i++) ; - - clearPlayerError(); - playlist_stopOnError = 1; - playlist_errorCount = 0; - - if (playlist_state == PLAYLIST_STATE_PLAY) { - if (playlist.queued >= 0) { - lockPlaylistInteraction(); - clearPlayerQueue(); - unlockPlaylistInteraction(); - } - } else if (playPlaylistOrderNumber(fd, i) < 0) - return -1; - - if (playlist.current != i) { - if (playPlaylistOrderNumber(fd, i) < 0) - return -1; - } - - return playerSeek(fd, playlist.songs[playlist.order[i]], time); -} - -int seekSongInPlaylistById(int fd, int id, float time) -{ - checkSongId(id); - - return seekSongInPlaylist(fd, playlist.idToPosition[id], time); -} - -int getPlaylistSongId(int song) -{ - return playlist.positionToId[song]; -} - -int PlaylistInfo(int fd, char *utf8file, int detail) -{ - ListNode *node; - StoredPlaylist *sp = loadStoredPlaylist(utf8file, fd); - if (sp == NULL) - return -1; - - node = sp->list->firstNode; - while (node != NULL) { - char *temp = node->data; - int wrote = 0; - - if (detail) { - Song *song = getSongFromDB(temp); - if (song) { - printSongInfo(fd, song); - wrote = 1; - } - } - - if (!wrote) { - fdprintf(fd, SONG_FILE "%s\n", temp); - } - - node = node->nextNode; - } - - freeStoredPlaylist(sp); - return 0; -} - -int loadPlaylist(int fd, char *utf8file) -{ - ListNode *node; - StoredPlaylist *sp = loadStoredPlaylist(utf8file, fd); - if (sp == NULL) - return -1; - - node = sp->list->firstNode; - while (node != NULL) { - char *temp = node->data; - if ((addToPlaylist(STDERR_FILENO, temp, 0)) < 0) { - /* for windows compatibility, convert slashes */ - char *temp2 = xstrdup(temp); - char *p = temp2; - while (*p) { - if (*p == '\\') - *p = '/'; - p++; - } - if ((addToPlaylist(STDERR_FILENO, temp2, 0)) < 0) { - commandError(fd, ACK_ERROR_PLAYLIST_LOAD, - "can't add file \"%s\"", temp2); - } - free(temp2); - } - - node = node->nextNode; - } - - freeStoredPlaylist(sp); - return 0; -} - -void searchForSongsInPlaylist(int fd, int numItems, LocateTagItem * items) -{ - int i; - char **originalNeedles = xmalloc(numItems * sizeof(char *)); - - for (i = 0; i < numItems; i++) { - originalNeedles[i] = items[i].needle; - items[i].needle = strDupToUpper(originalNeedles[i]); - } - - for (i = 0; i < playlist.length; i++) { - if (strstrSearchTags(playlist.songs[i], numItems, items)) - printPlaylistSongInfo(fd, i); - } - - for (i = 0; i < numItems; i++) { - free(items[i].needle); - items[i].needle = originalNeedles[i]; - } - - free(originalNeedles); -} - -void findSongsInPlaylist(int fd, int numItems, LocateTagItem * items) -{ - int i; - - for (i = 0; i < playlist.length; i++) { - if (tagItemsFoundAndMatches(playlist.songs[i], numItems, items)) - printPlaylistSongInfo(fd, i); - } -} diff --git a/trunk/src/playlist.h b/trunk/src/playlist.h deleted file mode 100644 index 0ae3a677f..000000000 --- a/trunk/src/playlist.h +++ /dev/null @@ -1,144 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PLAYLIST_H -#define PLAYLIST_H - -#include "../config.h" - -#include "dbUtils.h" - -#include <stdio.h> -#include <sys/param.h> -#include <time.h> - -#define PLAYLIST_FILE_SUFFIX "m3u" -#define PLAYLIST_COMMENT '#' - -typedef struct _Playlist { - Song **songs; - /* holds version a song was modified on */ - mpd_uint32 *songMod; - int *order; - int *positionToId; - int *idToPosition; - int length; - int current; - int queued; - int repeat; - int random; - mpd_uint32 version; -} Playlist; - -extern int playlist_saveAbsolutePaths; - -void initPlaylist(void); - -void finishPlaylist(void); - -void readPlaylistState(FILE *); - -void savePlaylistState(FILE *); - -int clearPlaylist(int fd); - -int clearStoredPlaylist(int fd, char *utf8file); - -int addToPlaylist(int fd, char *file, int printId); - -int addToStoredPlaylist(int fd, char *file, char *utf8file); - -int addSongToPlaylist(int fd, Song * song, int printId); - -int showPlaylist(int fd); - -int deleteFromPlaylist(int fd, int song); - -int deleteFromPlaylistById(int fd, int song); - -int playlistInfo(int fd, int song); - -int playlistId(int fd, int song); - -int stopPlaylist(int fd); - -int playPlaylist(int fd, int song, int stopOnError); - -int playPlaylistById(int fd, int song, int stopOnError); - -int nextSongInPlaylist(int fd); - -void syncPlayerAndPlaylist(void); - -int previousSongInPlaylist(int fd); - -int shufflePlaylist(int fd); - -int savePlaylist(int fd, char *utf8file); - -int deletePlaylist(int fd, char *utf8file); - -int deletePlaylistById(int fd, char *utf8file); - -void deleteASongFromPlaylist(Song * song); - -int moveSongInPlaylist(int fd, int from, int to); - -int moveSongInPlaylistById(int fd, int id, int to); - -int swapSongsInPlaylist(int fd, int song1, int song2); - -int swapSongsInPlaylistById(int fd, int id1, int id2); - -int loadPlaylist(int fd, char *utf8file); - -int getPlaylistRepeatStatus(void); - -int setPlaylistRepeatStatus(int fd, int status); - -int getPlaylistRandomStatus(void); - -int setPlaylistRandomStatus(int fd, int status); - -int getPlaylistCurrentSong(void); - -int getPlaylistSongId(int song); - -int getPlaylistLength(void); - -unsigned long getPlaylistVersion(void); - -void playPlaylistIfPlayerStopped(void); - -int seekSongInPlaylist(int fd, int song, float time); - -int seekSongInPlaylistById(int fd, int id, float time); - -void playlistVersionChange(void); - -int playlistChanges(int fd, mpd_uint32 version); - -int playlistChangesPosId(int fd, mpd_uint32 version); - -int PlaylistInfo(int fd, char *utf8file, int detail); - -void searchForSongsInPlaylist(int fd, int numItems, LocateTagItem * items); - -void findSongsInPlaylist(int fd, int numItems, LocateTagItem * items); - -#endif diff --git a/trunk/src/replayGain.c b/trunk/src/replayGain.c deleted file mode 100644 index 7c20919b8..000000000 --- a/trunk/src/replayGain.c +++ /dev/null @@ -1,165 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * (c)2004 replayGain code by AliasMrJones - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "replayGain.h" -#include "utils.h" - -#include "log.h" -#include "conf.h" - -#include <string.h> -#include <math.h> -#include <stdlib.h> - -/* Added 4/14/2004 by AliasMrJones */ -int replayGainState = REPLAYGAIN_OFF; - -static float replayGainPreamp = 1.0; - -void initReplayGainState(void) -{ - ConfigParam *param = getConfigParam(CONF_REPLAYGAIN); - - if (!param) - return; - - if (strcmp(param->value, "track") == 0) { - replayGainState = REPLAYGAIN_TRACK; - } else if (strcmp(param->value, "album") == 0) { - replayGainState = REPLAYGAIN_ALBUM; - } else { - FATAL("replaygain value \"%s\" at line %i is invalid\n", - param->value, param->line); - } - - param = getConfigParam(CONF_REPLAYGAIN_PREAMP); - - if (param) { - char *test; - float f = strtod(param->value, &test); - - if (*test != '\0') { - FATAL("Replaygain preamp \"%s\" is not a number at " - "line %i\n", param->value, param->line); - } - - if (f < -15 || f > 15) { - FATAL("Replaygain preamp \"%s\" is not between -15 and" - "15 at line %i\n", param->value, param->line); - } - - replayGainPreamp = pow(10, f / 20.0); - } -} - -static float computeReplayGainScale(float gain, float peak) -{ - float scale; - - if (gain == 0.0) - return (1); - scale = pow(10.0, gain / 20.0); - scale *= replayGainPreamp; - if (scale > 15.0) - scale = 15.0; - - if (scale * peak > 1.0) { - scale = 1.0 / peak; - } - return (scale); -} - -ReplayGainInfo *newReplayGainInfo(void) -{ - ReplayGainInfo *ret = xmalloc(sizeof(ReplayGainInfo)); - - ret->albumGain = 0.0; - ret->albumPeak = 0.0; - - ret->trackGain = 0.0; - ret->trackPeak = 0.0; - - /* set to -1 so that we know in doReplayGain to compute the scale */ - ret->scale = -1.0; - - return ret; -} - -void freeReplayGainInfo(ReplayGainInfo * info) -{ - free(info); -} - -void doReplayGain(ReplayGainInfo * info, char *buffer, int bufferSize, - AudioFormat * format) -{ - mpd_sint16 *buffer16; - mpd_sint8 *buffer8; - mpd_sint32 temp32; - float scale; - - if (replayGainState == REPLAYGAIN_OFF || !info) - return; - - if (info->scale < 0) { - switch (replayGainState) { - case REPLAYGAIN_TRACK: - info->scale = computeReplayGainScale(info->trackGain, - info->trackPeak); - break; - default: - info->scale = computeReplayGainScale(info->albumGain, - info->albumPeak); - break; - } - } - - if (info->scale <= 1.01 && info->scale >= 0.99) - return; - - buffer16 = (mpd_sint16 *) buffer; - buffer8 = (mpd_sint8 *) buffer; - - scale = info->scale; - - switch (format->bits) { - case 16: - while (bufferSize > 0) { - temp32 = *buffer16; - temp32 *= scale; - *buffer16 = temp32 > 32767 ? 32767 : - (temp32 < -32768 ? -32768 : temp32); - buffer16++; - bufferSize -= 2; - } - break; - case 8: - while (bufferSize > 0) { - temp32 = *buffer8; - temp32 *= scale; - *buffer8 = temp32 > 127 ? 127 : - (temp32 < -128 ? -128 : temp32); - buffer8++; - bufferSize--; - } - break; - default: - ERROR("%i bits not supported by doReplaygain!\n", format->bits); - } -} diff --git a/trunk/src/replayGain.h b/trunk/src/replayGain.h deleted file mode 100644 index c2d471464..000000000 --- a/trunk/src/replayGain.h +++ /dev/null @@ -1,50 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * (c)2004 replayGain code by AliasMrJones - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef REPLAYGAIN_H -#define REPLAYGAIN_H - -#include "audio.h" - -#define REPLAYGAIN_OFF 0 -#define REPLAYGAIN_TRACK 1 -#define REPLAYGAIN_ALBUM 2 - -extern int replayGainState; - -typedef struct _ReplayGainInfo { - float albumGain; - float albumPeak; - float trackGain; - float trackPeak; - - /* used internally by mpd, to mess with it */ - float scale; -} ReplayGainInfo; - -ReplayGainInfo *newReplayGainInfo(void); - -void freeReplayGainInfo(ReplayGainInfo * info); - -void initReplayGainState(void); - -void doReplayGain(ReplayGainInfo * info, char *buffer, int bufferSize, - AudioFormat * format); - -#endif diff --git a/trunk/src/sig_handlers.c b/trunk/src/sig_handlers.c deleted file mode 100644 index fc29d2522..000000000 --- a/trunk/src/sig_handlers.c +++ /dev/null @@ -1,159 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * (c) 2004 Nick Welch (mack@incise.org) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sig_handlers.h" -#include "player.h" -#include "playerData.h" -#include "playlist.h" -#include "directory.h" -#include "command.h" -#include "signal_check.h" -#include "log.h" -#include "player.h" -#include "decode.h" - -#include <signal.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <sys/wait.h> -#include <errno.h> -#include <unistd.h> - -int handlePendingSignals(void) -{ - if (signal_is_pending(SIGINT) || signal_is_pending(SIGTERM)) { - DEBUG("main process got SIGINT or SIGTERM, exiting\n"); - return COMMAND_RETURN_KILL; - } - - if (signal_is_pending(SIGHUP)) { - DEBUG("got SIGHUP, rereading DB\n"); - signal_clear(SIGHUP); - if (!isUpdatingDB()) { - readDirectoryDB(); - playlistVersionChange(); - } - if (cycle_log_files() < 0) - return COMMAND_RETURN_KILL; - playerCycleLogFiles(); - } - - return 0; -} - -static void chldSigHandler(int signal) -{ - int status; - int pid; - DEBUG("main process got SIGCHLD\n"); - while (0 != (pid = wait3(&status, WNOHANG, NULL))) { - if (pid < 0) { - if (errno == EINTR) - continue; - else - break; - } - player_sigChldHandler(pid, status); - directory_sigChldHandler(pid, status); - } -} - -void initSigHandlers(void) -{ - struct sigaction sa; - - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sa.sa_handler = SIG_IGN; - while (sigaction(SIGPIPE, &sa, NULL) < 0 && errno == EINTR) ; - sa.sa_handler = chldSigHandler; - while (sigaction(SIGCHLD, &sa, NULL) < 0 && errno == EINTR) ; - signal_handle(SIGUSR1); - signal_handle(SIGINT); - signal_handle(SIGTERM); - signal_handle(SIGHUP); -} - -void finishSigHandlers(void) -{ - signal_unhandle(SIGINT); - signal_unhandle(SIGUSR1); - signal_unhandle(SIGTERM); - signal_unhandle(SIGHUP); -} - -void setSigHandlersForDecoder(void) -{ - struct sigaction sa; - - finishSigHandlers(); - - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sa.sa_handler = SIG_IGN; - while (sigaction(SIGHUP, &sa, NULL) < 0 && errno == EINTR) ; - while (sigaction(SIGINT, &sa, NULL) < 0 && errno == EINTR) ; - sa.sa_flags = SA_SIGINFO; - sa.sa_sigaction = decodeSigHandler; - while (sigaction(SIGCHLD, &sa, NULL) < 0 && errno == EINTR) ; - while (sigaction(SIGTERM, &sa, NULL) < 0 && errno == EINTR) ; -} - -void ignoreSignals(void) -{ - struct sigaction sa; - - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sa.sa_handler = SIG_IGN; - sa.sa_sigaction = NULL; - while (sigaction(SIGPIPE, &sa, NULL) < 0 && errno == EINTR) ; - while (sigaction(SIGCHLD, &sa, NULL) < 0 && errno == EINTR) ; - while (sigaction(SIGUSR1, &sa, NULL) < 0 && errno == EINTR) ; - while (sigaction(SIGINT, &sa, NULL) < 0 && errno == EINTR) ; - while (sigaction(SIGTERM, &sa, NULL) < 0 && errno == EINTR) ; - while (sigaction(SIGHUP, &sa, NULL) < 0 && errno == EINTR) ; -} - -void blockSignals(void) -{ - sigset_t sset; - - sigemptyset(&sset); - sigaddset(&sset, SIGCHLD); - sigaddset(&sset, SIGUSR1); - sigaddset(&sset, SIGHUP); - sigaddset(&sset, SIGINT); - sigaddset(&sset, SIGTERM); - while (sigprocmask(SIG_BLOCK, &sset, NULL) < 0 && errno == EINTR) ; -} - -void unblockSignals(void) -{ - sigset_t sset; - - sigemptyset(&sset); - sigaddset(&sset, SIGCHLD); - sigaddset(&sset, SIGUSR1); - sigaddset(&sset, SIGHUP); - sigaddset(&sset, SIGINT); - sigaddset(&sset, SIGTERM); - while (sigprocmask(SIG_UNBLOCK, &sset, NULL) < 0 && errno == EINTR) ; -} diff --git a/trunk/src/sig_handlers.h b/trunk/src/sig_handlers.h deleted file mode 100644 index 15fa181ee..000000000 --- a/trunk/src/sig_handlers.h +++ /dev/null @@ -1,42 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SIG_HANDLERS_H -#define SIG_HANDLERS_H - -#include "../config.h" - -int handlePendingSignals(void); - -void initSigHandlers(void); - -void finishSigHandlers(void); - -void setSigHandlersForDecoder(void); - -void ignoreSignals(void); - -void blockSignals(void); - -void unblockSignals(void); - -void blockTermSignal(void); - -void unblockTermSignal(void); - -#endif diff --git a/trunk/src/signal_check.c b/trunk/src/signal_check.c deleted file mode 100644 index 77a2b1251..000000000 --- a/trunk/src/signal_check.c +++ /dev/null @@ -1,60 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * (c)2004 by mackstann - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "signal_check.h" - -#include <errno.h> -#include <stddef.h> - -static volatile sig_atomic_t __caught_signals[NSIG]; - -static void __signal_handler(int sig) -{ - __caught_signals[sig] = 1; -} - -static void __set_signal_handler(int sig, void (*handler) (int)) -{ - struct sigaction act; - act.sa_flags = 0; - sigemptyset(&act.sa_mask); - act.sa_handler = handler; - while (sigaction(sig, &act, NULL) && errno == EINTR) ; -} - -void signal_handle(int sig) -{ - __set_signal_handler(sig, __signal_handler); -} - -void signal_unhandle(int sig) -{ - signal_clear(sig); - __set_signal_handler(sig, SIG_DFL); -} - -int signal_is_pending(int sig) -{ - return __caught_signals[sig]; -} - -void signal_clear(int sig) -{ - __caught_signals[sig] = 0; -} diff --git a/trunk/src/signal_check.h b/trunk/src/signal_check.h deleted file mode 100644 index 58c9f3c3e..000000000 --- a/trunk/src/signal_check.h +++ /dev/null @@ -1,30 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * (c)2004 by mackstann - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SIGNAL_CHECK_H -#define SIGNAL_CHECK_H - -#include <signal.h> - -void signal_handle(int sig); -void signal_unhandle(int sig); -int signal_is_pending(int sig); -void signal_clear(int sig); - -#endif /* SIGNAL_CHECK_H */ diff --git a/trunk/src/sllist.c b/trunk/src/sllist.c deleted file mode 100644 index 00408a3cd..000000000 --- a/trunk/src/sllist.c +++ /dev/null @@ -1,72 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* a very simple singly-linked-list structure for queues/buffers */ - -#include <string.h> -#include "sllist.h" -#include "utils.h" - -static void init_strnode(struct strnode *x, char *s) -{ - x->data = s; - x->next = NULL; -} - -struct strnode *new_strnode(char *s) -{ - struct strnode *x = xmalloc(sizeof(struct strnode)); - init_strnode(x, s); - return x; -} - -struct strnode *new_strnode_dup(char *s, const size_t size) -{ - struct strnode *x = xmalloc(sizeof(struct strnode) + size); - x->next = NULL; - x->data = ((char *)x + sizeof(struct strnode)); - memcpy((void *)x->data, (void*)s, size); - return x; -} - -struct sllnode *new_sllnode(void *s, const size_t size) -{ - struct sllnode *x = xmalloc(sizeof(struct sllnode) + size); - x->next = NULL; - x->size = size; - x->data = ((char *)x + sizeof(struct sllnode)); - memcpy(x->data, (void *)s, size); - return x; -} - -struct strnode *dup_strlist(struct strnode *old) -{ - struct strnode *tmp, *new, *cur; - - tmp = old; - cur = new = new_strnode_dup(tmp->data, strlen(tmp->data) + 1); - tmp = tmp->next; - while (tmp) { - cur->next = new_strnode_dup(tmp->data, strlen(tmp->data) + 1); - cur = cur->next; - tmp = tmp->next; - } - return new; -} - - diff --git a/trunk/src/sllist.h b/trunk/src/sllist.h deleted file mode 100644 index 1e81abef3..000000000 --- a/trunk/src/sllist.h +++ /dev/null @@ -1,52 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* a very simple singly-linked-list structure for queues/buffers */ - -#ifndef SLLIST_H -#define SLLIST_H - -#include <stddef.h> - -/* just free the entire structure if it's free-able, the 'data' member - * should _NEVER_ be explicitly freed - * - * there's no free command, iterate through them yourself and just - * call free() on it iff you xmalloc'd them */ - -struct strnode { - struct strnode *next; - char *data; -}; - -struct sllnode { - struct sllnode *next; - void *data; - size_t size; -}; - -struct strnode *new_strnode(char *s); - -struct strnode *new_strnode_dup(char *s, const size_t size); - -struct strnode *dup_strlist(struct strnode *old); - -struct sllnode *new_sllnode(void *s, const size_t size); - - -#endif /* SLLIST_H */ diff --git a/trunk/src/song.c b/trunk/src/song.c deleted file mode 100644 index 9bcb1a0b4..000000000 --- a/trunk/src/song.c +++ /dev/null @@ -1,353 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "song.h" -#include "ls.h" -#include "directory.h" -#include "utils.h" -#include "tag.h" -#include "log.h" -#include "path.h" -#include "playlist.h" -#include "inputPlugin.h" -#include "myfprintf.h" - -#define SONG_KEY "key: " -#define SONG_MTIME "mtime: " - -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -Song *newNullSong(void) -{ - Song *song = xmalloc(sizeof(Song)); - - song->tag = NULL; - song->url = NULL; - song->type = SONG_TYPE_FILE; - song->parentDir = NULL; - - return song; -} - -Song *newSong(char *url, int type, Directory * parentDir) -{ - Song *song = NULL; - - if (strchr(url, '\n')) { - DEBUG("newSong: '%s' is not a valid uri\n", url); - return NULL; - } - - song = newNullSong(); - - song->url = xstrdup(url); - song->type = type; - song->parentDir = parentDir; - - assert(type == SONG_TYPE_URL || parentDir); - - if (song->type == SONG_TYPE_FILE) { - InputPlugin *plugin; - unsigned int next = 0; - char *song_url = getSongUrl(song); - char *abs_path = rmp2amp(utf8ToFsCharset(song_url)); - while (!song->tag && (plugin = isMusic(song_url, - &(song->mtime), - next++))) { - song->tag = plugin->tagDupFunc(abs_path); - } - if (!song->tag || song->tag->time < 0) { - freeSong(song); - song = NULL; - } - } - - return song; -} - -void freeSong(Song * song) -{ - deleteASongFromPlaylist(song); - freeJustSong(song); -} - -void freeJustSong(Song * song) -{ - free(song->url); - if (song->tag) - freeMpdTag(song->tag); - free(song); - getSongUrl(NULL); -} - -SongList *newSongList(void) -{ - return makeList((ListFreeDataFunc *) freeSong, 0); -} - -Song *addSongToList(SongList * list, char *url, char *utf8path, - int songType, Directory * parentDirectory) -{ - Song *song = NULL; - - switch (songType) { - case SONG_TYPE_FILE: - if (isMusic(utf8path, NULL, 0)) { - song = newSong(url, songType, parentDirectory); - } - break; - case SONG_TYPE_URL: - song = newSong(url, songType, parentDirectory); - break; - default: - DEBUG("addSongToList: Trying to add an invalid song type\n"); - } - - if (song == NULL) - return NULL; - - insertInList(list, song->url, (void *)song); - - return song; -} - -void freeSongList(SongList * list) -{ - freeList(list); -} - -void printSongUrl(int fd, Song * song) -{ - if (song->parentDir && song->parentDir->path) { - fdprintf(fd, "%s%s/%s\n", SONG_FILE, - getDirectoryPath(song->parentDir), song->url); - } else { - fdprintf(fd, "%s%s\n", SONG_FILE, song->url); - } -} - -int printSongInfo(int fd, Song * song) -{ - printSongUrl(fd, song); - - if (song->tag) - printMpdTag(fd, song->tag); - - return 0; -} - -int printSongInfoFromList(int fd, SongList * list) -{ - ListNode *tempNode = list->firstNode; - - while (tempNode != NULL) { - printSongInfo(fd, (Song *) tempNode->data); - tempNode = tempNode->nextNode; - } - - return 0; -} - -void writeSongInfoFromList(FILE * fp, SongList * list) -{ - ListNode *tempNode = list->firstNode; - - fprintf(fp, "%s\n", SONG_BEGIN); - - while (tempNode != NULL) { - fprintf(fp, "%s%s\n", SONG_KEY, tempNode->key); - fflush(fp); - printSongInfo(fileno(fp), (Song *) tempNode->data); - fprintf(fp, "%s%li\n", SONG_MTIME, - (long)((Song *) tempNode->data)->mtime); - tempNode = tempNode->nextNode; - } - - fprintf(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; - deleteNodeFromList(list, *nextSongNode); - *nextSongNode = nodeTemp; - } - - if (!(*nextSongNode)) { - insertInList(list, song->url, (void *)song); - } else if (cmpRet == 0) { - Song *tempSong = (Song *) ((*nextSongNode)->data); - if (tempSong->mtime != song->mtime) { - freeMpdTag(tempSong->tag); - tempSong->tag = song->tag; - tempSong->mtime = song->mtime; - song->tag = NULL; - } - freeJustSong(song); - *nextSongNode = (*nextSongNode)->nextNode; - } else { - insertInListBeforeNode(list, *nextSongNode, -1, song->url, - (void *)song); - } -} - -static int matchesAnMpdTagItemKey(char *buffer, int *itemType) -{ - int i; - - for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) { - if (0 == strncmp(mpdTagItemKeys[i], buffer, - strlen(mpdTagItemKeys[i]))) { - *itemType = i; - return 1; - } - } - - return 0; -} - -void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir) -{ - char buffer[MAXPATHLEN + 1024]; - int bufferSize = MAXPATHLEN + 1024; - Song *song = NULL; - ListNode *nextSongNode = list->firstNode; - ListNode *nodeTemp; - int itemType; - - while (myFgets(buffer, bufferSize, fp) && 0 != strcmp(SONG_END, buffer)) { - if (0 == strncmp(SONG_KEY, buffer, strlen(SONG_KEY))) { - if (song) { - insertSongIntoList(list, &nextSongNode, - song->url, song); - song = NULL; - } - - song = newNullSong(); - song->url = xstrdup(buffer + strlen(SONG_KEY)); - song->type = SONG_TYPE_FILE; - song->parentDir = parentDir; - } else if (0 == strncmp(SONG_FILE, buffer, strlen(SONG_FILE))) { - if (!song) - FATAL("Problems reading song info\n"); - /* we don't need this info anymore - song->url = xstrdup(&(buffer[strlen(SONG_FILE)])); - */ - } else if (matchesAnMpdTagItemKey(buffer, &itemType)) { - if (!song->tag) - song->tag = newMpdTag(); - addItemToMpdTag(song->tag, itemType, - &(buffer - [strlen(mpdTagItemKeys[itemType]) + - 2])); - } else if (0 == strncmp(SONG_TIME, buffer, strlen(SONG_TIME))) { - if (!song->tag) - song->tag = newMpdTag(); - song->tag->time = atoi(&(buffer[strlen(SONG_TIME)])); - } else if (0 == strncmp(SONG_MTIME, buffer, strlen(SONG_MTIME))) { - song->mtime = atoi(&(buffer[strlen(SONG_MTIME)])); - } - /* ignore empty lines (starting with '\0') */ - else if (*buffer) - FATAL("songinfo: unknown line in db: %s\n", buffer); - } - - if (song) { - insertSongIntoList(list, &nextSongNode, song->url, song); - song = NULL; - } - - while (nextSongNode) { - nodeTemp = nextSongNode->nextNode; - deleteNodeFromList(list, nextSongNode); - nextSongNode = nodeTemp; - } -} - -int updateSongInfo(Song * song) -{ - if (song->type == SONG_TYPE_FILE) { - InputPlugin *plugin; - unsigned int next = 0; - char *song_url = getSongUrl(song); - char *abs_path = rmp2amp(song_url); - - if (song->tag) - freeMpdTag(song->tag); - - song->tag = NULL; - - while (!song->tag && (plugin = isMusic(song_url, - &(song->mtime), - next++))) { - song->tag = plugin->tagDupFunc(abs_path); - } - if (!song->tag || song->tag->time < 0) - return -1; - } - - return 0; -} - -/* 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*/ -char *getSongUrl(Song * song) -{ - static char *buffer; - static int bufferSize; - static Song *lastSong; - int slen; - int dlen; - int size; - - if (!song) { - lastSong = song; - return NULL; - } - - if (!song->parentDir || !song->parentDir->path) - return song->url; - - /* be careful with this! */ - if (song == lastSong) - return buffer; - - slen = strlen(song->url); - dlen = strlen(getDirectoryPath(song->parentDir)); - - size = slen + dlen + 2; - - if (size > bufferSize) { - buffer = xrealloc(buffer, size); - bufferSize = size; - } - - strcpy(buffer, getDirectoryPath(song->parentDir)); - buffer[dlen] = '/'; - strcpy(buffer + dlen + 1, song->url); - - return buffer; -} diff --git a/trunk/src/song.h b/trunk/src/song.h deleted file mode 100644 index c4100d2a2..000000000 --- a/trunk/src/song.h +++ /dev/null @@ -1,79 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SONG_H -#define SONG_H - -#include "../config.h" - -#include <sys/param.h> -#include <time.h> - -#include "tag.h" -#include "list.h" - -#define SONG_BEGIN "songList begin" -#define SONG_END "songList end" - -#define SONG_TYPE_FILE 1 -#define SONG_TYPE_URL 2 - -#define SONG_FILE "file: " -#define SONG_TIME "Time: " - -typedef struct _Song { - char *url; - mpd_sint8 type; - MpdTag *tag; - struct _Directory *parentDir; - time_t mtime; -} Song; - -typedef List SongList; - -Song *newNullSong(void); - -Song *newSong(char *url, int songType, struct _Directory *parentDir); - -void freeSong(Song *); - -void freeJustSong(Song *); - -SongList *newSongList(void); - -void freeSongList(SongList * list); - -Song *addSongToList(SongList * list, char *url, char *utf8path, - int songType, struct _Directory *parentDir); - -int printSongInfo(int fd, Song * song); - -int printSongInfoFromList(int fd, SongList * list); - -void writeSongInfoFromList(FILE * fp, SongList * list); - -void readSongInfoIntoList(FILE * fp, SongList * list, - struct _Directory *parent); - -int updateSongInfo(Song * song); - -void printSongUrl(int fd, Song * song); - -char *getSongUrl(Song * song); - -#endif diff --git a/trunk/src/state_file.c b/trunk/src/state_file.c deleted file mode 100644 index ac2fcde7a..000000000 --- a/trunk/src/state_file.c +++ /dev/null @@ -1,111 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../config.h" -#include "state_file.h" -#include "conf.h" -#include "gcc.h" -#include "log.h" -#include "audio.h" -#include "playlist.h" -#include "utils.h" -#include "volume.h" - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> - -static struct _sf_cb { - void (*reader)(FILE *); - void (*writer)(FILE *); -} sf_callbacks [] = { - { read_sw_volume_state, save_sw_volume_state }, - { readAudioDevicesState, saveAudioDevicesState }, - { readPlaylistState, savePlaylistState }, -}; - -static const char *sfpath; - -static void get_state_file_path(void) -{ - ConfigParam *param; - if (sfpath) - return; - param = parseConfigFilePath(CONF_STATE_FILE, 0); - if (param) - sfpath = (const char *)param->value; -} - -void write_state_file(void) -{ - int i; - FILE *fp; - - if (!sfpath) - return; - while (!(fp = fopen(sfpath, "w")) && errno == EINTR); - - if (mpd_unlikely(!fp)) { - ERROR("problems opening state file \"%s\" for writing: %s\n", - sfpath, strerror(errno)); - return; - } - - for (i = 0; i < ARRAY_SIZE(sf_callbacks); i++) - sf_callbacks[i].writer(fp); - - while(fclose(fp) && errno == EINTR) /* nothing */; -} - -void read_state_file(void) -{ - struct stat st; - int i; - FILE *fp; - - get_state_file_path(); - if (!sfpath) - return; - if (stat(sfpath, &st) < 0) { - DEBUG("failed to stat state file: %s\n", sfpath); - return; - } - if (!S_ISREG(st.st_mode)) - FATAL("state file \"%s\" is not a regular file\n", sfpath); - - while (!(fp = fopen(sfpath, "r")) && errno == EINTR); - if (mpd_unlikely(!fp)) { - FATAL("problems opening state file \"%s\" for reading: %s\n", - sfpath, strerror(errno)); - } - for (i = 0; i < ARRAY_SIZE(sf_callbacks); i++) { - sf_callbacks[i].reader(fp); - rewind(fp); - } - - while(fclose(fp) && errno == EINTR) /* nothing */; -} - -void mpd_noreturn state_file_fatal(void) -{ - FATAL("error parsing state file \"%s\"\n", sfpath); - exit(EXIT_FAILURE); -} - diff --git a/trunk/src/state_file.h b/trunk/src/state_file.h deleted file mode 100644 index 4a7d012ec..000000000 --- a/trunk/src/state_file.h +++ /dev/null @@ -1,30 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef STATE_FILE_H -#define STATE_FILE_H - -#include "gcc.h" - -#include <stdio.h> - -void write_state_file(void); -void read_state_file(void); -void mpd_noreturn state_file_fatal(void); - -#endif /* STATE_FILE_H */ diff --git a/trunk/src/stats.c b/trunk/src/stats.c deleted file mode 100644 index 5045077c0..000000000 --- a/trunk/src/stats.c +++ /dev/null @@ -1,48 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "stats.h" - -#include "directory.h" -#include "myfprintf.h" -#include "player.h" -#include "tag.h" -#include "tagTracker.h" - -#include <time.h> - -Stats stats; - -void initStats(void) -{ - stats.daemonStart = time(NULL); - stats.numberOfSongs = 0; -} - -int printStats(int fd) -{ - fdprintf(fd, "artists: %i\n", getNumberOfTagItems(TAG_ITEM_ARTIST)); - fdprintf(fd, "albums: %i\n", getNumberOfTagItems(TAG_ITEM_ALBUM)); - fdprintf(fd, "songs: %i\n", stats.numberOfSongs); - fdprintf(fd, "uptime: %li\n", time(NULL) - stats.daemonStart); - fdprintf(fd, "playtime: %li\n", - (long)(getPlayerTotalPlayTime() + 0.5)); - fdprintf(fd, "db_playtime: %li\n", stats.dbPlayTime); - fdprintf(fd, "db_update: %li\n", getDbModTime()); - return 0; -} diff --git a/trunk/src/stats.h b/trunk/src/stats.h deleted file mode 100644 index cd7d0122c..000000000 --- a/trunk/src/stats.h +++ /dev/null @@ -1,40 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef STATS_H -#define STATS_H - -#include "../config.h" - -#include <stdio.h> - -typedef struct _Stats { - unsigned long daemonStart; - int numberOfSongs; - unsigned long dbPlayTime; - /*unsigned long playTime; - unsigned long songsPlayed; */ -} Stats; - -extern Stats stats; - -void initStats(void); - -int printStats(int fd); - -#endif diff --git a/trunk/src/storedPlaylist.c b/trunk/src/storedPlaylist.c deleted file mode 100644 index 322cb1b5b..000000000 --- a/trunk/src/storedPlaylist.c +++ /dev/null @@ -1,501 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "storedPlaylist.h" -#include "log.h" -#include "path.h" -#include "utils.h" -#include "playlist.h" -#include "ack.h" -#include "command.h" -#include "ls.h" -#include "directory.h" - -#include <string.h> -#include <errno.h> - -static char *utf8pathToFsPathInStoredPlaylist(const char *utf8path, int fd) -{ - char *file; - char *rfile; - char *actualFile; - - if (strstr(utf8path, "/")) { - commandError(fd, ACK_ERROR_ARG, "playlist name \"%s\" is " - "invalid: playlist names may not contain slashes", - utf8path); - return NULL; - } - - file = utf8ToFsCharset((char *)utf8path); - - rfile = xmalloc(strlen(file) + strlen(".") + - strlen(PLAYLIST_FILE_SUFFIX) + 1); - - strcpy(rfile, file); - strcat(rfile, "."); - strcat(rfile, PLAYLIST_FILE_SUFFIX); - - actualFile = rpp2app(rfile); - - free(rfile); - - return actualFile; -} - -static unsigned int lengthOfStoredPlaylist(StoredPlaylist *sp) -{ - return sp->list->numberOfNodes; -} - -static ListNode *nodeOfStoredPlaylist(StoredPlaylist *sp, int index) -{ - int forward; - ListNode *node; - int i; - - if (index >= lengthOfStoredPlaylist(sp) || index < 0) - return NULL; - - if (index > lengthOfStoredPlaylist(sp)/2) { - forward = 0; - node = sp->list->lastNode; - i = lengthOfStoredPlaylist(sp) - 1; - } else { - forward = 1; - node = sp->list->firstNode; - i = 0; - } - - while (node != NULL) { - if (i == index) - return node; - - if (forward) { - i++; - node = node->nextNode; - } else { - i--; - node = node->prevNode; - } - } - - return NULL; -} - -static void appendSongToStoredPlaylist(StoredPlaylist *sp, Song *song) -{ - insertInListWithoutKey(sp->list, xstrdup(getSongUrl(song))); -} - -StoredPlaylist *newStoredPlaylist(const char *utf8name, int fd, int ignoreExisting) -{ - struct stat buf; - char *filename = NULL; - StoredPlaylist *sp = calloc(1, sizeof(*sp)); - if (!sp) - return NULL; - - if (utf8name) { - filename = utf8pathToFsPathInStoredPlaylist(utf8name, fd); - - if (filename && stat(filename, &buf) == 0 && - ignoreExisting == 0) { - commandError(fd, ACK_ERROR_EXIST, - "a file or directory already exists with " - "the name \"%s\"", utf8name); - free(sp); - return NULL; - } - } - - sp->list = makeList(DEFAULT_FREE_DATA_FUNC, 0); - sp->fd = fd; - - if (filename) - sp->fspath = xstrdup(filename); - - return sp; -} - -StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd) -{ - char *filename; - StoredPlaylist *sp; - FILE *file; - char s[MAXPATHLEN + 1]; - int slength = 0; - char *temp = utf8ToFsCharset((char *)utf8path); - char *parent = parentPath(temp); - int parentlen = strlen(parent); - int tempInt; - int commentCharFound = 0; - Song *song; - - filename = utf8pathToFsPathInStoredPlaylist(utf8path, fd); - if (!filename) - return NULL; - - while (!(file = fopen(filename, "r")) && errno == EINTR); - if (file == NULL) { - commandError(fd, ACK_ERROR_NO_EXIST, "could not open file " - "\"%s\": %s", filename, strerror(errno)); - return NULL; - } - - sp = newStoredPlaylist(utf8path, fd, 1); - if (!sp) - goto out; - - while ((tempInt = fgetc(file)) != EOF) { - s[slength] = tempInt; - if (s[slength] == '\n' || s[slength] == '\0') { - commentCharFound = 0; - s[slength] = '\0'; - if (s[0] == PLAYLIST_COMMENT) - commentCharFound = 1; - if (strncmp(s, musicDir, strlen(musicDir)) == 0) { - strcpy(s, &(s[strlen(musicDir)])); - } else if (parentlen) { - temp = xstrdup(s); - memset(s, 0, MAXPATHLEN + 1); - strcpy(s, parent); - strncat(s, "/", MAXPATHLEN - parentlen); - strncat(s, temp, MAXPATHLEN - parentlen - 1); - if (strlen(s) >= MAXPATHLEN) { - commandError(sp->fd, - ACK_ERROR_PLAYLIST_LOAD, - "\"%s\" is too long", temp); - free(temp); - freeStoredPlaylist(sp); - sp = NULL; - goto out; - } - free(temp); - } - slength = 0; - temp = fsCharsetToUtf8(s); - if (temp && !commentCharFound) { - song = getSongFromDB(temp); - if (song) { - appendSongToStoredPlaylist(sp, song); - continue; - } - - if (!isValidRemoteUtf8Url(temp)) - continue; - - song = newSong(temp, SONG_TYPE_URL, NULL); - if (song) { - appendSongToStoredPlaylist(sp, song); - freeJustSong(song); - } - } - } else if (slength == MAXPATHLEN) { - s[slength] = '\0'; - commandError(sp->fd, ACK_ERROR_PLAYLIST_LOAD, - "line \"%s\" in playlist \"%s\" " - "is too long", s, utf8path); - freeStoredPlaylist(sp); - sp = NULL; - goto out; - } else if (s[slength] != '\r') { - slength++; - } - } - -out: - while (fclose(file) && errno == EINTR); - return sp; -} - -void freeStoredPlaylist(StoredPlaylist *sp) -{ - if (sp->list) - freeList(sp->list); - if (sp->fspath) - free(sp->fspath); - - free(sp); -} - -static int moveSongInStoredPlaylist(int fd, StoredPlaylist *sp, int src, int dest) -{ - ListNode *srcNode, *destNode; - - if (src >= lengthOfStoredPlaylist(sp) || dest >= lengthOfStoredPlaylist(sp) || src < 0 || dest < 0 || src == dest) { - commandError(fd, ACK_ERROR_ARG, "argument out of range"); - return -1; - } - - srcNode = nodeOfStoredPlaylist(sp, src); - if (!srcNode) - return -1; - - destNode = nodeOfStoredPlaylist(sp, dest); - - /* remove src */ - if (srcNode->prevNode) - srcNode->prevNode->nextNode = srcNode->nextNode; - else - sp->list->firstNode = srcNode->nextNode; - - if (srcNode->nextNode) - srcNode->nextNode->prevNode = srcNode->prevNode; - else - sp->list->lastNode = srcNode->prevNode; - - /* this is all a bit complicated - but I tried to - * maintain the same order stuff is moved as in the - * real playlist */ - if (dest == 0) { - sp->list->firstNode->prevNode = srcNode; - srcNode->nextNode = sp->list->firstNode; - srcNode->prevNode = NULL; - sp->list->firstNode = srcNode; - } else if ((dest + 1) == lengthOfStoredPlaylist(sp)) { - sp->list->lastNode->nextNode = srcNode; - srcNode->nextNode = NULL; - srcNode->prevNode = sp->list->lastNode; - sp->list->lastNode = srcNode; - } else { - if (destNode == NULL) { - /* this shouldn't be happening. */ - return -1; - } - - if (src > dest) { - destNode->prevNode->nextNode = srcNode; - srcNode->prevNode = destNode->prevNode; - srcNode->nextNode = destNode; - destNode->prevNode = srcNode; - } else { - destNode->nextNode->prevNode = srcNode; - srcNode->prevNode = destNode; - srcNode->nextNode = destNode->nextNode; - destNode->nextNode = srcNode; - } - } - - return 0; -} - -int moveSongInStoredPlaylistByPath(int fd, const char *utf8path, int src, int dest) -{ - StoredPlaylist *sp = loadStoredPlaylist(utf8path, fd); - if (!sp) { - commandError(fd, ACK_ERROR_UNKNOWN, "could not open playlist"); - return -1; - } - - if (moveSongInStoredPlaylist(fd, sp, src, dest) != 0) { - freeStoredPlaylist(sp); - return -1; - } - - if (writeStoredPlaylist(sp) != 0) { - commandError(fd, ACK_ERROR_UNKNOWN, "failed to save playlist"); - freeStoredPlaylist(sp); - return -1; - } - - freeStoredPlaylist(sp); - return 0; -} - -/* Not used currently -static void removeAllFromStoredPlaylist(StoredPlaylist *sp) -{ - freeList(sp->list); - sp->list = makeList(DEFAULT_FREE_DATA_FUNC, 0); -} -*/ - -int removeAllFromStoredPlaylistByPath(int fd, const char *utf8path) -{ - char *filename; - FILE *file; - - filename = utf8pathToFsPathInStoredPlaylist(utf8path, fd); - if (!filename) - return -1; - - while (!(file = fopen(filename, "w")) && errno == EINTR); - if (file == NULL) { - commandError(fd, ACK_ERROR_NO_EXIST, "could not open file " - "\"%s\": %s", filename, strerror(errno)); - return -1; - } - - while (fclose(file) != 0 && errno == EINTR); - return 0; -} - -static int removeOneSongFromStoredPlaylist(int fd, StoredPlaylist *sp, int pos) -{ - ListNode *node = nodeOfStoredPlaylist(sp, pos); - if (!node) { - commandError(fd, ACK_ERROR_ARG, - "could not find song at position"); - return -1; - } - - deleteNodeFromList(sp->list, node); - - return 0; -} - -int removeOneSongFromStoredPlaylistByPath(int fd, const char *utf8path, int pos) -{ - StoredPlaylist *sp = loadStoredPlaylist(utf8path, fd); - if (!sp) { - commandError(fd, ACK_ERROR_UNKNOWN, "could not open playlist"); - return -1; - } - - if (removeOneSongFromStoredPlaylist(fd, sp, pos) != 0) { - freeStoredPlaylist(sp); - return -1; - } - - if (writeStoredPlaylist(sp) != 0) { - commandError(fd, ACK_ERROR_UNKNOWN, "failed to save playlist"); - freeStoredPlaylist(sp); - return -1; - } - - freeStoredPlaylist(sp); - return 0; -} - -static int writeStoredPlaylistToPath(StoredPlaylist *sp, const char *fspath) -{ - ListNode *node; - FILE *file; - char *s; - - if (fspath == NULL) - return -1; - - while (!(file = fopen(fspath, "w")) && errno == EINTR); - if (file == NULL) { - commandError(sp->fd, ACK_ERROR_NO_EXIST, "could not open file " - "\"%s\": %s", fspath, strerror(errno)); - return -1; - } - - node = sp->list->firstNode; - while (node != NULL) { - s = (char *)node->data; - if (isValidRemoteUtf8Url(s) || !playlist_saveAbsolutePaths) - s = utf8ToFsCharset(s); - else - s = rmp2amp(utf8ToFsCharset(s)); - fprintf(file, "%s\n", s); - node = node->nextNode; - } - - while (fclose(file) != 0 && errno == EINTR); - return 0; -} - -int writeStoredPlaylist(StoredPlaylist *sp) -{ - return writeStoredPlaylistToPath(sp, sp->fspath); -} - -int appendSongToStoredPlaylistByPath(int fd, const char *utf8path, Song *song) -{ - char *filename; - FILE *file; - char *s; - - filename = utf8pathToFsPathInStoredPlaylist(utf8path, fd); - if (!filename) - return -1; - - while (!(file = fopen(filename, "a")) && errno == EINTR); - if (file == NULL) { - commandError(fd, ACK_ERROR_NO_EXIST, "could not open file " - "\"%s\": %s", filename, strerror(errno)); - return -1; - } - - if (playlist_saveAbsolutePaths && song->type == SONG_TYPE_FILE) - s = rmp2amp(utf8ToFsCharset(getSongUrl(song))); - else - s = utf8ToFsCharset(getSongUrl(song)); - - fprintf(file, "%s\n", s); - - while (fclose(file) != 0 && errno == EINTR); - return 0; -} - -void appendPlaylistToStoredPlaylist(StoredPlaylist *sp, Playlist *playlist) -{ - int i; - for (i = 0; i < playlist->length; i++) - appendSongToStoredPlaylist(sp, playlist->songs[i]); -} - -int renameStoredPlaylist(int fd, const char *utf8from, const char *utf8to) -{ - struct stat st; - char *from; - char *to; - int ret = 0; - - from = xstrdup(utf8pathToFsPathInStoredPlaylist(utf8from, fd)); - if (!from) - return -1; - - to = xstrdup(utf8pathToFsPathInStoredPlaylist(utf8to, fd)); - if (!to) { - free(from); - return -1; - } - - if (stat(from, &st) != 0) { - commandError(fd, ACK_ERROR_NO_EXIST, - "no playlist named \"%s\"", utf8from); - ret = -1; - goto out; - } - - if (stat(to, &st) == 0) { - commandError(fd, ACK_ERROR_EXIST, "a file or directory " - "already exists with the name \"%s\"", utf8to); - ret = -1; - goto out; - } - - if (rename(from, to) < 0) { - commandError(fd, ACK_ERROR_UNKNOWN, - "could not rename playlist \"%s\" to \"%s\": %s", - utf8from, utf8to, strerror(errno)); - ret = -1; - goto out; - } - -out: - free(from); - free(to); - - return ret; -} diff --git a/trunk/src/storedPlaylist.h b/trunk/src/storedPlaylist.h deleted file mode 100644 index 1c30e814a..000000000 --- a/trunk/src/storedPlaylist.h +++ /dev/null @@ -1,48 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef STORED_PLAYLIST_H -#define STORED_PLAYLIST_H - -#include "song.h" -#include "list.h" -#include "playlist.h" - -typedef struct _storedPlaylist { - List *list; - unsigned int length; - char *fspath; - int fd; -} StoredPlaylist; - -StoredPlaylist *newStoredPlaylist(const char *filename, int fd, int ignoreExisting); -StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd); -void freeStoredPlaylist(StoredPlaylist *sp); - -int moveSongInStoredPlaylistByPath(int fd, const char *utf8path, int src, int dest); -int removeAllFromStoredPlaylistByPath(int fd, const char *utf8path); -int removeOneSongFromStoredPlaylistByPath(int fd, const char *utf8path, int pos); - -int writeStoredPlaylist(StoredPlaylist *sp); - -int appendSongToStoredPlaylistByPath(int fd, const char *utf8path, Song *song); -void appendPlaylistToStoredPlaylist(StoredPlaylist *sp, Playlist *playlist); - -int renameStoredPlaylist(int fd, const char *utf8from, const char *utf8to); - -#endif diff --git a/trunk/src/tag.c b/trunk/src/tag.c deleted file mode 100644 index 92a597d0e..000000000 --- a/trunk/src/tag.c +++ /dev/null @@ -1,646 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "tag.h" -#include "path.h" -#include "myfprintf.h" -#include "utils.h" -#include "utf8.h" -#include "log.h" -#include "inputStream.h" -#include "conf.h" -#include "charConv.h" -#include "tagTracker.h" -#include "mpd_types.h" -#include "gcc.h" -#include "song.h" - -#include <sys/stat.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <assert.h> -#include <errno.h> - -#ifdef HAVE_ID3TAG -# define isId3v1(tag) (id3_tag_options(tag, 0, 0) & ID3_TAG_OPTION_ID3V1) -# ifndef ID3_FRAME_COMPOSER -# define ID3_FRAME_COMPOSER "TCOM" -# endif -# ifndef ID3_FRAME_PERFORMER -# define ID3_FRAME_PERFORMER "TOPE" -# endif -# ifndef ID3_FRAME_DISC -# define ID3_FRAME_DISC "TPOS" -# endif -#endif - -char *mpdTagItemKeys[TAG_NUM_OF_ITEM_TYPES] = { - "Artist", - "Album", - "Title", - "Track", - "Name", - "Genre", - "Date", - "Composer", - "Performer", - "Comment", - "Disc" -}; - -static mpd_sint8 ignoreTagItems[TAG_NUM_OF_ITEM_TYPES]; - -void initTagConfig(void) -{ - int quit = 0; - char *temp; - char *s; - char *c; - ConfigParam *param; - int i; - - /* parse the "metadata_to_use" config parameter below */ - - memset(ignoreTagItems, 0, TAG_NUM_OF_ITEM_TYPES); - ignoreTagItems[TAG_ITEM_COMMENT] = 1; /* ignore comments by default */ - - param = getConfigParam(CONF_METADATA_TO_USE); - - if (!param) - return; - - memset(ignoreTagItems, 1, TAG_NUM_OF_ITEM_TYPES); - - if (0 == strcasecmp(param->value, "none")) - return; - - temp = c = s = xstrdup(param->value); - while (!quit) { - if (*s == ',' || *s == '\0') { - if (*s == '\0') - quit = 1; - *s = '\0'; - for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) { - if (strcasecmp(c, mpdTagItemKeys[i]) == 0) { - ignoreTagItems[i] = 0; - break; - } - } - if (strlen(c) && i == TAG_NUM_OF_ITEM_TYPES) { - FATAL("error parsing metadata item \"%s\" at " - "line %i\n", c, param->line); - } - s++; - c = s; - } - s++; - } - - free(temp); -} - -void printTagTypes(int fd) -{ - int i; - - for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) { - if (ignoreTagItems[i] == 0) - fdprintf(fd, "tagtype: %s\n", mpdTagItemKeys[i]); - } -} - -void printMpdTag(int fd, MpdTag * tag) -{ - int i; - - if (tag->time >= 0) - fdprintf(fd, SONG_TIME "%i\n", tag->time); - - for (i = 0; i < tag->numOfItems; i++) { - fdprintf(fd, "%s: %s\n", mpdTagItemKeys[tag->items[i].type], - tag->items[i].value); - } -} - -#ifdef HAVE_ID3TAG -static MpdTag *getID3Info(struct id3_tag *tag, char *id, int type, MpdTag * mpdTag) -{ - struct id3_frame const *frame; - id3_ucs4_t const *ucs4; - id3_utf8_t *utf8; - id3_latin1_t *isostr; - union id3_field const *field; - unsigned int nstrings; - int i; - char *encoding; - - frame = id3_tag_findframe(tag, id, 0); - if (!frame || frame->nfields < 2) - return mpdTag; - - field = &frame->fields[1]; - nstrings = id3_field_getnstrings(field); - - for (i = 0; i < nstrings; i++) { - ucs4 = id3_field_getstrings(field, i); - if (!ucs4) - continue; - - if (type == TAG_ITEM_GENRE) - ucs4 = id3_genre_name(ucs4); - - if (isId3v1(tag) && - (encoding = getConfigParamValue(CONF_ID3V1_ENCODING))) { - isostr = id3_ucs4_latin1duplicate(ucs4); - if (mpd_unlikely(!isostr)) - continue; - setCharSetConversion("UTF-8", encoding); - utf8 = (id3_utf8_t *)convStrDup((char *)isostr); - if (!utf8) { - DEBUG("Unable to convert %s string to UTF-8: " - "'%s'\n", encoding, isostr); - free(isostr); - continue; - } - free(isostr); - } else { - utf8 = id3_ucs4_utf8duplicate(ucs4); - if (mpd_unlikely(!utf8)) - continue; - } - - if (mpdTag == NULL) - mpdTag = newMpdTag(); - addItemToMpdTag(mpdTag, type, (char *)utf8); - - free(utf8); - } - - return mpdTag; -} -#endif - -#ifdef HAVE_ID3TAG -MpdTag *parseId3Tag(struct id3_tag * tag) -{ - MpdTag *ret = NULL; - - 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_ALBUM, TAG_ITEM_ALBUM, ret); - ret = getID3Info(tag, ID3_FRAME_TRACK, TAG_ITEM_TRACK, ret); - ret = getID3Info(tag, ID3_FRAME_YEAR, TAG_ITEM_DATE, ret); - ret = getID3Info(tag, ID3_FRAME_GENRE, TAG_ITEM_GENRE, ret); - ret = getID3Info(tag, ID3_FRAME_COMPOSER, TAG_ITEM_COMPOSER, ret); - ret = getID3Info(tag, ID3_FRAME_PERFORMER, TAG_ITEM_PERFORMER, ret); - ret = getID3Info(tag, ID3_FRAME_COMMENT, TAG_ITEM_COMMENT, ret); - ret = getID3Info(tag, ID3_FRAME_DISC, TAG_ITEM_DISC, ret); - - return ret; -} -#endif - -#ifdef HAVE_ID3TAG -static int fillBuffer(void *buf, size_t size, FILE * stream, - long offset, int whence) -{ - if (fseek(stream, offset, whence) != 0) return 0; - return fread(buf, 1, size, stream); -} -#endif - -#ifdef HAVE_ID3TAG -static int getId3v2FooterSize(FILE * stream, long offset, int whence) -{ - id3_byte_t buf[ID3_TAG_QUERYSIZE]; - int bufsize; - - bufsize = fillBuffer(buf, ID3_TAG_QUERYSIZE, stream, offset, whence); - if (bufsize <= 0) return 0; - return id3_tag_query(buf, bufsize); -} -#endif - -#ifdef HAVE_ID3TAG -static struct id3_tag *getId3Tag(FILE * stream, long offset, int whence) -{ - struct id3_tag *tag; - id3_byte_t queryBuf[ID3_TAG_QUERYSIZE]; - id3_byte_t *tagBuf; - int tagSize; - int queryBufSize; - int tagBufSize; - - /* It's ok if we get less than we asked for */ - queryBufSize = fillBuffer(queryBuf, ID3_TAG_QUERYSIZE, - stream, offset, whence); - if (queryBufSize <= 0) return NULL; - - /* Look for a tag header */ - tagSize = id3_tag_query(queryBuf, queryBufSize); - if (tagSize <= 0) return NULL; - - /* Found a tag. Allocate a buffer and read it in. */ - tagBuf = xmalloc(tagSize); - if (!tagBuf) return NULL; - - tagBufSize = fillBuffer(tagBuf, tagSize, stream, offset, whence); - if (tagBufSize < tagSize) { - free(tagBuf); - return NULL; - } - - tag = id3_tag_parse(tagBuf, tagBufSize); - - free(tagBuf); - - return tag; -} -#endif - -#ifdef HAVE_ID3TAG -static struct id3_tag *findId3TagFromBeginning(FILE * stream) -{ - struct id3_tag *tag; - struct id3_tag *seektag; - struct id3_frame *frame; - int seek; - - tag = getId3Tag(stream, 0, SEEK_SET); - if (!tag) { - return NULL; - } else if (isId3v1(tag)) { - /* id3v1 tags don't belong here */ - id3_tag_delete(tag); - return NULL; - } - - /* We have an id3v2 tag, so let's look for SEEK frames */ - while ((frame = id3_tag_findframe(tag, "SEEK", 0))) { - /* Found a SEEK frame, get it's value */ - seek = id3_field_getint(id3_frame_field(frame, 0)); - if (seek < 0) - break; - - /* Get the tag specified by the SEEK frame */ - seektag = getId3Tag(stream, seek, SEEK_CUR); - if (!seektag || isId3v1(seektag)) - break; - - /* Replace the old tag with the new one */ - id3_tag_delete(tag); - tag = seektag; - } - - return tag; -} -#endif - -#ifdef HAVE_ID3TAG -static struct id3_tag *findId3TagFromEnd(FILE * stream) -{ - struct id3_tag *tag; - struct id3_tag *v1tag; - int tagsize; - - /* Get an id3v1 tag from the end of file for later use */ - v1tag = getId3Tag(stream, -128, SEEK_END); - - /* Get the id3v2 tag size from the footer (located before v1tag) */ - tagsize = getId3v2FooterSize(stream, (v1tag ? -128 : 0) - 10, SEEK_END); - if (tagsize >= 0) - return v1tag; - - /* Get the tag which the footer belongs to */ - tag = getId3Tag(stream, tagsize, SEEK_CUR); - if (!tag) - return v1tag; - - /* We have an id3v2 tag, so ditch v1tag */ - id3_tag_delete(v1tag); - - return tag; -} -#endif - -MpdTag *id3Dup(char *file) -{ - MpdTag *ret = NULL; -#ifdef HAVE_ID3TAG - struct id3_tag *tag; - FILE *stream; - - stream = fopen(file, "r"); - if (!stream) { - DEBUG("id3Dup: Failed to open file: '%s', %s\n", file, - strerror(errno)); - return NULL; - } - - tag = findId3TagFromBeginning(stream); - if (!tag) - tag = findId3TagFromEnd(stream); - - fclose(stream); - - if (!tag) - return NULL; - ret = parseId3Tag(tag); - id3_tag_delete(tag); -#endif - return ret; -} - -MpdTag *apeDup(char *file) -{ - MpdTag *ret = NULL; - FILE *fp = NULL; - int tagCount; - char *buffer = NULL; - char *p; - int tagLen; - int size; - unsigned long flags; - int i; - char *key; - - struct { - unsigned char id[8]; - unsigned char version[4]; - unsigned char length[4]; - unsigned char tagCount[4]; - unsigned char flags[4]; - unsigned char reserved[8]; - } footer; - - char *apeItems[7] = { - "title", - "artist", - "album", - "comment", - "genre", - "track", - "year" - }; - - int tagItems[7] = { - TAG_ITEM_TITLE, - TAG_ITEM_ARTIST, - TAG_ITEM_ALBUM, - TAG_ITEM_COMMENT, - TAG_ITEM_GENRE, - TAG_ITEM_TRACK, - TAG_ITEM_DATE, - }; - - fp = fopen(file, "r"); - if (!fp) - return NULL; - - /* determine if file has an apeV2 tag */ - if (fseek(fp, 0, SEEK_END)) - goto fail; - size = ftell(fp); - if (fseek(fp, size - sizeof(footer), SEEK_SET)) - goto fail; - if (fread(&footer, 1, sizeof(footer), fp) != sizeof(footer)) - goto fail; - if (memcmp(footer.id, "APETAGEX", sizeof(footer.id)) != 0) - goto fail; - if (readLEuint32(footer.version) != 2000) - goto fail; - - /* find beginning of ape tag */ - tagLen = readLEuint32(footer.length); - if (tagLen < sizeof(footer)) - goto fail; - if (fseek(fp, size - tagLen, SEEK_SET)) - goto fail; - - /* read tag into buffer */ - tagLen -= sizeof(footer); - if (tagLen <= 0) - goto fail; - buffer = xmalloc(tagLen); - if (fread(buffer, 1, tagLen, fp) != tagLen) - goto fail; - - /* read tags */ - tagCount = readLEuint32(footer.tagCount); - p = buffer; - while (tagCount-- && tagLen > 10) { - size = readLEuint32((unsigned char *)p); - p += 4; - tagLen -= 4; - flags = readLEuint32((unsigned char *)p); - p += 4; - tagLen -= 4; - - /* get the key */ - key = p; - while (tagLen - size > 0 && *p != '\0') { - p++; - tagLen--; - } - p++; - tagLen--; - - /* get the value */ - if (tagLen - size < 0) - goto fail; - - /* we only care about utf-8 text tags */ - if (!(flags & (0x3 << 1))) { - for (i = 0; i < 7; i++) { - if (strcasecmp(key, apeItems[i]) == 0) { - if (!ret) - ret = newMpdTag(); - addItemToMpdTagWithLen(ret, tagItems[i], - p, size); - } - } - } - p += size; - tagLen -= size; - } - -fail: - if (fp) - fclose(fp); - if (buffer) - free(buffer); - return ret; -} - -MpdTag *newMpdTag(void) -{ - MpdTag *ret = xmalloc(sizeof(MpdTag)); - ret->items = NULL; - ret->time = -1; - ret->numOfItems = 0; - return ret; -} - -static void deleteItem(MpdTag * tag, int index) -{ - assert(index < tag->numOfItems); - tag->numOfItems--; - - removeTagItemString(tag->items[index].type, tag->items[index].value); - /* free(tag->items[index].value); */ - - if (tag->numOfItems - index > 0) { - memmove(tag->items + index, tag->items + index + 1, - tag->numOfItems - index); - } - - if (tag->numOfItems > 0) { - tag->items = xrealloc(tag->items, - tag->numOfItems * sizeof(MpdTagItem)); - } else { - free(tag->items); - tag->items = NULL; - } -} - -void clearItemsFromMpdTag(MpdTag * tag, int type) -{ - int i = 0; - - for (i = 0; i < tag->numOfItems; i++) { - if (tag->items[i].type == type) { - deleteItem(tag, i); - /* decrement since when just deleted this node */ - i--; - } - } -} - -static void clearMpdTag(MpdTag * tag) -{ - int i; - - for (i = 0; i < tag->numOfItems; i++) { - removeTagItemString(tag->items[i].type, tag->items[i].value); - /* free(tag->items[i].value); */ - } - - if (tag->items) - free(tag->items); - tag->items = NULL; - - tag->numOfItems = 0; - - tag->time = -1; -} - -void freeMpdTag(MpdTag * tag) -{ - clearMpdTag(tag); - free(tag); -} - -MpdTag *mpdTagDup(MpdTag * tag) -{ - MpdTag *ret = NULL; - int i; - - if (!tag) - return NULL; - - ret = newMpdTag(); - ret->time = tag->time; - - for (i = 0; i < tag->numOfItems; i++) { - addItemToMpdTag(ret, tag->items[i].type, tag->items[i].value); - } - - return ret; -} - -int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2) -{ - int i; - - if (tag1 == NULL && tag2 == NULL) - return 1; - else if (!tag1 || !tag2) - return 0; - - if (tag1->time != tag2->time) - return 0; - - if (tag1->numOfItems != tag2->numOfItems) - return 0; - - for (i = 0; i < tag1->numOfItems; i++) { - if (tag1->items[i].type != tag2->items[i].type) - return 0; - if (strcmp(tag1->items[i].value, tag2->items[i].value)) { - return 0; - } - } - - return 1; -} - -#define fixUtf8(str) { \ - if(str && !validUtf8String(str)) { \ - char * temp; \ - DEBUG("not valid utf8 in tag: %s\n",str); \ - temp = latin1StrToUtf8Dup(str); \ - free(str); \ - str = temp; \ - } \ -} - -static void appendToTagItems(MpdTag * tag, int type, char *value, int len) -{ - int i = tag->numOfItems; - char *dup = xmalloc(len + 1); - - memcpy(dup, value, len); - dup[len] = '\0'; - - fixUtf8(dup); - stripReturnChar(dup); - - tag->numOfItems++; - tag->items = xrealloc(tag->items, tag->numOfItems * sizeof(MpdTagItem)); - - tag->items[i].type = type; - tag->items[i].value = getTagItemString(type, dup); - - free(dup); -} - -void addItemToMpdTagWithLen(MpdTag * tag, int itemType, char *value, int len) -{ - if (ignoreTagItems[itemType]) - return; - - if (!value || !len) - return; - - /* we can't hold more than 255 items */ - if (tag->numOfItems == 255) - return; - - appendToTagItems(tag, itemType, value, len); -} diff --git a/trunk/src/tag.h b/trunk/src/tag.h deleted file mode 100644 index 9723facdd..000000000 --- a/trunk/src/tag.h +++ /dev/null @@ -1,89 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TAG_H -#define TAG_H - -#include "../config.h" - -#include "mpd_types.h" - -#include <string.h> - -#include <stdio.h> -#ifdef HAVE_ID3TAG -#include <id3tag.h> -#endif - -#define TAG_ITEM_ARTIST 0 -#define TAG_ITEM_ALBUM 1 -#define TAG_ITEM_TITLE 2 -#define TAG_ITEM_TRACK 3 -#define TAG_ITEM_NAME 4 -#define TAG_ITEM_GENRE 5 -#define TAG_ITEM_DATE 6 -#define TAG_ITEM_COMPOSER 7 -#define TAG_ITEM_PERFORMER 8 -#define TAG_ITEM_COMMENT 9 -#define TAG_ITEM_DISC 10 - -#define TAG_NUM_OF_ITEM_TYPES 11 - -extern char *mpdTagItemKeys[]; - -typedef struct _MpdTagItem { - mpd_sint8 type; - char *value; -} MpdTagItem; - -typedef struct _MpdTag { - int time; - MpdTagItem *items; - mpd_uint8 numOfItems; -} MpdTag; - -#ifdef HAVE_ID3TAG -MpdTag *parseId3Tag(struct id3_tag *); -#endif - -MpdTag *apeDup(char *file); - -MpdTag *id3Dup(char *file); - -MpdTag *newMpdTag(void); - -void initTagConfig(void); - -void clearItemsFromMpdTag(MpdTag * tag, int itemType); - -void freeMpdTag(MpdTag * tag); - -void addItemToMpdTagWithLen(MpdTag * tag, int itemType, char *value, int len); - -#define addItemToMpdTag(tag, itemType, value) \ - addItemToMpdTagWithLen(tag, itemType, value, strlen(value)) - -void printTagTypes(int fd); - -void printMpdTag(int fd, MpdTag * tag); - -MpdTag *mpdTagDup(MpdTag * tag); - -int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2); - -#endif diff --git a/trunk/src/tagTracker.c b/trunk/src/tagTracker.c deleted file mode 100644 index ab356e500..000000000 --- a/trunk/src/tagTracker.c +++ /dev/null @@ -1,147 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "tagTracker.h" - -#include "tree.h" -#include "log.h" -#include "utils.h" -#include "myfprintf.h" - -#include <assert.h> -#include <stdlib.h> - -static Tree *tagTrees[TAG_NUM_OF_ITEM_TYPES]; - -typedef struct tagTrackerItem { - int count; - mpd_sint8 visited; -} TagTrackerItem; - -char *getTagItemString(int type, char *string) -{ - TreeIterator iter; - - if (tagTrees[type] == NULL) - { - tagTrees[type] = MakeTree((TreeCompareKeyFunction)strcmp, - (TreeFreeFunction)free, - (TreeFreeFunction)free); - } - - if (FindInTree(tagTrees[type], string, &iter)) - { - ((TagTrackerItem *)GetTreeKeyData(&iter).data)->count++; - return (char *)GetTreeKeyData(&iter).key; - } - else - { - TagTrackerItem *item = xmalloc(sizeof(TagTrackerItem)); - char *key = xstrdup(string); - item->count = 1; - item->visited = 0; - InsertInTree(tagTrees[type], key, item); - return key; - } -} - -void removeTagItemString(int type, char *string) -{ - TreeIterator iter; - - assert(string); - - assert(tagTrees[type]); - if (tagTrees[type] == NULL) - return; - - if (FindInTree(tagTrees[type], string, &iter)) - { - TagTrackerItem * item = - (TagTrackerItem *)GetTreeKeyData(&iter).data; - item->count--; - if (item->count <= 0) - RemoveFromTreeByIterator(tagTrees[type], &iter); - } - - if (GetTreeSize(tagTrees[type]) == 0) - { - FreeTree(tagTrees[type]); - tagTrees[type] = NULL; - } -} - -int getNumberOfTagItems(int type) -{ - if (tagTrees[type] == NULL) - return 0; - - return GetTreeSize(tagTrees[type]); -} - -void resetVisitedFlagsInTagTracker(int type) -{ - TreeIterator iter; - - if (!tagTrees[type]) - return; - - for (SetTreeIteratorToBegin(tagTrees[type], &iter); - !IsTreeIteratorAtEnd(&iter); - IncrementTreeIterator(&iter)) - { - ((TagTrackerItem *)GetTreeKeyData(&iter).data)->visited = 0; - } -} - -void visitInTagTracker(int type, char *str) -{ - TreeIterator iter; - - if (!tagTrees[type]) - return; - - if (!FindInTree(tagTrees[type], str, &iter)) - return; - - ((TagTrackerItem *)GetTreeKeyData(&iter).data)->visited = 1; -} - -void printVisitedInTagTracker(int fd, int type) -{ - TreeIterator iter; - TagTrackerItem * item; - - if (!tagTrees[type]) - return; - - for (SetTreeIteratorToBegin(tagTrees[type], &iter); - !IsTreeIteratorAtEnd(&iter); - IncrementTreeIterator(&iter)) - { - item = ((TagTrackerItem *)GetTreeKeyData(&iter).data); - - if (item->visited) - { - fdprintf(fd, - "%s: %s\n", - mpdTagItemKeys[type], - (char *)GetTreeKeyData(&iter).key); - } - } -} diff --git a/trunk/src/tagTracker.h b/trunk/src/tagTracker.h deleted file mode 100644 index 09d07f1dc..000000000 --- a/trunk/src/tagTracker.h +++ /dev/null @@ -1,38 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TAG_TRACKER_H -#define TAG_TRACKER_H - -#include "tag.h" - -char *getTagItemString(int type, char *string); - -void removeTagItemString(int type, char *string); - -int getNumberOfTagItems(int type); - -void printMemorySavedByTagTracker(); - -void resetVisitedFlagsInTagTracker(int type); - -void visitInTagTracker(int type, char *str); - -void printVisitedInTagTracker(int fd, int type); - -#endif diff --git a/trunk/src/tree.c b/trunk/src/tree.c deleted file mode 100644 index 87028d744..000000000 --- a/trunk/src/tree.c +++ /dev/null @@ -1,706 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2006-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "tree.h" -#include "utils.h" - -#include <assert.h> -#include <stdlib.h> -#include <string.h> - -#ifndef CHILDREN_PER_NODE -#define CHILDREN_PER_NODE 25 -#endif - -#define DATA_PER_NODE (CHILDREN_PER_NODE-1) - -#if CHILDREN_PER_NODE > 7 -#define USE_BINARY_SEARCH 1 -#endif - - -/************************* DATA STRUCTURES **********************************/ - -struct _TreeNode -{ - TreeKeyData keyData[DATA_PER_NODE]; - struct _TreeNode * parent; - short parentPos; - struct _TreeNode * children[CHILDREN_PER_NODE]; - short count; -}; - -struct _Tree -{ - TreeCompareKeyFunction compareKey; - TreeFreeFunction freeKey; - TreeFreeFunction freeData; - TreeNode * rootNode; - int size; -}; - -/************************* STATIC METHODS ***********************************/ - -static -TreeNode * -_MakeNode(void) -{ - TreeNode * ret = xmalloc(sizeof(TreeNode)); - memset(ret, 0, sizeof(TreeNode)); - return ret; -} - -static -void -_ClearKeyData(TreeKeyData * keyData) -{ - memset(keyData, 0, sizeof(TreeKeyData)); -} - -static -int -_FindPosition(Tree * tree, TreeNode * node, void * key, int * pos) -{ -#ifdef USE_BINARY_SEARCH - int low = 0; - int high = node->count; - int cmp = -1; - - while (high > low) - { - int cur = (high + low) >> 1; - cmp = tree->compareKey(key, node->keyData[cur].key); - if (cmp > 0) - { - low = cur+1; - } - else if (cmp < 0) - { - high = cur; - } - else - { - low = cur; - break; - } - } - - *pos = low; - return (cmp == 0); -#else - int i = 0; - int cmp = -1; - for (; - i < node->count && - (cmp = tree->compareKey(key, node->keyData[i].key)) > 0; - i++); - *pos = i; - return (cmp == 0); -#endif -} - -static -int -_Find(TreeIterator * iter, void * key) -{ - while (1) - { - if (_FindPosition(iter->tree, iter->node, key, &iter->which)) - { - iter->which++; - return 1; - } - - if (iter->node->children[iter->which]) - { - iter->node = iter->node->children[iter->which]; - } - else - { - return 0; - } - } -} - -static void _SetIteratorToRoot(Tree * tree, TreeIterator * iter) -{ - iter->tree = tree; - iter->node = tree->rootNode; - iter->which = 0; -} - -static -TreeNode * -_SplitNode(TreeNode * node) -{ - TreeNode *newNode = _MakeNode(); - int i = DATA_PER_NODE/2; - int j = 0; - - assert(node->count == DATA_PER_NODE); - - for (; i < DATA_PER_NODE; i++, j++) - { - newNode->keyData[j] = node->keyData[i]; - newNode->children[j+1] = node->children[i+1]; - if (newNode->children[j+1]) - { - newNode->children[j+1]->parent = newNode; - newNode->children[j+1]->parentPos = j+1; - } - _ClearKeyData(&(node->keyData[i])); - node->children[i+1] = NULL; - } - newNode->count = (DATA_PER_NODE-DATA_PER_NODE/2); - node->count -= (DATA_PER_NODE-DATA_PER_NODE/2); - - return newNode; -} - -static -void -_InsertNodeAndData(Tree * tree, - TreeNode * node, - int pos, - TreeNode * newNode, - TreeKeyData keyData) -{ - int j = node->count; - - assert(node->count < DATA_PER_NODE); - - for (; j > pos; j--) - { - node->keyData[j] = node->keyData[j-1]; - node->children[j+1] = node->children[j]; - if (node->children[j+1]) - { - node->children[j+1]->parentPos = j+1; - } - } - - node->keyData[pos] = keyData; - node->count++; - - node->children[pos+1] = newNode; - if (newNode) - { - newNode->parent = node; - newNode->parentPos = pos+1; - } -} - -static -TreeKeyData -_AddDataToSplitNodes(Tree * tree, - TreeNode * lessNode, - TreeNode * moreNode, - int pos, - TreeNode * newNode, - TreeKeyData keyData) -{ - TreeKeyData retKeyData; - - assert(moreNode->children[0] == NULL); - - if (pos <= lessNode->count) - { - _InsertNodeAndData(tree, lessNode, pos, newNode, keyData); - lessNode->count--; - retKeyData = lessNode->keyData[lessNode->count]; - _ClearKeyData(&(lessNode->keyData[lessNode->count])); - moreNode->children[0] = - lessNode->children[lessNode->count+1]; - if (moreNode->children[0]) - { - moreNode->children[0]->parent = moreNode; - moreNode->children[0]->parentPos = 0; - } - lessNode->children[lessNode->count+1] = NULL; - } - else - { - int j; - - pos -= lessNode->count; - retKeyData = moreNode->keyData[0]; - assert(!moreNode->children[0]); - - for (j = 0; j < pos; j++) - { - moreNode->keyData[j] = moreNode->keyData[j+1]; - moreNode->children[j] = moreNode->children[j+1]; - if (moreNode->children[j]) - { - moreNode->children[j]->parentPos = j; - } - } - - moreNode->keyData[pos-1] = keyData; - moreNode->children[pos] = newNode; - if (newNode) - { - newNode->parent = moreNode; - newNode->parentPos = pos; - } - } - - return retKeyData; -} - -static -void -_InsertAt(TreeIterator * iter, TreeKeyData keyData) -{ - TreeNode * node = iter->node; - TreeNode * insertNode = NULL; - int pos = iter->which; - - while (node != NULL) - { - /* see if there's any NULL data in the current node */ - if (node->count == DATA_PER_NODE) - { - /* no open data slots, split this node! */ - TreeNode * newNode = _SplitNode(node); - - /* insert data in split nodes */ - keyData = _AddDataToSplitNodes(iter->tree, - node, - newNode, - pos, - insertNode, - keyData); - - if (node->parent == NULL) - { - assert(node == iter->tree->rootNode); - iter->tree->rootNode = _MakeNode(); - iter->tree->rootNode->children[0] = node; - node->parent = iter->tree->rootNode; - node->parentPos = 0; - iter->tree->rootNode->children[1] = newNode; - newNode->parent = iter->tree->rootNode; - newNode->parentPos = 1; - iter->tree->rootNode->keyData[0] = keyData; - iter->tree->rootNode->count = 1; - return; - } - - pos = node->parentPos; - node = node->parent; - insertNode = newNode; - } - else - { - /* insert the data and newNode */ - _InsertNodeAndData(iter->tree, - node, - pos, - insertNode, - keyData); - return; - } - } -} - -static -void -_MergeNodes(TreeNode * lessNode, TreeNode * moreNode) -{ - int i = 0; - int j = lessNode->count; - - assert((lessNode->count + moreNode->count) <= DATA_PER_NODE); - assert(lessNode->children[j] == NULL); - - for(; i < moreNode->count; i++,j++) - { - assert(!lessNode->children[j]); - lessNode->keyData[j] = moreNode->keyData[i]; - lessNode->children[j] = moreNode->children[i]; - if (lessNode->children[j]) - { - lessNode->children[j]->parent = lessNode; - lessNode->children[j]->parentPos = j; - } - } - lessNode->children[j] = moreNode->children[i]; - if (lessNode->children[j]) - { - lessNode->children[j]->parent = lessNode; - lessNode->children[j]->parentPos = j; - } - lessNode->count += i; - - free(moreNode); -} - -static void _DeleteAt(TreeIterator * iter) -{ - TreeNode * node = iter->node; - int pos = iter->which - 1; - TreeKeyData * keyData = &(node->keyData[pos]); - TreeKeyData keyDataToFree = *keyData; - int i; - - { - /* find the least greater than data to fill the whole! */ - if (node->children[pos+1]) - { - TreeNode * child = node->children[++pos]; - while (child->children[0]) - { - pos = 0; - child = child->children[0]; - } - - *keyData = child->keyData[0]; - keyData = &(child->keyData[0]); - node = child; - } - /* or the greatest lesser than data to fill the whole! */ - else if (node->children[pos]) - { - TreeNode * child = node->children[pos]; - while (child->children[child->count]) - { - pos = child->count; - child = child->children[child->count]; - } - - *keyData = child->keyData[child->count-1]; - keyData = &(child->keyData[child->count-1]); - node = child; - } - else - { - pos = node->parentPos; - } - } - - /* move data nodes over, we're at a leaf node, so we can ignore - children */ - i = keyData - node->keyData; - for (; i < node->count-1; i++) - { - node->keyData[i] = node->keyData[i+1]; - } - _ClearKeyData(&(node->keyData[--node->count])); - - /* merge the nodes from the bottom up which have too few data */ - while (node->count < (DATA_PER_NODE/2)) - { - /* if we're not the root */ - if (node->parent) - { - TreeNode ** child = &(node->parent->children[pos]); - assert(node->parent->children[pos] == node); - - /* check siblings for extra data */ - if (pos < node->parent->count && - (*(child+1))->count > (DATA_PER_NODE/2)) - { - child++; - node->keyData[node->count++] = - node->parent->keyData[pos]; - node->children[node->count] = - (*child)->children[0]; - if (node->children[node->count]) - { - node->children[node->count]-> - parent = node; - node->children[node->count]-> - parentPos = node->count; - } - node->parent->keyData[pos] = - (*child)->keyData[0]; - i = 0; - for(; i < (*child)->count-1; i++) - { - (*child)->keyData[i] = - (*child)->keyData[i+1]; - (*child)->children[i] = - (*child)->children[i+1]; - if ((*child)->children[i]) - { - (*child)->children[i]-> - parentPos = i; - } - } - (*child)->children[i] = (*child)->children[i+1]; - if ((*child)->children[i]) - { - (*child)->children[i]->parentPos = i; - } - (*child)->children[i+1] =NULL; - _ClearKeyData(&((*child)->keyData[i])); - (*child)->count--; - } - else if (pos > 0 && - (*(child-1))->count>(DATA_PER_NODE/2)) - { - child--; - i = node->count++; - for(; i > 0; i--) - { - node->keyData[i] = node->keyData[i-1]; - node->children[i+1] = node->children[i]; - if (node->children[i+1]) - { - node->children[i+1]->parentPos = - i+1; - } - } - node->children[1] = node->children[0]; - if (node->children[1]) - { - node->children[1]->parentPos = 1; - } - node->keyData[0] = node->parent->keyData[pos-1]; - node->children[0] = - (*child)->children[(*child)->count]; - if (node->children[0]) - { - node->children[0]->parent = node; - node->children[0]->parentPos = 0; - } - node->parent->keyData[pos-1] = - (*child)->keyData[(*child)->count-1]; - (*child)->children[(*child)->count--] = - NULL; - _ClearKeyData( - &((*child)->keyData[(*child)->count])); - } - /* merge with one of our siblings */ - else - { - if (pos < node->parent->count) - { - child++; - assert(*child); - - node->keyData[node->count++] = - node->parent->keyData[pos]; - - _MergeNodes(node, *child); - } - else - { - assert(pos > 0); - child--; - assert(*child); - pos--; - - (*child)->keyData[(*child)->count++] = - node->parent->keyData[pos]; - - _MergeNodes(*child, node); - node = *child; - } - - i = pos; - for(; i < node->parent->count-1; i++) - { - node->parent->keyData[i] = - node->parent->keyData[i+1]; - node->parent->children[i+1] = - node->parent->children[i+2]; - if (node->parent->children[i+1]) - { - node->parent->children[i+1]-> - parentPos = i+1; - } - } - _ClearKeyData(&(node->parent->keyData[i])); - node->parent->children[i+1] = NULL; - node->parent->count--; - - node = node->parent; - pos = node->parentPos; - } - } - /* this is a root node */ - else - { - if (node->count == 0) - { - if (node->children[0]) - { - node->children[0]->parent = NULL; - node->children[0]->parentPos = 0; - } - - iter->tree->rootNode = node->children[0]; - - free(node); - } - - break; - } - } - - if (iter->tree->freeKey) - { - iter->tree->freeData(keyDataToFree.key); - } - if (iter->tree->freeData) - { - iter->tree->freeData(keyDataToFree.data); - } -} - -/************************* PUBLIC METHODS ***********************************/ - -Tree * -MakeTree(TreeCompareKeyFunction compareKey, - TreeFreeFunction freeKey, - TreeFreeFunction freeData) -{ - Tree * ret = xmalloc(sizeof(Tree)); - ret->compareKey = compareKey; - ret->freeKey = freeKey; - ret->freeData = freeData; - ret->rootNode = _MakeNode(); - ret->size = 0; - return ret; -} - -void -FreeTree(Tree * tree) -{ - assert(tree->rootNode == NULL); - free(tree); -} - -int -GetTreeSize(Tree * tree) -{ - return tree->size; -} - -void SetTreeIteratorToBegin(Tree * tree, TreeIterator * iter) -{ - _SetIteratorToRoot(tree, iter); - IncrementTreeIterator(iter); -} - -int IsTreeIteratorAtEnd(const TreeIterator * iter) -{ - return (iter->node == NULL); -} - -void IncrementTreeIterator(TreeIterator * iter) -{ - while(iter->node) - { - if (iter->node->children[iter->which]) - { - iter->node = iter->node->children[iter->which]; - iter->which = 0; - } - else - { - iter->which++; - } - - while (iter->node && iter->which > iter->node->count) - { - iter->which = iter->node->parentPos + 1; - iter->node = iter->node->parent; - } - - if (iter->node && - iter->which > 0 && iter->which <= iter->node->count) - { - return; - } - } -} - -TreeKeyData -GetTreeKeyData(TreeIterator * iter) -{ - assert(iter->node && - iter->which > 0 && - iter->which <= iter->node->count); - return iter->node->keyData[iter->which-1]; -} - -int -InsertInTree(Tree * tree, void * key, void * data) -{ - TreeKeyData keyData; - TreeIterator iter; - - _SetIteratorToRoot(tree, &iter); - - if (_Find(&iter, key)) - { - return 0; - } - - keyData.key = key; - keyData.data = data; - _InsertAt(&iter, keyData); - tree->size++; - - return 1; -} - -int -RemoveFromTreeByKey(Tree * tree, void * key) -{ - TreeIterator iter; - _SetIteratorToRoot(tree, &iter); - - if (_Find(&iter, key)) - { - _DeleteAt(&iter); - tree->size--; - return 1; - } - - return 0; -} - -void -RemoveFromTreeByIterator(Tree * tree, TreeIterator * iter) -{ - _DeleteAt(iter); - tree->size--; -} - -int -FindInTree(Tree * tree, void * key, TreeIterator * iter) -{ - TreeIterator i; - - if (iter == NULL) - { - iter = &i; - } - - _SetIteratorToRoot(tree, iter); - if (_Find(iter, key)) - { - return 1; - } - - return 0; -} diff --git a/trunk/src/tree.h b/trunk/src/tree.h deleted file mode 100644 index 76a980cd2..000000000 --- a/trunk/src/tree.h +++ /dev/null @@ -1,62 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2006-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TREE_H -#define TREE_H - -typedef struct _Tree Tree; -typedef struct _TreeNode TreeNode; -typedef struct _TreeIterator TreeIterator; -typedef struct _TreeKeyData TreeKeyData; - -struct _TreeIterator -{ - Tree * tree; - TreeNode * node; - int which; -}; - -struct _TreeKeyData -{ - void * key; - void * data; -}; - -typedef int (*TreeCompareKeyFunction)(const void * key1, const void * key2); -typedef void (*TreeFreeFunction)(void * data); - -Tree * MakeTree(TreeCompareKeyFunction compareFunc, - TreeFreeFunction freeKey, - TreeFreeFunction freeData); -void FreeTree(Tree * tree); - -int GetTreeSize(Tree * tree); - -void SetTreeIteratorToBegin(Tree * tree, TreeIterator * iter); -int IsTreeIteratorAtEnd(const TreeIterator * iter); -void IncrementTreeIterator(TreeIterator * iter); - -TreeKeyData GetTreeKeyData(TreeIterator * iter); - -int InsertInTree(Tree * tree, void * key, void * data); -int RemoveFromTreeByKey(Tree * tree, void * key); -void RemoveFromTreeByIterator(Tree * tree, TreeIterator * iter); - -int FindInTree(Tree * tree, void * key, TreeIterator * iter /* can be NULL */); - -#endif diff --git a/trunk/src/utf8.c b/trunk/src/utf8.c deleted file mode 100644 index 2061a78de..000000000 --- a/trunk/src/utf8.c +++ /dev/null @@ -1,148 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "utf8.h" -#include "utils.h" - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -static char *latin1ToUtf8(char c) -{ - static unsigned char utf8[3]; - unsigned char uc = c; - - memset(utf8, 0, 3); - - if (uc < 128) - utf8[0] = uc; - else if (uc < 192) { - utf8[0] = 194; - utf8[1] = uc; - } else { - utf8[0] = 195; - utf8[1] = uc - 64; - } - - return (char *)utf8; -} - -char *latin1StrToUtf8Dup(char *latin1) -{ - /* utf8 should have at most two char's per latin1 char */ - int len = strlen(latin1) * 2 + 1; - char *ret = xmalloc(len); - char *cp = ret; - char *utf8; - - memset(ret, 0, len); - - len = 0; - - while (*latin1) { - utf8 = latin1ToUtf8(*latin1); - while (*utf8) { - *(cp++) = *(utf8++); - len++; - } - latin1++; - } - - return xrealloc(ret, len + 1); -} - -static char utf8ToLatin1(char *inUtf8) -{ - unsigned char c = 0; - unsigned char *utf8 = (unsigned char *)inUtf8; - - if (utf8[0] < 128) - return utf8[0]; - else if (utf8[0] == 195) - c += 64; - else if (utf8[0] != 194) - return '?'; - return (char)(c + utf8[1]); -} - -static int validateUtf8Char(char *inUtf8Char) -{ - unsigned char *utf8Char = (unsigned char *)inUtf8Char; - - if (utf8Char[0] < 0x80) - return 1; - - if (utf8Char[0] >= 0xC0 && utf8Char[0] <= 0xFD) { - int count = 1; - char t = 1 << 5; - int i; - while (count < 6 && (t & utf8Char[0])) { - t = (t >> 1); - count++; - } - if (count > 5) - return 0; - for (i = 1; i <= count; i++) { - if (utf8Char[i] < 0x80 || utf8Char[i] > 0xBF) - return 0; - } - return count + 1; - } else - return 0; -} - -int validUtf8String(char *string) -{ - int ret; - - while (*string) { - ret = validateUtf8Char(string); - if (0 == ret) - return 0; - string += ret; - } - - return 1; -} - -char *utf8StrToLatin1Dup(char *utf8) -{ - /* utf8 should have at most two char's per latin1 char */ - int len = strlen(utf8) + 1; - char *ret = xmalloc(len); - char *cp = ret; - int count; - - memset(ret, 0, len); - - len = 0; - - while (*utf8) { - count = validateUtf8Char(utf8); - if (!count) { - free(ret); - return NULL; - } - *(cp++) = utf8ToLatin1(utf8); - utf8 += count; - len++; - } - - return xrealloc(ret, len + 1); -} diff --git a/trunk/src/utf8.h b/trunk/src/utf8.h deleted file mode 100644 index 0eb60d82c..000000000 --- a/trunk/src/utf8.h +++ /dev/null @@ -1,28 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef UTF_8_H -#define UTF_8_H - -char *latin1StrToUtf8Dup(char *latin1); - -char *utf8StrToLatin1Dup(char *utf8); - -int validUtf8String(char *string); - -#endif diff --git a/trunk/src/utils.c b/trunk/src/utils.c deleted file mode 100644 index a6dd9d8ae..000000000 --- a/trunk/src/utils.c +++ /dev/null @@ -1,161 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "utils.h" -#include "log.h" - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/select.h> -#include <sys/time.h> -#include <unistd.h> -#include <assert.h> - -char *myFgets(char *buffer, int bufferSize, FILE * fp) -{ - char *ret = fgets(buffer, bufferSize, fp); - 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') { - buffer[strlen(buffer) - 1] = '\0'; - } - return ret; -} - -char *strDupToUpper(char *str) -{ - char *ret = xstrdup(str); - int i; - - for (i = 0; i < strlen(str); i++) - ret[i] = toupper((int)ret[i]); - - return ret; -} - -void stripReturnChar(char *string) -{ - while (string && (string = strchr(string, '\n'))) { - *string = ' '; - } -} - -void my_usleep(long usec) -{ - struct timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = usec; - - select(0, NULL, NULL, NULL, &tv); -} - -int ipv6Supported(void) -{ -#ifdef HAVE_IPV6 - int s; - s = socket(AF_INET6, SOCK_STREAM, 0); - if (s == -1) - return 0; - close(s); - return 1; -#endif - return 0; -} - -char *appendToString(char *dest, const char *src) -{ - int destlen; - int srclen = strlen(src); - - if (dest == NULL) { - dest = xmalloc(srclen + 1); - memset(dest, 0, srclen + 1); - destlen = 0; - } else { - destlen = strlen(dest); - dest = xrealloc(dest, destlen + srclen + 1); - } - - memcpy(dest + destlen, src, srclen); - dest[destlen + srclen] = '\0'; - - return dest; -} - -unsigned long readLEuint32(const unsigned char *p) -{ - return ((unsigned long)p[0] << 0) | - ((unsigned long)p[1] << 8) | - ((unsigned long)p[2] << 16) | ((unsigned long)p[3] << 24); -} - -mpd_malloc char *xstrdup(const char *s) -{ - char *ret = strdup(s); - if (mpd_unlikely(!ret)) - FATAL("OOM: strdup\n"); - return ret; -} - -/* borrowed from git :) */ - -mpd_malloc void *xmalloc(size_t size) -{ - void *ret; - - assert(mpd_likely(size)); - - ret = malloc(size); - if (mpd_unlikely(!ret)) - FATAL("OOM: malloc\n"); - return ret; -} - -mpd_malloc void *xrealloc(void *ptr, size_t size) -{ - void *ret = realloc(ptr, size); - - /* some C libraries return NULL when size == 0, - * make sure we get a free()-able pointer (free(NULL) - * doesn't work with all C libraries, either) */ - if (mpd_unlikely(!ret && !size)) - ret = realloc(ptr, 1); - - if (mpd_unlikely(!ret)) - FATAL("OOM: realloc\n"); - return ret; -} - -mpd_malloc void *xcalloc(size_t nmemb, size_t size) -{ - void *ret; - - assert(mpd_likely(nmemb && size)); - - ret = calloc(nmemb, size); - if (mpd_unlikely(!ret)) - FATAL("OOM: calloc\n"); - return ret; -} - - diff --git a/trunk/src/utils.h b/trunk/src/utils.h deleted file mode 100644 index 2f911499b..000000000 --- a/trunk/src/utils.h +++ /dev/null @@ -1,85 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef UTILS_H -#define UTILS_H - -#include "../config.h" -#include "gcc.h" - -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) - -char *myFgets(char *buffer, int bufferSize, FILE * fp); - -char *strDupToUpper(char *str); - -void stripReturnChar(char *string); - -void my_usleep(long usec); - -int ipv6Supported(void); - -char *appendToString(char *dest, const char *src); - -unsigned long readLEuint32(const unsigned char *p); - -/* trivial functions, keep them inlined */ -static inline void xclose(int fd) -{ - while (close(fd) && errno == EINTR); -} - -static inline ssize_t xread(int fd, void *buf, size_t len) -{ - ssize_t nr; - while (1) { - nr = read(fd, buf, len); - if ((nr < 0) && (errno == EAGAIN || errno == EINTR)) - continue; - return nr; - } -} - -static inline ssize_t xwrite(int fd, const void *buf, size_t len) -{ - ssize_t nr; - while (1) { - nr = write(fd, buf, len); - if ((nr < 0) && (errno == EAGAIN || errno == EINTR)) - continue; - return nr; - } -} - -mpd_malloc char *xstrdup(const char *s); - -mpd_malloc void *xmalloc(size_t size); - -mpd_malloc void *xrealloc(void *ptr, size_t size); - -mpd_malloc void *xcalloc(size_t nmemb, size_t size); - -#endif diff --git a/trunk/src/volume.c b/trunk/src/volume.c deleted file mode 100644 index 59e8b550c..000000000 --- a/trunk/src/volume.c +++ /dev/null @@ -1,552 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "volume.h" - -#include "command.h" -#include "conf.h" -#include "log.h" -#include "player.h" -#include "state_file.h" -#include "gcc.h" -#include "utils.h" - -#include <math.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <errno.h> -#ifdef HAVE_OSS -#include <sys/soundcard.h> -#endif -#ifdef HAVE_ALSA -#include <alsa/asoundlib.h> -#endif - -#define VOLUME_MIXER_TYPE_SOFTWARE 0 -#define VOLUME_MIXER_TYPE_OSS 1 -#define VOLUME_MIXER_TYPE_ALSA 2 - -#define VOLUME_MIXER_SOFTWARE_DEFAULT "" -#define VOLUME_MIXER_OSS_DEFAULT "/dev/mixer" -#define VOLUME_MIXER_ALSA_DEFAULT "default" -#define VOLUME_MIXER_ALSA_CONTROL_DEFAULT "PCM" -#define SW_VOLUME_STATE "sw_volume: " - -#ifdef HAVE_OSS -#define VOLUME_MIXER_TYPE_DEFAULT VOLUME_MIXER_TYPE_OSS -#define VOLUME_MIXER_DEVICE_DEFAULT VOLUME_MIXER_OSS_DEFAULT -#else -#ifdef HAVE_ALSA -#define VOLUME_MIXER_TYPE_DEFAULT VOLUME_MIXER_TYPE_ALSA -#define VOLUME_MIXER_DEVICE_DEFAULT VOLUME_MIXER_ALSA_DEFAULT -#else -#define VOLUME_MIXER_TYPE_DEFAULT VOLUME_MIXER_TYPE_SOFTWARE -#define VOLUME_MIXER_DEVICE_DEFAULT VOLUME_MIXER_SOFTWARE_DEFAULT -#endif -#endif - -static int volume_mixerType = VOLUME_MIXER_TYPE_DEFAULT; -static char *volume_mixerDevice = VOLUME_MIXER_DEVICE_DEFAULT; - -static int volume_softwareSet = 100; - -#ifdef HAVE_OSS -static int volume_ossFd = -1; -static int volume_ossControl = SOUND_MIXER_PCM; -#endif - -#ifdef HAVE_ALSA -static snd_mixer_t *volume_alsaMixerHandle; -static snd_mixer_elem_t *volume_alsaElem; -static long volume_alsaMin; -static long volume_alsaMax; -static int volume_alsaSet = -1; -#endif - -#ifdef HAVE_OSS - -static void closeOssMixer(void) -{ - while (close(volume_ossFd) && errno == EINTR) ; - volume_ossFd = -1; -} - -static int prepOssMixer(char *device) -{ - ConfigParam *param; - - if ((volume_ossFd = open(device, O_RDONLY)) < 0) { - WARNING("unable to open oss mixer \"%s\"\n", device); - return -1; - } - - param = getConfigParam(CONF_MIXER_CONTROL); - - if (param) { - char *labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS; - char *dup; - int i, j; - int devmask = 0; - - if (ioctl(volume_ossFd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { - WARNING("errors getting read_devmask for oss mixer\n"); - closeOssMixer(); - return -1; - } - - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { - dup = xstrdup(labels[i]); - /* eliminate spaces at the end */ - j = strlen(dup) - 1; - while (j >= 0 && dup[j] == ' ') - dup[j--] = '\0'; - if (strcasecmp(dup, param->value) == 0) { - free(dup); - break; - } - free(dup); - } - - if (i >= SOUND_MIXER_NRDEVICES) { - WARNING("mixer control \"%s\" not found at line %i\n", - param->value, param->line); - closeOssMixer(); - return -1; - } else if (!((1 << i) & devmask)) { - WARNING("mixer control \"%s\" not usable at line %i\n", - param->value, param->line); - closeOssMixer(); - return -1; - } - - volume_ossControl = i; - } - - return 0; -} - -static int ensure_oss_open(void) -{ - if ((volume_ossFd < 0 && prepOssMixer(volume_mixerDevice) < 0)) - return -1; - return 0; -} - -static int getOssVolumeLevel(void) -{ - int left, right, level; - - if (ensure_oss_open() < 0) - return -1; - - if (ioctl(volume_ossFd, MIXER_READ(volume_ossControl), &level) < 0) { - closeOssMixer(); - WARNING("unable to read volume\n"); - return -1; - } - - left = level & 0xff; - right = (level & 0xff00) >> 8; - - if (left != right) { - WARNING("volume for left and right is not the same, \"%i\" and " - "\"%i\"\n", left, right); - } - - return left; -} - -static int changeOssVolumeLevel(int fd, int change, int rel) -{ - int current; - int new; - int level; - - if (rel) { - if ((current = getOssVolumeLevel()) < 0) { - commandError(fd, ACK_ERROR_SYSTEM, - "problem getting current volume"); - return -1; - } - - new = current + change; - } else { - if (ensure_oss_open() < 0) - return -1; - new = change; - } - - if (new < 0) - new = 0; - else if (new > 100) - new = 100; - - level = (new << 8) + new; - - if (ioctl(volume_ossFd, MIXER_WRITE(volume_ossControl), &level) < 0) { - closeOssMixer(); - commandError(fd, ACK_ERROR_SYSTEM, "problems setting volume"); - return -1; - } - - return 0; -} -#endif - -#ifdef HAVE_ALSA -static void closeAlsaMixer(void) -{ - snd_mixer_close(volume_alsaMixerHandle); - volume_alsaMixerHandle = NULL; -} - -static int prepAlsaMixer(char *card) -{ - int err; - snd_mixer_elem_t *elem; - char *controlName = VOLUME_MIXER_ALSA_CONTROL_DEFAULT; - ConfigParam *param; - - err = snd_mixer_open(&volume_alsaMixerHandle, 0); - snd_config_update_free_global(); - if (err < 0) { - WARNING("problems opening alsa mixer: %s\n", snd_strerror(err)); - return -1; - } - - if ((err = snd_mixer_attach(volume_alsaMixerHandle, card)) < 0) { - closeAlsaMixer(); - WARNING("problems attaching alsa mixer: %s\n", - snd_strerror(err)); - return -1; - } - - if ((err = - snd_mixer_selem_register(volume_alsaMixerHandle, NULL, - NULL)) < 0) { - closeAlsaMixer(); - WARNING("problems snd_mixer_selem_register'ing: %s\n", - snd_strerror(err)); - return -1; - } - - if ((err = snd_mixer_load(volume_alsaMixerHandle)) < 0) { - closeAlsaMixer(); - WARNING("problems snd_mixer_selem_register'ing: %s\n", - snd_strerror(err)); - return -1; - } - - elem = snd_mixer_first_elem(volume_alsaMixerHandle); - - param = getConfigParam(CONF_MIXER_CONTROL); - - if (param) { - controlName = param->value; - } - - while (elem) { - if (snd_mixer_elem_get_type(elem) == SND_MIXER_ELEM_SIMPLE) { - if (strcasecmp(controlName, - snd_mixer_selem_get_name(elem)) == 0) { - break; - } - } - elem = snd_mixer_elem_next(elem); - } - - if (elem) { - volume_alsaElem = elem; - snd_mixer_selem_get_playback_volume_range(volume_alsaElem, - &volume_alsaMin, - &volume_alsaMax); - return 0; - } - - WARNING("can't find alsa mixer_control \"%s\"\n", controlName); - - closeAlsaMixer(); - return -1; -} - -static int prep_alsa_get_level(long *level) -{ - const char *cmd; - int err; - - if (!volume_alsaMixerHandle && prepAlsaMixer(volume_mixerDevice) < 0) - return -1; - - if ((err = snd_mixer_handle_events(volume_alsaMixerHandle)) < 0) { - cmd = "handle_events"; - goto error; - } - if ((err = snd_mixer_selem_get_playback_volume(volume_alsaElem, - SND_MIXER_SCHN_FRONT_LEFT, - level)) < 0) { - cmd = "selem_get_playback_volume"; - goto error; - } - return 0; - -error: - WARNING("problems getting alsa volume: %s (snd_mixer_%s)\n", - snd_strerror(err), cmd); - closeAlsaMixer(); - return -1; -} - -static int getAlsaVolumeLevel(void) -{ - int ret; - long level; - long max = volume_alsaMax; - long min = volume_alsaMin; - - if (prep_alsa_get_level(&level) < 0) - return -1; - - ret = ((volume_alsaSet / 100.0) * (max - min) + min) + 0.5; - if (volume_alsaSet > 0 && ret == level) { - ret = volume_alsaSet; - } else - ret = (int)(100 * (((float)(level - min)) / (max - min)) + 0.5); - - return ret; -} - -static int changeAlsaVolumeLevel(int fd, int change, int rel) -{ - float vol; - long level; - long test; - long max = volume_alsaMax; - long min = volume_alsaMin; - int err; - - if (prep_alsa_get_level(&level) < 0) - return -1; - - if (rel) { - test = ((volume_alsaSet / 100.0) * (max - min) + min) + 0.5; - if (volume_alsaSet >= 0 && level == test) { - vol = volume_alsaSet; - } else - vol = 100.0 * (((float)(level - min)) / (max - min)); - vol += change; - } else - vol = change; - - volume_alsaSet = vol + 0.5; - volume_alsaSet = volume_alsaSet > 100 ? 100 : - (volume_alsaSet < 0 ? 0 : volume_alsaSet); - - level = (long)(((vol / 100.0) * (max - min) + min) + 0.5); - level = level > max ? max : level; - level = level < min ? min : level; - - if ((err = - snd_mixer_selem_set_playback_volume_all(volume_alsaElem, - level)) < 0) { - commandError(fd, ACK_ERROR_SYSTEM, "problems setting volume"); - WARNING("problems setting alsa volume: %s\n", - snd_strerror(err)); - closeAlsaMixer(); - return -1; - } - - return 0; -} -#endif - -static int prepMixer(char *device) -{ - switch (volume_mixerType) { -#ifdef HAVE_ALSA - case VOLUME_MIXER_TYPE_ALSA: - return prepAlsaMixer(device); -#endif -#ifdef HAVE_OSS - case VOLUME_MIXER_TYPE_OSS: - return prepOssMixer(device); -#endif - } - - return 0; -} - -void finishVolume(void) -{ - switch (volume_mixerType) { -#ifdef HAVE_ALSA - case VOLUME_MIXER_TYPE_ALSA: - closeAlsaMixer(); - break; -#endif -#ifdef HAVE_OSS - case VOLUME_MIXER_TYPE_OSS: - closeOssMixer(); - break; -#endif - } -} - -void initVolume(void) -{ - ConfigParam *param = getConfigParam(CONF_MIXER_TYPE); - - if (param) { - if (0) ; -#ifdef HAVE_ALSA - else if (strcmp(param->value, VOLUME_MIXER_ALSA) == 0) { - volume_mixerType = VOLUME_MIXER_TYPE_ALSA; - volume_mixerDevice = VOLUME_MIXER_ALSA_DEFAULT; - } -#endif -#ifdef HAVE_OSS - else if (strcmp(param->value, VOLUME_MIXER_OSS) == 0) { - volume_mixerType = VOLUME_MIXER_TYPE_OSS; - volume_mixerDevice = VOLUME_MIXER_OSS_DEFAULT; - } -#endif - else if (strcmp(param->value, VOLUME_MIXER_SOFTWARE) == 0) { - volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE; - volume_mixerDevice = VOLUME_MIXER_SOFTWARE_DEFAULT; - } else { - FATAL("unknown mixer type %s at line %i\n", - param->value, param->line); - } - } - - param = getConfigParam(CONF_MIXER_DEVICE); - - if (param) { - volume_mixerDevice = param->value; - } -} - -void openVolumeDevice(void) -{ - if (prepMixer(volume_mixerDevice) < 0) { - WARNING("using software volume\n"); - volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE; - } -} - -static int getSoftwareVolume(void) -{ - return volume_softwareSet; -} - -int getVolumeLevel(void) -{ - switch (volume_mixerType) { -#ifdef HAVE_ALSA - case VOLUME_MIXER_TYPE_ALSA: - return getAlsaVolumeLevel(); -#endif -#ifdef HAVE_OSS - case VOLUME_MIXER_TYPE_OSS: - return getOssVolumeLevel(); -#endif - case VOLUME_MIXER_TYPE_SOFTWARE: - return getSoftwareVolume(); - default: - return -1; - } -} - -static int changeSoftwareVolume(int fd, int change, int rel) -{ - int new = change; - - if (rel) - new += volume_softwareSet; - - if (new > 100) - new = 100; - else if (new < 0) - new = 0; - - volume_softwareSet = new; - - /*new = 100.0*(exp(new/50.0)-1)/(M_E*M_E-1)+0.5; */ - if (new >= 100) - new = 1000; - else if (new <= 0) - new = 0; - else - new = - 1000.0 * (exp(new / 25.0) - 1) / (54.5981500331F - 1) + 0.5; - - setPlayerSoftwareVolume(new); - - return 0; -} - -int changeVolumeLevel(int fd, int change, int rel) -{ - switch (volume_mixerType) { -#ifdef HAVE_ALSA - case VOLUME_MIXER_TYPE_ALSA: - return changeAlsaVolumeLevel(fd, change, rel); -#endif -#ifdef HAVE_OSS - case VOLUME_MIXER_TYPE_OSS: - return changeOssVolumeLevel(fd, change, rel); -#endif - case VOLUME_MIXER_TYPE_SOFTWARE: - return changeSoftwareVolume(fd, change, rel); - default: - return 0; - break; - } -} - -void read_sw_volume_state(FILE *fp) -{ - /* strlen(SW_VOLUME_STATE) + strlen('100') + '\0' */ - #define bufsize 16 - char buf[bufsize]; - const size_t len = strlen(SW_VOLUME_STATE); - char *end = NULL; - long int sv; - - if (volume_mixerType != VOLUME_MIXER_TYPE_SOFTWARE) - return; - while (myFgets(buf, bufsize, fp)) { - if (strncmp(buf, SW_VOLUME_STATE, len)) - continue; - sv = strtol(buf + len, &end, 10); - if (mpd_likely(!*end)) - changeSoftwareVolume(STDERR_FILENO, sv, 0); - else - ERROR("Can't parse software volume: %s\n", buf); - return; - } - #undef bufsize -} - -void save_sw_volume_state(FILE *fp) -{ - if (volume_mixerType == VOLUME_MIXER_TYPE_SOFTWARE) - fprintf(fp, SW_VOLUME_STATE "%d\n", volume_softwareSet); -} - diff --git a/trunk/src/volume.h b/trunk/src/volume.h deleted file mode 100644 index fcaefc64d..000000000 --- a/trunk/src/volume.h +++ /dev/null @@ -1,44 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef VOLUME_H -#define VOLUME_H - -#include "../config.h" - -#include <stdio.h> - -#define VOLUME_MIXER_OSS "oss" -#define VOLUME_MIXER_ALSA "alsa" -#define VOLUME_MIXER_SOFTWARE "software" - -void initVolume(void); - -void openVolumeDevice(void); - -void finishVolume(void); - -int getVolumeLevel(void); - -int changeVolumeLevel(int fd, int change, int rel); - -void read_sw_volume_state(FILE *fp); - -void save_sw_volume_state(FILE *fp); - -#endif diff --git a/trunk/src/zeroconf.c b/trunk/src/zeroconf.c deleted file mode 100644 index eeec794cd..000000000 --- a/trunk/src/zeroconf.c +++ /dev/null @@ -1,498 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <stdlib.h> -#include <assert.h> -#include <string.h> - -#include "zeroconf.h" -#include "conf.h" -#include "log.h" -#include "listen.h" -#include "ioops.h" -#include "utils.h" - -/* The dns-sd service type qualifier to publish */ -#define SERVICE_TYPE "_mpd._tcp" - -/* The default service name to publish - * (overridden by 'zeroconf_name' config parameter) - */ -#define SERVICE_NAME "Music Player" - -/* Here is the implementation for Avahi (http://avahi.org) Zeroconf support */ -#ifdef HAVE_AVAHI - -#include <avahi-client/client.h> -#include <avahi-client/publish.h> - -#include <avahi-common/alternative.h> -#include <avahi-common/domain.h> -#include <avahi-common/malloc.h> -#include <avahi-common/error.h> - -/* Static avahi data */ -static AvahiEntryGroup *avahiGroup; -static char *avahiName; -static AvahiClient* avahiClient; -static AvahiPoll avahiPoll; -static int avahiRunning; - -static int avahiFdset( fd_set* rfds, fd_set* wfds, fd_set* efds ); -static int avahiFdconsume( int fdCount, fd_set* rfds, fd_set* wfds, fd_set* efds ); -static struct ioOps avahiIo = { - .fdset = avahiFdset, - .consume = avahiFdconsume, -}; - -/* Forward Declaration */ -static void avahiRegisterService(AvahiClient *c); - -struct AvahiWatch { - struct AvahiWatch* prev; - struct AvahiWatch* next; - int fd; - AvahiWatchEvent requestedEvent; - AvahiWatchEvent observedEvent; - AvahiWatchCallback callback; - void* userdata; -}; - -struct AvahiTimeout { - struct AvahiTimeout* prev; - struct AvahiTimeout* next; - struct timeval expiry; - int enabled; - AvahiTimeoutCallback callback; - void* userdata; -}; - -static AvahiWatch* avahiWatchList; -static AvahiTimeout* avahiTimeoutList; - -static AvahiWatch* avahiWatchNew( const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata ) -{ - struct AvahiWatch* newWatch = xmalloc( sizeof(struct AvahiWatch) ); - - newWatch->fd = fd; - newWatch->requestedEvent = event; - newWatch->observedEvent = 0; - newWatch->callback = callback; - newWatch->userdata = userdata; - - /* Insert at front of list */ - newWatch->next = avahiWatchList; - avahiWatchList = newWatch; - newWatch->prev = NULL; - if( newWatch->next ) - newWatch->next->prev = newWatch; - - return newWatch; -} - -static void avahiWatchUpdate( AvahiWatch *w, AvahiWatchEvent event ) -{ - assert( w != NULL ); - w->requestedEvent = event; -} - -static AvahiWatchEvent avahiWatchGetEvents( AvahiWatch *w ) -{ - assert( w != NULL ); - return w->observedEvent; -} - -static void avahiWatchFree( AvahiWatch *w ) -{ - assert( w != NULL ); - - if( avahiWatchList == w ) - avahiWatchList = w->next; - else if( w->prev != NULL ) - w->prev->next = w->next; - - free( w ); -} - -static void avahiCheckExpiry( AvahiTimeout *t ) -{ - assert( t != NULL ); - if( t->enabled ) { - struct timeval now; - gettimeofday( &now, NULL ); - if( timercmp( &now, &(t->expiry), > ) ) { - t->enabled = 0; - t->callback( t, t->userdata ); - } - } -} - -static void avahiTimeoutUpdate( AvahiTimeout *t, const struct timeval *tv ) -{ - assert( t != NULL ); - if( tv ) { - t->enabled = 1; - t->expiry.tv_sec = tv->tv_sec; - t->expiry.tv_usec = tv->tv_usec; - } else { - t->enabled = 0; - } -} - -static void avahiTimeoutFree( AvahiTimeout *t ) -{ - assert( t != NULL ); - - if( avahiTimeoutList == t ) - avahiTimeoutList = t->next; - else if( t->prev != NULL ) - t->prev->next = t->next; - - free( t ); -} - -static AvahiTimeout* avahiTimeoutNew( const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata ) -{ - struct AvahiTimeout* newTimeout = xmalloc( sizeof(struct AvahiTimeout) ); - - newTimeout->callback = callback; - newTimeout->userdata = userdata; - - avahiTimeoutUpdate( newTimeout, tv ); - - /* Insert at front of list */ - newTimeout->next = avahiTimeoutList; - avahiTimeoutList = newTimeout; - newTimeout->prev = NULL; - if( newTimeout->next ) - newTimeout->next->prev = newTimeout; - - return newTimeout; -} - -/* Callback when the EntryGroup changes state */ -static void avahiGroupCallback( - AvahiEntryGroup *g, - AvahiEntryGroupState state, - void *userdata) -{ - assert(g); - - DEBUG( "Avahi: Service group changed to state %d\n", state ); - - switch (state) { - case AVAHI_ENTRY_GROUP_ESTABLISHED : - /* The entry group has been established successfully */ - LOG( "Avahi: Service '%s' successfully established.\n", avahiName ); - break; - - case AVAHI_ENTRY_GROUP_COLLISION : { - char *n; - - /* A service name collision happened. Let's pick a new name */ - n = avahi_alternative_service_name(avahiName); - avahi_free(avahiName); - avahiName = n; - - LOG( "Avahi: Service name collision, renaming service to '%s'\n", avahiName ); - - /* And recreate the services */ - avahiRegisterService(avahi_entry_group_get_client(g)); - break; - } - - case AVAHI_ENTRY_GROUP_FAILURE : - ERROR( "Avahi: Entry group failure: %s\n", - avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))) ); - /* Some kind of failure happened while we were registering our services */ - avahiRunning = 0; - break; - - case AVAHI_ENTRY_GROUP_UNCOMMITED: - DEBUG( "Avahi: Service group is UNCOMMITED\n" ); - break; - case AVAHI_ENTRY_GROUP_REGISTERING: - DEBUG( "Avahi: Service group is REGISTERING\n" ); - ; - } -} - -/* Registers a new service with avahi */ -static void avahiRegisterService(AvahiClient *c) -{ - int ret; - assert(c); - DEBUG( "Avahi: Registering service %s/%s\n", SERVICE_TYPE, avahiName ); - - /* If this is the first time we're called, let's create a new entry group */ - if (!avahiGroup) { - avahiGroup = avahi_entry_group_new(c, avahiGroupCallback, NULL); - if( !avahiGroup ) { - ERROR( "Avahi: Failed to create avahi EntryGroup: %s\n", avahi_strerror(avahi_client_errno(c)) ); - goto fail; - } - } - - /* Add the service */ - /* TODO: This currently binds to ALL interfaces. - * We could maybe add a service per actual bound interface, if that's better. */ - ret = avahi_entry_group_add_service(avahiGroup, - AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, - avahiName, SERVICE_TYPE, - NULL, NULL, - getBoundPort(), - NULL); - if( ret < 0 ) { - ERROR( "Avahi: Failed to add service %s: %s\n", SERVICE_TYPE, avahi_strerror(ret) ); - goto fail; - } - - /* Tell the server to register the service group */ - ret = avahi_entry_group_commit(avahiGroup); - if( ret < 0 ) { - ERROR( "Avahi: Failed to commit service group: %s\n", avahi_strerror(ret) ); - goto fail; - } - return; - -fail: - avahiRunning = 0; -} - -/* Callback when avahi changes state */ -static void avahiClientCallback(AvahiClient *c, AvahiClientState state, void *userdata) -{ - assert(c); - - /* Called whenever the client or server state changes */ - DEBUG( "Avahi: Client changed to state %d\n", state ); - - switch (state) { - case AVAHI_CLIENT_S_RUNNING: - DEBUG( "Avahi: Client is RUNNING\n" ); - - /* The server has startup successfully and registered its host - * name on the network, so it's time to create our services */ - if (!avahiGroup) - avahiRegisterService(c); - break; - - case AVAHI_CLIENT_FAILURE: - { - int reason = avahi_client_errno(c); - if( reason == AVAHI_ERR_DISCONNECTED ) { - LOG( "Avahi: Client Disconnected, will reconnect shortly\n"); - avahi_entry_group_free( avahiGroup ); - avahiGroup = NULL; - avahi_client_free( avahiClient ); - avahiClient = NULL; - avahiClient = avahi_client_new( &avahiPoll, AVAHI_CLIENT_NO_FAIL, - avahiClientCallback, NULL, &reason ); - if( !avahiClient ) { - ERROR( "Avahi: Could not reconnect: %s\n", avahi_strerror(reason) ); - avahiRunning = 0; - } - } else { - ERROR( "Avahi: Client failure: %s (terminal)\n", avahi_strerror(reason)); - avahiRunning = 0; - } - } - break; - - case AVAHI_CLIENT_S_COLLISION: - DEBUG( "Avahi: Client is COLLISION\n" ); - /* Let's drop our registered services. When the server is back - * in AVAHI_SERVER_RUNNING state we will register them - * again with the new host name. */ - if (avahiGroup) { - DEBUG( "Avahi: Resetting group\n" ); - avahi_entry_group_reset(avahiGroup); - } - - case AVAHI_CLIENT_S_REGISTERING: - DEBUG( "Avahi: Client is REGISTERING\n" ); - /* The server records are now being established. This - * might be caused by a host name change. We need to wait - * for our own records to register until the host name is - * properly esatblished. */ - - if (avahiGroup) { - DEBUG( "Avahi: Resetting group\n" ); - avahi_entry_group_reset(avahiGroup); - } - - break; - - case AVAHI_CLIENT_CONNECTING: - DEBUG( "Avahi: Client is CONNECTING\n" ); - ; - } -} - -static int avahiFdset( fd_set* rfds, fd_set* wfds, fd_set* efds ) -{ - AvahiWatch* w; - int maxfd = -1; - if( !avahiRunning ) - return maxfd; - for( w = avahiWatchList; w != NULL; w = w->next ) { - if( w->requestedEvent & AVAHI_WATCH_IN ) { - FD_SET( w->fd, rfds ); - } - if( w->requestedEvent & AVAHI_WATCH_OUT ) { - FD_SET( w->fd, wfds ); - } - if( w->requestedEvent & AVAHI_WATCH_ERR ) { - FD_SET( w->fd, efds ); - } - if( w->requestedEvent & AVAHI_WATCH_HUP ) { - ERROR( "Avahi: No support for HUP events! (ignoring)\n" ); - } - - if( w->fd > maxfd ) - maxfd = w->fd; - } - return maxfd; -} - -static int avahiFdconsume( int fdCount, fd_set* rfds, fd_set* wfds, fd_set* efds ) -{ - int retval = fdCount; - AvahiTimeout* t; - AvahiWatch* w = avahiWatchList; - - while( w != NULL && retval > 0 ) { - AvahiWatch* current = w; - current->observedEvent = 0; - if( FD_ISSET( current->fd, rfds ) ) { - current->observedEvent |= AVAHI_WATCH_IN; - FD_CLR( current->fd, rfds ); - retval--; - } - if( FD_ISSET( current->fd, wfds ) ) { - current->observedEvent |= AVAHI_WATCH_OUT; - FD_CLR( current->fd, wfds ); - retval--; - } - if( FD_ISSET( current->fd, efds ) ) { - current->observedEvent |= AVAHI_WATCH_ERR; - FD_CLR( current->fd, efds ); - retval--; - } - - /* Advance to the next one right now, in case the callback - * removes itself - */ - w = w->next; - - if( current->observedEvent && avahiRunning ) { - current->callback( current, current->fd, - current->observedEvent, current->userdata ); - } - } - - t = avahiTimeoutList; - while( t != NULL && avahiRunning ) { - AvahiTimeout* current = t; - - /* Advance to the next one right now, in case the callback - * removes itself - */ - t = t->next; - avahiCheckExpiry( current ); - } - - return retval; -} - -static void init_avahi(const char *serviceName) -{ - int error; - DEBUG( "Avahi: Initializing interface\n" ); - - if( avahi_is_valid_service_name( serviceName ) ) { - avahiName = avahi_strdup( serviceName ); - } else { - ERROR( "Invalid zeroconf_name \"%s\", defaulting to \"%s\" instead.\n", serviceName, SERVICE_NAME ); - avahiName = avahi_strdup( SERVICE_NAME ); - } - - avahiRunning = 1; - - avahiPoll.userdata = NULL; - avahiPoll.watch_new = avahiWatchNew; - avahiPoll.watch_update = avahiWatchUpdate; - avahiPoll.watch_get_events = avahiWatchGetEvents; - avahiPoll.watch_free = avahiWatchFree; - avahiPoll.timeout_new = avahiTimeoutNew; - avahiPoll.timeout_update = avahiTimeoutUpdate; - avahiPoll.timeout_free = avahiTimeoutFree; - - avahiClient = avahi_client_new( &avahiPoll, AVAHI_CLIENT_NO_FAIL, - avahiClientCallback, NULL, &error ); - - if( !avahiClient ) { - ERROR( "Avahi: Failed to create client: %s\n", avahi_strerror(error) ); - goto fail; - } - - avahiIo.fdset = avahiFdset; - avahiIo.consume = avahiFdconsume; - registerIO( &avahiIo ); - - return; - -fail: - finishZeroconf(); -} -#else /* !HAVE_AVAHI */ -static void init_avahi(const char *serviceName) { } -#endif /* HAVE_AVAHI */ - -void initZeroconf(void) -{ - const char* serviceName = SERVICE_NAME; - ConfigParam *param; - - param = getConfigParam(CONF_ZEROCONF_NAME); - - if (param && strlen(param->value) > 0) - serviceName = param->value; - init_avahi(serviceName); -} - -void finishZeroconf(void) -{ -#ifdef HAVE_AVAHI - DEBUG( "Avahi: Shutting down interface\n" ); - deregisterIO( &avahiIo ); - - if( avahiGroup ) { - avahi_entry_group_free( avahiGroup ); - avahiGroup = NULL; - } - - if( avahiClient ) { - avahi_client_free( avahiClient ); - avahiClient = NULL; - } - - avahi_free( avahiName ); - avahiName = NULL; -#endif /* HAVE_AVAHI */ -} diff --git a/trunk/src/zeroconf.h b/trunk/src/zeroconf.h deleted file mode 100644 index ef7167d53..000000000 --- a/trunk/src/zeroconf.h +++ /dev/null @@ -1,27 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef ZEROCONF_H -#define ZEROCONF_H - -#include "../config.h" - -void initZeroconf(void); -void finishZeroconf(void); - -#endif |