summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-01-11 22:08:31 +0100
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-01-11 22:19:27 +0100
commitf6fdf11dcbc98fa1477bcfc5ae7317a5b2e75ede (patch)
treeabee6c4200df2b4e924da4ef54f6bcae0c77a62f
parent92a8bcfc52f15022e3e7c0bdbc82f12ac327ecca (diff)
decoder plugin reentrancy WIP (mp3 works)
-rw-r--r--Makefile.am44
-rw-r--r--deadbeef.h25
-rw-r--r--main.c2
-rw-r--r--moduleconf.h6
-rw-r--r--playlist.c6
-rw-r--r--plugins.c10
-rw-r--r--plugins/gtkui/gtkui.c8
-rw-r--r--plugins/mpgmad/mpgmad.c413
-rw-r--r--streamer.c67
-rw-r--r--streamer.h2
-rw-r--r--vfs.c4
11 files changed, 312 insertions, 275 deletions
diff --git a/Makefile.am b/Makefile.am
index 9e9ca153..8c943340 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,25 +1,34 @@
-SUBDIRS = gme/Game_Music_Emu-0.5.2\
- gme/Game_Music_Emu-0.5.2/gme\
- sid/sidplay-libs-2.1.0\
- dumb\
+SUBDIRS = ${MPGMAD_DIR}\
pixmaps\
icons\
plugins/hotkeys\
- plugins/ffap\
plugins/nullout\
- plugins/vtx\
- plugins/adplug\
${ALSA_DIR}\
${LFM_DIR}\
- ${MPGMAD_DIR}\
- ${VORBIS_DIR}\
- ${FLAC_DIR}\
- ${WAVPACK_DIR}\
- ${SNDFILE_DIR}\
${VFS_CURL_DIR}\
- ${CDDA_DIR}\
- ${GTKUI_DIR}\
- ${FFMPEG_DIR}
+ ${GTKUI_DIR}
+
+#SUBDIRS = gme/Game_Music_Emu-0.5.2\
+# sid/sidplay-libs-2.1.0\
+# dumb\
+# pixmaps\
+# icons\
+# plugins/hotkeys\
+# plugins/ffap\
+# plugins/nullout\
+# plugins/vtx\
+# plugins/adplug\
+# ${ALSA_DIR}\
+# ${LFM_DIR}\
+# ${MPGMAD_DIR}\
+# ${VORBIS_DIR}\
+# ${FLAC_DIR}\
+# ${WAVPACK_DIR}\
+# ${SNDFILE_DIR}\
+# ${VFS_CURL_DIR}\
+# ${CDDA_DIR}\
+# ${GTKUI_DIR}\
+# ${FFMPEG_DIR}
dumbpath=@top_srcdir@/dumb
sidpath=@top_srcdir@/sid/sidplay-libs-2.1.0
@@ -35,7 +44,6 @@ deadbeef_SOURCES =\
codec.c codec.h\
messagepump.c messagepump.h\
conf.c conf.h\
- cgme.c cdumb.c csid.cpp\
playback.h\
threading_pthread.c threading.h\
md5/md5.c md5/md5.h md5/md5_loc.h\
@@ -45,11 +53,13 @@ deadbeef_SOURCES =\
optmath.h\
vfs.c vfs.h vfs_stdio.c\
timeline.c timeline.h
+# cgme.c cdumb.c csid.cpp
sdkdir = $(pkgincludedir)
sdk_HEADERS = deadbeef.h
-deadbeef_LDADD = $(LDADD) $(DEPS_LIBS) gme/Game_Music_Emu-0.5.2/gme/libgme.a sid/sidplay-libs-2.1.0/libsidplay2.a dumb/libdumb.a -lstdc++
+#deadbeef_LDADD = $(LDADD) $(DEPS_LIBS) gme/Game_Music_Emu-0.5.2/gme/libgme.a sid/sidplay-libs-2.1.0/libsidplay2.a dumb/libdumb.a -lstdc++
+deadbeef_LDADD = $(LDADD) $(DEPS_LIBS) -lstdc++
AM_CFLAGS = $(DEPS_CFLAGS) -I$(gmepath) -std=c99
AM_CPPFLAGS = $(DEPS_CFLAGS) -I$(sidpath)/libsidplay/include -I$(sidpath)/builders/resid-builder/include
diff --git a/deadbeef.h b/deadbeef.h
index a9bb9aff..801fd8e9 100644
--- a/deadbeef.h
+++ b/deadbeef.h
@@ -67,7 +67,7 @@ extern "C" {
.plugin.api_vmajor = DB_API_VERSION_MAJOR,\
.plugin.api_vminor = DB_API_VERSION_MINOR,
-#define MAX_OUTPUT_PLUGINS 30
+#define MAX_DECODER_PLUGINS 50
////////////////////////////
// playlist structures
@@ -251,7 +251,7 @@ typedef struct {
int (*streamer_read) (char *bytes, int size);
void (*streamer_set_bitrate) (int bitrate);
int (*streamer_get_apx_bitrate) (void);
- struct DB_decoder_s *(*streamer_get_current_decoder) (void);
+ struct DB_fileinfo_s *(*streamer_get_current_decoder) (void);
// process control
const char *(*get_config_dir) (void);
void (*quit) (void);
@@ -421,7 +421,8 @@ typedef struct DB_plugin_s {
const char *configdialog;
} DB_plugin_t;
-typedef struct {
+typedef struct DB_fileinfo_s {
+ struct DB_decoder_s *plugin;
int bps;
int channels;
int samplerate;
@@ -431,36 +432,36 @@ typedef struct {
// decoder plugin
typedef struct DB_decoder_s {
DB_plugin_t plugin;
- DB_fileinfo_t info;
+// DB_fileinfo_t info;
// init is called to prepare song to be started
- int (*init) (DB_playItem_t *it);
+ DB_fileinfo_t *(*init) (DB_playItem_t *it);
// free is called after decoding is finished
- void (*free) (void);
+ void (*free) (DB_fileinfo_t *info);
// read is called by streamer to decode specified number of bytes
// must return number of bytes that were successfully decoded (sample aligned)
// read_int16 must always output 16 bit signed integer samples
- int (*read_int16) (char *buffer, int size);
+ int (*read_int16) (DB_fileinfo_t *info, char *buffer, int size);
// read_float32 must always output 32 bit floating point samples
- int (*read_float32) (char *buffer, int size);
+ int (*read_float32) (DB_fileinfo_t *info, char *buffer, int size);
- int (*seek) (float seconds);
+ int (*seek) (DB_fileinfo_t *info, float seconds);
// perform seeking in samples (if possible)
// return -1 if failed, or 0 on success
// if -1 is returned, that will mean that streamer must skip that song
- int (*seek_sample) (int sample);
+ int (*seek_sample) (DB_fileinfo_t *info, int sample);
// 'insert' is called to insert new item to playlist
// decoder is responsible to calculate duration, split it into subsongs, load cuesheet, etc
// after==NULL means "prepend before 1st item in playlist"
DB_playItem_t * (*insert) (DB_playItem_t *after, const char *fname);
- int (*numvoices) (void);
- void (*mutevoice) (int voice, int mute);
+ int (*numvoices) (DB_fileinfo_t *info);
+ void (*mutevoice) (DB_fileinfo_t *info, int voice, int mute);
// NULL terminated array of all supported extensions
const char **exts;
diff --git a/main.c b/main.c
index 73552cb6..83c150fa 100644
--- a/main.c
+++ b/main.c
@@ -127,7 +127,7 @@ server_exec_command_line (const char *cmdline, int len, char *sendback, int sbsi
}
if (sendback) {
playItem_t *curr = streamer_get_playing_track ();
- DB_decoder_t *dec = streamer_get_current_decoder ();
+ DB_fileinfo_t *dec = streamer_get_current_decoder ();
if (curr && dec) {
const char np[] = "nowplaying ";
memcpy (sendback, np, sizeof (np)-1);
diff --git a/moduleconf.h b/moduleconf.h
index 4fdc123c..40aa3038 100644
--- a/moduleconf.h
+++ b/moduleconf.h
@@ -1,4 +1,4 @@
-PLUG(gme)
-PLUG(dumb)
-PLUG(sid)
+//PLUG(gme)
+//PLUG(dumb)
+//PLUG(sid)
PLUG(stdio)
diff --git a/playlist.c b/playlist.c
index 62ea6a7a..aef7d531 100644
--- a/playlist.c
+++ b/playlist.c
@@ -42,8 +42,8 @@
#define PLAYLIST_MAJOR_VER 1
#define PLAYLIST_MINOR_VER 1
-//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
-#define trace(fmt,...)
+#define trace(...) { fprintf(stderr, __VA_ARGS__); }
+//#define trace(fmt,...)
#define SKIP_BLANK_CUE_TRACKS 1
@@ -682,6 +682,7 @@ pl_insert_pls (playItem_t *after, const char *fname, int *pabort, int (*cb)(play
playItem_t *
pl_insert_file (playItem_t *after, const char *fname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data) {
+ trace ("pl_insert_file %s\n", fname);
if (!fname || !(*fname)) {
return NULL;
}
@@ -738,6 +739,7 @@ pl_insert_file (playItem_t *after, const char *fname, int *pabort, int (*cb)(pla
DB_decoder_t **decoders = plug_get_decoder_list ();
// match by decoder
for (int i = 0; decoders[i]; i++) {
+ trace ("matching decoder %d(%s)...\n", i, decoders[i]->id);
if (decoders[i]->exts && decoders[i]->insert) {
const char **exts = decoders[i]->exts;
for (int e = 0; exts[e]; e++) {
diff --git a/plugins.c b/plugins.c
index 8ce57d92..8163ec11 100644
--- a/plugins.c
+++ b/plugins.c
@@ -200,12 +200,12 @@ plug_volume_set_amp (float amp) {
#define MAX_PLUGINS 100
DB_plugin_t *g_plugins[MAX_PLUGINS+1];
-#define MAX_DECODER_PLUGINS 50
DB_decoder_t *g_decoder_plugins[MAX_DECODER_PLUGINS+1];
#define MAX_VFS_PLUGINS 10
DB_vfs_t *g_vfs_plugins[MAX_VFS_PLUGINS+1];
+#define MAX_OUTPUT_PLUGINS 10
DB_output_t *g_output_plugins[MAX_OUTPUT_PLUGINS+1];
DB_output_t *output_plugin = NULL;
@@ -734,13 +734,13 @@ plug_reinit_sound (void) {
}
// list of all unique decoder ids used in current session
-static char *decoder_ids[MAX_OUTPUT_PLUGINS];
+static char *decoder_ids[MAX_DECODER_PLUGINS];
const char *
plug_get_decoder_id (const char *id) {
int i;
char **lastnull = NULL;
- for (i = 0; i < MAX_OUTPUT_PLUGINS; i++) {
+ for (i = 0; i < MAX_DECODER_PLUGINS; i++) {
if (decoder_ids[i] && !strcmp (id, decoder_ids[i])) {
return decoder_ids[i];
}
@@ -759,7 +759,7 @@ plug_get_decoder_id (const char *id) {
void
plug_remove_decoder_id (const char *id) {
int i;
- for (i = 0; i < MAX_OUTPUT_PLUGINS; i++) {
+ for (i = 0; i < MAX_DECODER_PLUGINS; i++) {
if (decoder_ids[i] && !strcmp (decoder_ids[i], id)) {
free (decoder_ids[i]);
decoder_ids[i] = NULL;
@@ -770,7 +770,7 @@ plug_remove_decoder_id (const char *id) {
void
plug_free_decoder_ids (void) {
int i;
- for (i = 0; i < MAX_OUTPUT_PLUGINS; i++) {
+ for (i = 0; i < MAX_DECODER_PLUGINS; i++) {
if (decoder_ids[i]) {
free (decoder_ids[i]);
decoder_ids[i] = NULL;
diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c
index 4fa1cddb..69dec742 100644
--- a/plugins/gtkui/gtkui.c
+++ b/plugins/gtkui/gtkui.c
@@ -83,7 +83,7 @@ update_songinfo (gpointer ctx) {
}
else {
// codec_lock ();
- DB_decoder_t *c = deadbeef->streamer_get_current_decoder ();
+ DB_fileinfo_t *c = deadbeef->streamer_get_current_decoder ();
if (c) {
float playpos = deadbeef->streamer_get_playpos ();
int minpos = playpos / 60;
@@ -91,9 +91,9 @@ update_songinfo (gpointer ctx) {
int mindur = duration / 60;
int secdur = duration - mindur * 60;
- const char *mode = c->info.channels == 1 ? "Mono" : "Stereo";
- int samplerate = c->info.samplerate;
- int bitspersample = c->info.bps;
+ const char *mode = c->channels == 1 ? "Mono" : "Stereo";
+ int samplerate = c->samplerate;
+ int bitspersample = c->bps;
songpos = playpos;
// codec_unlock ();
diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c
index 49754dfa..b67fbc6a 100644
--- a/plugins/mpgmad/mpgmad.c
+++ b/plugins/mpgmad/mpgmad.c
@@ -82,10 +82,14 @@ typedef struct {
int enddelay;
} buffer_t;
-static buffer_t buffer;
-static struct mad_stream stream;
-static struct mad_frame frame;
-static struct mad_synth synth;
+typedef struct {
+ DB_fileinfo_t info;
+ buffer_t buffer;
+ struct mad_stream stream;
+ struct mad_frame frame;
+ struct mad_synth synth;
+} mpgmad_info_t;
+
static uint32_t
extract_i32 (unsigned char *buf)
@@ -422,7 +426,7 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
deadbeef->fread (buf, 1, 4, buffer->file);
// uint32_t musiclen = extract_i32 (buf);
- trace ("lpf: %d, peaksignalamp: %f, radiogain: %d, audiophile: %d, startdelay: %d, enddelay: %d, mp3gain: %d, musiclen: %d\n", lpf, rg_peaksignalamp, rg_radio, rg_audiophile, startdelay, enddelay, mp3gain, musiclen);
+ //trace ("lpf: %d, peaksignalamp: %f, radiogain: %d, audiophile: %d, startdelay: %d, enddelay: %d, mp3gain: %d, musiclen: %d\n", lpf, rg_peaksignalamp, rg_radio, rg_audiophile, startdelay, enddelay, mp3gain, musiclen);
// skip crc
//deadbeef->fseek (buffer->file, 4, SEEK_CUR);
buffer->startdelay = startdelay;
@@ -513,47 +517,51 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
}
-static int
+static DB_fileinfo_t *
cmp3_init (DB_playItem_t *it) {
- memset (&buffer, 0, sizeof (buffer));
- buffer.file = deadbeef->fopen (it->fname);
- if (!buffer.file) {
- return -1;
+ DB_fileinfo_t *_info = malloc (sizeof (mpgmad_info_t));
+ mpgmad_info_t *info = (mpgmad_info_t *)_info;
+ memset (info, 0, sizeof (mpgmad_info_t));
+ _info->plugin = &plugin;
+ memset (&info->buffer, 0, sizeof (info->buffer));
+ info->buffer.file = deadbeef->fopen (it->fname);
+ if (!info->buffer.file) {
+ return NULL;
}
- buffer.it = it;
- plugin.info.readpos = 0;
- if (!buffer.file->vfs->streaming) {
- int skip = deadbeef->junk_get_leading_size (buffer.file);
+ info->buffer.it = it;
+ info->info.readpos = 0;
+ if (!info->buffer.file->vfs->streaming) {
+ int skip = deadbeef->junk_get_leading_size (info->buffer.file);
if (skip > 0) {
- deadbeef->fseek(buffer.file, skip, SEEK_SET);
+ deadbeef->fseek (info->buffer.file, skip, SEEK_SET);
}
- cmp3_scan_stream (&buffer, -1); // scan entire stream, calc duration
+ cmp3_scan_stream (&info->buffer, -1); // scan entire stream, calc duration
if (it->endsample > 0) {
- buffer.startsample = it->startsample;
- buffer.endsample = it->endsample;
+ info->buffer.startsample = it->startsample;
+ info->buffer.endsample = it->endsample;
// that comes from cue, don't calc duration, just seek and play
- plugin.seek_sample (0);
+ plugin.seek_sample (_info, 0);
}
else {
- deadbeef->pl_set_item_duration (it, buffer.duration);
- buffer.startsample = 0;
- buffer.endsample = buffer.totalsamples-1;
- buffer.skipsamples = buffer.startdelay;
- buffer.currentsample = buffer.startdelay;
- deadbeef->fseek (buffer.file, buffer.startoffset, SEEK_SET);
+ deadbeef->pl_set_item_duration (it, info->buffer.duration);
+ info->buffer.startsample = 0;
+ info->buffer.endsample = info->buffer.totalsamples-1;
+ info->buffer.skipsamples = info->buffer.startdelay;
+ info->buffer.currentsample = info->buffer.startdelay;
+ deadbeef->fseek (info->buffer.file, info->buffer.startoffset, SEEK_SET);
}
}
else {
- buffer.it->filetype = NULL;
- int len = deadbeef->fgetlength (buffer.file);
- const char *name = deadbeef->fget_content_name (buffer.file);
- const char *genre = deadbeef->fget_content_genre (buffer.file);
+ info->buffer.it->filetype = NULL;
+ int len = deadbeef->fgetlength (info->buffer.file);
+ const char *name = deadbeef->fget_content_name (info->buffer.file);
+ const char *genre = deadbeef->fget_content_genre (info->buffer.file);
if (len > 0) {
deadbeef->pl_delete_all_meta (it);
- int v2err = deadbeef->junk_read_id3v2 (it, buffer.file);
+ int v2err = deadbeef->junk_read_id3v2 (it, info->buffer.file);
deadbeef->pl_add_meta (it, "title", NULL);
if (v2err != 0) {
- deadbeef->fseek (buffer.file, 0, SEEK_SET);
+ deadbeef->fseek (info->buffer.file, 0, SEEK_SET);
}
}
else {
@@ -568,46 +576,46 @@ cmp3_init (DB_playItem_t *it) {
deadbeef->pl_add_meta (it, "genre", genre);
}
}
- int res = cmp3_scan_stream (&buffer, 0);
+ int res = cmp3_scan_stream (&info->buffer, 0);
if (res < 0) {
trace ("mpgmad: cmp3_init: initial cmp3_scan_stream failed\n");
- plugin.free ();
- return -1;
+ plugin.free (_info);
+ return NULL;
}
- deadbeef->pl_set_item_duration (it, buffer.duration);
- if (buffer.duration >= 0) {
- buffer.endsample = buffer.totalsamples - 1;
+ deadbeef->pl_set_item_duration (it, info->buffer.duration);
+ if (info->buffer.duration >= 0) {
+ info->buffer.endsample = info->buffer.totalsamples - 1;
}
else {
-// buffer.duration = 200;
-// buffer.totalsamples = 10000000;
-// buffer.endsample = buffer.totalsamples-1;
- buffer.endsample = -1;
- buffer.totalsamples = -1;
+// info->buffer.duration = 200;
+// info->buffer.totalsamples = 10000000;
+// info->buffer.endsample = info->buffer.totalsamples-1;
+ info->buffer.endsample = -1;
+ info->buffer.totalsamples = -1;
}
- buffer.skipsamples = 0;
- buffer.currentsample = 0;
- if (buffer.duration < 0) {
- buffer.duration = -1;
- buffer.totalsamples = -1;
- buffer.endsample = -1;
+ info->buffer.skipsamples = 0;
+ info->buffer.currentsample = 0;
+ if (info->buffer.duration < 0) {
+ info->buffer.duration = -1;
+ info->buffer.totalsamples = -1;
+ info->buffer.endsample = -1;
}
- trace ("duration=%f, endsample=%d, totalsamples=%d\n", buffer.duration, buffer.endsample, buffer.totalsamples);
+ trace ("duration=%f, endsample=%d, totalsamples=%d\n", info->buffer.duration, info->buffer.endsample, info->buffer.totalsamples);
}
- if (buffer.samplerate == 0) {
+ if (info->buffer.samplerate == 0) {
trace ("bad mpeg file: %f\n", it->fname);
- plugin.free ();
- return -1;
+ plugin.free (_info);
+ return NULL;
}
- plugin.info.bps = buffer.bitspersample;
- plugin.info.samplerate = buffer.samplerate;
- plugin.info.channels = buffer.channels;
+ _info->bps = info->buffer.bitspersample;
+ _info->samplerate = info->buffer.samplerate;
+ _info->channels = info->buffer.channels;
- mad_stream_init(&stream);
- mad_frame_init(&frame);
- mad_synth_init(&synth);
+ mad_stream_init(&info->stream);
+ mad_frame_init(&info->frame);
+ mad_synth_init(&info->synth);
- return 0;
+ return _info;
}
/****************************************************************************
@@ -657,86 +665,86 @@ MadFixedToFloat (mad_fixed_t Fixed) {
// cuts readsize if it's beyond boundaries
static int
-cmp3_decode_cut (int framesize) {
- if (buffer.duration >= 0) {
- if (buffer.currentsample + buffer.readsize / (framesize * buffer.channels) > buffer.endsample) {
- int sz = (buffer.endsample - buffer.currentsample + 1) * framesize * buffer.channels;
- trace ("size truncated to %d bytes, cursample=%d, endsample=%d, totalsamples=%d\n", buffer.readsize, buffer.currentsample, buffer.endsample, buffer.totalsamples);
+cmp3_decode_cut (mpgmad_info_t *info, int framesize) {
+ if (info->buffer.duration >= 0) {
+ if (info->buffer.currentsample + info->buffer.readsize / (framesize * info->buffer.channels) > info->buffer.endsample) {
+ int sz = (info->buffer.endsample - info->buffer.currentsample + 1) * framesize * info->buffer.channels;
+ trace ("size truncated to %d bytes, cursample=%d, endsample=%d, totalsamples=%d\n", info->buffer.readsize, info->buffer.currentsample, info->buffer.endsample, info->buffer.totalsamples);
if (sz <= 0) {
return 1;
}
- buffer.readsize = sz;
+ info->buffer.readsize = sz;
}
}
return 0;
}
static inline void
-cmp3_skip (void) {
- if (buffer.skipsamples > 0) {
- int skip = min (buffer.skipsamples, buffer.decode_remaining);
- buffer.skipsamples -= skip;
- buffer.decode_remaining -= skip;
+cmp3_skip (mpgmad_info_t *info) {
+ if (info->buffer.skipsamples > 0) {
+ int skip = min (info->buffer.skipsamples, info->buffer.decode_remaining);
+ info->buffer.skipsamples -= skip;
+ info->buffer.decode_remaining -= skip;
}
}
// decoded requested number of samples to int16 format
static void
-cmp3_decode_requested_int16 (void) {
- cmp3_skip ();
+cmp3_decode_requested_int16 (mpgmad_info_t *info) {
+ cmp3_skip (info);
// copy synthesized samples into readbuffer
- int idx = synth.pcm.length-buffer.decode_remaining;
- while (buffer.decode_remaining > 0 && buffer.readsize > 0) {
- *((int16_t*)buffer.out) = MadFixedToSshort (synth.pcm.samples[0][idx]);
- buffer.readsize -= 2;
- buffer.out += 2;
- if (MAD_NCHANNELS(&frame.header) == 2) {
- *((int16_t*)buffer.out) = MadFixedToSshort (synth.pcm.samples[1][idx]);
- buffer.readsize -= 2;
- buffer.out += 2;
+ int idx = info->synth.pcm.length-info->buffer.decode_remaining;
+ while (info->buffer.decode_remaining > 0 && info->buffer.readsize > 0) {
+ *((int16_t*)info->buffer.out) = MadFixedToSshort (info->synth.pcm.samples[0][idx]);
+ info->buffer.readsize -= 2;
+ info->buffer.out += 2;
+ if (MAD_NCHANNELS(&info->frame.header) == 2) {
+ *((int16_t*)info->buffer.out) = MadFixedToSshort (info->synth.pcm.samples[1][idx]);
+ info->buffer.readsize -= 2;
+ info->buffer.out += 2;
}
- buffer.decode_remaining--;
+ info->buffer.decode_remaining--;
idx++;
}
- assert (buffer.readsize >= 0);
+ assert (info->buffer.readsize >= 0);
}
// decoded requested number of samples to int16 format
static void
-cmp3_decode_requested_float32 (void) {
- cmp3_skip ();
- // copy synthesized samples into readbuffer
- int idx = synth.pcm.length-buffer.decode_remaining;
- while (buffer.decode_remaining > 0 && buffer.readsize > 0) {
- *((float*)buffer.out) = MadFixedToFloat (synth.pcm.samples[0][idx]);
- buffer.readsize -= 4;
- buffer.out += 4;
- if (MAD_NCHANNELS(&frame.header) == 2) {
- *((float*)buffer.out) = MadFixedToFloat (synth.pcm.samples[1][idx]);
- buffer.readsize -= 4;
- buffer.out += 4;
+cmp3_decode_requested_float32 (mpgmad_info_t *info) {
+ cmp3_skip (info);
+ // copy synthesized samples into readinfo->buffer
+ int idx = info->synth.pcm.length-info->buffer.decode_remaining;
+ while (info->buffer.decode_remaining > 0 && info->buffer.readsize > 0) {
+ *((float*)info->buffer.out) = MadFixedToFloat (info->synth.pcm.samples[0][idx]);
+ info->buffer.readsize -= 4;
+ info->buffer.out += 4;
+ if (MAD_NCHANNELS(&info->frame.header) == 2) {
+ *((float*)info->buffer.out) = MadFixedToFloat (info->synth.pcm.samples[1][idx]);
+ info->buffer.readsize -= 4;
+ info->buffer.out += 4;
}
- buffer.decode_remaining--;
+ info->buffer.decode_remaining--;
idx++;
}
- assert (buffer.readsize >= 0);
+ assert (info->buffer.readsize >= 0);
}
static int
-cmp3_stream_frame (void) {
+cmp3_stream_frame (mpgmad_info_t *info) {
int eof = 0;
- while (!eof && (stream.buffer == NULL || buffer.decode_remaining <= 0)) {
+ while (!eof && (info->stream.buffer == NULL || info->buffer.decode_remaining <= 0)) {
// read more MPEG data if needed
- if(stream.buffer==NULL || stream.error==MAD_ERROR_BUFLEN) {
+ if(info->stream.buffer==NULL || info->stream.error==MAD_ERROR_BUFLEN) {
// copy part of last frame to beginning
- if (stream.next_frame != NULL) {
- buffer.remaining = stream.bufend - stream.next_frame;
- memmove (buffer.input, stream.next_frame, buffer.remaining);
+ if (info->stream.next_frame != NULL) {
+ info->buffer.remaining = info->stream.bufend - info->stream.next_frame;
+ memmove (info->buffer.input, info->stream.next_frame, info->buffer.remaining);
}
- int size = READBUFFER - buffer.remaining;
+ int size = READBUFFER - info->buffer.remaining;
int bytesread = 0;
- uint8_t *bytes = buffer.input + buffer.remaining;
- bytesread = deadbeef->fread (bytes, 1, size, buffer.file);
+ uint8_t *bytes = info->buffer.input + info->buffer.remaining;
+ bytesread = deadbeef->fread (bytes, 1, size, info->buffer.file);
if (!bytesread) {
// add guard
eof = 1;
@@ -748,70 +756,70 @@ cmp3_stream_frame (void) {
size -= bytesread;
bytes += bytesread;
}
- bytesread += buffer.remaining;
- mad_stream_buffer(&stream,buffer.input,bytesread);
- if (stream.buffer==NULL) {
+ bytesread += info->buffer.remaining;
+ mad_stream_buffer(&info->stream,info->buffer.input,bytesread);
+ if (info->stream.buffer==NULL) {
// check sync bits
if (bytes[0] != 0xff || (bytes[1]&(3<<5)) != (3<<5)) {
trace ("mpgmad: read didn't start at frame boundary!\ncmp3_scan_stream is broken\n");
}
}
}
- stream.error=0;
+ info->stream.error=0;
// decode next frame
- if(mad_frame_decode(&frame,&stream))
+ if(mad_frame_decode(&info->frame,&info->stream))
{
- if(MAD_RECOVERABLE(stream.error))
+ if(MAD_RECOVERABLE(info->stream.error))
{
#if 0
- if(stream.error!=MAD_ERROR_LOSTSYNC) {
+ if(info->stream.error!=MAD_ERROR_LOSTSYNC) {
trace ("mpgmad: recoverable frame level error (%s)\n", MadErrorString(&stream));
}
#endif
continue;
}
else {
- if(stream.error==MAD_ERROR_BUFLEN) {
+ if(info->stream.error==MAD_ERROR_BUFLEN) {
continue;
}
else
{
- trace ("mpgmad: unrecoverable frame level error (%s).\n", MadErrorString(&stream));
+ trace ("mpgmad: unrecoverable frame level error (%s).\n", MadErrorString(&info->stream));
return -1; // fatal error
}
}
}
- if (!buffer.it->filetype) {
- int layer = frame.header.layer;
+ if (!info->buffer.it->filetype) {
+ int layer = info->frame.header.layer;
if (layer >= 1 && layer <= 3) {
- buffer.it->filetype = plugin.filetypes[layer-1];
+ info->buffer.it->filetype = plugin.filetypes[layer-1];
}
}
- plugin.info.samplerate = frame.header.samplerate;
- plugin.info.channels = MAD_NCHANNELS(&frame.header);
+ info->info.samplerate = info->frame.header.samplerate;
+ info->info.channels = MAD_NCHANNELS(&info->frame.header);
// synthesize single frame
- mad_synth_frame(&synth,&frame);
- buffer.decode_remaining = synth.pcm.length;
- deadbeef->streamer_set_bitrate (frame.header.bitrate/1000);
+ mad_synth_frame(&info->synth,&info->frame);
+ info->buffer.decode_remaining = info->synth.pcm.length;
+ deadbeef->streamer_set_bitrate (info->frame.header.bitrate/1000);
break;
}
return eof;
}
static int
-cmp3_decode_int16 (void) {
- if (cmp3_decode_cut (4)) {
+cmp3_decode_int16 (mpgmad_info_t *info) {
+ if (cmp3_decode_cut (info, 4)) {
return 0;
}
int eof = 0;
while (!eof) {
- eof = cmp3_stream_frame ();
- if (buffer.decode_remaining > 0) {
- cmp3_decode_requested_int16 ();
- if (buffer.readsize == 0) {
+ eof = cmp3_stream_frame (info);
+ if (info->buffer.decode_remaining > 0) {
+ cmp3_decode_requested_int16 (info);
+ if (info->buffer.readsize == 0) {
return 0;
}
}
@@ -820,17 +828,17 @@ cmp3_decode_int16 (void) {
}
static int
-cmp3_decode_float32 (void) {
- if (cmp3_decode_cut (8)) {
+cmp3_decode_float32 (mpgmad_info_t *info) {
+ if (cmp3_decode_cut (info, 8)) {
trace ("read request ignored (end of track passed)\n");
return 0;
}
int eof = 0;
while (!eof) {
- eof = cmp3_stream_frame ();
- if (buffer.decode_remaining > 0) {
- cmp3_decode_requested_float32 ();
- if (buffer.readsize == 0) {
+ eof = cmp3_stream_frame (info);
+ if (info->buffer.decode_remaining > 0) {
+ cmp3_decode_requested_float32 (info);
+ if (info->buffer.readsize == 0) {
return 0;
}
}
@@ -839,60 +847,65 @@ cmp3_decode_float32 (void) {
}
static void
-cmp3_free (void) {
- if (buffer.file) {
- deadbeef->fclose (buffer.file);
- buffer.file = NULL;
- mad_synth_finish (&synth);
- mad_frame_finish (&frame);
- mad_stream_finish (&stream);
+cmp3_free (DB_fileinfo_t *_info) {
+ mpgmad_info_t *info = (mpgmad_info_t *)_info;
+ if (info->buffer.file) {
+ deadbeef->fclose (info->buffer.file);
+ info->buffer.file = NULL;
+ mad_synth_finish (&info->synth);
+ mad_frame_finish (&info->frame);
+ mad_stream_finish (&info->stream);
}
+ free (info);
}
static int
-cmp3_read_int16 (char *bytes, int size) {
- buffer.readsize = size;
- buffer.out = bytes;
- cmp3_decode_int16 ();
- buffer.currentsample += (size - buffer.readsize) / 4;
- plugin.info.readpos = (float)(buffer.currentsample - buffer.startsample) / buffer.samplerate;
- return size - buffer.readsize;
+cmp3_read_int16 (DB_fileinfo_t *_info, char *bytes, int size) {
+ mpgmad_info_t *info = (mpgmad_info_t *)_info;
+ info->buffer.readsize = size;
+ info->buffer.out = bytes;
+ cmp3_decode_int16 (info);
+ info->buffer.currentsample += (size - info->buffer.readsize) / 4;
+ _info->readpos = (float)(info->buffer.currentsample - info->buffer.startsample) / info->buffer.samplerate;
+ return size - info->buffer.readsize;
}
static int
-cmp3_read_float32 (char *bytes, int size) {
- buffer.readsize = size;
- buffer.out = bytes;
- cmp3_decode_float32 ();
- buffer.currentsample += (size - buffer.readsize) / 8;
- plugin.info.readpos = (float)(buffer.currentsample - buffer.startsample) / buffer.samplerate;
- return size - buffer.readsize;
+cmp3_read_float32 (DB_fileinfo_t *_info, char *bytes, int size) {
+ mpgmad_info_t *info = (mpgmad_info_t *)_info;
+ info->buffer.readsize = size;
+ info->buffer.out = bytes;
+ cmp3_decode_float32 (info);
+ info->buffer.currentsample += (size - info->buffer.readsize) / 8;
+ _info->readpos = (float)(info->buffer.currentsample - info->buffer.startsample) / info->buffer.samplerate;
+ return size - info->buffer.readsize;
}
static int
-cmp3_seek_sample (int sample) {
- if (!buffer.file) {
+cmp3_seek_sample (DB_fileinfo_t *_info, int sample) {
+ mpgmad_info_t *info = (mpgmad_info_t *)_info;
+ if (!info->buffer.file) {
return -1;
}
- if (buffer.file->vfs->streaming) {
- if (buffer.totalsamples > 0) {
+ if (info->buffer.file->vfs->streaming) {
+ if (info->buffer.totalsamples > 0) {
// approximation
- int64_t l = deadbeef->fgetlength (buffer.file);
- l = l * sample / buffer.totalsamples;
- int r = deadbeef->fseek (buffer.file, l, SEEK_SET);
+ int64_t l = deadbeef->fgetlength (info->buffer.file);
+ l = l * sample / info->buffer.totalsamples;
+ int r = deadbeef->fseek (info->buffer.file, l, SEEK_SET);
if (!r) {
- buffer.currentsample = sample;
- plugin.info.readpos = (float)(buffer.currentsample - buffer.startsample) / buffer.samplerate;
-
- mad_synth_finish (&synth);
- mad_frame_finish (&frame);
- mad_stream_finish (&stream);
- buffer.remaining = 0;
- buffer.decode_remaining = 0;
- mad_stream_init(&stream);
- mad_frame_init(&frame);
- mad_synth_init(&synth);
+ info->buffer.currentsample = sample;
+ _info->readpos = (float)(info->buffer.currentsample - info->buffer.startsample) / info->buffer.samplerate;
+
+ mad_synth_finish (&info->synth);
+ mad_frame_finish (&info->frame);
+ mad_stream_finish (&info->stream);
+ info->buffer.remaining = 0;
+ info->buffer.decode_remaining = 0;
+ mad_stream_init(&info->stream);
+ mad_frame_init(&info->frame);
+ mad_synth_init(&info->synth);
return 0;
}
@@ -901,47 +914,48 @@ cmp3_seek_sample (int sample) {
return 0;
}
- sample += buffer.startsample + buffer.startdelay;
- if (sample > buffer.endsample) {
- trace ("seek sample %d is beyond end of track (%d)\n", sample, buffer.endsample);
+ sample += info->buffer.startsample + info->buffer.startdelay;
+ if (sample > info->buffer.endsample) {
+ trace ("seek sample %d is beyond end of track (%d)\n", sample, info->buffer.endsample);
return -1; // eof
}
// restart file, and load until we hit required pos
- deadbeef->fseek (buffer.file, 0, SEEK_SET);
- int skip = deadbeef->junk_get_leading_size (buffer.file);
+ deadbeef->fseek (info->buffer.file, 0, SEEK_SET);
+ int skip = deadbeef->junk_get_leading_size (info->buffer.file);
if (skip > 0) {
- deadbeef->fseek(buffer.file, skip, SEEK_SET);
+ deadbeef->fseek (info->buffer.file, skip, SEEK_SET);
}
- mad_synth_finish (&synth);
- mad_frame_finish (&frame);
- mad_stream_finish (&stream);
- buffer.remaining = 0;
- buffer.readsize = 0;
- buffer.decode_remaining = 0;
+ mad_synth_finish (&info->synth);
+ mad_frame_finish (&info->frame);
+ mad_stream_finish (&info->stream);
+ info->buffer.remaining = 0;
+ info->buffer.readsize = 0;
+ info->buffer.decode_remaining = 0;
if (sample == 0) {
- plugin.info.readpos = 0;
- buffer.currentsample = 0;
- buffer.skipsamples = buffer.startdelay;
+ _info->readpos = 0;
+ info->buffer.currentsample = 0;
+ info->buffer.skipsamples = info->buffer.startdelay;
return 0;
}
- if (cmp3_scan_stream (&buffer, sample) == -1) {
+ if (cmp3_scan_stream (&info->buffer, sample) == -1) {
trace ("failed to seek to sample %d\n", sample);
- plugin.info.readpos = 0;
+ _info->readpos = 0;
return -1;
}
- mad_stream_init(&stream);
- mad_frame_init(&frame);
- mad_synth_init(&synth);
- plugin.info.readpos = (float)(buffer.currentsample - buffer.startsample) / buffer.samplerate;
+ mad_stream_init(&info->stream);
+ mad_frame_init(&info->frame);
+ mad_synth_init(&info->synth);
+ _info->readpos = (float)(info->buffer.currentsample - info->buffer.startsample) / info->buffer.samplerate;
return 0;
}
static int
-cmp3_seek (float time) {
- int sample = time * buffer.samplerate;
- return cmp3_seek_sample (sample);
+cmp3_seek (DB_fileinfo_t *_info, float time) {
+ mpgmad_info_t *info = (mpgmad_info_t *)_info;
+ int sample = time * info->buffer.samplerate;
+ return cmp3_seek_sample (_info, sample);
}
static const char *filetypes[] = {
@@ -950,8 +964,10 @@ static const char *filetypes[] = {
static DB_playItem_t *
cmp3_insert (DB_playItem_t *after, const char *fname) {
+ trace ("cmp3_insert %s\n", fname);
DB_FILE *fp = deadbeef->fopen (fname);
if (!fp) {
+ trace ("failed to open file %s\n", fname);
return NULL;
}
if (fp->vfs->streaming) {
@@ -975,6 +991,7 @@ cmp3_insert (DB_playItem_t *after, const char *fname) {
// calc approx. mp3 duration
int res = cmp3_scan_stream (&buffer, 0);
if (res < 0) {
+ trace ("mpgmad: cmp3_scan_stream returned error\n");
deadbeef->fclose (fp);
return NULL;
}
diff --git a/streamer.c b/streamer.c
index d84922e0..c2e1e436 100644
--- a/streamer.c
+++ b/streamer.c
@@ -89,7 +89,7 @@ playItem_t str_streaming_song;
static playItem_t *orig_playing_song;
static playItem_t *orig_streaming_song;
// current decoder
-static DB_decoder_t *str_current_decoder;
+static DB_fileinfo_t *str_current_decoder;
static int streamer_buffering;
@@ -144,7 +144,7 @@ streamer_set_current (playItem_t *it) {
#endif
trace ("streamer_set_current %p, buns=%d\n", it);
if(str_current_decoder) {
- str_current_decoder->free ();
+ str_current_decoder->plugin->free (str_current_decoder);
str_current_decoder = NULL;
pl_item_free (&str_streaming_song);
}
@@ -183,25 +183,23 @@ streamer_set_current (playItem_t *it) {
dec = plug_get_decoder_for_id (it->decoder_id);
}
if (dec) {
- str_current_decoder = dec;
streamer_lock ();
streamer_unlock ();
- int ret = str_current_decoder->init (DB_PLAYITEM (it));
+ str_current_decoder = dec->init (DB_PLAYITEM (it));
streamer_lock ();
streamer_unlock ();
pl_item_copy (&str_streaming_song, it);
- if (ret < 0) {
- str_current_decoder = NULL;
- trace ("decoder->init returned %d\n", ret);
+ if (!str_current_decoder) {
+ trace ("decoder->init returned NULL\n");
trace ("orig_playing_song = %p\n", orig_playing_song);
if (orig_playing_song == it) {
orig_playing_song = NULL;
messagepump_push (M_TRACKCHANGED, 0, to, 0);
}
- return ret;
+ return -1;
}
else {
- trace ("bps=%d, channels=%d, samplerate=%d\n", dec->info.bps, dec->info.channels, dec->info.samplerate);
+ trace ("bps=%d, channels=%d, samplerate=%d\n", str_current_decoder->bps, str_current_decoder->channels, str_current_decoder->samplerate);
}
streamer_reset (0); // reset SRC
}
@@ -378,9 +376,9 @@ streamer_thread (void *ctx) {
plug_trigger_event (DB_EV_SONGSTARTED, 0);
playpos = 0;
// change samplerate
- if (prevtrack_samplerate != str_current_decoder->info.samplerate) {
- plug_get_output ()->change_rate (str_current_decoder->info.samplerate);
- prevtrack_samplerate = str_current_decoder->info.samplerate;
+ if (prevtrack_samplerate != str_current_decoder->samplerate) {
+ plug_get_output ()->change_rate (str_current_decoder->samplerate);
+ prevtrack_samplerate = str_current_decoder->samplerate;
}
}
@@ -393,7 +391,8 @@ streamer_thread (void *ctx) {
trace ("streamer already switched to next track\n");
// restart playing from new position
if(str_current_decoder) {
- str_current_decoder->free ();
+ str_current_decoder->plugin->free (str_current_decoder);
+ str_current_decoder = NULL;
pl_item_free (&str_streaming_song);
}
orig_streaming_song = orig_playing_song;
@@ -404,8 +403,11 @@ streamer_thread (void *ctx) {
if (trk != -1) {
messagepump_push (M_TRACKCHANGED, 0, trk, 0);
}
- int ret = str_current_decoder->init (DB_PLAYITEM (orig_streaming_song));
- if (ret < 0) {
+ DB_decoder_t *plug = plug_get_decoder_for_id (orig_streaming_song->decoder_id);
+ if (plug) {
+ str_current_decoder = plug->init (DB_PLAYITEM (orig_streaming_song));
+ }
+ if (!plug || !str_current_decoder) {
streamer_buffering = 0;
if (trk != -1) {
messagepump_push (M_TRACKCHANGED, 0, trk, 0);
@@ -430,8 +432,8 @@ streamer_thread (void *ctx) {
codec_lock ();
codecleft = 0;
codec_unlock ();
- if (str_current_decoder->seek (pos) >= 0) {
- playpos = str_current_decoder->info.readpos;
+ if (str_current_decoder->plugin->seek (str_current_decoder, pos) >= 0) {
+ playpos = str_current_decoder->readpos;
}
last_bitrate = -1;
avg_bitrate = -1;
@@ -475,7 +477,8 @@ streamer_thread (void *ctx) {
// stop streaming song
if(str_current_decoder) {
- str_current_decoder->free ();
+ str_current_decoder->plugin->free (str_current_decoder);
+ str_current_decoder = NULL;
}
pl_item_free (&str_streaming_song);
pl_item_free (&str_playing_song);
@@ -670,24 +673,28 @@ streamer_read_async (char *bytes, int size) {
for (;;) {
int bytesread = 0;
codec_lock ();
- DB_decoder_t *decoder = str_current_decoder;
+ if (!str_current_decoder) {
+ codec_unlock ();
+ break;
+ }
+ DB_decoder_t *decoder = str_current_decoder->plugin;
if (!decoder) {
// means there's nothing left to stream, so just do nothing
codec_unlock ();
break;
}
- if (decoder->info.samplerate != -1) {
- int nchannels = decoder->info.channels;
- int samplerate = decoder->info.samplerate;
- if (decoder->info.samplerate == p_get_rate ()) {
+ if (str_current_decoder->samplerate != -1) {
+ int nchannels = str_current_decoder->channels;
+ int samplerate = str_current_decoder->samplerate;
+ if (str_current_decoder->samplerate == p_get_rate ()) {
// samplerate match
- if (decoder->info.channels == 2) {
- bytesread = decoder->read_int16 (bytes, size);
+ if (str_current_decoder->channels == 2) {
+ bytesread = decoder->read_int16 (str_current_decoder, bytes, size);
apply_replay_gain_int16 (&str_streaming_song, bytes, size);
codec_unlock ();
}
else {
- bytesread = decoder->read_int16 (g_readbuffer, size>>1);
+ bytesread = decoder->read_int16 (str_current_decoder, g_readbuffer, size>>1);
apply_replay_gain_int16 (&str_streaming_song, g_readbuffer, size>>1);
mono_int16_to_stereo_int16 ((int16_t*)g_readbuffer, (int16_t*)bytes, size>>2);
bytesread *= 2;
@@ -710,7 +717,7 @@ streamer_read_async (char *bytes, int size) {
trace ("input buffer overflow\n");
nbytes = INPUT_BUFFER_SIZE;
}
- bytesread = decoder->read_int16 (g_readbuffer, nbytes);
+ bytesread = decoder->read_int16 (str_current_decoder, g_readbuffer, nbytes);
apply_replay_gain_int16 (&str_streaming_song, g_readbuffer, nbytes);
}
else {
@@ -737,7 +744,7 @@ streamer_read_async (char *bytes, int size) {
float *fbuffer = g_fbuffer + codecleft*2;
if (nchannels == 1) {
codec_lock ();
- bytesread = decoder->read_float32 (g_readbuffer, nbytes*2);
+ bytesread = decoder->read_float32 (str_current_decoder, g_readbuffer, nbytes*2);
codec_unlock ();
apply_replay_gain_float32 (&str_streaming_song, g_readbuffer, nbytes*2);
nsamples = bytesread / (samplesize * nchannels) + codecleft;
@@ -745,7 +752,7 @@ streamer_read_async (char *bytes, int size) {
}
else {
codec_lock ();
- bytesread = decoder->read_float32 ((char *)fbuffer, nbytes*2);
+ bytesread = decoder->read_float32 (str_current_decoder, (char *)fbuffer, nbytes*2);
codec_unlock ();
apply_replay_gain_float32 (&str_streaming_song, (char *)fbuffer, nbytes*2);
nsamples = bytesread / (samplesize * nchannels) + codecleft;
@@ -1169,7 +1176,7 @@ streamer_get_current (void) {
return orig_playing_song;
}
-struct DB_decoder_s *
+struct DB_fileinfo_s *
streamer_get_current_decoder (void) {
return str_current_decoder;
}
diff --git a/streamer.h b/streamer.h
index a74eeb7a..9389a4f8 100644
--- a/streamer.h
+++ b/streamer.h
@@ -98,7 +98,7 @@ streamer_move_randomsong (void);
playItem_t *
streamer_get_current (void);
-struct DB_decoder_s *
+struct DB_fileinfo_s *
streamer_get_current_decoder (void);
#endif // __STREAMER_H
diff --git a/vfs.c b/vfs.c
index aff6c0ad..432e844f 100644
--- a/vfs.c
+++ b/vfs.c
@@ -21,8 +21,8 @@
#include "vfs.h"
#include "plugins.h"
-//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
-#define trace(fmt,...)
+#define trace(...) { fprintf(stderr, __VA_ARGS__); }
+//#define trace(fmt,...)
DB_FILE *
vfs_fopen (const char *fname) {