diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2010-04-11 14:48:51 +0200 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2010-04-11 14:48:51 +0200 |
commit | dc0b9121ff16d57f92f4ab2b16bf78518d3a8b9b (patch) | |
tree | 858e45bd9314dccb468740602b90c8f3b003fac6 /plugins/gme/cgme.c | |
parent | fc339cf23d021e9cfe6893a5d30d168bf7107192 (diff) |
changed gme to dynamic plugin
Diffstat (limited to 'plugins/gme/cgme.c')
-rw-r--r-- | plugins/gme/cgme.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/plugins/gme/cgme.c b/plugins/gme/cgme.c new file mode 100644 index 00000000..2bed740c --- /dev/null +++ b/plugins/gme/cgme.c @@ -0,0 +1,248 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2010 Alexey Yakovenko <waker@users.sourceforge.net> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "gme/gme.h" +#include "deadbeef.h" + +static DB_decoder_t plugin; +static DB_functions_t *deadbeef; + +typedef struct { + DB_fileinfo_t info; + Music_Emu *emu; + int reallength; + uint32_t cgme_voicemask; + float duration; // of current song +} gme_info_t; + +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->conf_get_int ("synth.samplerate", 48000); + if (gme_open_file (it->fname, &info->emu, samplerate)) { + plugin.free (_info); + return NULL; + } + gme_mute_voices (info->emu, info->cgme_voicemask); + gme_start_track (info->emu, it->tracknum); + + track_info_t inf; + + 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->readpos = 0; + return _info; +} + +static void +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 (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)info->samplerate * 4; + } + if (gme_play (info->emu, size/2, (short*)bytes)) { + return 0; + } + _info->readpos += t; + if (info->reallength == -1) { + if (gme_track_ended (info->emu)) { + return 0; + } + } + return size; +} + +static int +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; + } + _info->readpos = time; + return 0; +} + +static DB_playItem_t * +cgme_insert (DB_playItem_t *after, const char *fname) { + Music_Emu *emu; + if (!gme_open_file (fname, &emu, gme_info_only)) { + int cnt = gme_track_count (emu); + for (int i = 0; i < cnt; i++) { + track_info_t inf; + 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.plugin.id); + it->fname = strdup (fname); + char str[1024]; + if (inf.song[0]) { + snprintf (str, 1024, "%d %s - %s", i, inf.game, inf.song); + } + else { + snprintf (str, 1024, "%d %s - ?", i, inf.game); + } + it->tracknum = i; + + // add metadata + deadbeef->pl_add_meta (it, "system", inf.system); + deadbeef->pl_add_meta (it, "album", inf.game); + int tl = sizeof (inf.song); + int n; + for (n = 0; i < tl && inf.song[n] && inf.song[n] == ' '; n++); + if (n == tl || !inf.song[n]) { + deadbeef->pl_add_meta (it, "title", NULL); + } + else { + deadbeef->pl_add_meta (it, "title", inf.song); + } + deadbeef->pl_add_meta (it, "artist", inf.author); + deadbeef->pl_add_meta (it, "copyright", inf.copyright); + deadbeef->pl_add_meta (it, "comment", inf.comment); + deadbeef->pl_add_meta (it, "dumper", inf.dumper); + char trk[10]; + snprintf (trk, 10, "%d", i+1); + deadbeef->pl_add_meta (it, "track", trk); + if (inf.length == -1) { + float songlength = deadbeef->conf_get_float ("gme.songlength", 3); + deadbeef->pl_set_item_duration (it, songlength * 60.f); + } + else { + deadbeef->pl_set_item_duration (it, (float)inf.length/1000.f); + } + const char *ext = fname + strlen (fname) - 1; + while (ext >= fname && *ext != '.') { + ext--; + } + it->filetype = NULL; + if (*ext == '.') { + ext++; + for (int i = 0; plugin.exts[i]; i++) { + if (!strcasecmp (ext, plugin.exts[i])) { + it->filetype = plugin.exts[i]; + } + } + } + after = deadbeef->pl_insert_item (after, it); + deadbeef->pl_item_unref (it); + } + else { + printf ("gme error: %s\n", ret); + } + } + if (emu) { + gme_delete (emu); + } + } + else { + printf ("error adding %s\n", fname); + } + return after; +} + +static const char * exts[]= +{ + "ay","gbs","gym","hes","kss","nsf","nsfe","sap","spc","vgm","vgz",NULL +}; + +#if 0 +static int +cgme_numvoices (void) { + if (!emu) { + return 0; + } + return gme_voice_count (emu); +} + +static void +cgme_mutevoice (int voice, int mute) { + cgme_voicemask &= ~ (1<<voice); + cgme_voicemask |= ((mute ? 1 : 0) << voice); + if (emu) { + gme_mute_voices (emu, cgme_voicemask); + } +} +#endif + +static int +cgme_start (void) { + return 0; +} + +static int +cgme_stop (void) { + return 0; +} + +static const char settings_dlg[] = + "property \"Max song length (in minutes)\" entry gme.songlength 3;\n" +; + +// define plugin interface +static DB_decoder_t plugin = { + DB_PLUGIN_SET_API_VERSION + .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", + .plugin.email = "waker@users.sourceforge.net", + .plugin.website = "http://deadbeef.sf.net", + .plugin.start = cgme_start, + .plugin.stop = cgme_stop, + .plugin.configdialog = settings_dlg, + .init = cgme_init, + .free = cgme_free, + .read_int16 = cgme_read, + .seek = cgme_seek, + .insert = cgme_insert, + .exts = exts, + .filetypes = exts +}; + +DB_plugin_t * +gme_load (DB_functions_t *api) { + deadbeef = api; + return DB_PLUGIN (&plugin); +} |