summaryrefslogtreecommitdiff
path: root/plugins/vorbis/vorbis.c
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-10-04 13:08:03 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-10-04 13:08:03 +0200
commit08e724afb2c7f09e8f7a4b2222694a8d4faffde7 (patch)
tree754a37b567651b1be2db103f14b8e9185ae6c08e /plugins/vorbis/vorbis.c
parent764853731fa9bb6246e2b16c148172d1f00c7c07 (diff)
experimental vorbis streaming support
Diffstat (limited to 'plugins/vorbis/vorbis.c')
-rw-r--r--plugins/vorbis/vorbis.c195
1 files changed, 144 insertions, 51 deletions
diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c
index 32d99660..0c277f04 100644
--- a/plugins/vorbis/vorbis.c
+++ b/plugins/vorbis/vorbis.c
@@ -40,6 +40,8 @@ static int cur_bit_stream;
static int startsample;
static int endsample;
static int currentsample;
+static int last_comment_update;
+static DB_playItem_t *ptrack;
static void
cvorbis_free (void);
@@ -52,6 +54,9 @@ cvorbis_fread (void *ptr, size_t size, size_t nmemb, void *datasource) {
static int
cvorbis_fseek (void *datasource, ogg_int64_t offset, int whence) {
DB_FILE *f = (DB_FILE *)datasource;
+ if (f->vfs->streaming) {
+ return -1;
+ }
return deadbeef->fseek (datasource, offset, whence);
}
@@ -66,29 +71,91 @@ cvorbis_ftell (void *datasource) {
return deadbeef->ftell (datasource);
}
+static void
+update_vorbis_comments (DB_playItem_t *it, vorbis_comment *vc) {
+ if (vc) {
+ deadbeef->pl_delete_all_meta (it);
+ deadbeef->pl_add_meta (it, "vendor", vc->vendor);
+ for (int i = 0; i < vc->comments; i++) {
+ if (!strncasecmp (vc->user_comments[i], "artist=", 7)) {
+ deadbeef->pl_add_meta (it, "artist", vc->user_comments[i] + 7);
+ }
+ else if (!strncasecmp (vc->user_comments[i], "album=", 6)) {
+ deadbeef->pl_add_meta (it, "album", vc->user_comments[i] + 6);
+ }
+ else if (!strncasecmp (vc->user_comments[i], "title=", 6)) {
+ deadbeef->pl_add_meta (it, "title", vc->user_comments[i] + 6);
+ }
+ else if (!strncasecmp (vc->user_comments[i], "date=", 5)) {
+ deadbeef->pl_add_meta (it, "date", vc->user_comments[i] + 5);
+ }
+ else if (!strncasecmp (vc->user_comments[i], "replaygain_album_gain=", 22)) {
+ it->replaygain_album_gain = atof (vc->user_comments[i] + 22);
+ }
+ else if (!strncasecmp (vc->user_comments[i], "replaygain_album_peak=", 22)) {
+ it->replaygain_album_peak = atof (vc->user_comments[i] + 22);
+ }
+ else if (!strncasecmp (vc->user_comments[i], "replaygain_track_gain=", 22)) {
+ it->replaygain_track_gain = atof (vc->user_comments[i] + 22);
+ }
+ else if (!strncasecmp (vc->user_comments[i], "replaygain_track_peak=", 22)) {
+ it->replaygain_track_peak = atof (vc->user_comments[i] + 22);
+ }
+ }
+ }
+ deadbeef->pl_add_meta (it, "title", NULL);
+}
+
static int
cvorbis_init (DB_playItem_t *it) {
file = NULL;
vi = NULL;
cur_bit_stream = -1;
+ ptrack = it;
file = deadbeef->fopen (it->fname);
if (!file) {
return -1;
}
- ov_callbacks ovcb = {
- .read_func = cvorbis_fread,
- .seek_func = cvorbis_fseek,
- .close_func = cvorbis_fclose,
- .tell_func = cvorbis_ftell
- };
-
memset (&plugin.info, 0, sizeof (plugin.info));
- ov_open_callbacks (file, &vorbis_file, NULL, 0, ovcb);
+ if (file->vfs->streaming) {
+ ov_callbacks ovcb = {
+ .read_func = cvorbis_fread,
+ .seek_func = NULL,
+ .close_func = cvorbis_fclose,
+ .tell_func = NULL
+ };
+
+ int err;
+ trace ("calling ov_open_callbacks\n");
+ if (err = ov_open_callbacks (file, &vorbis_file, NULL, 0, ovcb) != 0) {
+ trace ("ov_open_callbacks returned %d\n", err);
+ plugin.free ();
+ return -1;
+ }
+ }
+ else
+ {
+ ov_callbacks ovcb = {
+ .read_func = cvorbis_fread,
+ .seek_func = cvorbis_fseek,
+ .close_func = cvorbis_fclose,
+ .tell_func = cvorbis_ftell
+ };
+
+ trace ("calling ov_open_callbacks\n");
+ int err;
+ if (err = ov_open_callbacks (file, &vorbis_file, NULL, 0, ovcb) != 0) {
+ trace ("ov_open_callbacks returned %d\n", err);
+ plugin.free ();
+ return -1;
+ }
+ }
vi = ov_info (&vorbis_file, -1);
if (!vi) { // not a vorbis stream
cvorbis_free ();
+ trace ("not a vorbis stream\n");
return -1;
}
plugin.info.bps = 16;
@@ -97,14 +164,26 @@ cvorbis_init (DB_playItem_t *it) {
plugin.info.samplerate = vi->rate;
plugin.info.readpos = 0;
currentsample = 0;
- if (it->endsample > 0) {
- startsample = it->startsample;
- endsample = it->endsample;
- plugin.seek_sample (0);
+ if (!file->vfs->streaming) {
+ if (it->endsample > 0) {
+ startsample = it->startsample;
+ endsample = it->endsample;
+ plugin.seek_sample (0);
+ }
+ else {
+ startsample = 0;
+ endsample = ov_pcm_total (&vorbis_file, -1)-1;
+ }
}
else {
startsample = 0;
endsample = ov_pcm_total (&vorbis_file, -1)-1;
+ if (endsample <= 0) {
+ endsample = -1;
+ }
+ it->duration = -1;
+ vorbis_comment *vc = ov_comment (&vorbis_file, -1);
+ update_vorbis_comments (it, vc);
}
return 0;
}
@@ -112,6 +191,7 @@ cvorbis_init (DB_playItem_t *it) {
static void
cvorbis_free (void) {
if (file) {
+ ptrack = NULL;
ov_clear (&vorbis_file);
//fclose (file); //-- ov_clear closes it
file = NULL;
@@ -121,13 +201,31 @@ cvorbis_free (void) {
static int
cvorbis_read (char *bytes, int size) {
- if (currentsample + size / (2 * plugin.info.channels) > endsample) {
- size = (endsample - currentsample + 1) * 2 * plugin.info.channels;
- trace ("size truncated to %d bytes, cursample=%d, endsample=%d, totalsamples=%d\n", size, currentsample, endsample, ov_pcm_total (&vorbis_file, -1));
- if (size <= 0) {
- return 0;
+// trace ("cvorbis_read %d bytes\n", size);
+ if (!file->vfs->streaming) {
+ if (currentsample + size / (2 * plugin.info.channels) > endsample) {
+ size = (endsample - currentsample + 1) * 2 * plugin.info.channels;
+// trace ("size truncated to %d bytes, cursample=%d, endsample=%d, totalsamples=%d\n", size, currentsample, endsample, ov_pcm_total (&vorbis_file, -1));
+ if (size <= 0) {
+ return 0;
+ }
}
}
+ else {
+ if (ptrack && currentsample - last_comment_update > 5 * plugin.info.samplerate) {
+ int idx = deadbeef->pl_get_idx_of (ptrack);
+ if (idx >= 0) {
+ last_comment_update = currentsample;
+ vorbis_comment *vc = ov_comment (&vorbis_file, -1);
+ update_vorbis_comments (ptrack, vc);
+ deadbeef->sendmessage (M_TRACKCHANGED, 0, idx, 0);
+ }
+ else {
+ ptrack = NULL;
+ }
+ }
+ }
+// trace ("cvorbis_read %d bytes[2]\n", size);
int initsize = size;
for (;;)
{
@@ -139,6 +237,23 @@ cvorbis_read (char *bytes, int size) {
long ret=ov_read (&vorbis_file, bytes, size, endianess, 2, 1, &cur_bit_stream);
if (ret <= 0)
{
+ if (ret < 0) {
+ trace ("ov_read returned %d\n", ret);
+ switch (ret) {
+ case OV_HOLE:
+ trace ("OV_HOLE\n");
+ break;
+ case OV_EBADLINK:
+ trace ("OV_EBADLINK\n");
+ break;
+ case OV_EINVAL:
+ trace ("OV_EINVAL\n");
+ break;
+ }
+ }
+ if (ret == OV_HOLE) {
+ continue;
+ }
// error or eof
break;
}
@@ -155,6 +270,7 @@ cvorbis_read (char *bytes, int size) {
}
}
plugin.info.readpos = (float)(ov_pcm_tell(&vorbis_file)-startsample)/vi->rate;
+// trace ("cvorbis_read got %d bytes\n", initsize-size);
return initsize - size;
}
@@ -189,6 +305,16 @@ cvorbis_insert (DB_playItem_t *after, const char *fname) {
fprintf (stderr, "vorbis: failed to fopen %s\n", fname);
return NULL;
}
+ if (fp->vfs->streaming) {
+ DB_playItem_t *it = deadbeef->pl_item_alloc ();
+ it->decoder = &plugin;
+ it->fname = strdup (fname);
+ it->filetype = "OggVorbis";
+ it->duration = -1;
+ deadbeef->pl_add_meta (it, "title", NULL);
+ after = deadbeef->pl_insert_item (after, it);
+ return after;
+ }
ov_callbacks ovcb = {
.read_func = cvorbis_fread,
.seek_func = cvorbis_fseek,
@@ -218,41 +344,8 @@ cvorbis_insert (DB_playItem_t *after, const char *fname) {
it->duration = duration;
// metainfo
- int title_added = 0;
vorbis_comment *vc = ov_comment (&vorbis_file, -1);
- if (vc) {
- deadbeef->pl_add_meta (it, "vendor", vc->vendor);
- for (int i = 0; i < vc->comments; i++) {
- if (!strncasecmp (vc->user_comments[i], "artist=", 7)) {
- deadbeef->pl_add_meta (it, "artist", vc->user_comments[i] + 7);
- }
- else if (!strncasecmp (vc->user_comments[i], "album=", 6)) {
- deadbeef->pl_add_meta (it, "album", vc->user_comments[i] + 6);
- }
- else if (!strncasecmp (vc->user_comments[i], "title=", 6)) {
- deadbeef->pl_add_meta (it, "title", vc->user_comments[i] + 6);
- title_added = 1;
- }
- else if (!strncasecmp (vc->user_comments[i], "date=", 5)) {
- deadbeef->pl_add_meta (it, "date", vc->user_comments[i] + 5);
- }
- else if (!strncasecmp (vc->user_comments[i], "replaygain_album_gain=", 22)) {
- it->replaygain_album_gain = atof (vc->user_comments[i] + 22);
- }
- else if (!strncasecmp (vc->user_comments[i], "replaygain_album_peak=", 22)) {
- it->replaygain_album_peak = atof (vc->user_comments[i] + 22);
- }
- else if (!strncasecmp (vc->user_comments[i], "replaygain_track_gain=", 22)) {
- it->replaygain_track_gain = atof (vc->user_comments[i] + 22);
- }
- else if (!strncasecmp (vc->user_comments[i], "replaygain_track_peak=", 22)) {
- it->replaygain_track_peak = atof (vc->user_comments[i] + 22);
- }
- }
- }
- if (!title_added) {
- deadbeef->pl_add_meta (it, "title", NULL);
- }
+ update_vorbis_comments (it, vc);
ov_clear (&vorbis_file);
after = deadbeef->pl_insert_item (after, it);
return after;