Mercurial > audlegacy-plugins
changeset 2303:5561e63e9133
threw out the WAV plugin in favour of the sndfile plugin
author | mf0102 <0102@gmx.at> |
---|---|
date | Sat, 12 Jan 2008 18:41:04 +0100 |
parents | 227de9a5467d |
children | ccca9906abd0 |
files | configure.ac src/sndfile/Makefile src/sndfile/plugin.c src/sndfile/plugin.h src/wav/Makefile src/wav/wav-sndfile.c src/wav/wav-sndfile.h src/wav/wav.c src/wav/wav.h |
diffstat | 9 files changed, 637 insertions(+), 1240 deletions(-) [+] |
line wrap: on
line diff
--- a/configure.ac Sat Jan 12 16:35:26 2008 +0100 +++ b/configure.ac Sat Jan 12 18:41:04 2008 +0100 @@ -120,7 +120,7 @@ dnl These plugins are always built. -INPUT_PLUGINS="tonegen console sexypsf wav cue alac metronom vtx" +INPUT_PLUGINS="tonegen console sexypsf cue alac metronom vtx" OUTPUT_PLUGINS="null" EFFECT_PLUGINS="audiocompress ladspa voice_removal sndstretch stereo_plugin echo_plugin" GENERAL_PLUGINS="song_change alarm" @@ -713,11 +713,9 @@ fi if test "$enable_sndfile" = "yes"; then - WAV_SNDFILE="-sndfile" + INPUT_PLUGINS="$INPUT_PLUGINS sndfile" fi -AC_SUBST(WAV_SNDFILE) - dnl *** modplug AC_ARG_ENABLE(modplug, @@ -1635,8 +1633,7 @@ echo " -> dummy backend: $enable_amidiplug_dummy" echo " MIDI to WAVE converter (timidity): $enable_timidity" echo " CD Digital Audio (cdaudio_ng): $enable_cdaudio_ng" -echo " Microsoft WAV (wav): yes" -echo " + sndfile extensions: $enable_sndfile" +echo " sndfile extensions: $enable_sndfile" echo " Tone Generator: yes" echo " Ogg Vorbis (vorbis): $have_oggvorbis" echo " Free Lossless Audio Codec (flacng): $have_flacng"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sndfile/Makefile Sat Jan 12 18:41:04 2008 +0100 @@ -0,0 +1,13 @@ +include ../../extra.mk + +PLUGIN = sndfile${PLUGIN_SUFFIX} + +SRCS = plugin.c + +include ../../buildsys.mk + +plugindir := ${plugindir}/${INPUT_PLUGIN_DIR} + +CFLAGS += ${PLUGIN_CFLAGS} +CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MOWGLI_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${PANGO_CFLAGS} ${DBUS_CFLAGS} -I../../intl -I../.. +LIBS += ${MOWGLI_LIBS} ${SNDFILE_LIBS} ${GTK_LIBS} ${GLIB_LIBS} ${PANGO_LIBS}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sndfile/plugin.c Sat Jan 12 18:41:04 2008 +0100 @@ -0,0 +1,591 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005 Audacious development team. + * + * Based on the xmms_sndfile input plugin: + * Copyright (C) 2000, 2002 Erik de Castro Lopo + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * Rewritten 17-Feb-2007 (nenolod): + * - now uses conditional variables to ensure that sndfile mutex is + * entirely protected. + * - pausing works now + * - fixed some potential race conditions when dealing with NFS. + * - TITLE_LEN removed + */ + +#include "config.h" + +#include <glib.h> +#include <string.h> +#include <math.h> + +#include <audacious/plugin.h> +#include <audacious/util.h> +#include <audacious/i18n.h> +#include <audacious/main.h> +#include <audacious/output.h> +#include "plugin.h" + +#include <sndfile.h> + +static SNDFILE *sndfile = NULL; +static SF_INFO sfinfo; + +static int song_length; +static int bit_rate = 0; +static glong seek_time = -1; + +static GThread *decode_thread; +static GMutex *decode_mutex; +static GCond *decode_cond; + + + + +static sf_count_t sf_get_filelen (void *user_data) +{ + return aud_vfs_fsize (user_data); +} +static sf_count_t sf_vseek (sf_count_t offset, int whence, void *user_data) +{ + return aud_vfs_fseek(user_data, offset, whence); +} +static sf_count_t sf_vread (void *ptr, sf_count_t count, void *user_data) +{ + return aud_vfs_fread(ptr, 1, count, user_data); +} +static sf_count_t sf_vwrite (const void *ptr, sf_count_t count, void *user_data) +{ + return aud_vfs_fwrite(ptr, 1, count, user_data); +} +static sf_count_t sf_tell (void *user_data) +{ + return aud_vfs_ftell(user_data); +} +static SF_VIRTUAL_IO sf_virtual_io = +{ + sf_get_filelen, + sf_vseek, + sf_vread, + sf_vwrite, + sf_tell +}; + +static SNDFILE * +open_sndfile_from_uri(gchar *filename, VFSFile *vfsfile, SF_INFO *tmp_sfinfo) +{ + SNDFILE *snd_file = NULL; + vfsfile = aud_vfs_fopen(filename, "rb"); + + if (vfsfile == NULL) + return NULL; + + snd_file = sf_open_virtual (&sf_virtual_io, SFM_READ, tmp_sfinfo, vfsfile); + if (snd_file == NULL) + aud_vfs_fclose(vfsfile); + + return snd_file; +} + +static void +close_sndfile(SNDFILE *snd_file, VFSFile *vfsfile) +{ + sf_close(snd_file); + aud_vfs_fclose(vfsfile); +} + + + +static void +plugin_init (void) +{ + seek_time = -1; + + decode_mutex = g_mutex_new(); + decode_cond = g_cond_new(); +} + +static void +plugin_cleanup (void) +{ + g_cond_free(decode_cond); + g_mutex_free(decode_mutex); +} + +static void +fill_song_tuple (char *filename, Tuple *ti) +{ + VFSFile *vfsfile = NULL; + SNDFILE *tmp_sndfile; + SF_INFO tmp_sfinfo; + unsigned int lossy = 0; + gchar *codec = NULL, *format, *subformat = NULL; + GString *codec_gs = NULL; + + tmp_sndfile = open_sndfile_from_uri(filename, vfsfile, &tmp_sfinfo); + if ( sf_get_string(tmp_sndfile, SF_STR_TITLE) == NULL) + aud_tuple_associate_string(ti, FIELD_TITLE, NULL, g_path_get_basename(filename)); + else + aud_tuple_associate_string(ti, FIELD_TITLE, NULL, sf_get_string(tmp_sndfile, SF_STR_TITLE)); + + aud_tuple_associate_string(ti, FIELD_ARTIST, NULL, sf_get_string(tmp_sndfile, SF_STR_ARTIST)); + aud_tuple_associate_string(ti, FIELD_COMMENT, NULL, sf_get_string(tmp_sndfile, SF_STR_COMMENT)); + aud_tuple_associate_string(ti, FIELD_DATE, NULL, sf_get_string(tmp_sndfile, SF_STR_DATE)); + aud_tuple_associate_string(ti, -1, "software", sf_get_string(tmp_sndfile, SF_STR_SOFTWARE)); + + if (!tmp_sndfile) + return; + + close_sndfile (tmp_sndfile, vfsfile); + tmp_sndfile = NULL; + + if (tmp_sfinfo.samplerate > 0) + aud_tuple_associate_int(ti, FIELD_LENGTH, NULL, (int) ceil (1000.0 * tmp_sfinfo.frames / tmp_sfinfo.samplerate)); + + switch (tmp_sfinfo.format & SF_FORMAT_TYPEMASK) + { + case SF_FORMAT_WAV: + case SF_FORMAT_WAVEX: + format = "Microsoft WAV"; + break; + case SF_FORMAT_AIFF: + format = "Apple/SGI AIFF"; + break; + case SF_FORMAT_AU: + format = "Sun/NeXT AU"; + break; + case SF_FORMAT_RAW: + format = "Raw PCM data"; + break; + case SF_FORMAT_PAF: + format = "Ensoniq PARIS"; + break; + case SF_FORMAT_SVX: + format = "Amiga IFF / SVX8 / SV16"; + break; + case SF_FORMAT_NIST: + format = "Sphere NIST"; + break; + case SF_FORMAT_VOC: + format = "Creative VOC"; + break; + case SF_FORMAT_IRCAM: + format = "Berkeley/IRCAM/CARL"; + break; + case SF_FORMAT_W64: + format = "Sonic Foundry's 64 bit RIFF/WAV"; + break; + case SF_FORMAT_MAT4: + format = "Matlab (tm) V4.2 / GNU Octave 2.0"; + break; + case SF_FORMAT_MAT5: + format = "Matlab (tm) V5.0 / GNU Octave 2.1"; + break; + case SF_FORMAT_PVF: + format = "Portable Voice Format"; + break; + case SF_FORMAT_XI: + format = "Fasttracker 2 Extended Instrument"; + break; + case SF_FORMAT_HTK: + format = "HMM Tool Kit"; + break; + case SF_FORMAT_SDS: + format = "Midi Sample Dump Standard"; + break; + case SF_FORMAT_AVR: + format = "Audio Visual Research"; + break; + case SF_FORMAT_SD2: + format = "Sound Designer 2"; + break; + case SF_FORMAT_FLAC: + format = "Free Lossless Audio Codec"; + break; + case SF_FORMAT_CAF: + format = "Core Audio File"; + break; + default: + format = "unknown sndfile"; + } + switch (tmp_sfinfo.format & SF_FORMAT_SUBMASK) + { + case SF_FORMAT_PCM_S8: + subformat = "signed 8 bit"; + break; + case SF_FORMAT_PCM_16: + subformat = "signed 16 bit"; + break; + case SF_FORMAT_PCM_24: + subformat = "signed 24 bit"; + break; + case SF_FORMAT_PCM_32: + subformat = "signed 32 bit"; + break; + case SF_FORMAT_PCM_U8: + subformat = "unsigned 8 bit"; + break; + case SF_FORMAT_FLOAT: + subformat = "32 bit float"; + break; + case SF_FORMAT_DOUBLE: + subformat = "64 bit float"; + break; + case SF_FORMAT_ULAW: + subformat = "U-Law"; + lossy = 1; + break; + case SF_FORMAT_ALAW: + subformat = "A-Law"; + lossy = 1; + break; + case SF_FORMAT_IMA_ADPCM: + subformat = "IMA ADPCM"; + lossy = 1; + break; + case SF_FORMAT_MS_ADPCM: + subformat = "MS ADPCM"; + lossy = 1; + break; + case SF_FORMAT_GSM610: + subformat = "GSM 6.10"; + lossy = 1; + break; + case SF_FORMAT_VOX_ADPCM: + subformat = "Oki Dialogic ADPCM"; + lossy = 1; + break; + case SF_FORMAT_G721_32: + subformat = "32kbs G721 ADPCM"; + lossy = 1; + break; + case SF_FORMAT_G723_24: + subformat = "24kbs G723 ADPCM"; + lossy = 1; + break; + case SF_FORMAT_G723_40: + subformat = "40kbs G723 ADPCM"; + lossy = 1; + break; + case SF_FORMAT_DWVW_12: + subformat = "12 bit Delta Width Variable Word"; + lossy = 1; + break; + case SF_FORMAT_DWVW_16: + subformat = "16 bit Delta Width Variable Word"; + lossy = 1; + break; + case SF_FORMAT_DWVW_24: + subformat = "24 bit Delta Width Variable Word"; + lossy = 1; + break; + case SF_FORMAT_DWVW_N: + subformat = "N bit Delta Width Variable Word"; + lossy = 1; + break; + case SF_FORMAT_DPCM_8: + subformat = "8 bit differential PCM"; + break; + case SF_FORMAT_DPCM_16: + subformat = "16 bit differential PCM"; + } + + codec_gs = g_string_new(""); + if (subformat != NULL) + g_string_append_printf(codec_gs, "%s (%s)", format, subformat); + else + g_string_append_printf(codec_gs, "%s", format); + codec = g_strdup(codec_gs->str); + g_string_free(codec_gs, TRUE); + aud_tuple_associate_string(ti, FIELD_CODEC, NULL, codec); + + if (lossy != 0) + aud_tuple_associate_string(ti, FIELD_QUALITY, NULL, "lossy"); + else + aud_tuple_associate_string(ti, FIELD_QUALITY, NULL, "lossless"); +} + +static gchar *get_title(char *filename) +{ + Tuple *tuple; + gchar *title; + + tuple = aud_tuple_new_from_filename(filename); + fill_song_tuple(filename, tuple); + title = aud_tuple_formatter_make_title_string(tuple, aud_get_gentitle_format()); + if (*title == '\0') + { + g_free(title); + title = g_strdup(aud_tuple_get_string(tuple, FIELD_FILE_NAME, NULL)); + } + + aud_tuple_free(tuple); + return title; +} + +static int +is_our_file (char *filename) +{ + VFSFile *vfsfile = NULL; + SNDFILE *tmp_sndfile; + SF_INFO tmp_sfinfo; + + /* Have to open the file to see if libsndfile can handle it. */ + tmp_sndfile = open_sndfile_from_uri(filename, vfsfile, &tmp_sfinfo); + + if (!tmp_sndfile) { + return FALSE; + } + + /* It can so close file and return TRUE. */ + close_sndfile (tmp_sndfile, vfsfile); + tmp_sndfile = NULL; + + return TRUE; +} + +static gpointer +play_loop (gpointer arg) +{ + static short buffer [BUFFER_SIZE]; + int samples; + InputPlayback *playback = arg; + + for (;;) + { + GTimeVal sleeptime; + + /* sf_read_short will return 0 for all reads at EOF. */ + samples = sf_read_short (sndfile, buffer, BUFFER_SIZE); + + if (samples > 0 && playback->playing == TRUE) { + while ((playback->output->buffer_free () < samples) && + playback->playing == TRUE) { + g_get_current_time(&sleeptime); + g_time_val_add(&sleeptime, 500000); + g_mutex_lock(decode_mutex); + g_cond_timed_wait(decode_cond, decode_mutex, &sleeptime); + g_mutex_unlock(decode_mutex); + + if (playback->playing == FALSE) + break; + } + + playback->pass_audio(playback, FMT_S16_NE, sfinfo.channels, + samples * sizeof (short), buffer, &playback->playing); + } + else { + while(playback->output->buffer_playing()) { + g_get_current_time(&sleeptime); + g_time_val_add(&sleeptime, 500000); + g_mutex_lock(decode_mutex); + g_cond_timed_wait(decode_cond, decode_mutex, &sleeptime); + g_mutex_unlock(decode_mutex); + + if(playback->playing == FALSE) + break; + } + + playback->eof = TRUE; + playback->playing = FALSE; + + g_mutex_unlock(decode_mutex); + break; + } + + /* Do seek if seek_time is valid. */ + if (seek_time >= 0) { + sf_seek (sndfile, (sf_count_t)((gint64)seek_time * (gint64)sfinfo.samplerate / 1000L), + SEEK_SET); + playback->output->flush (seek_time); + seek_time = -1; + } + + if (playback->playing == FALSE) + break; + } + + sf_close (sndfile); + sndfile = NULL; + seek_time = -1; + + playback->output->close_audio(); + + return NULL; +} + +static void +play_start (InputPlayback *playback) +{ + VFSFile *vfsfile = NULL; + int pcmbitwidth; + gchar *song_title; + + if (sndfile) /* already opened */ + return; + + pcmbitwidth = 32; + song_title = get_title(playback->filename); + + sndfile = open_sndfile_from_uri(playback->filename, vfsfile, &sfinfo); + + if (!sndfile) + return; + + bit_rate = sfinfo.samplerate * pcmbitwidth; + + if (sfinfo.samplerate > 0) + song_length = (int) ceil (1000.0 * sfinfo.frames / sfinfo.samplerate); + else + song_length = 0; + + if (! playback->output->open_audio (FMT_S16_NE, sfinfo.samplerate, sfinfo.channels)) + { + close_sndfile (sndfile, vfsfile); + sndfile = NULL; + return; + } + + playback->set_params(playback, song_title, song_length, bit_rate, sfinfo.samplerate, sfinfo.channels); + g_free (song_title); + + playback->playing = TRUE; + + decode_thread = g_thread_self(); + playback->set_pb_ready(playback); + play_loop(playback); +} + +static void +play_pause (InputPlayback *playback, gshort p) +{ + playback->output->pause(p); +} + +static void +play_stop (InputPlayback *playback) +{ + if (decode_thread == NULL) + return; + + g_mutex_lock(decode_mutex); + playback->playing = FALSE; + g_mutex_unlock(decode_mutex); + g_cond_signal(decode_cond); + + g_thread_join (decode_thread); + + sndfile = NULL; + decode_thread = NULL; + seek_time = -1; +} + +static void +file_mseek (InputPlayback *playback, gulong millisecond) +{ + if (! sfinfo.seekable) + return; + + seek_time = (glong)millisecond; + + while (seek_time != -1) + g_usleep (80000); +} + +static void +file_seek (InputPlayback *playback, gint time) +{ + gulong millisecond = time * 1000; + file_mseek(playback, millisecond); +} + +static Tuple* +get_song_tuple (gchar *filename) +{ + Tuple *ti = aud_tuple_new_from_filename(filename); + fill_song_tuple(filename, ti); + return ti; +} + +static int is_our_file_from_vfs(char *filename, VFSFile *fin) +{ + SNDFILE *tmp_sndfile; + SF_INFO tmp_sfinfo; + + /* Have to open the file to see if libsndfile can handle it. */ + tmp_sndfile = sf_open_virtual (&sf_virtual_io, SFM_READ, &tmp_sfinfo, fin); + + if (!tmp_sndfile) + return FALSE; + + /* It can so close file and return TRUE. */ + sf_close (tmp_sndfile); + tmp_sndfile = NULL; + + return TRUE; +} + +static void plugin_about(void) +{ + static GtkWidget *box; + if (!box) + { + box = audacious_info_dialog(_("About sndfile plugin"), + _("Adapted for Audacious usage by Tony Vroon <chainsaw@gentoo.org>\n" + "from the xmms_sndfile plugin which is:\n" + "Copyright (C) 2000, 2002 Erik de Castro Lopo\n\n" + "This program is free software ; you can redistribute it and/or modify \n" + "it under the terms of the GNU General Public License as published by \n" + "the Free Software Foundation ; either version 2 of the License, or \n" + "(at your option) any later version. \n \n" + "This program is distributed in the hope that it will be useful, \n" + "but WITHOUT ANY WARRANTY ; without even the implied warranty of \n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. \n" + "See the GNU General Public License for more details. \n\n" + "You should have received a copy of the GNU General Public \n" + "License along with this program ; if not, write to \n" + "the Free Software Foundation, Inc., \n" + "51 Franklin Street, Fifth Floor, \n" + "Boston, MA 02110-1301 USA"), + _("Ok"), FALSE, NULL, NULL); + g_signal_connect(G_OBJECT(box), "destroy", + (GCallback)gtk_widget_destroyed, &box); + } +} + +static gchar *fmts[] = { "aiff", "au", "raw", "wav", NULL }; + +InputPlugin sndfile_ip = { + .description = "sndfile plugin", + .init = plugin_init, + .about = plugin_about, + .is_our_file = is_our_file, + .play_file = play_start, + .stop = play_stop, + .pause = play_pause, + .seek = file_seek, + .cleanup = plugin_cleanup, + .get_song_tuple = get_song_tuple, + .is_our_file_from_vfs = is_our_file_from_vfs, + .vfs_extensions = fmts, + .mseek = file_mseek, +}; + +InputPlugin *sndfile_iplist[] = { &sndfile_ip, NULL }; + +SIMPLE_INPUT_PLUGIN(sndfile, sndfile_iplist)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sndfile/plugin.h Sat Jan 12 18:41:04 2008 +0100 @@ -0,0 +1,29 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005 Audacious development team. + * + * Based on the xmms_sndfile input plugin: + * Copyright (C) 2000, 2002 Erik de Castro Lopo + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PLUGIN_H +#define PLUGIN_H + +#define BUFFER_SIZE 8192 + +extern InputPlugin sndfile_ip; + +#endif
--- a/src/wav/Makefile Sat Jan 12 16:35:26 2008 +0100 +++ b/src/wav/Makefile Sat Jan 12 18:41:04 2008 +0100 @@ -2,7 +2,7 @@ PLUGIN = wav${PLUGIN_SUFFIX} -SRCS = wav${WAV_SNDFILE}.c +SRCS = wav.c include ../../buildsys.mk
--- a/src/wav/wav-sndfile.c Sat Jan 12 16:35:26 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,591 +0,0 @@ -/* Audacious - Cross-platform multimedia player - * Copyright (C) 2005 Audacious development team. - * - * Based on the xmms_sndfile input plugin: - * Copyright (C) 2000, 2002 Erik de Castro Lopo - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * Rewritten 17-Feb-2007 (nenolod): - * - now uses conditional variables to ensure that sndfile mutex is - * entirely protected. - * - pausing works now - * - fixed some potential race conditions when dealing with NFS. - * - TITLE_LEN removed - */ - -#include "config.h" - -#include <glib.h> -#include <string.h> -#include <math.h> - -#include <audacious/plugin.h> -#include <audacious/util.h> -#include <audacious/i18n.h> -#include <audacious/main.h> -#include <audacious/output.h> -#include "wav-sndfile.h" - -#include <sndfile.h> - -static SNDFILE *sndfile = NULL; -static SF_INFO sfinfo; - -static int song_length; -static int bit_rate = 0; -static glong seek_time = -1; - -static GThread *decode_thread; -static GMutex *decode_mutex; -static GCond *decode_cond; - - - - -static sf_count_t sf_get_filelen (void *user_data) -{ - return aud_vfs_fsize (user_data); -} -static sf_count_t sf_vseek (sf_count_t offset, int whence, void *user_data) -{ - return aud_vfs_fseek(user_data, offset, whence); -} -static sf_count_t sf_vread (void *ptr, sf_count_t count, void *user_data) -{ - return aud_vfs_fread(ptr, 1, count, user_data); -} -static sf_count_t sf_vwrite (const void *ptr, sf_count_t count, void *user_data) -{ - return aud_vfs_fwrite(ptr, 1, count, user_data); -} -static sf_count_t sf_tell (void *user_data) -{ - return aud_vfs_ftell(user_data); -} -static SF_VIRTUAL_IO sf_virtual_io = -{ - sf_get_filelen, - sf_vseek, - sf_vread, - sf_vwrite, - sf_tell -}; - -static SNDFILE * -open_sndfile_from_uri(gchar *filename, VFSFile *vfsfile, SF_INFO *tmp_sfinfo) -{ - SNDFILE *snd_file = NULL; - vfsfile = aud_vfs_fopen(filename, "rb"); - - if (vfsfile == NULL) - return NULL; - - snd_file = sf_open_virtual (&sf_virtual_io, SFM_READ, tmp_sfinfo, vfsfile); - if (snd_file == NULL) - aud_vfs_fclose(vfsfile); - - return snd_file; -} - -static void -close_sndfile(SNDFILE *snd_file, VFSFile *vfsfile) -{ - sf_close(snd_file); - aud_vfs_fclose(vfsfile); -} - - - -static void -plugin_init (void) -{ - seek_time = -1; - - decode_mutex = g_mutex_new(); - decode_cond = g_cond_new(); -} - -static void -plugin_cleanup (void) -{ - g_cond_free(decode_cond); - g_mutex_free(decode_mutex); -} - -static void -fill_song_tuple (char *filename, Tuple *ti) -{ - VFSFile *vfsfile = NULL; - SNDFILE *tmp_sndfile; - SF_INFO tmp_sfinfo; - unsigned int lossy = 0; - gchar *codec = NULL, *format, *subformat = NULL; - GString *codec_gs = NULL; - - tmp_sndfile = open_sndfile_from_uri(filename, vfsfile, &tmp_sfinfo); - if ( sf_get_string(tmp_sndfile, SF_STR_TITLE) == NULL) - aud_tuple_associate_string(ti, FIELD_TITLE, NULL, g_path_get_basename(filename)); - else - aud_tuple_associate_string(ti, FIELD_TITLE, NULL, sf_get_string(tmp_sndfile, SF_STR_TITLE)); - - aud_tuple_associate_string(ti, FIELD_ARTIST, NULL, sf_get_string(tmp_sndfile, SF_STR_ARTIST)); - aud_tuple_associate_string(ti, FIELD_COMMENT, NULL, sf_get_string(tmp_sndfile, SF_STR_COMMENT)); - aud_tuple_associate_string(ti, FIELD_DATE, NULL, sf_get_string(tmp_sndfile, SF_STR_DATE)); - aud_tuple_associate_string(ti, -1, "software", sf_get_string(tmp_sndfile, SF_STR_SOFTWARE)); - - if (!tmp_sndfile) - return; - - close_sndfile (tmp_sndfile, vfsfile); - tmp_sndfile = NULL; - - if (tmp_sfinfo.samplerate > 0) - aud_tuple_associate_int(ti, FIELD_LENGTH, NULL, (int) ceil (1000.0 * tmp_sfinfo.frames / tmp_sfinfo.samplerate)); - - switch (tmp_sfinfo.format & SF_FORMAT_TYPEMASK) - { - case SF_FORMAT_WAV: - case SF_FORMAT_WAVEX: - format = "Microsoft WAV"; - break; - case SF_FORMAT_AIFF: - format = "Apple/SGI AIFF"; - break; - case SF_FORMAT_AU: - format = "Sun/NeXT AU"; - break; - case SF_FORMAT_RAW: - format = "Raw PCM data"; - break; - case SF_FORMAT_PAF: - format = "Ensoniq PARIS"; - break; - case SF_FORMAT_SVX: - format = "Amiga IFF / SVX8 / SV16"; - break; - case SF_FORMAT_NIST: - format = "Sphere NIST"; - break; - case SF_FORMAT_VOC: - format = "Creative VOC"; - break; - case SF_FORMAT_IRCAM: - format = "Berkeley/IRCAM/CARL"; - break; - case SF_FORMAT_W64: - format = "Sonic Foundry's 64 bit RIFF/WAV"; - break; - case SF_FORMAT_MAT4: - format = "Matlab (tm) V4.2 / GNU Octave 2.0"; - break; - case SF_FORMAT_MAT5: - format = "Matlab (tm) V5.0 / GNU Octave 2.1"; - break; - case SF_FORMAT_PVF: - format = "Portable Voice Format"; - break; - case SF_FORMAT_XI: - format = "Fasttracker 2 Extended Instrument"; - break; - case SF_FORMAT_HTK: - format = "HMM Tool Kit"; - break; - case SF_FORMAT_SDS: - format = "Midi Sample Dump Standard"; - break; - case SF_FORMAT_AVR: - format = "Audio Visual Research"; - break; - case SF_FORMAT_SD2: - format = "Sound Designer 2"; - break; - case SF_FORMAT_FLAC: - format = "Free Lossless Audio Codec"; - break; - case SF_FORMAT_CAF: - format = "Core Audio File"; - break; - default: - format = "unknown sndfile"; - } - switch (tmp_sfinfo.format & SF_FORMAT_SUBMASK) - { - case SF_FORMAT_PCM_S8: - subformat = "signed 8 bit"; - break; - case SF_FORMAT_PCM_16: - subformat = "signed 16 bit"; - break; - case SF_FORMAT_PCM_24: - subformat = "signed 24 bit"; - break; - case SF_FORMAT_PCM_32: - subformat = "signed 32 bit"; - break; - case SF_FORMAT_PCM_U8: - subformat = "unsigned 8 bit"; - break; - case SF_FORMAT_FLOAT: - subformat = "32 bit float"; - break; - case SF_FORMAT_DOUBLE: - subformat = "64 bit float"; - break; - case SF_FORMAT_ULAW: - subformat = "U-Law"; - lossy = 1; - break; - case SF_FORMAT_ALAW: - subformat = "A-Law"; - lossy = 1; - break; - case SF_FORMAT_IMA_ADPCM: - subformat = "IMA ADPCM"; - lossy = 1; - break; - case SF_FORMAT_MS_ADPCM: - subformat = "MS ADPCM"; - lossy = 1; - break; - case SF_FORMAT_GSM610: - subformat = "GSM 6.10"; - lossy = 1; - break; - case SF_FORMAT_VOX_ADPCM: - subformat = "Oki Dialogic ADPCM"; - lossy = 1; - break; - case SF_FORMAT_G721_32: - subformat = "32kbs G721 ADPCM"; - lossy = 1; - break; - case SF_FORMAT_G723_24: - subformat = "24kbs G723 ADPCM"; - lossy = 1; - break; - case SF_FORMAT_G723_40: - subformat = "40kbs G723 ADPCM"; - lossy = 1; - break; - case SF_FORMAT_DWVW_12: - subformat = "12 bit Delta Width Variable Word"; - lossy = 1; - break; - case SF_FORMAT_DWVW_16: - subformat = "16 bit Delta Width Variable Word"; - lossy = 1; - break; - case SF_FORMAT_DWVW_24: - subformat = "24 bit Delta Width Variable Word"; - lossy = 1; - break; - case SF_FORMAT_DWVW_N: - subformat = "N bit Delta Width Variable Word"; - lossy = 1; - break; - case SF_FORMAT_DPCM_8: - subformat = "8 bit differential PCM"; - break; - case SF_FORMAT_DPCM_16: - subformat = "16 bit differential PCM"; - } - - codec_gs = g_string_new(""); - if (subformat != NULL) - g_string_append_printf(codec_gs, "%s (%s)", format, subformat); - else - g_string_append_printf(codec_gs, "%s", format); - codec = g_strdup(codec_gs->str); - g_string_free(codec_gs, TRUE); - aud_tuple_associate_string(ti, FIELD_CODEC, NULL, codec); - - if (lossy != 0) - aud_tuple_associate_string(ti, FIELD_QUALITY, NULL, "lossy"); - else - aud_tuple_associate_string(ti, FIELD_QUALITY, NULL, "lossless"); -} - -static gchar *get_title(char *filename) -{ - Tuple *tuple; - gchar *title; - - tuple = aud_tuple_new_from_filename(filename); - fill_song_tuple(filename, tuple); - title = aud_tuple_formatter_make_title_string(tuple, aud_get_gentitle_format()); - if (*title == '\0') - { - g_free(title); - title = g_strdup(aud_tuple_get_string(tuple, FIELD_FILE_NAME, NULL)); - } - - aud_tuple_free(tuple); - return title; -} - -static int -is_our_file (char *filename) -{ - VFSFile *vfsfile = NULL; - SNDFILE *tmp_sndfile; - SF_INFO tmp_sfinfo; - - /* Have to open the file to see if libsndfile can handle it. */ - tmp_sndfile = open_sndfile_from_uri(filename, vfsfile, &tmp_sfinfo); - - if (!tmp_sndfile) { - return FALSE; - } - - /* It can so close file and return TRUE. */ - close_sndfile (tmp_sndfile, vfsfile); - tmp_sndfile = NULL; - - return TRUE; -} - -static gpointer -play_loop (gpointer arg) -{ - static short buffer [BUFFER_SIZE]; - int samples; - InputPlayback *playback = arg; - - for (;;) - { - GTimeVal sleeptime; - - /* sf_read_short will return 0 for all reads at EOF. */ - samples = sf_read_short (sndfile, buffer, BUFFER_SIZE); - - if (samples > 0 && playback->playing == TRUE) { - while ((playback->output->buffer_free () < samples) && - playback->playing == TRUE) { - g_get_current_time(&sleeptime); - g_time_val_add(&sleeptime, 500000); - g_mutex_lock(decode_mutex); - g_cond_timed_wait(decode_cond, decode_mutex, &sleeptime); - g_mutex_unlock(decode_mutex); - - if (playback->playing == FALSE) - break; - } - - playback->pass_audio(playback, FMT_S16_NE, sfinfo.channels, - samples * sizeof (short), buffer, &playback->playing); - } - else { - while(playback->output->buffer_playing()) { - g_get_current_time(&sleeptime); - g_time_val_add(&sleeptime, 500000); - g_mutex_lock(decode_mutex); - g_cond_timed_wait(decode_cond, decode_mutex, &sleeptime); - g_mutex_unlock(decode_mutex); - - if(playback->playing == FALSE) - break; - } - - playback->eof = TRUE; - playback->playing = FALSE; - - g_mutex_unlock(decode_mutex); - break; - } - - /* Do seek if seek_time is valid. */ - if (seek_time >= 0) { - sf_seek (sndfile, (sf_count_t)((gint64)seek_time * (gint64)sfinfo.samplerate / 1000L), - SEEK_SET); - playback->output->flush (seek_time); - seek_time = -1; - } - - if (playback->playing == FALSE) - break; - } - - sf_close (sndfile); - sndfile = NULL; - seek_time = -1; - - playback->output->close_audio(); - - return NULL; -} - -static void -play_start (InputPlayback *playback) -{ - VFSFile *vfsfile = NULL; - int pcmbitwidth; - gchar *song_title; - - if (sndfile) /* already opened */ - return; - - pcmbitwidth = 32; - song_title = get_title(playback->filename); - - sndfile = open_sndfile_from_uri(playback->filename, vfsfile, &sfinfo); - - if (!sndfile) - return; - - bit_rate = sfinfo.samplerate * pcmbitwidth; - - if (sfinfo.samplerate > 0) - song_length = (int) ceil (1000.0 * sfinfo.frames / sfinfo.samplerate); - else - song_length = 0; - - if (! playback->output->open_audio (FMT_S16_NE, sfinfo.samplerate, sfinfo.channels)) - { - close_sndfile (sndfile, vfsfile); - sndfile = NULL; - return; - } - - playback->set_params(playback, song_title, song_length, bit_rate, sfinfo.samplerate, sfinfo.channels); - g_free (song_title); - - playback->playing = TRUE; - - decode_thread = g_thread_self(); - playback->set_pb_ready(playback); - play_loop(playback); -} - -static void -play_pause (InputPlayback *playback, gshort p) -{ - playback->output->pause(p); -} - -static void -play_stop (InputPlayback *playback) -{ - if (decode_thread == NULL) - return; - - g_mutex_lock(decode_mutex); - playback->playing = FALSE; - g_mutex_unlock(decode_mutex); - g_cond_signal(decode_cond); - - g_thread_join (decode_thread); - - sndfile = NULL; - decode_thread = NULL; - seek_time = -1; -} - -static void -file_mseek (InputPlayback *playback, gulong millisecond) -{ - if (! sfinfo.seekable) - return; - - seek_time = (glong)millisecond; - - while (seek_time != -1) - g_usleep (80000); -} - -static void -file_seek (InputPlayback *playback, gint time) -{ - gulong millisecond = time * 1000; - file_mseek(playback, millisecond); -} - -static Tuple* -get_song_tuple (gchar *filename) -{ - Tuple *ti = aud_tuple_new_from_filename(filename); - fill_song_tuple(filename, ti); - return ti; -} - -static int is_our_file_from_vfs(char *filename, VFSFile *fin) -{ - SNDFILE *tmp_sndfile; - SF_INFO tmp_sfinfo; - - /* Have to open the file to see if libsndfile can handle it. */ - tmp_sndfile = sf_open_virtual (&sf_virtual_io, SFM_READ, &tmp_sfinfo, fin); - - if (!tmp_sndfile) - return FALSE; - - /* It can so close file and return TRUE. */ - sf_close (tmp_sndfile); - tmp_sndfile = NULL; - - return TRUE; -} - -static void wav_about(void) -{ - static GtkWidget *box; - if (!box) - { - box = audacious_info_dialog(_("About sndfile WAV support"), - _("Adapted for Audacious usage by Tony Vroon <chainsaw@gentoo.org>\n" - "from the xmms_sndfile plugin which is:\n" - "Copyright (C) 2000, 2002 Erik de Castro Lopo\n\n" - "This program is free software ; you can redistribute it and/or modify \n" - "it under the terms of the GNU General Public License as published by \n" - "the Free Software Foundation ; either version 2 of the License, or \n" - "(at your option) any later version. \n \n" - "This program is distributed in the hope that it will be useful, \n" - "but WITHOUT ANY WARRANTY ; without even the implied warranty of \n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. \n" - "See the GNU General Public License for more details. \n\n" - "You should have received a copy of the GNU General Public \n" - "License along with this program ; if not, write to \n" - "the Free Software Foundation, Inc., \n" - "51 Franklin Street, Fifth Floor, \n" - "Boston, MA 02110-1301 USA"), - _("Ok"), FALSE, NULL, NULL); - g_signal_connect(G_OBJECT(box), "destroy", - (GCallback)gtk_widget_destroyed, &box); - } -} - -static gchar *fmts[] = { "aiff", "au", "raw", "wav", NULL }; - -InputPlugin wav_ip = { - .description = "sndfile WAV plugin", - .init = plugin_init, - .about = wav_about, - .is_our_file = is_our_file, - .play_file = play_start, - .stop = play_stop, - .pause = play_pause, - .seek = file_seek, - .cleanup = plugin_cleanup, - .get_song_tuple = get_song_tuple, - .is_our_file_from_vfs = is_our_file_from_vfs, - .vfs_extensions = fmts, - .mseek = file_mseek, -}; - -InputPlugin *wav_iplist[] = { &wav_ip, NULL }; - -SIMPLE_INPUT_PLUGIN(wav-sndfile, wav_iplist)
--- a/src/wav/wav-sndfile.h Sat Jan 12 16:35:26 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -/* Audacious - Cross-platform multimedia player - * Copyright (C) 2005 Audacious development team. - * - * Based on the xmms_sndfile input plugin: - * Copyright (C) 2000, 2002 Erik de Castro Lopo - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef WAV_SNDFILE_H -#define WAV_SNDFILE_H - -#define BUFFER_SIZE 8192 - -extern InputPlugin wav_ip; - -#endif
--- a/src/wav/wav.c Sat Jan 12 16:35:26 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,552 +0,0 @@ -/* BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * - * Based on XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include "wav.h" - -#include <glib.h> -#include <string.h> - -#include <audacious/util.h> -#include <audacious/main.h> -#include <audacious/output.h> -#include <audacious/i18n.h> - -gchar *wav_fmts[] = { "wav", "raw", "pcm", NULL }; - -InputPlugin wav_ip = { - .description = "WAV Audio Plugin", /* Description */ - .init = wav_init, - .is_our_file = is_our_file, - .play_file = play_file, - .stop = stop, - .pause = wav_pause, - .seek = seek, - .get_time = get_time, - .get_song_info = get_song_info, - .vfs_extensions = wav_fmts, - .mseek = mseek, -}; - -WaveFile *wav_file = NULL; -static GThread *decode_thread; -static gboolean audio_error = FALSE; - -InputPlugin *wav_iplist[] = { &wav_ip, NULL }; - -DECLARE_PLUGIN(wav, NULL, NULL, wav_iplist, NULL, NULL, NULL, NULL, NULL); - -static void -wav_init(void) -{ - /* empty */ -} - -/* needed for is_our_file() */ -static gint -read_n_bytes(VFSFile * file, guint8 * buf, gsize n) -{ - if (aud_vfs_fread(buf, 1, n, file) != n) { - return FALSE; - } - return TRUE; -} - -static guint32 -convert_to_header(guint8 * buf) -{ - - return (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]; -} - -static guint32 -convert_to_long(guint8 * buf) -{ - - return (buf[3] << 24) + (buf[2] << 16) + (buf[1] << 8) + buf[0]; -} - -static guint16 -read_wav_id(gchar * filename) -{ - VFSFile *file; - guint16 wavid; - guint8 buf[4]; - guint32 head; - glong seek; - - if (!(file = aud_vfs_fopen(filename, "rb"))) { /* Could not open file */ - return 0; - } - if (!(read_n_bytes(file, buf, 4))) { - aud_vfs_fclose(file); - return 0; - } - head = convert_to_header(buf); - if (head == ('R' << 24) + ('I' << 16) + ('F' << 8) + 'F') { /* Found a riff -- maybe WAVE */ - if (aud_vfs_fseek(file, 4, SEEK_CUR) != 0) { /* some error occured */ - aud_vfs_fclose(file); - return 0; - } - if (!(read_n_bytes(file, buf, 4))) { - aud_vfs_fclose(file); - return 0; - } - head = convert_to_header(buf); - if (head == ('W' << 24) + ('A' << 16) + ('V' << 8) + 'E') { /* Found a WAVE */ - seek = 0; - do { /* we'll be looking for the fmt-chunk which comes before the data-chunk */ - /* A chunk consists of an header identifier (4 bytes), the length of the chunk - (4 bytes), and the chunkdata itself, padded to be an even number of bytes. - We'll skip all chunks until we find the "data"-one which could contain - mpeg-data */ - if (seek != 0) { - if (aud_vfs_fseek(file, seek, SEEK_CUR) != 0) { /* some error occured */ - aud_vfs_fclose(file); - return 0; - } - } - if (!(read_n_bytes(file, buf, 4))) { - aud_vfs_fclose(file); - return 0; - } - head = convert_to_header(buf); - if (!(read_n_bytes(file, buf, 4))) { - aud_vfs_fclose(file); - return 0; - } - seek = convert_to_long(buf); - seek = seek + (seek % 2); /* Has to be even (padding) */ - if (seek >= 2 - && head == ('f' << 24) + ('m' << 16) + ('t' << 8) + ' ') { - if (!(read_n_bytes(file, buf, 2))) { - aud_vfs_fclose(file); - return 0; - } - wavid = buf[0] + 256 * buf[1]; - seek -= 2; - /* we could go on looking for other things, but all we wanted was the wavid */ - aud_vfs_fclose(file); - return wavid; - } - } - while (head != ('d' << 24) + ('a' << 16) + ('t' << 8) + 'a'); - /* it's RIFF WAVE */ - } - /* it's RIFF */ - } - /* it's not even RIFF */ - aud_vfs_fclose(file); - return 0; -} - -static gboolean -is_our_file(gchar * filename) -{ - gchar *ext; - - ext = strrchr(filename, '.'); - if (ext) - if (!strcasecmp(ext, ".wav")) - if (read_wav_id(filename) == WAVE_FORMAT_PCM) - return TRUE; - return FALSE; -} - - -static gchar * -get_title(const gchar * filename) -{ - Tuple *tuple; - gchar *title; - - tuple = aud_tuple_new_from_filename(filename); - - aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, "RIFF/WAV Audio (ADPCM)"); - aud_tuple_associate_string(tuple, FIELD_QUALITY, NULL, "lossless"); - - title = aud_tuple_formatter_make_title_string(tuple, aud_get_gentitle_format()); - if (*title == '\0') - { - g_free(title); - title = g_strdup(aud_tuple_get_string(tuple, FIELD_FILE_NAME, NULL)); - } - - aud_tuple_free(tuple); - - return title; -} - -static gint -read_le_long(VFSFile * file, glong * ret) -{ - guchar buf[4]; - - if (aud_vfs_fread(buf, 1, 4, file) != 4) - return 0; - - *ret = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; - return TRUE; -} - -#define read_le_ulong(file,ret) read_le_long(file,(long*)ret) - -static int -read_le_short(VFSFile * file, gshort * ret) -{ - guchar buf[2]; - - if (aud_vfs_fread(buf, 1, 2, file) != 2) - return 0; - - *ret = (buf[1] << 8) | buf[0]; - return TRUE; -} - -static gpointer -play_loop(gpointer arg) -{ - InputPlayback *playback = arg; - gchar data[2048 * 2]; - gsize bytes, blk_size, rate; - gint actual_read; - - blk_size = 512 * (wav_file->bits_per_sample / 8) * wav_file->channels; - rate = - wav_file->samples_per_sec * wav_file->channels * - (wav_file->bits_per_sample / 8); - while (playback->playing) { - if (!playback->eof) { - bytes = blk_size; - if (wav_file->length - wav_file->position < bytes) - bytes = wav_file->length - wav_file->position; - if (bytes > 0) { - actual_read = aud_vfs_fread(data, 1, bytes, wav_file->file); - - if (actual_read == 0) - playback->eof = TRUE; - else { - if (wav_file->seek_to == -1) - playback->pass_audio(playback, - (wav_file->bits_per_sample == - 16) ? FMT_S16_LE : FMT_U8, - wav_file->channels, bytes, data, - &playback->playing); - wav_file->position += actual_read; - } - } - else - playback->eof = TRUE; - } - else { - playback->output->buffer_free (); - playback->output->buffer_free (); - while (playback->output->buffer_playing()) - g_usleep(10000); - playback->playing = 0; - } - - if (wav_file->seek_to != -1) { - wav_file->position = (unsigned long)((gint64)wav_file->seek_to * (gint64)rate / 1000L); - aud_vfs_fseek(wav_file->file, - wav_file->position + wav_file->data_offset, SEEK_SET); - playback->output->flush(wav_file->seek_to); - wav_file->seek_to = -1; - } - - } - aud_vfs_fclose(wav_file->file); - return NULL; -} - -static void -play_file(InputPlayback * playback) -{ - gchar * filename = playback->filename; - gchar magic[4], *name; - gulong len; - gint rate; - - audio_error = FALSE; - - wav_file = g_new0(WaveFile, 1); - if ((wav_file->file = aud_vfs_fopen(filename, "rb"))) { - aud_vfs_fread(magic, 1, 4, wav_file->file); - if (strncmp(magic, "RIFF", 4)) { - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - read_le_ulong(wav_file->file, &len); - aud_vfs_fread(magic, 1, 4, wav_file->file); - if (strncmp(magic, "WAVE", 4)) { - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - for (;;) { - aud_vfs_fread(magic, 1, 4, wav_file->file); - if (!read_le_ulong(wav_file->file, &len)) { - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - if (!strncmp("fmt ", magic, 4)) - break; - aud_vfs_fseek(wav_file->file, len, SEEK_CUR); - } - if (len < 16) { - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - read_le_short(wav_file->file, &wav_file->format_tag); - switch (wav_file->format_tag) { - case WAVE_FORMAT_UNKNOWN: - case WAVE_FORMAT_ALAW: - case WAVE_FORMAT_MULAW: - case WAVE_FORMAT_ADPCM: - case WAVE_FORMAT_OKI_ADPCM: - case WAVE_FORMAT_DIGISTD: - case WAVE_FORMAT_DIGIFIX: - case IBM_FORMAT_MULAW: - case IBM_FORMAT_ALAW: - case IBM_FORMAT_ADPCM: - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - read_le_short(wav_file->file, &wav_file->channels); - read_le_long(wav_file->file, &wav_file->samples_per_sec); - read_le_long(wav_file->file, &wav_file->avg_bytes_per_sec); - read_le_short(wav_file->file, &wav_file->block_align); - read_le_short(wav_file->file, &wav_file->bits_per_sample); - if (wav_file->bits_per_sample != 8 && wav_file->bits_per_sample != 16) { - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - len -= 16; - if (len) - aud_vfs_fseek(wav_file->file, len, SEEK_CUR); - - for (;;) { - aud_vfs_fread(magic, 4, 1, wav_file->file); - - if (!read_le_ulong(wav_file->file, &len)) { - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - if (!strncmp("data", magic, 4)) - break; - aud_vfs_fseek(wav_file->file, len, SEEK_CUR); - } - wav_file->data_offset = aud_vfs_ftell(wav_file->file); - wav_file->length = len; - - wav_file->position = 0; - playback->playing = 1; - - if (playback->output-> - open_audio((wav_file->bits_per_sample == - 16) ? FMT_S16_LE : FMT_U8, - wav_file->samples_per_sec, wav_file->channels) == 0) { - audio_error = TRUE; - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - name = get_title(filename); - rate = - wav_file->samples_per_sec * wav_file->channels * - (wav_file->bits_per_sample / 8); - playback->set_params(playback, name, 1000 * (wav_file->length / rate), 8 * rate, - wav_file->samples_per_sec, wav_file->channels); - g_free(name); - wav_file->seek_to = -1; - decode_thread = g_thread_self(); - playback->set_pb_ready(playback); - play_loop(playback); - } -} - -static void -stop(InputPlayback * playback) -{ - if (wav_file && playback->playing) { - playback->playing = 0; - g_thread_join(decode_thread); - playback->output->close_audio(); - g_free(wav_file); - wav_file = NULL; - } -} - -static void -wav_pause(InputPlayback * playback, gshort p) -{ - playback->output->pause(p); -} - -static void -mseek(InputPlayback * playback, gulong millisecond) -{ - wav_file->seek_to = millisecond; - - playback->eof = FALSE; - - while (wav_file->seek_to != -1) - g_usleep(10000); -} - -static void -seek(InputPlayback * data, gint time) -{ - gulong millisecond = time * 1000; - mseek(data, millisecond); -} - -static int -get_time(InputPlayback *playback) -{ - if (audio_error) - return -2; - if (!wav_file) - return -1; - if (!playback->playing - || (playback->eof && !playback->output->buffer_playing())) - return -1; - else { - return playback->output->output_time(); - } -} - -static void -get_song_info(gchar * filename, gchar ** title, gint * length) -{ - gchar magic[4]; - gulong len; - gint rate; - WaveFile *wav_file; - - wav_file = g_malloc(sizeof(WaveFile)); - memset(wav_file, 0, sizeof(WaveFile)); - if (!(wav_file->file = aud_vfs_fopen(filename, "rb"))) - return; - - aud_vfs_fread(magic, 1, 4, wav_file->file); - if (strncmp(magic, "RIFF", 4)) { - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - read_le_ulong(wav_file->file, &len); - aud_vfs_fread(magic, 1, 4, wav_file->file); - if (strncmp(magic, "WAVE", 4)) { - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - for (;;) { - aud_vfs_fread(magic, 1, 4, wav_file->file); - if (!read_le_ulong(wav_file->file, &len)) { - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - if (!strncmp("fmt ", magic, 4)) - break; - aud_vfs_fseek(wav_file->file, len, SEEK_CUR); - } - if (len < 16) { - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - read_le_short(wav_file->file, &wav_file->format_tag); - switch (wav_file->format_tag) { - case WAVE_FORMAT_UNKNOWN: - case WAVE_FORMAT_ALAW: - case WAVE_FORMAT_MULAW: - case WAVE_FORMAT_ADPCM: - case WAVE_FORMAT_OKI_ADPCM: - case WAVE_FORMAT_DIGISTD: - case WAVE_FORMAT_DIGIFIX: - case IBM_FORMAT_MULAW: - case IBM_FORMAT_ALAW: - case IBM_FORMAT_ADPCM: - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - read_le_short(wav_file->file, &wav_file->channels); - read_le_long(wav_file->file, &wav_file->samples_per_sec); - read_le_long(wav_file->file, &wav_file->avg_bytes_per_sec); - read_le_short(wav_file->file, &wav_file->block_align); - read_le_short(wav_file->file, &wav_file->bits_per_sample); - if (wav_file->bits_per_sample != 8 && wav_file->bits_per_sample != 16) { - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - len -= 16; - if (len) - aud_vfs_fseek(wav_file->file, len, SEEK_CUR); - - for (;;) { - aud_vfs_fread(magic, 4, 1, wav_file->file); - - if (!read_le_ulong(wav_file->file, &len)) { - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; - return; - } - if (!strncmp("data", magic, 4)) - break; - aud_vfs_fseek(wav_file->file, len, SEEK_CUR); - } - rate = - wav_file->samples_per_sec * wav_file->channels * - (wav_file->bits_per_sample / 8); - (*length) = 1000 * (len / rate); - (*title) = get_title(filename); - - aud_vfs_fclose(wav_file->file); - g_free(wav_file); - wav_file = NULL; -}
--- a/src/wav/wav.h Sat Jan 12 16:35:26 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* XMMS - Cross-platform multimedia player - * Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef WAV_H -#define WAV_H - -#include "config.h" - -#include <glib.h> -#include <sys/types.h> -#include <audacious/plugin.h> - -#define WAVE_FORMAT_UNKNOWN (0x0000) -#define WAVE_FORMAT_PCM (0x0001) -#define WAVE_FORMAT_ADPCM (0x0002) -#define WAVE_FORMAT_ALAW (0x0006) -#define WAVE_FORMAT_MULAW (0x0007) -#define WAVE_FORMAT_OKI_ADPCM (0x0010) -#define WAVE_FORMAT_DIGISTD (0x0015) -#define WAVE_FORMAT_DIGIFIX (0x0016) -#define IBM_FORMAT_MULAW (0x0101) -#define IBM_FORMAT_ALAW (0x0102) -#define IBM_FORMAT_ADPCM (0x0103) - -extern InputPlugin wav_ip; - -typedef struct { - VFSFile *file; - short format_tag, channels, block_align, bits_per_sample; - long samples_per_sec, avg_bytes_per_sec; - unsigned long position, length; - glong seek_to; - int data_offset; - pid_t pid; -} WaveFile; - -static void wav_init(void); -static int is_our_file(char *filename); -static void play_file(InputPlayback * data); -static void stop(InputPlayback * data); -static void seek(InputPlayback * data, int time); -static void wav_pause(InputPlayback * data, short p); -static int get_time(InputPlayback * data); -static void get_song_info(char *filename, char **title, int *length); -static void mseek(InputPlayback * data, gulong millisecond); - -#endif