diff options
-rw-r--r-- | src/inputPlugins/mod_plugin.c | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/src/inputPlugins/mod_plugin.c b/src/inputPlugins/mod_plugin.c new file mode 100644 index 000000000..59161c17c --- /dev/null +++ b/src/inputPlugins/mod_plugin.c @@ -0,0 +1,267 @@ +/* the Music Player Daemon (MPD) + * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu) + * 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_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() { + return VC_Init(); +} + +static void mod_mpd_Exit() { + VC_Exit(); +} + +static void mod_mpd_Update() { +} + +static BOOL mod_mpd_IsThere() { + return 1; +} + +MDRIVER drv_mpd = +{ + NULL, + "MPD", + "MPD Output Driver v0.1", + 0, + 255, + "mpd", + NULL, + 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 = 0; +static int mod_mikModInitError = 0; + +static int mod_initMikMod() { + if(mod_mikModInitiated) return 0; + if(mod_mikModInitError) return -1; + + mod_mikModInitiated = 1; + + MikMod_RegisterDriver(&drv_mpd); + MikMod_RegisterAllLoaders(); + + md_reverb = 0; + md_mode = (DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX | 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; +} + +void mod_finishMikMod() { + 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, 255, 0))) return NULL; + + data = malloc(sizeof(mod_Data)); + + data->audio_buffer = malloc(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); +} + +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); + return -1; + } + + 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); + } + + flushOutputBuffer(cb); + + mod_close(data); + + if(dc->stop) { + dc->state = DECODE_STATE_STOP; + dc->stop = 0; + } + else dc->state = DECODE_STATE_STOP; + + return 0; +} + +MpdTag * modTagDup(char * file) { + MpdTag * ret = NULL; + MODULE * moduleHandle; + + if(mod_initMikMod() < 0) return NULL; + + if(!(moduleHandle = Player_Load(file, 255, 0))) return NULL; + + Player_Free(moduleHandle); + + ret = newMpdTag(); + + ret->time = 0; + ret->title = Player_LoadTitle(file); + + return ret; +} + +char * modSuffixes[] = {"amf", + "dsm", + "far", + "gdm", + "imf", + "it", + "med", + "mod", + "mtm", + "s3m", + "stm", + "stx", + "ult", + "uni", + "xm", + NULL}; + +InputPlugin modPlugin = +{ + "audiofile", + NULL, + mod_finishMikMod, + NULL, + mod_decode, + modTagDup, + INPUT_PLUGIN_STREAM_FILE, + modSuffixes, + NULL +}; + +#else + +InputPlugin modPlugin = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + NULL, + NULL +}; + +#endif /* HAVE_AUDIOFILE */ |