From 8ef5d928c1183f43c3f30a4f59c8ef995ac711a9 Mon Sep 17 00:00:00 2001 From: waker Date: Sun, 30 Aug 2009 12:13:52 +0200 Subject: ported flac to plugin api --- Makefile.am | 2 +- cflac.c | 161 +++++++++++++++++++++++++++++++++-------------------------- moduleconf.h | 1 + 3 files changed, 91 insertions(+), 73 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2bd1af8d..9eaf05a9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,7 +20,7 @@ deadbeef_SOURCES =\ messagepump.c messagepump.h messages.h\ conf.c conf.h\ search.c search.h\ - cmp3.c cvorbis.c\ + cmp3.c cvorbis.c cflac.c\ palsa.c palsa.h playback.h\ threading_pthread.c threading.h\ md5/md5.c md5/md5.h md5/md5_loc.h\ diff --git a/cflac.c b/cflac.c index ad82df53..67fdba98 100644 --- a/cflac.c +++ b/cflac.c @@ -19,10 +19,13 @@ #include #include #include -#include "codec.h" -#include "cflac.h" -#include "common.h" -#include "playlist.h" +#include "deadbeef.h" + +static DB_decoder_t plugin; +static DB_functions_t *deadbeef; + +#define min(x,y) ((x)<(y)?(x):(y)) +#define max(x,y) ((x)>(y)?(x):(y)) static FLAC__StreamDecoder *decoder = 0; #define BUFFERSIZE 40000 @@ -31,26 +34,26 @@ static int remaining; // bytes remaining in buffer from last read static float timestart; static float timeend; -FLAC__StreamDecoderWriteStatus +static FLAC__StreamDecoderWriteStatus cflac_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const inputbuffer[], void *client_data) { if (frame->header.blocksize == 0) { return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } - int readbytes = frame->header.blocksize * cflac.info.channels * cflac.info.bitsPerSample / 8; + int readbytes = frame->header.blocksize * plugin.info.channels * plugin.info.bps / 8; int bufsize = BUFFERSIZE-remaining; - int bufsamples = bufsize / (cflac.info.channels * cflac.info.bitsPerSample / 8); + int bufsamples = bufsize / (plugin.info.channels * plugin.info.bps / 8); int nsamples = min (bufsamples, frame->header.blocksize); char *bufptr = &buffer[remaining]; for (int i = 0; i < nsamples; i++) { FLAC__int16 lsample = (FLAC__int16)inputbuffer[0][i]; ((int16_t*)bufptr)[0] = lsample; - bufptr += cflac.info.bitsPerSample / 8; - remaining += cflac.info.bitsPerSample / 8; - if (cflac.info.channels > 1) { + bufptr += plugin.info.bps / 8; + remaining += plugin.info.bps / 8; + if (plugin.info.channels > 1) { FLAC__int16 rsample = (FLAC__int16)inputbuffer[1][i]; ((int16_t*)bufptr)[0] = rsample; - bufptr += cflac.info.bitsPerSample / 8; - remaining += cflac.info.bitsPerSample / 8; + bufptr += plugin.info.bps / 8; + remaining += plugin.info.bps / 8; } } if (readbytes > bufsize) { @@ -60,36 +63,36 @@ cflac_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *fra return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } -void +static void cflac_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) { FLAC__uint64 total_samples = metadata->data.stream_info.total_samples; int sample_rate = metadata->data.stream_info.sample_rate; int channels = metadata->data.stream_info.channels; int bps = metadata->data.stream_info.bits_per_sample; - cflac.info.samplesPerSecond = sample_rate; - cflac.info.channels = channels; - cflac.info.bitsPerSample = bps; - cflac.info.readposition = 0; + plugin.info.samplerate = sample_rate; + plugin.info.channels = channels; + plugin.info.bps = bps; + plugin.info.readpos = 0; } -void +static void cflac_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) { // fprintf(stderr, "cflac: got error callback: %s\n", FLAC__StreamDecoderErrorStatusString[status]); } static int cflac_init_stop_decoding; -void +static void cflac_init_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) { // fprintf(stderr, "cflac: got error callback: %s\n", FLAC__StreamDecoderErrorStatusString[status]); cflac_init_stop_decoding = 1; } -void +static void cflac_free (void); -int -cflac_init (playItem_t *it) { +static int +cflac_init (DB_playItem_t *it) { FILE *fp = fopen (it->fname, "rb"); if (!fp) { return -1; @@ -118,26 +121,26 @@ cflac_init (playItem_t *it) { cflac_free (); return -1; } - cflac.info.samplesPerSecond = -1; + plugin.info.samplerate = -1; if (!FLAC__stream_decoder_process_until_end_of_metadata (decoder)) { cflac_free (); return -1; } - if (cflac.info.samplesPerSecond == -1) { // not a FLAC stream + if (plugin.info.samplerate == -1) { // not a FLAC stream cflac_free (); return -1; } timestart = it->timestart; timeend = it->timeend; if (timeend > timestart || timeend < 0) { - cflac.seek (0); + plugin.seek (0); } remaining = 0; return 0; } -void +static void cflac_free (void) { if (decoder) { FLAC__stream_decoder_delete(decoder); @@ -145,12 +148,12 @@ cflac_free (void) { } } -int +static int cflac_read (char *bytes, int size) { int initsize = size; - int nsamples = size / (cflac.info.channels * cflac.info.bitsPerSample / 8); + int nsamples = size / (plugin.info.channels * plugin.info.bps / 8); if (timeend > timestart) { - if (cflac.info.readposition + timestart > timeend) { + if (plugin.info.readpos + timestart > timeend) { return 0; } } @@ -164,9 +167,9 @@ cflac_read (char *bytes, int size) { remaining -= sz; bytes += sz; size -= sz; - cflac.info.readposition += (float)sz / (cflac.info.channels * cflac.info.samplesPerSecond * cflac.info.bitsPerSample / 8); + plugin.info.readpos += (float)sz / (plugin.info.channels * plugin.info.samplerate * plugin.info.bps / 8); if (timeend > timestart) { - if (cflac.info.readposition + timestart > timeend) { + if (plugin.info.readpos + timestart > timeend) { break; } } @@ -188,14 +191,14 @@ cflac_read (char *bytes, int size) { return initsize - size; } -int +static int cflac_seek (float time) { time += timestart; - if (!FLAC__stream_decoder_seek_absolute (decoder, (FLAC__uint64)(time * cflac.info.samplesPerSecond))) { + if (!FLAC__stream_decoder_seek_absolute (decoder, (FLAC__uint64)(time * plugin.info.samplerate))) { return -1; } remaining = 0; - cflac.info.readposition = time - timestart; + plugin.info.readpos = time - timestart; return 0; } @@ -208,15 +211,15 @@ cflac_init_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame } typedef struct { - playItem_t *after; - playItem_t *last; + DB_playItem_t *after; + DB_playItem_t *last; const char *fname; int samplerate; int nchannels; float duration; } cue_cb_data_t; -void +static void cflac_init_cue_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) { if (cflac_init_stop_decoding) { return; @@ -227,17 +230,19 @@ cflac_init_cue_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC_ cb->nchannels = metadata->data.stream_info.channels; cb->duration = metadata->data.stream_info.total_samples / (float)metadata->data.stream_info.sample_rate; } + // {{{ disabled +#if 0 else if (metadata->type == FLAC__METADATA_TYPE_CUESHEET) { //printf ("loading embedded cuesheet!\n"); const FLAC__StreamMetadata_CueSheet *cue = &metadata->data.cue_sheet; - playItem_t *prev = NULL; + DB_playItem_t *prev = NULL; for (int i = 0; i < cue->num_tracks; i++) { FLAC__StreamMetadata_CueSheet_Track *t = &cue->tracks[i]; if (t->type == 0 && t->num_indices > 0) { FLAC__StreamMetadata_CueSheet_Index *idx = t->indices; - playItem_t *it = malloc (sizeof (playItem_t)); - memset (it, 0, sizeof (playItem_t)); - it->codec = &cflac; + DB_playItem_t *it = malloc (sizeof (DB_playItem_t)); + memset (it, 0, sizeof (DB_playItem_t)); + it->decoder = &plugin; it->fname = strdup (cb->fname); it->tracknum = t->number; it->timestart = (float)t->offset / cb->samplerate; @@ -248,12 +253,12 @@ cflac_init_cue_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC_ } it->filetype = "FLAC"; //printf ("N: %d, t: %f, bps=%d\n", it->tracknum, it->timestart/60.f, cb->samplerate); - playItem_t *ins = pl_insert_item (cb->last, it); + DB_playItem_t *ins = deadbeef->pl_insert_item (cb->last, it); if (ins) { cb->last = ins; } else { - pl_item_free (it); + deadbeef->pl_item_free (it); it = NULL; } prev = it; @@ -265,7 +270,7 @@ cflac_init_cue_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC_ } } else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { - playItem_t *it = NULL; + DB_playItem_t *it = NULL; if (cb->after) { it = cb->after->next[PL_MAIN]; } @@ -281,14 +286,17 @@ cflac_init_cue_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC_ } } } +#endif +// }}} } -void + +static void cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) { if (cflac_init_stop_decoding) { printf ("error flag is set, ignoring init_metadata callback..\n"); return; } - playItem_t *it = (playItem_t *)client_data; + DB_playItem_t *it = (DB_playItem_t *)client_data; //it->tracknum = 0; if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { it->duration = metadata->data.stream_info.total_samples / (float)metadata->data.stream_info.sample_rate; @@ -303,25 +311,25 @@ cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__Str s[c->length] = 0; memcpy (s, c->entry, c->length); if (!strncasecmp (s, "ARTIST=", 7)) { - pl_add_meta (it, "artist", s + 7); + deadbeef->pl_add_meta (it, "artist", s + 7); } else if (!strncasecmp (s, "TITLE=", 6)) { - pl_add_meta (it, "title", s + 6); + deadbeef->pl_add_meta (it, "title", s + 6); title_added = 1; } else if (!strncasecmp (s, "ALBUM=", 6)) { - pl_add_meta (it, "album", s + 6); + deadbeef->pl_add_meta (it, "album", s + 6); } else if (!strncasecmp (s, "TRACKNUMBER=", 12)) { - pl_add_meta (it, "track", s + 12); + deadbeef->pl_add_meta (it, "track", s + 12); } else if (!strncasecmp (s, "DATE=", 5)) { - pl_add_meta (it, "date", s + 5); + deadbeef->pl_add_meta (it, "date", s + 5); } } } if (!title_added) { - pl_add_meta (it, "title", NULL); + deadbeef->pl_add_meta (it, "title", NULL); } // pl_add_meta (it, "artist", performer); @@ -333,9 +341,9 @@ cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__Str // *psr = metadata->data.stream_info.sample_rate; } -playItem_t * -cflac_insert (playItem_t *after, const char *fname) { - playItem_t *it = NULL; +static DB_playItem_t * +cflac_insert (DB_playItem_t *after, const char *fname) { + DB_playItem_t *it = NULL; FLAC__StreamDecoder *decoder = NULL; FILE *fp = fopen (fname, "rb"); if (!fp) { @@ -382,7 +390,7 @@ cflac_insert (playItem_t *after, const char *fname) { } // try external cue - playItem_t *cue_after = pl_insert_cue (after, fname, &cflac, "flac"); + DB_playItem_t *cue_after = deadbeef->pl_insert_cue (after, fname, &plugin, "flac"); if (cue_after) { cue_after->timeend = cb.duration; cue_after->duration = cue_after->timeend - cue_after->timestart; @@ -396,9 +404,8 @@ cflac_insert (playItem_t *after, const char *fname) { // try single FLAC file without cue FLAC__stream_decoder_set_metadata_respond_all (decoder); int samplerate = -1; - it = malloc (sizeof (playItem_t)); - memset (it, 0, sizeof (playItem_t)); - it->codec = &cflac; + it = deadbeef->pl_item_alloc (); + it->decoder = &plugin; it->fname = strdup (fname); it->tracknum = 0; it->timestart = 0; @@ -413,11 +420,11 @@ cflac_insert (playItem_t *after, const char *fname) { FLAC__stream_decoder_delete(decoder); decoder = NULL; it->filetype = "FLAC"; - after = pl_insert_item (after, it); + after = deadbeef->pl_insert_item (after, it); return after; cflac_insert_fail: if (it) { - pl_item_free (it); + deadbeef->pl_item_free (it); } if (decoder) { FLAC__stream_decoder_delete(decoder); @@ -428,22 +435,32 @@ cflac_insert_fail: return NULL; } -static const char * exts[]= -{ - "flac",NULL -}; +static const char *exts[] = { "flac", NULL }; -const char **cflac_getexts (void) { - return exts; -} +static const char *filetypes[] = { "FLAC", NULL }; -codec_t cflac = { +// define plugin interface +static DB_decoder_t plugin = { + .plugin.version_major = 0, + .plugin.version_minor = 1, + .plugin.type = DB_PLUGIN_DECODER, + .plugin.name = "FLAC decoder", + .plugin.author = "Alexey Yakovenko", + .plugin.email = "waker@users.sourceforge.net", + .plugin.website = "http://deadbeef.sf.net", .init = cflac_init, .free = cflac_free, - .read = cflac_read, + .read_int16 = cflac_read, +// .read_float32 = cflac_read_float32, .seek = cflac_seek, .insert = cflac_insert, - .getexts = cflac_getexts, + .exts = exts, .id = "stdflac", - .filetypes = { "FLAC", NULL } + .filetypes = filetypes }; + +DB_plugin_t * +flac_load (DB_functions_t *api) { + deadbeef = api; + return DB_PLUGIN (&plugin); +} diff --git a/moduleconf.h b/moduleconf.h index 80270d46..fa6c0c13 100644 --- a/moduleconf.h +++ b/moduleconf.h @@ -1,2 +1,3 @@ PLUG(mpegmad) PLUG(oggvorbis) +PLUG(flac) -- cgit v1.2.3