From 9ae08cc0f9bed7a62801e2526537fcffe14e53a9 Mon Sep 17 00:00:00 2001 From: Alexey Yakovenko Date: Tue, 12 Jan 2010 09:13:17 +0100 Subject: ported gme and dumb to new api --- Makefile.am | 7 +- cdumb.c | 201 ++++++++++++++++++++++++++-------------------- cgme.c | 93 ++++++++++++--------- deadbeef.h | 16 ++-- moduleconf.h | 4 +- playlist.c | 2 +- plugins.c | 2 +- plugins/gtkui/callbacks.c | 2 +- plugins/mpgmad/mpgmad.c | 6 +- streamer.c | 9 +-- 10 files changed, 192 insertions(+), 150 deletions(-) diff --git a/Makefile.am b/Makefile.am index 8c943340..638c349e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,5 @@ SUBDIRS = ${MPGMAD_DIR}\ + gme/Game_Music_Emu-0.5.2\ pixmaps\ icons\ plugins/hotkeys\ @@ -52,14 +53,14 @@ deadbeef_SOURCES =\ junklib.h junklib.c utf8.c utf8.h\ optmath.h\ vfs.c vfs.h vfs_stdio.c\ - timeline.c timeline.h + timeline.c timeline.h\ + cgme.c cdumb.c # 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) -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++ 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/cdumb.c b/cdumb.c index 1b85450f..8cd8009b 100644 --- a/cdumb.c +++ b/cdumb.c @@ -23,12 +23,18 @@ #include "dumb/dumb-kode54/include/internal/it.h" #include "deadbeef.h" +//#define trace(...) { fprintf(stderr, __VA_ARGS__); } +#define trace(fmt,...) + static DB_decoder_t plugin; static DB_functions_t *deadbeef; -static int dumb_initialized; -static DUH *duh; -static DUH_SIGRENDERER *renderer; +typedef struct { + DB_fileinfo_t info; + DUH *duh; + DUH_SIGRENDERER *renderer; +} dumb_info_t; + //#define DUMB_RQ_ALIASING //#define DUMB_RQ_LINEAR //#define DUMB_RQ_CUBIC @@ -36,55 +42,18 @@ static DUH_SIGRENDERER *renderer; extern int dumb_resampling_quality; extern int dumb_it_max_to_mix; -static void -cdumb_free (void); - static int -cdumb_startrenderer (void); +cdumb_startrenderer (DB_fileinfo_t *_info); static DUH* open_module(const char *fname, const char *ext, int *start_order, int *is_it, int *is_dos, const char **filetype); -static DUMBFILE_SYSTEM dumb_vfs; - -static int -dumb_vfs_skip (void *f, long n) { - return deadbeef->fseek (f, n, SEEK_CUR); -} - -static int -dumb_vfs_getc (void *f) { - uint8_t c; - deadbeef->fread (&c, 1, 1, f); - return (int)c; -} - -static long -dumb_vfs_getnc (char *ptr, long n, void *f) { - return deadbeef->fread (ptr, 1, n, f); -} - -static void -dumb_vfs_close (void *f) { - deadbeef->fclose (f); -} - -static void -dumb_register_db_vfs (void) { - dumb_vfs.open = (void *(*)(const char *))deadbeef->fopen; - dumb_vfs.skip = dumb_vfs_skip; - dumb_vfs.getc = dumb_vfs_getc; - dumb_vfs.getnc = dumb_vfs_getnc; - dumb_vfs.close = dumb_vfs_close; - register_dumbfile_system (&dumb_vfs); -} - -static int +static DB_fileinfo_t * cdumb_init (DB_playItem_t *it) { - if (!dumb_initialized) { - atexit (&dumb_exit); - } - dumb_register_db_vfs (); + trace ("cdumb_init %s\n", it->fname); + DB_fileinfo_t *_info = malloc (sizeof (dumb_info_t)); + dumb_info_t *info = (dumb_info_t *)_info; + memset (_info, 0, sizeof (dumb_info_t)); int start_order = 0; int is_dos, is_it; @@ -94,36 +63,39 @@ cdumb_init (DB_playItem_t *it) { } ext++; const char *ftype; - duh = open_module(it->fname, ext, &start_order, &is_it, &is_dos, &ftype); + info->duh = open_module(it->fname, ext, &start_order, &is_it, &is_dos, &ftype); - dumb_it_do_initial_runthrough (duh); + dumb_it_do_initial_runthrough (info->duh); - plugin.info.bps = 16; - plugin.info.channels = 2; - plugin.info.samplerate = deadbeef->get_output ()->samplerate (); - plugin.info.readpos = 0; + _info->plugin = &plugin; + _info->bps = 16; + _info->channels = 2; + _info->samplerate = deadbeef->get_output ()->samplerate (); + _info->readpos = 0; - if (cdumb_startrenderer () < 0) { - return -1; + if (cdumb_startrenderer (_info) < 0) { + plugin.free (_info); + return NULL; } - return 0; + trace ("cdumb_init success (ptr=%p)\n", _info); + return _info; } static int -cdumb_startrenderer (void) { +cdumb_startrenderer (DB_fileinfo_t *_info) { + dumb_info_t *info = (dumb_info_t *)_info; // reopen - if (renderer) { - duh_end_sigrenderer (renderer); - renderer = NULL; + if (info->renderer) { + duh_end_sigrenderer (info->renderer); + info->renderer = NULL; } - renderer = duh_start_sigrenderer (duh, 0, 2, 0); - if (!renderer) { - cdumb_free (); + info->renderer = duh_start_sigrenderer (info->duh, 0, 2, 0); + if (!info->renderer) { return -1; } - DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer (renderer); + DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer (info->renderer); dumb_it_set_loop_callback (itsr, &dumb_it_callback_terminate, NULL); dumb_it_set_resampling_quality (itsr, 2); dumb_it_set_xm_speed_zero_callback (itsr, &dumb_it_callback_terminate, NULL); @@ -132,37 +104,49 @@ cdumb_startrenderer (void) { } static void -cdumb_free (void) { - if (renderer) { - duh_end_sigrenderer (renderer); - renderer = NULL; - } - if (duh) { - unload_duh (duh); - duh = NULL; +cdumb_free (DB_fileinfo_t *_info) { + trace ("cdumb_free %p\n", _info); + dumb_info_t *info = (dumb_info_t *)_info; + if (info) { + if (info->renderer) { + duh_end_sigrenderer (info->renderer); + info->renderer = NULL; + } + if (info->duh) { + unload_duh (info->duh); + info->duh = NULL; + } + free (info); } } static int -cdumb_read (char *bytes, int size) { +cdumb_read (DB_fileinfo_t *_info, char *bytes, int size) { + trace ("cdumb_read req %d\n", size); + dumb_info_t *info = (dumb_info_t *)_info; int length = size / 4; long ret; - ret = duh_render (renderer, 16, 0, 1, 65536.f / plugin.info.samplerate, length, bytes); - plugin.info.readpos += ret / (float)plugin.info.samplerate; + ret = duh_render (info->renderer, 16, 0, 1, 65536.f / _info->samplerate, length, bytes); + _info->readpos += ret / (float)_info->samplerate; + trace ("cdumb_read %d\n", ret*4); return ret*4; } static int -cdumb_seek (float time) { - if (time < plugin.info.readpos) { - cdumb_startrenderer (); +cdumb_seek (DB_fileinfo_t *_info, float time) { + trace ("cdumb_read seek %f\n", time); + dumb_info_t *info = (dumb_info_t *)_info; + if (time < _info->readpos) { + if (cdumb_startrenderer (_info) < 0) { + return -1; + } } else { - time -= plugin.info.readpos; + time -= _info->readpos; } - int pos = time * plugin.info.samplerate; - duh_sigrenderer_generate_samples (renderer, 0, 65536.0f / plugin.info.samplerate, pos, NULL); - plugin.info.readpos = duh_sigrenderer_get_position (renderer) / 65536.f; + int pos = time * _info->samplerate; + duh_sigrenderer_generate_samples (info->renderer, 0, 65536.0f / _info->samplerate, pos, NULL); + _info->readpos = duh_sigrenderer_get_position (info->renderer) / 65536.f; return 0; } @@ -766,14 +750,13 @@ cdumb_insert (DB_playItem_t *after, const char *fname) { int start_order = 0; int is_it; int is_dos; - dumb_register_db_vfs (); const char *ftype; DUH* duh = open_module(fname, ext, &start_order, &is_it, &is_dos, &ftype); if (!duh) { return NULL; } DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.id); + it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); it->fname = strdup (fname); DUMB_IT_SIGDATA * itsd = duh_get_it_sigdata(duh); if (itsd->name[0]) { @@ -793,13 +776,59 @@ cdumb_insert (DB_playItem_t *after, const char *fname) { dumb_it_do_initial_runthrough (duh); deadbeef->pl_set_item_duration (it, duh_get_length (duh)/65536.0f); it->filetype = ftype; -// printf ("duration: %f\n", plugin.info.duration); +// printf ("duration: %f\n", _info->duration); after = deadbeef->pl_insert_item (after, it); unload_duh (duh); return after; } +static DUMBFILE_SYSTEM dumb_vfs; + +static int +dumb_vfs_skip (void *f, long n) { + return deadbeef->fseek (f, n, SEEK_CUR); +} + +static int +dumb_vfs_getc (void *f) { + uint8_t c; + deadbeef->fread (&c, 1, 1, f); + return (int)c; +} + +static long +dumb_vfs_getnc (char *ptr, long n, void *f) { + return deadbeef->fread (ptr, 1, n, f); +} + +static void +dumb_vfs_close (void *f) { + deadbeef->fclose (f); +} + +static void +dumb_register_db_vfs (void) { + dumb_vfs.open = (void *(*)(const char *))deadbeef->fopen; + dumb_vfs.skip = dumb_vfs_skip; + dumb_vfs.getc = dumb_vfs_getc; + dumb_vfs.getnc = dumb_vfs_getnc; + dumb_vfs.close = dumb_vfs_close; + register_dumbfile_system (&dumb_vfs); +} + +int +cgme_start (void) { + dumb_register_db_vfs (); + return 0; +} + +int +cgme_stop (void) { + dumb_exit (); + return 0; +} + static const char *filetypes[] = { "IT", "XM", "S3M", "STM", "669", "PTM", "PSM", "MTM", "RIFF", "ASY", "MOD", NULL }; // define plugin interface @@ -808,18 +837,20 @@ static DB_decoder_t plugin = { .plugin.version_major = 0, .plugin.version_minor = 1, .plugin.type = DB_PLUGIN_DECODER, + .plugin.id = "stddumb", .plugin.name = "DUMB module player", .plugin.descr = "module player based on DUMB library", .plugin.author = "Alexey Yakovenko", .plugin.email = "waker@users.sourceforge.net", .plugin.website = "http://deadbeef.sf.net", + .plugin.start = cgme_start, + .plugin.stop = cgme_stop, .init = cdumb_init, .free = cdumb_free, .read_int16 = cdumb_read, .seek = cdumb_seek, .insert = cdumb_insert, .exts = exts, - .id = "stddumb", .filetypes = filetypes }; diff --git a/cgme.c b/cgme.c index f89f9175..371a2e04 100644 --- a/cgme.c +++ b/cgme.c @@ -24,56 +24,69 @@ static DB_decoder_t plugin; static DB_functions_t *deadbeef; -static Music_Emu *emu; -static int reallength; -static int nzerosamples; -static uint32_t cgme_voicemask = 0; -static float duration; // of current song +typedef struct { + DB_fileinfo_t info; + Music_Emu *emu; + int reallength; + int nzerosamples; + uint32_t cgme_voicemask; + float duration; // of current song +} gme_info_t; -static int +static DB_fileinfo_t * cgme_init (DB_playItem_t *it) { + DB_fileinfo_t *_info = malloc (sizeof (gme_info_t)); + gme_info_t *info = (gme_info_t*)_info; + memset (_info, 0, sizeof (gme_info_t)); int samplerate = deadbeef->get_output ()->samplerate (); - if (gme_open_file (it->fname, &emu, samplerate)) { - return -1; + if (gme_open_file (it->fname, &info->emu, samplerate)) { + plugin.free (_info); + return NULL; } - gme_mute_voices (emu, cgme_voicemask); - gme_start_track (emu, it->tracknum); + gme_mute_voices (info->emu, info->cgme_voicemask); + gme_start_track (info->emu, it->tracknum); + track_info_t inf; - gme_track_info (emu, &inf, it->tracknum); - plugin.info.bps = 16; - plugin.info.channels = 2; - plugin.info.samplerate = samplerate; - duration = deadbeef->pl_get_item_duration (it); - reallength = inf.length; - nzerosamples = 0; - plugin.info.readpos = 0; - return 0; + + gme_track_info (info->emu, &inf, it->tracknum); + + _info->plugin = &plugin; + _info->bps = 16; + _info->channels = 2; + _info->samplerate = samplerate; + info->duration = deadbeef->pl_get_item_duration (it); + info->reallength = inf.length; + info->nzerosamples = 0; + _info->readpos = 0; + return _info; } static void -cgme_free (void) { - if (emu) { - gme_delete (emu); - emu = NULL; +cgme_free (DB_fileinfo_t *_info) { + gme_info_t *info = (gme_info_t*)_info; + if (info->emu) { + gme_delete (info->emu); } + free (info); } static int -cgme_read (char *bytes, int size) { - float t = (size/4) / (float)plugin.info.samplerate; - if (plugin.info.readpos + t >= duration) { - t = duration - plugin.info.readpos; +cgme_read (DB_fileinfo_t *_info, char *bytes, int size) { + gme_info_t *info = (gme_info_t*)_info; + float t = (size/4) / (float)_info->samplerate; + if (_info->readpos + t >= info->duration) { + t = info->duration - _info->readpos; if (t <= 0) { return 0; } // DON'T ajust size, buffer must always be po2 - //size = t * (float)plugin.info.samplerate * 4; + //size = t * (float)info->samplerate * 4; } - if (gme_play (emu, size/2, (short*)bytes)) { + if (gme_play (info->emu, size/2, (short*)bytes)) { return 0; } - plugin.info.readpos += t; - if (reallength == -1) { + _info->readpos += t; + if (info->reallength == -1) { // check if whole buffer is zeroes int i; for (i = 0; i < size; i++) { @@ -82,30 +95,30 @@ cgme_read (char *bytes, int size) { } } if (i == size) { - nzerosamples += size / 4; - if (nzerosamples > plugin.info.samplerate * 4) { + info->nzerosamples += size / 4; + if (info->nzerosamples > _info->samplerate * 4) { return 0; } } else { - nzerosamples = 0; + info->nzerosamples = 0; } } return size; } static int -cgme_seek (float time) { - if (gme_seek (emu, (long)(time * 1000))) { +cgme_seek (DB_fileinfo_t *_info, float time) { + gme_info_t *info = (gme_info_t*)_info; + if (gme_seek (info->emu, (long)(time * 1000))) { return -1; } - plugin.info.readpos = time; + _info->readpos = time; return 0; } static DB_playItem_t * cgme_insert (DB_playItem_t *after, const char *fname) { -// printf ("adding %s chiptune\n", fname); Music_Emu *emu; if (!gme_open_file (fname, &emu, gme_info_only)) { int cnt = gme_track_count (emu); @@ -114,7 +127,7 @@ cgme_insert (DB_playItem_t *after, const char *fname) { const char *ret = gme_track_info (emu, &inf, i); if (!ret) { DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.id); + it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); it->fname = strdup (fname); char str[1024]; if (inf.song[0]) { @@ -209,6 +222,7 @@ static DB_decoder_t plugin = { .plugin.version_major = 0, .plugin.version_minor = 1, .plugin.type = DB_PLUGIN_DECODER, + .plugin.id = "stdgme", .plugin.name = "Game_Music_Emu decoder", .plugin.descr = "chiptune music player based on GME", .plugin.author = "Alexey Yakovenko", @@ -220,7 +234,6 @@ static DB_decoder_t plugin = { .seek = cgme_seek, .insert = cgme_insert, .exts = exts, - .id = "stdgme", .filetypes = exts }; diff --git a/deadbeef.h b/deadbeef.h index 801fd8e9..4118a97a 100644 --- a/deadbeef.h +++ b/deadbeef.h @@ -400,13 +400,16 @@ typedef struct DB_plugin_s { int inactive; // prevent plugin from being dynamically stopped int nostop; + // any of those can be left NULL // though it's much better to fill them with something useful - const char *name; - const char *descr; - const char *author; - const char *email; - const char *website; + const char *id; // id used for serialization and runtime binding + const char *name; // short name + const char *descr; // short description + const char *author; // author's name + const char *email; // author's email + const char *website; // author's website + // start is called to start plugin; can be NULL int (*start) (void); // stop is called to deinit plugin; can be NULL @@ -468,9 +471,6 @@ typedef struct DB_decoder_s { // NULL terminated array of all file type names const char **filetypes; - - // codec id used for playlist serialization - const char *id; } DB_decoder_t; // output plugin diff --git a/moduleconf.h b/moduleconf.h index 40aa3038..cc1df308 100644 --- a/moduleconf.h +++ b/moduleconf.h @@ -1,4 +1,4 @@ -//PLUG(gme) -//PLUG(dumb) +PLUG(gme) +PLUG(dumb) //PLUG(sid) PLUG(stdio) diff --git a/playlist.c b/playlist.c index aef7d531..62e98d95 100644 --- a/playlist.c +++ b/playlist.c @@ -739,7 +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); + trace ("matching decoder %d(%s)...\n", i, decoders[i]->plugin.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 8163ec11..de3bcf67 100644 --- a/plugins.c +++ b/plugins.c @@ -782,7 +782,7 @@ DB_decoder_t * plug_get_decoder_for_id (const char *id) { DB_decoder_t **plugins = plug_get_decoder_list (); for (int c = 0; plugins[c]; c++) { - if (!strcmp (id, plugins[c]->id)) { + if (!strcmp (id, plugins[c]->plugin.id)) { return plugins[c]; } } diff --git a/plugins/gtkui/callbacks.c b/plugins/gtkui/callbacks.c index 09b5b03d..0b6a0a9e 100644 --- a/plugins/gtkui/callbacks.c +++ b/plugins/gtkui/callbacks.c @@ -1005,7 +1005,7 @@ seekbar_draw (GtkWidget *widget) { return; } DB_playItem_t *trk = deadbeef->streamer_get_playing_track (); - DB_decoder_t *dec = deadbeef->streamer_get_current_decoder (); + DB_fileinfo_t *dec = deadbeef->streamer_get_current_decoder (); if (!dec || deadbeef->pl_get_item_duration (trk) < 0) { clearlooks_rounded_rectangle (cr, 2, widget->allocation.height/2-4, widget->allocation.width-4, 8, 4, 0xff); theme_set_cairo_source_rgb (cr, COLO_SEEKBAR_FRONT); diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c index b67fbc6a..aca849a7 100644 --- a/plugins/mpgmad/mpgmad.c +++ b/plugins/mpgmad/mpgmad.c @@ -972,7 +972,7 @@ cmp3_insert (DB_playItem_t *after, const char *fname) { } if (fp->vfs->streaming) { DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.id); + it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); it->fname = strdup (fname); deadbeef->fclose (fp); deadbeef->pl_add_meta (it, "title", NULL); @@ -1037,7 +1037,7 @@ cmp3_insert (DB_playItem_t *after, const char *fname) { } } DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.id); + it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); it->fname = strdup (fname); deadbeef->rewind (fp); @@ -1070,6 +1070,7 @@ static DB_decoder_t plugin = { .plugin.version_major = 0, .plugin.version_minor = 1, .plugin.type = DB_PLUGIN_DECODER, + .plugin.id = "stdmpg", .plugin.name = "MPEG decoder", .plugin.descr = "MPEG v1/2 layer1/2/3 decoder based on libmad", .plugin.author = "Alexey Yakovenko", @@ -1083,7 +1084,6 @@ static DB_decoder_t plugin = { .seek_sample = cmp3_seek_sample, .insert = cmp3_insert, .exts = exts, - .id = "stdmpg", .filetypes = filetypes }; diff --git a/streamer.c b/streamer.c index c2e1e436..38371b77 100644 --- a/streamer.c +++ b/streamer.c @@ -36,8 +36,8 @@ #include "volume.h" #include "vfs.h" -#define trace(...) { fprintf(stderr, __VA_ARGS__); } -//#define trace(fmt,...) +//#define trace(...) { fprintf(stderr, __VA_ARGS__); } +#define trace(fmt,...) static intptr_t streamer_tid; static int src_quality; @@ -183,11 +183,8 @@ streamer_set_current (playItem_t *it) { dec = plug_get_decoder_for_id (it->decoder_id); } if (dec) { - streamer_lock (); - streamer_unlock (); str_current_decoder = dec->init (DB_PLAYITEM (it)); - streamer_lock (); - streamer_unlock (); + trace ("str: acquired decoder ptr %p\n", str_current_decoder); pl_item_copy (&str_streaming_song, it); if (!str_current_decoder) { trace ("decoder->init returned NULL\n"); -- cgit v1.2.3