summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-05-01 15:39:52 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-05-01 15:39:52 +0200
commit76a27d6a8ffcc8d6ca608e674a78115cdf14b6ec (patch)
tree801dc43105be2d5e36124f02359c48cdc2805abb
parentddfbdc8c68cb2c8ebc65d4f4576dbc1eb270c209 (diff)
improved decoder API to be able to interrupt .init at any moment
-rw-r--r--deadbeef.h5
-rw-r--r--plugins/adplug/adplug-db.cpp18
-rw-r--r--plugins/adplug/plugin.c5
-rw-r--r--plugins/cdda/cdda.c21
-rw-r--r--plugins/dumb/cdumb.c17
-rw-r--r--plugins/ffap/ffap.c30
-rw-r--r--plugins/ffmpeg/ffmpeg.c34
-rw-r--r--plugins/flac/flac.c44
-rw-r--r--plugins/gme/cgme.c15
-rw-r--r--plugins/mpgmad/mpgmad.c19
-rw-r--r--plugins/sid/csid.cpp11
-rw-r--r--plugins/sid/csid.h3
-rw-r--r--plugins/sid/plugin.c1
-rw-r--r--plugins/sndfile/sndfile.c21
-rw-r--r--plugins/vfs_curl/vfs_curl.c7
-rw-r--r--plugins/vorbis/vorbis.c26
-rw-r--r--plugins/vtx/vtx.c29
-rw-r--r--plugins/wavpack/wavpack.c22
-rw-r--r--streamer.c59
19 files changed, 224 insertions, 163 deletions
diff --git a/deadbeef.h b/deadbeef.h
index 723ee64f..23e05961 100644
--- a/deadbeef.h
+++ b/deadbeef.h
@@ -565,8 +565,11 @@ typedef struct DB_fileinfo_s {
// decoder plugin
typedef struct DB_decoder_s {
DB_plugin_t plugin;
+
+ DB_fileinfo_t *(*open) (void);
+
// init is called to prepare song to be started
- DB_fileinfo_t *(*init) (DB_playItem_t *it);
+ int (*init) (DB_fileinfo_t *info, DB_playItem_t *it);
// free is called after decoding is finished
void (*free) (DB_fileinfo_t *info);
diff --git a/plugins/adplug/adplug-db.cpp b/plugins/adplug/adplug-db.cpp
index 4fa90b4d..9aa5efb2 100644
--- a/plugins/adplug/adplug-db.cpp
+++ b/plugins/adplug/adplug-db.cpp
@@ -53,13 +53,18 @@ typedef struct {
} adplug_info_t;
DB_fileinfo_t *
-adplug_init (DB_playItem_t *it) {
- // prepare to decode the track
- // return -1 on failure
-
+adplug_open (void) {
adplug_info_t *info = (adplug_info_t *)malloc (sizeof (adplug_info_t));
DB_fileinfo_t *_info = (DB_fileinfo_t *)info;
memset (info, 0, sizeof (adplug_info_t));
+ return _info;
+}
+
+int
+adplug_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
+ // prepare to decode the track
+ // return -1 on failure
+ adplug_info_t *info = (adplug_info_t *)_info;
int samplerate = deadbeef->conf_get_int ("synth.samplerate", 48000);
int bps = deadbeef->get_output ()->bitspersample ();
@@ -69,8 +74,7 @@ adplug_init (DB_playItem_t *it) {
info->decoder = CAdPlug::factory (it->fname, info->opl, CAdPlug::players);
if (!info->decoder) {
trace ("adplug: failed to open %s\n", it->fname);
- adplug_plugin.free (_info);
- return NULL;
+ return -1;
}
info->subsong = it->tracknum;
@@ -88,7 +92,7 @@ adplug_init (DB_playItem_t *it) {
trace ("adplug_init ok (duration=%f, totalsamples=%d)\n", deadbeef->pl_get_item_duration (it), totalsamples);
- return _info;
+ return 0;
}
void
diff --git a/plugins/adplug/plugin.c b/plugins/adplug/plugin.c
index 6b2a6ca5..c4e8e04c 100644
--- a/plugins/adplug/plugin.c
+++ b/plugins/adplug/plugin.c
@@ -26,7 +26,9 @@ extern const char *adplug_exts[];
extern const char *adplug_filetypes[];
DB_fileinfo_t *
-adplug_init (DB_playItem_t *it);
+adplug_open (void);
+int
+adplug_init (DB_fileinfo_t *_info, DB_playItem_t *it);
void
adplug_free (DB_fileinfo_t *);
int
@@ -56,6 +58,7 @@ DB_decoder_t adplug_plugin = {
.plugin.website = "http://deadbeef.sf.net",
.plugin.start = adplug_start,
.plugin.stop = adplug_stop,
+ .open = adplug_open,
.init = adplug_init,
.free = adplug_free,
.read_int16 = adplug_read_int16,
diff --git a/plugins/cdda/cdda.c b/plugins/cdda/cdda.c
index 998fd277..089041a1 100644
--- a/plugins/cdda/cdda.c
+++ b/plugins/cdda/cdda.c
@@ -69,10 +69,15 @@ min (int a, int b) {
}
static DB_fileinfo_t *
-cda_init (DB_playItem_t *it) {
+cda_open (void) {
DB_fileinfo_t *_info = malloc (sizeof (cdda_info_t));
+ memset (_info, 0, sizeof (cdda_info_t));
+ return _info;
+}
+
+static int
+cda_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
cdda_info_t *info = (cdda_info_t *)_info;
- memset (info, 0, sizeof (cdda_info_t));
trace ("cdda: init %s\n", it->fname);
@@ -86,8 +91,7 @@ cda_init (DB_playItem_t *it) {
}
else {
trace ("cdda: bad name: %s\n", it->fname);
- plugin.free (_info);
- return NULL;
+ return -1;
}
int track_nr = atoi (nr);
char *fname = (*location) ? location : NULL; //NULL if empty string; means pysical CD drive
@@ -96,15 +100,13 @@ cda_init (DB_playItem_t *it) {
if (!info->cdio)
{
trace ("cdda: Could not open CD\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
if (TRACK_FORMAT_AUDIO != cdio_get_track_format (info->cdio, track_nr))
{
trace ("cdda: Not an audio track (%d)\n", track_nr);
- plugin.free (_info);
- return NULL;
+ return -1;
}
_info->plugin = &plugin;
@@ -118,7 +120,7 @@ cda_init (DB_playItem_t *it) {
info->current_sector = info->first_sector;
info->tail_len = 0;
info->current_sample = 0;
- return _info;
+ return 0;
}
int
@@ -468,6 +470,7 @@ static DB_decoder_t plugin = {
.plugin.start = cda_start,
.plugin.stop = cda_stop,
.plugin.configdialog = settings_dlg,
+ .open = cda_open,
.init = cda_init,
.free = cda_free,
.read_int16 = cda_read_int16,
diff --git a/plugins/dumb/cdumb.c b/plugins/dumb/cdumb.c
index 92e27437..465a00e3 100644
--- a/plugins/dumb/cdumb.c
+++ b/plugins/dumb/cdumb.c
@@ -48,11 +48,16 @@ static DUH*
open_module(const char *fname, const char *ext, int *start_order, int *is_it, int *is_dos, const char **filetype);
static DB_fileinfo_t *
-cdumb_init (DB_playItem_t *it) {
- trace ("cdumb_init %s\n", it->fname);
+cdumb_open (void) {
DB_fileinfo_t *_info = malloc (sizeof (dumb_info_t));
- dumb_info_t *info = (dumb_info_t *)_info;
memset (_info, 0, sizeof (dumb_info_t));
+ return _info;
+}
+
+static int
+cdumb_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
+ trace ("cdumb_init %s\n", it->fname);
+ dumb_info_t *info = (dumb_info_t *)_info;
int start_order = 0;
int is_dos, is_it;
@@ -73,12 +78,11 @@ cdumb_init (DB_playItem_t *it) {
_info->readpos = 0;
if (cdumb_startrenderer (_info) < 0) {
- plugin.free (_info);
- return NULL;
+ return -1;
}
trace ("cdumb_init success (ptr=%p)\n", _info);
- return _info;
+ return 0;
}
static int
@@ -807,6 +811,7 @@ static DB_decoder_t plugin = {
.plugin.website = "http://deadbeef.sf.net",
.plugin.start = cgme_start,
.plugin.stop = cgme_stop,
+ .open = cdumb_open,
.init = cdumb_init,
.free = cdumb_free,
.read_int16 = cdumb_read,
diff --git a/plugins/ffap/ffap.c b/plugins/ffap/ffap.c
index 11456ebd..27b34332 100644
--- a/plugins/ffap/ffap.c
+++ b/plugins/ffap/ffap.c
@@ -24,6 +24,7 @@
demuxer and decoder joined into 1 module
no mallocs/reallocs during decoding
streaming through fixed ringbuffer (small mem footprint)
+ 24bit support merged from rockbox
*/
#if HAVE_CONFIG_H
@@ -670,16 +671,20 @@ ffap_free (DB_fileinfo_t *_info)
}
static DB_fileinfo_t *
-ffap_init(DB_playItem_t *it)
-{
+ffap_open (void) {
DB_fileinfo_t *_info = malloc (sizeof (ape_info_t));
+ memset (_info, 0, sizeof (ape_info_t));
+ return _info;
+}
+
+static int
+ffap_init (DB_fileinfo_t *_info, DB_playItem_t *it)
+{
ape_info_t *info = (ape_info_t*)_info;
- memset (info, 0, sizeof (ape_info_t));
info->fp = deadbeef->fopen (it->fname);
if (!info->fp) {
- plugin.free (_info);
- return NULL;
+ return -1;
}
memset (&info->ape_ctx, 0, sizeof (info->ape_ctx));
int skip = deadbeef->junk_get_leading_size (info->fp);
@@ -692,8 +697,7 @@ ffap_init(DB_playItem_t *it)
if (info->ape_ctx.channels > 2) {
fprintf (stderr, "ape: Only mono and stereo is supported\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
#if ENABLE_DEBUG
@@ -701,8 +705,7 @@ ffap_init(DB_playItem_t *it)
#endif
if (info->ape_ctx.compressiontype % 1000 || info->ape_ctx.compressiontype > COMPRESSION_LEVEL_INSANE) {
fprintf (stderr, "ape: Incorrect compression level %d\n", info->ape_ctx.compressiontype);
- plugin.free (_info);
- return NULL;
+ return -1;
}
info->ape_ctx.fset = info->ape_ctx.compressiontype / 1000 - 1;
for (i = 0; i < APE_FILTER_LEVELS; i++) {
@@ -711,8 +714,7 @@ ffap_init(DB_playItem_t *it)
int err = posix_memalign ((void **)&info->ape_ctx.filterbuf[i], 16, (ape_filter_orders[info->ape_ctx.fset][i] * 3 + HISTORY_SIZE) * 4);
if (err) {
trace ("ffap: out of memory (posix_memalign)\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
}
@@ -735,10 +737,9 @@ ffap_init(DB_playItem_t *it)
info->ape_ctx.packet_data = malloc (PACKET_BUFFER_SIZE);
if (!info->ape_ctx.packet_data) {
fprintf (stderr, "ape: failed to allocate memory for packet data\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
- return _info;
+ return 0;
}
/**
@@ -1900,6 +1901,7 @@ static DB_decoder_t plugin = {
.plugin.author = "Alexey Yakovenko",
.plugin.email = "waker@users.sourceforge.net",
.plugin.website = "http://deadbeef.sf.net",
+ .open = ffap_open,
.init = ffap_init,
.free = ffap_free,
.read_int16 = ffap_read_int16,
diff --git a/plugins/ffmpeg/ffmpeg.c b/plugins/ffmpeg/ffmpeg.c
index af03cb11..6d1330a9 100644
--- a/plugins/ffmpeg/ffmpeg.c
+++ b/plugins/ffmpeg/ffmpeg.c
@@ -93,14 +93,19 @@ typedef struct {
} ffmpeg_info_t;
static DB_playItem_t *current_track;
+static DB_fileinfo_t *current_info;
static DB_fileinfo_t *
-ffmpeg_init (DB_playItem_t *it) {
- trace ("ffmpeg init %s\n");
+ffmpeg_open (void) {
DB_fileinfo_t *_info = malloc (sizeof (ffmpeg_info_t));
- ffmpeg_info_t *info = (ffmpeg_info_t*)_info;
- memset (info, 0, sizeof (ffmpeg_info_t));
+ memset (_info, 0, sizeof (ffmpeg_info_t));
+ return _info;
+}
+static int
+ffmpeg_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
+ ffmpeg_info_t *info = (ffmpeg_info_t *)_info;
+ trace ("ffmpeg init %s\n", it->fname);
// prepare to decode the track
// return -1 on failure
@@ -119,13 +124,15 @@ ffmpeg_init (DB_playItem_t *it) {
// open file
trace ("\033[0;31mffmpeg av_open_input_file\033[37;0m\n");
current_track = it;
+ current_info = _info;
if ((ret = av_open_input_file(&info->fctx, uri, NULL, 0, NULL)) < 0) {
current_track = NULL;
trace ("\033[0;31minfo->fctx is %p, ret %d/%s\033[0;31m\n", info->fctx, ret, strerror(-ret));
- plugin.free (_info);
- return NULL;
+ return -1;
}
+ trace ("\033[0;31mav_open_input_file done, ret=%d\033[0;31m\n", ret);
current_track = NULL;
+ current_info = NULL;
trace ("\033[0;31mffmpeg av_find_stream_info\033[37;0m\n");
info->stream_id = -1;
@@ -146,16 +153,14 @@ ffmpeg_init (DB_playItem_t *it) {
if (info->codec == NULL)
{
trace ("ffmpeg can't decode %s\n", it->fname);
- plugin.free (_info);
- return NULL;
+ return -1;
}
trace ("ffmpeg can decode %s\n", it->fname);
trace ("ffmpeg: codec=%s, stream=%d\n", info->codec->name, i);
if (avcodec_open (info->ctx, info->codec) < 0) {
trace ("ffmpeg: avcodec_open failed\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
int bps = av_get_bits_per_sample_format (info->ctx->sample_fmt);
@@ -175,8 +180,7 @@ ffmpeg_init (DB_playItem_t *it) {
int err = posix_memalign ((void **)&info->buffer, 16, AVCODEC_MAX_AUDIO_FRAME_SIZE);
if (err) {
fprintf (stderr, "ffmpeg: failed to allocate buffer memory\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
// fill in mandatory plugin fields
@@ -197,7 +201,7 @@ ffmpeg_init (DB_playItem_t *it) {
info->startsample = 0;
info->endsample = totalsamples - 1;
}
- return _info;
+ return 0;
}
static void
@@ -545,6 +549,9 @@ ffmpeg_vfs_open(URLContext *h, const char *filename, int flags)
if (f->vfs->streaming) {
deadbeef->fset_track (f, current_track);
+ if (current_info) {
+ current_info->file = f;
+ }
}
h->priv_data = f;
@@ -635,6 +642,7 @@ static DB_decoder_t plugin = {
.plugin.website = "http://deadbeef.sf.net",
.plugin.start = ffmpeg_start,
.plugin.stop = ffmpeg_stop,
+ .open = ffmpeg_open,
.init = ffmpeg_init,
.free = ffmpeg_free,
.read_int16 = ffmpeg_read_int16,
diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c
index 5edb9526..08b8f1c8 100644
--- a/plugins/flac/flac.c
+++ b/plugins/flac/flac.c
@@ -171,17 +171,21 @@ cflac_init_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecode
}
static DB_fileinfo_t *
-cflac_init (DB_playItem_t *it) {
- trace ("cflac_init %s\n", it->fname);
+cflac_open (void) {
DB_fileinfo_t *_info = malloc (sizeof (flac_info_t));
+ memset (_info, 0, sizeof (flac_info_t));
+ return _info;
+}
+
+static int
+cflac_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
+ trace ("cflac_init %s\n", it->fname);
flac_info_t *info = (flac_info_t *)_info;
- memset (info, 0, sizeof (flac_info_t));
info->file = deadbeef->fopen (it->fname);
if (!info->file) {
trace ("cflac_init failed to open file\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
info->flac_critical_error = 0;
@@ -207,20 +211,17 @@ cflac_init (DB_playItem_t *it) {
char sign[4];
if (deadbeef->fread (sign, 1, 4, info->file) != 4) {
trace ("cflac_init failed to read signature\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
if (strncmp (sign, "fLaC", 4)) {
trace ("cflac_init bad signature\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
deadbeef->fseek (info->file, -4, SEEK_CUR);
}
else if (!FLAC_API_SUPPORTS_OGG_FLAC) {
trace ("flac: ogg transport support is not compiled into FLAC library\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
else {
isogg = 1;
@@ -230,8 +231,7 @@ cflac_init (DB_playItem_t *it) {
info->decoder = FLAC__stream_decoder_new ();
if (!info->decoder) {
trace ("FLAC__stream_decoder_new failed\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
FLAC__stream_decoder_set_md5_checking (info->decoder, 0);
if (isogg) {
@@ -242,14 +242,12 @@ cflac_init (DB_playItem_t *it) {
}
if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
trace ("cflac_init bad decoder status\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
//_info->samplerate = -1;
if (!FLAC__stream_decoder_process_until_end_of_metadata (info->decoder)) {
trace ("cflac_init metadata failed\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
// bps/samplerate/channels were set by callbacks
@@ -258,8 +256,7 @@ cflac_init (DB_playItem_t *it) {
if (_info->samplerate == -1) { // not a FLAC stream
trace ("cflac_init not a flac stream\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
info->buffer = malloc (BUFFERSIZE);
if (it->endsample > 0) {
@@ -267,8 +264,7 @@ cflac_init (DB_playItem_t *it) {
info->endsample = it->endsample;
if (plugin.seek_sample (_info, 0) < 0) {
trace ("cflac_init failed to seek to sample 0\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
trace ("flac(cue): startsample=%d, endsample=%d, totalsamples=%d, currentsample=%d\n", info->startsample, info->endsample, info->totalsamples, info->currentsample);
}
@@ -281,12 +277,11 @@ cflac_init (DB_playItem_t *it) {
if (info->flac_critical_error) {
trace ("flac: critical error while initializing\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
info->remaining = 0;
- return _info;
+ return 0;
}
static void
@@ -843,6 +838,7 @@ static DB_decoder_t plugin = {
.plugin.author = "Alexey Yakovenko",
.plugin.email = "waker@users.sourceforge.net",
.plugin.website = "http://deadbeef.sf.net",
+ .open = cflac_open,
.init = cflac_init,
.free = cflac_free,
.read_int16 = cflac_read_int16,
diff --git a/plugins/gme/cgme.c b/plugins/gme/cgme.c
index 77253df0..0b95fc22 100644
--- a/plugins/gme/cgme.c
+++ b/plugins/gme/cgme.c
@@ -33,14 +33,18 @@ typedef struct {
} gme_info_t;
static DB_fileinfo_t *
-cgme_init (DB_playItem_t *it) {
+cgme_open (void) {
DB_fileinfo_t *_info = malloc (sizeof (gme_info_t));
- gme_info_t *info = (gme_info_t*)_info;
memset (_info, 0, sizeof (gme_info_t));
+ return _info;
+}
+
+static int
+cgme_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
+ gme_info_t *info = (gme_info_t*)_info;
int samplerate = deadbeef->conf_get_int ("synth.samplerate", 48000);
if (gme_open_file (it->fname, &info->emu, samplerate)) {
- plugin.free (_info);
- return NULL;
+ return -1;
}
gme_mute_voices (info->emu, info->cgme_voicemask);
gme_start_track (info->emu, it->tracknum);
@@ -56,7 +60,7 @@ cgme_init (DB_playItem_t *it) {
info->duration = deadbeef->pl_get_item_duration (it);
info->reallength = inf.length;
_info->readpos = 0;
- return _info;
+ return 0;
}
static void
@@ -232,6 +236,7 @@ static DB_decoder_t plugin = {
.plugin.start = cgme_start,
.plugin.stop = cgme_stop,
.plugin.configdialog = settings_dlg,
+ .open = cgme_open,
.init = cgme_init,
.free = cgme_free,
.read_int16 = cgme_read,
diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c
index 1a7a8450..5c9e1ea3 100644
--- a/plugins/mpgmad/mpgmad.c
+++ b/plugins/mpgmad/mpgmad.c
@@ -560,15 +560,21 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
static DB_fileinfo_t *
-cmp3_init (DB_playItem_t *it) {
+cmp3_open (void) {
DB_fileinfo_t *_info = malloc (sizeof (mpgmad_info_t));
mpgmad_info_t *info = (mpgmad_info_t *)_info;
memset (info, 0, sizeof (mpgmad_info_t));
+ return _info;
+}
+
+static int
+cmp3_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
+ mpgmad_info_t *info = (mpgmad_info_t *)_info;
_info->plugin = &plugin;
memset (&info->buffer, 0, sizeof (info->buffer));
info->buffer.file = deadbeef->fopen (it->fname);
if (!info->buffer.file) {
- return NULL;
+ return -1;
}
info->info.file = info->buffer.file;
deadbeef->pl_item_ref (it);
@@ -611,8 +617,7 @@ cmp3_init (DB_playItem_t *it) {
int res = cmp3_scan_stream (&info->buffer, 0);
if (res < 0) {
trace ("mpgmad: cmp3_init: initial cmp3_scan_stream failed\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
deadbeef->pl_set_item_duration (it, info->buffer.duration);
if (info->buffer.duration >= 0) {
@@ -636,8 +641,7 @@ cmp3_init (DB_playItem_t *it) {
}
if (info->buffer.samplerate == 0) {
trace ("bad mpeg file: %f\n", it->fname);
- plugin.free (_info);
- return NULL;
+ return -1;
}
_info->bps = info->buffer.bitspersample;
_info->samplerate = info->buffer.samplerate;
@@ -648,7 +652,7 @@ cmp3_init (DB_playItem_t *it) {
mad_frame_init(&info->frame);
mad_synth_init(&info->synth);
- return _info;
+ return 0;
}
/****************************************************************************
@@ -1213,6 +1217,7 @@ static DB_decoder_t plugin = {
.plugin.author = "Alexey Yakovenko",
.plugin.email = "waker@users.sourceforge.net",
.plugin.website = "http://deadbeef.sf.net",
+ .open = cmp3_open,
.init = cmp3_init,
.free = cmp3_free,
.read_int16 = cmp3_read_int16,
diff --git a/plugins/sid/csid.cpp b/plugins/sid/csid.cpp
index 26f0a456..c3d8c8b6 100644
--- a/plugins/sid/csid.cpp
+++ b/plugins/sid/csid.cpp
@@ -273,16 +273,21 @@ sldb_find (const uint8_t *digest) {
}
DB_fileinfo_t *
-csid_init (DB_playItem_t *it) {
+csid_open (void) {
DB_fileinfo_t *_info = (DB_fileinfo_t *)malloc (sizeof (sid_info_t));
memset (_info, 0, sizeof (sid_info_t));
+ return _info;
+}
+
+int
+csid_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
sid_info_t *info = (sid_info_t *)_info;
// libsidplay crashes if file doesn't exist
// so i have to check it here
FILE *fp = fopen (it->fname, "rb");
if (!fp ){
- return NULL;
+ return -1;
}
fclose (fp);
@@ -326,7 +331,7 @@ csid_init (DB_playItem_t *it) {
}
}
}
- return _info;
+ return 0;
}
void
diff --git a/plugins/sid/csid.h b/plugins/sid/csid.h
index 608b3568..273daa2c 100644
--- a/plugins/sid/csid.h
+++ b/plugins/sid/csid.h
@@ -23,7 +23,8 @@
extern "C" {
#endif
-DB_fileinfo_t *csid_init (DB_playItem_t *it);
+DB_fileinfo_t *csid_open (void);
+int csid_init (DB_fileinfo_t *_info, DB_playItem_t *it);
void csid_free (DB_fileinfo_t *);
int csid_read (DB_fileinfo_t *, char *bytes, int size);
int csid_seek (DB_fileinfo_t *, float time);
diff --git a/plugins/sid/plugin.c b/plugins/sid/plugin.c
index 3535ad87..91c74bb5 100644
--- a/plugins/sid/plugin.c
+++ b/plugins/sid/plugin.c
@@ -42,6 +42,7 @@ DB_decoder_t sid_plugin = {
.plugin.stop = csid_stop,
.plugin.configdialog = settings_dlg,
.plugin.id = "stdsid",
+ .open = csid_open,
.init = csid_init,
.free = csid_free,
.read_int16 = csid_read,
diff --git a/plugins/sndfile/sndfile.c b/plugins/sndfile/sndfile.c
index e9467788..8535d1fd 100644
--- a/plugins/sndfile/sndfile.c
+++ b/plugins/sndfile/sndfile.c
@@ -85,17 +85,21 @@ static SF_VIRTUAL_IO vfs = {
};
static DB_fileinfo_t *
-sndfile_init (DB_playItem_t *it) {
+sndfile_open (void) {
DB_fileinfo_t *_info = malloc (sizeof (sndfile_info_t));
+ memset (_info, 0, sizeof (sndfile_info_t));
+ return _info;
+}
+
+static int
+sndfile_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
sndfile_info_t *info = (sndfile_info_t*)_info;
- memset (info, 0, sizeof (sndfile_info_t));
SF_INFO inf;
DB_FILE *fp = deadbeef->fopen (it->fname);
if (!fp) {
trace ("sndfile: failed to open %s\n", it->fname);
- plugin.free (_info);
- return NULL;
+ return -1;
}
int fsize = deadbeef->fgetlength (fp);
@@ -103,8 +107,7 @@ sndfile_init (DB_playItem_t *it) {
info->ctx = sf_open_virtual (&vfs, SFM_READ, &inf, info);
if (!info->ctx) {
trace ("sndfile: %s: unsupported file format\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
_info->plugin = &plugin;
_info->bps = 16;
@@ -115,8 +118,7 @@ sndfile_init (DB_playItem_t *it) {
info->startsample = it->startsample;
info->endsample = it->endsample;
if (plugin.seek_sample (_info, 0) < 0) {
- plugin.free (_info);
- return NULL;
+ return -1;
}
}
else {
@@ -132,7 +134,7 @@ sndfile_init (DB_playItem_t *it) {
info->bitrate = -1;
}
- return _info;
+ return 0;
}
static void
@@ -262,6 +264,7 @@ static DB_decoder_t plugin = {
.plugin.author = "Alexey Yakovenko",
.plugin.email = "waker@users.sourceforge.net",
.plugin.website = "http://deadbeef.sf.net",
+ .open = sndfile_open,
.init = sndfile_init,
.free = sndfile_free,
.read_int16 = sndfile_read_int16,
diff --git a/plugins/vfs_curl/vfs_curl.c b/plugins/vfs_curl/vfs_curl.c
index e7e5a390..6f459a53 100644
--- a/plugins/vfs_curl/vfs_curl.c
+++ b/plugins/vfs_curl/vfs_curl.c
@@ -617,14 +617,15 @@ http_close (DB_FILE *stream) {
static size_t
http_read (void *ptr, size_t size, size_t nmemb, DB_FILE *stream) {
-// trace ("http_read %d\n", size*nmemb);
assert (stream);
assert (ptr);
HTTP_FILE *fp = (HTTP_FILE *)stream;
+// trace ("http_read %d (status=%d)\n", size*nmemb, fp->status);
fp->seektoend = 0;
int sz = size * nmemb;
-// assert (size * nmemb <= BUFFER_SIZE);
-// trace ("readpos=%d, readsize=%d\n", fp->pos & BUFFER_SIZE, sz);
+ if (fp->status == STATUS_ABORTED || fp->status == STATUS_FINISHED) {
+ return -1;
+ }
if (!fp->tid) {
http_start_streamer (fp);
}
diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c
index c35bf190..2f15124c 100644
--- a/plugins/vorbis/vorbis.c
+++ b/plugins/vorbis/vorbis.c
@@ -131,10 +131,16 @@ update_vorbis_comments (DB_playItem_t *it, vorbis_comment *vc) {
}
static DB_fileinfo_t *
-cvorbis_init (DB_playItem_t *it) {
+cvorbis_open (void) {
DB_fileinfo_t *_info = malloc (sizeof (ogg_info_t));
ogg_info_t *info = (ogg_info_t *)_info;
memset (info, 0, sizeof (ogg_info_t));
+ return _info;
+}
+
+static int
+cvorbis_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
+ ogg_info_t *info = (ogg_info_t *)_info;
info->info.file = NULL;
info->vi = NULL;
info->cur_bit_stream = -1;
@@ -144,8 +150,7 @@ cvorbis_init (DB_playItem_t *it) {
info->info.file = deadbeef->fopen (it->fname);
if (!info->info.file) {
trace ("ogg: failed to open file %s\n", it->fname);
- plugin.free (_info);
- return NULL;
+ return -1;
}
int ln = deadbeef->fgetlength (info->info.file);
if (info->info.file->vfs->streaming && ln == -1) {
@@ -160,8 +165,7 @@ cvorbis_init (DB_playItem_t *it) {
int err = ov_open_callbacks (info->info.file, &info->vorbis_file, NULL, 0, ovcb);
if (err != 0) {
trace ("ov_open_callbacks returned %d\n", err);
- plugin.free (_info);
- return NULL;
+ return -1;
}
deadbeef->pl_set_item_duration (it, -1);
}
@@ -178,21 +182,18 @@ cvorbis_init (DB_playItem_t *it) {
int err = ov_open_callbacks (info->info.file, &info->vorbis_file, NULL, 0, ovcb);
if (err != 0) {
trace ("ov_open_callbacks returned %d\n", err);
- plugin.free (_info);
- return NULL;
+ return -1;
}
// deadbeef->pl_set_item_duration (it, ov_time_total (&vorbis_file, -1));
}
info->vi = ov_info (&info->vorbis_file, -1);
if (!info->vi) { // not a vorbis stream
trace ("not a vorbis stream\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
if (info->vi->rate <= 0) {
trace ("vorbis: bad samplerate\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
_info->plugin = &plugin;
_info->bps = 16;
@@ -223,7 +224,7 @@ cvorbis_init (DB_playItem_t *it) {
vorbis_comment *vc = ov_comment (&info->vorbis_file, -1);
update_vorbis_comments (it, vc);
}
- return _info;
+ return 0;
}
static void
@@ -616,6 +617,7 @@ static DB_decoder_t plugin = {
.plugin.website = "http://deadbeef.sf.net",
.plugin.start = vorbis_start,
.plugin.stop = vorbis_stop,
+ .open = cvorbis_open,
.init = cvorbis_init,
.free = cvorbis_free,
.read_int16 = cvorbis_read,
diff --git a/plugins/vtx/vtx.c b/plugins/vtx/vtx.c
index e05870c9..9bb4efa7 100644
--- a/plugins/vtx/vtx.c
+++ b/plugins/vtx/vtx.c
@@ -47,12 +47,17 @@ typedef struct {
} vtx_info_t;
static DB_fileinfo_t *
-vtx_init (DB_playItem_t *it) {
+vtx_open (void) {
+ DB_fileinfo_t *_info = malloc (sizeof (vtx_info_t));
+ memset (_info, 0, sizeof (vtx_info_t));
+ return _info;
+}
+
+static int
+vtx_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
// prepare to decode the track
// return -1 on failure
- DB_fileinfo_t *_info = malloc (sizeof (vtx_info_t));
vtx_info_t *info = (vtx_info_t *)_info;
- memset (info, 0, sizeof (vtx_info_t));
size_t sz = 0;
char *buf = NULL;
@@ -60,36 +65,31 @@ vtx_init (DB_playItem_t *it) {
DB_FILE *fp = deadbeef->fopen (it->fname);
if (!fp) {
trace ("vtx: failed to open file %s\n", it->fname);
- plugin.free (_info);
- return NULL;
+ return -1;
}
sz = deadbeef->fgetlength (fp);
if (sz <= 0) {
trace ("vtx: bad file size\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
buf = malloc (sz);
if (!buf) {
trace ("vtx: out of memory\n");
- plugin.free (_info);
- return NULL;
+ return -1;
}
if (deadbeef->fread (buf, 1, sz, fp) != sz) {
trace ("vtx: read failed\n");
free (buf);
- plugin.free (_info);
- return NULL;
+ return -1;
}
info->decoder = ayemu_vtx_load (buf, sz);
if (!info->decoder) {
trace ("vtx: ayemu_vtx_load failed\n");
free (buf);
- plugin.free (_info);
- return NULL;
+ return -1;
}
trace ("vtx: data=%p, size=%d\n", info->decoder->regdata, info->decoder->regdata_size);
@@ -112,7 +112,7 @@ vtx_init (DB_playItem_t *it) {
_info->channels = deadbeef->get_output ()->channels ();
_info->samplerate = samplerate;
_info->readpos = 0;
- return _info;
+ return 0;
}
static void
@@ -304,6 +304,7 @@ static DB_decoder_t plugin = {
.plugin.website = "http://deadbeef.sf.net",
.plugin.start = vtx_start,
.plugin.stop = vtx_stop,
+ .open = vtx_open,
.init = vtx_init,
.free = vtx_free,
.read_int16 = vtx_read_int16,
diff --git a/plugins/wavpack/wavpack.c b/plugins/wavpack/wavpack.c
index f54f0603..9e3abd68 100644
--- a/plugins/wavpack/wavpack.c
+++ b/plugins/wavpack/wavpack.c
@@ -92,20 +92,22 @@ static WavpackStreamReader wsr = {
};
static DB_fileinfo_t *
-wv_init (DB_playItem_t *it) {
+wv_open (void) {
DB_fileinfo_t *_info = malloc (sizeof (wvctx_t));
- wvctx_t *info = (wvctx_t *)_info;
- memset (info, 0, sizeof (wvctx_t));
+ memset (_info, 0, sizeof (wvctx_t));
+ return _info;
+}
+static int
+wv_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
+ wvctx_t *info = (wvctx_t *)_info;
info->file = deadbeef->fopen (it->fname);
if (!info->file) {
- plugin.free (_info);
- return NULL;
+ return -1;
}
info->ctx = WavpackOpenFileInputEx (&wsr, info->file, NULL, NULL, OPEN_2CH_MAX/*|OPEN_WVC*/, 0);
if (!info->ctx) {
- plugin.free (_info);
- return NULL;
+ return -1;
}
_info->plugin = &plugin;
_info->bps = WavpackGetBitsPerSample (info->ctx);
@@ -116,15 +118,14 @@ wv_init (DB_playItem_t *it) {
info->startsample = it->startsample;
info->endsample = it->endsample;
if (plugin.seek_sample (_info, 0) < 0) {
- plugin.free (_info);
- return NULL;
+ return -1;
}
}
else {
info->startsample = 0;
info->endsample = WavpackGetNumSamples (info->ctx)-1;
}
- return _info;
+ return 0;
}
static void
@@ -372,6 +373,7 @@ static DB_decoder_t plugin = {
.plugin.author = "Alexey Yakovenko",
.plugin.email = "waker@users.sourceforge.net",
.plugin.website = "http://deadbeef.sf.net",
+ .open = wv_open,
.init = wv_init,
.free = wv_free,
.read_int16 = wv_read_int16,
diff --git a/streamer.c b/streamer.c
index 0f3e70c3..d7a746e4 100644
--- a/streamer.c
+++ b/streamer.c
@@ -541,17 +541,20 @@ streamer_set_current (playItem_t *it) {
}
if (it->decoder_id) {
DB_decoder_t *dec = NULL;
- DB_fileinfo_t *info = NULL;
dec = plug_get_decoder_for_id (it->decoder_id);
if (dec) {
trace ("\033[0;33minit decoder for %s\033[37;0m\n", it->fname);
- info = dec->init (DB_PLAYITEM (it));
- trace ("\033[0;33mgot decoder for %s\033[37;0m\n", it->fname);
+ fileinfo = dec->open ();
+ if (fileinfo && dec->init (fileinfo, DB_PLAYITEM (it)) != 0) {
+ trace ("\033[0;31mfailed to init decoder\033[37;0m\n")
+ dec->free (fileinfo);
+ fileinfo = NULL;
+ }
}
- if (!dec || !info) {
+ if (!dec || !fileinfo) {
it->played = 1;
- trace ("decoder->init returned %p\n", info);
+ trace ("decoder->init returned %p\n", fileinfo);
streamer_buffering = 0;
if (playlist_track == it) {
trace ("redraw track %d; playing_track=%p; playlist_track=%p\n", to, playing_track, playlist_track);
@@ -562,14 +565,13 @@ streamer_set_current (playItem_t *it) {
}
else {
mutex_lock (decodemutex);
- fileinfo = info;
if (streaming_track) {
pl_item_unref (streaming_track);
}
streaming_track = it;
pl_item_ref (streaming_track);
mutex_unlock (decodemutex);
- trace ("bps=%d, channels=%d, samplerate=%d\n", info->bps, info->channels, info->samplerate);
+ trace ("bps=%d, channels=%d, samplerate=%d\n", fileinfo->bps, fileinfo->channels, fileinfo->samplerate);
}
// FIXME: that might break streaming at boundaries between 2 different samplerates
// streamer_reset (0); // reset SRC
@@ -624,7 +626,7 @@ streamer_set_nextsong (int song, int pstate) {
trace ("streamer_set_nextsong %d %d\n", song, pstate);
//plug_trigger_event (DB_EV_ABORTREAD, 0);
if (fileinfo && fileinfo->file) {
- trace ("\033[0;31maborting current song: %s\033[37;0m\n", streaming_track ? streaming_track->fname : NULL);
+ trace ("\033[0;31maborting current song: %s (fileinfo %p, file %p)\033[37;0m\n", streaming_track ? streaming_track->fname : NULL, fileinfo, fileinfo ? fileinfo->file : NULL);
mutex_lock (decodemutex);
deadbeef->fabort (fileinfo->file);
if (streamer_file) {
@@ -698,9 +700,15 @@ streamer_start_new_song (void) {
}
trace ("\033[0;34mbadsong=%d\033[37;0m\n", badsong);
// try jump to next song
- streamer_move_to_nextsong (0);
- trace ("streamer_move_to_nextsong switched to track %d\n", nextsong);
- usleep (50000);
+ if (nextsong == sng) {
+ streamer_move_to_nextsong (0);
+ trace ("streamer_move_to_nextsong switched to track %d\n", nextsong);
+ usleep (50000);
+ }
+ else {
+ trace ("nextsong changed to %d by another thread, reinit\n", nextsong);
+ badsong = -1;
+ }
return;
}
pl_item_unref (try);
@@ -735,6 +743,7 @@ streamer_thread (void *ctx) {
struct timeval tm1;
gettimeofday (&tm1, NULL);
if (nextsong >= 0) { // start streaming next song
+ trace ("\033[0;34mnextsong=%d\033[37;0m\n", nextsong);
streamer_start_new_song ();
// it's totally possible that song was switched
// while streamer_set_current was running,
@@ -810,22 +819,24 @@ streamer_thread (void *ctx) {
fileinfo->plugin->free (fileinfo);
fileinfo = NULL;
DB_decoder_t *dec = NULL;
- DB_fileinfo_t *info = NULL;
dec = plug_get_decoder_for_id (streaming_track->decoder_id);
if (dec) {
- info = dec->init (DB_PLAYITEM (streaming_track));
+ fileinfo = dec->open ();
+ if (fileinfo && dec->init (fileinfo, DB_PLAYITEM (streaming_track) < 0)) {
+ dec->free (fileinfo);
+ fileinfo = NULL;
+ }
}
- if (!dec || !info) {
+ if (!dec || !fileinfo) {
// FIXME: handle error
}
- else {
- fileinfo = info;
- }
mutex_unlock (decodemutex);
bytes_until_next_song = -1;
streamer_buffering = 1;
streamer_reset (1);
- prevtrack_samplerate = fileinfo->samplerate;
+ if (fileinfo) {
+ prevtrack_samplerate = fileinfo->samplerate;
+ }
}
}
@@ -870,14 +881,17 @@ streamer_thread (void *ctx) {
mutex_lock (decodemutex);
DB_decoder_t *dec = NULL;
- DB_fileinfo_t *info = NULL;
dec = plug_get_decoder_for_id (streaming_track->decoder_id);
if (dec) {
- info = dec->init (DB_PLAYITEM (streaming_track));
+ fileinfo = dec->open ();
+ if (fileinfo && dec->init (fileinfo, DB_PLAYITEM (streaming_track)) != 0) {
+ dec->free (fileinfo);
+ fileinfo = NULL;
+ }
}
mutex_unlock (decodemutex);
- if (!dec || !info) {
+ if (!dec || !fileinfo) {
if (streaming_track) {
plug_trigger_event_trackinfochanged (streaming_track);
}
@@ -887,9 +901,6 @@ streamer_thread (void *ctx) {
usleep (50000);
continue;
}
- else {
- fileinfo = info;
- }
}
bytes_until_next_song = -1;