From e62acd10103783e1d4c51d4b041530400137521a Mon Sep 17 00:00:00 2001 From: Alexey Yakovenko Date: Sun, 3 Nov 2013 22:29:19 +0100 Subject: initial work on new file adding API --- deadbeef.h | 43 ++++++++++++++++++++++--- playlist.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 125 insertions(+), 23 deletions(-) diff --git a/deadbeef.h b/deadbeef.h index 3871be25..4c31f809 100644 --- a/deadbeef.h +++ b/deadbeef.h @@ -90,6 +90,12 @@ extern "C" { #define DDB_API_LEVEL DB_API_VERSION_MINOR #endif +#if (DDB_API_LEVEL >= 5) +#define DEPRECATED_15 __attribute__ ((deprecated("since deadbeef API 1.5"))) +#else +#define DEPRECATED_15 +#endif + #define DDB_PLUGIN_SET_API_VERSION\ .plugin.api_vmajor = DB_API_VERSION_MAJOR,\ .plugin.api_vminor = DB_API_VERSION_MINOR, @@ -367,11 +373,17 @@ typedef struct { #if (DDB_API_LEVEL >= 5) #define DDB_FREQ_BANDS 256 #define DDB_FREQ_MAX_CHANNELS 9 -typedef struct { +typedef struct ddb_audio_data_s { const ddb_waveformat_t *fmt; const float *data; int nframes; } ddb_audio_data_t; + +typedef struct ddb_fileadd_data_s { + int visibility; + ddb_playlist_t *plt; + ddb_playItem_t *track; +} ddb_fileadd_data_t; #endif // forward decl for plugin struct @@ -537,8 +549,8 @@ typedef struct { // operating on playlist items DB_playItem_t * (*plt_insert_item) (ddb_playlist_t *playlist, DB_playItem_t *after, DB_playItem_t *it); - DB_playItem_t * (*plt_insert_file) (ddb_playlist_t *playlist, DB_playItem_t *after, const char *fname, int *pabort, int (*cb)(DB_playItem_t *it, void *data), void *user_data); - DB_playItem_t *(*plt_insert_dir) (ddb_playlist_t *plt, DB_playItem_t *after, const char *dirname, int *pabort, int (*cb)(DB_playItem_t *it, void *data), void *user_data); + DB_playItem_t * (*plt_insert_file) (ddb_playlist_t *playlist, DB_playItem_t *after, const char *fname, int *pabort, int (*cb)(DB_playItem_t *it, void *data), void *user_data) DEPRECATED_15; + DB_playItem_t *(*plt_insert_dir) (ddb_playlist_t *plt, DB_playItem_t *after, const char *dirname, int *pabort, int (*cb)(DB_playItem_t *it, void *data), void *user_data) DEPRECATED_15; void (*plt_set_item_duration) (ddb_playlist_t *plt, DB_playItem_t *it, float duration); int (*plt_remove_item) (ddb_playlist_t *playlist, DB_playItem_t *it); int (*plt_getselcount) (ddb_playlist_t *playlist); @@ -879,6 +891,23 @@ typedef struct { // save referenced playlist in config int (*plt_save_n) (int n); int (*plt_save_config) (ddb_playlist_t *plt); + + // register file added callback + // the callback will be called for each file + // the visibility is taken from plt_add_* arguments + + void (*listen_file_added) (int (*callback)(ddb_fileadd_data_t *data, void *user_data), void *user_data); + void (*unlisten_file_added) (int (*callback)(ddb_fileadd_data_t *data, void *user_data), void *user_data); + + // visibility is a number, which tells listeners about the caller + // 0 is reserved for callers which want the GUI to intercept the calls, + // and show visual updates. + // this is the default value passed from plt_load, plt_add_dir, plt_add_file. + DB_playItem_t * (*plt_load2) (int visibility, ddb_playlist_t *plt, ddb_playItem_t *after, const char *fname, int *pabort); + int (*plt_add_file2) (int visibility, ddb_playlist_t *plt, const char *fname); + int (*plt_add_dir2) (int visibility, ddb_playlist_t *plt, const char *dirname); + ddb_playItem_t * (*plt_insert_file2) (int visibility, ddb_playlist_t *playlist, ddb_playItem_t *after, const char *fname, int *pabort); + ddb_playItem_t *(*plt_insert_dir2) (int visibility, ddb_playlist_t *plt, ddb_playItem_t *after, const char *dirname, int *pabort); #endif } DB_functions_t; @@ -1203,8 +1232,7 @@ typedef struct DB_vfs_s { int (*is_container) (const char *fname); // should return 1 if this plugin can parse specified file -// this is an evil hack to interrupt frozen vfs_curl streams -// FIXME: pass it through command API +// this allows interruption of hanging network streams void (*abort) (DB_FILE *stream); // file access, follows stdio API with few extension @@ -1274,6 +1302,11 @@ typedef struct DB_playlist_s { int (*save) (ddb_playlist_t *plt, const char *fname, DB_playItem_t *first, DB_playItem_t *last); const char **extensions; // NULL-terminated list of supported file extensions, e.g. {"m3u", "pls", NULL} + + // since 1.5 +#if (DDB_API_LEVEL >= 5) + DB_playItem_t * (*load2) (int visibility, ddb_playlist_t *plt, DB_playItem_t *after, const char *fname, int *pabort); +#endif } DB_playlist_t; #ifdef __cplusplus diff --git a/playlist.c b/playlist.c index c6a330d9..0f8c1899 100644 --- a/playlist.c +++ b/playlist.c @@ -1232,11 +1232,14 @@ plt_insert_cue (playlist_t *plt, playItem_t *after, playItem_t *origin, int nums static int follow_symlinks = 0; static int ignore_archives = 0; -playItem_t * -plt_insert_dir_int (playlist_t *playlist, DB_vfs_t *vfs, playItem_t *after, const char *dirname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data); +static playItem_t * +plt_insert_dir_int (int visibility, playlist_t *playlist, DB_vfs_t *vfs, playItem_t *after, const char *dirname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data); -playItem_t * -plt_insert_file (playlist_t *playlist, playItem_t *after, const char *fname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data) { +static playItem_t * +plt_load_int (int visibility, playlist_t *plt, playItem_t *after, const char *fname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data); + +static playItem_t * +plt_insert_file_int (int visibility, playlist_t *playlist, playItem_t *after, const char *fname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data) { trace ("count: %d\n", playlist->count[PL_MAIN]); trace ("pl_insert_file %s\n", fname); if (!fname || !(*fname)) { @@ -1251,7 +1254,7 @@ plt_insert_file (playlist_t *playlist, playItem_t *after, const char *fname, int trace ("%s cont test\n", fname); if (vfsplugs[i]->is_container (fname)) { trace ("inserting %s via vfs %s\n", fname, vfsplugs[i]->plugin.id); - playItem_t *it = plt_insert_dir_int (playlist, vfsplugs[i], after, fname, pabort, cb, user_data); + playItem_t *it = plt_insert_dir_int (visibility, playlist, vfsplugs[i], after, fname, pabort, cb, user_data); if (it) { return it; } @@ -1376,12 +1379,17 @@ plt_insert_file (playlist_t *playlist, playItem_t *after, const char *fname, int return NULL; } +playItem_t * +plt_insert_file (playlist_t *playlist, playItem_t *after, const char *fname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data) { + return plt_insert_file_int (0, playlist, after, fname, pabort, cb, user_data); +} + static int dirent_alphasort (const struct dirent **a, const struct dirent **b) { return strcmp ((*a)->d_name, (*b)->d_name); } -playItem_t * -plt_insert_dir_int (playlist_t *playlist, DB_vfs_t *vfs, playItem_t *after, const char *dirname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data) { +static playItem_t * +plt_insert_dir_int (int visibility, playlist_t *playlist, DB_vfs_t *vfs, playItem_t *after, const char *dirname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data) { if (!strncmp (dirname, "file://", 7)) { dirname += 7; } @@ -1419,16 +1427,16 @@ plt_insert_dir_int (playlist_t *playlist, DB_vfs_t *vfs, playItem_t *after, cons if (!vfs) { char fullname[PATH_MAX]; snprintf (fullname, sizeof (fullname), "%s/%s", dirname, namelist[i]->d_name); - inserted = plt_insert_dir_int (playlist, vfs, after, fullname, pabort, cb, user_data); + inserted = plt_insert_dir_int (visibility, playlist, vfs, after, fullname, pabort, cb, user_data); if (!inserted) { - inserted = plt_insert_file (playlist, after, fullname, pabort, cb, user_data); + inserted = plt_insert_file_int (visibility, playlist, after, fullname, pabort, cb, user_data); } } else { - inserted = plt_insert_file (playlist, after, namelist[i]->d_name, pabort, cb, user_data); + inserted = plt_insert_file_int (visibility, playlist, after, namelist[i]->d_name, pabort, cb, user_data); if (!inserted) { // special case for loading playlists in zip files - inserted = plt_load (playlist, after, namelist[i]->d_name, pabort, cb, user_data); + inserted = plt_load_int (visibility, playlist, after, namelist[i]->d_name, pabort, cb, user_data); } } if (inserted) { @@ -1450,17 +1458,17 @@ plt_insert_dir (playlist_t *playlist, playItem_t *after, const char *dirname, in follow_symlinks = conf_get_int ("add_folders_follow_symlinks", 0); ignore_archives = conf_get_int ("ignore_archives", 1); - playItem_t *ret = plt_insert_dir_int (playlist, NULL, after, dirname, pabort, cb, user_data); + playItem_t *ret = plt_insert_dir_int (0, playlist, NULL, after, dirname, pabort, cb, user_data); ignore_archives = 0; return ret; } -int -plt_add_file (playlist_t *plt, const char *fname, int (*cb)(playItem_t *it, void *data), void *user_data) { +static int +plt_add_file_int (int visibility, playlist_t *plt, const char *fname, int (*cb)(playItem_t *it, void *data), void *user_data) { int abort = 0; - playItem_t *it = plt_insert_file (plt, plt->tail[PL_MAIN], fname, &abort, cb, user_data); + playItem_t *it = plt_insert_file_int (visibility, plt, plt->tail[PL_MAIN], fname, &abort, cb, user_data); if (it) { // pl_insert_file doesn't hold reference, don't unref here return 0; @@ -1468,6 +1476,11 @@ plt_add_file (playlist_t *plt, const char *fname, int (*cb)(playItem_t *it, void return -1; } +int +plt_add_file (playlist_t *plt, const char *fname, int (*cb)(playItem_t *it, void *data), void *user_data) { + return plt_add_file_int (0, plt, fname, cb, user_data); +} + int plt_add_dir (playlist_t *plt, const char *dirname, int (*cb)(playItem_t *it, void *data), void *user_data) { int abort = 0; @@ -1914,6 +1927,9 @@ plt_save (playlist_t *plt, playItem_t *first, playItem_t *last, const char *fnam for (playItem_t *it = plt->head[PL_MAIN]; it; it = it->next[PL_MAIN]) { uint16_t l; uint8_t ll; + if (cb) { + cb(it, user_data); + } #if (PLAYLIST_MINOR_VER==2) const char *fname = pl_find_meta_raw (it, ":URI"); l = strlen (fname); @@ -2141,8 +2157,8 @@ pl_save_all (void) { return err; } -playItem_t * -plt_load (playlist_t *plt, playItem_t *after, const char *fname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data) { +static playItem_t * +plt_load_int (int visibility, playlist_t *plt, playItem_t *after, const char *fname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data) { // try plugins 1st const char *ext = strrchr (fname, '.'); if (ext) { @@ -2153,7 +2169,13 @@ plt_load (playlist_t *plt, playItem_t *after, const char *fname, int *pabort, in for (p = 0; plug[p]; p++) { for (e = 0; plug[p]->extensions[e]; e++) { if (plug[p]->load && !strcasecmp (ext, plug[p]->extensions[e])) { - DB_playItem_t *it = plug[p]->load ((ddb_playlist_t *)plt, (DB_playItem_t *)after, fname, pabort, (int (*)(DB_playItem_t *, void *))cb, user_data); + DB_playItem_t *it = NULL; + if (cb || (plug[p]->load && !plug[p]->load2)) { + it = plug[p]->load ((ddb_playlist_t *)plt, (DB_playItem_t *)after, fname, pabort, (int (*)(DB_playItem_t *, void *))cb, user_data); + } + else if (plug[p]->load2) { + plug[p]->load2 (visibility, (ddb_playlist_t *)plt, (DB_playItem_t *)after, fname, pabort); + } return (playItem_t *)it; } } @@ -2419,6 +2441,12 @@ load_fail: return last_added; } + +playItem_t * +plt_load (playlist_t *plt, playItem_t *after, const char *fname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data) { + return plt_load_int (0, plt, after, fname, pabort, cb, user_data); +} + int pl_load_all (void) { int i = 0; @@ -3910,3 +3938,44 @@ plt_save_config (playlist_t *plt) { } return plt_save_n (i); } + +void +listen_file_added (int (*callback)(ddb_fileadd_data_t *data, void *user_data), void *user_data) { +} + +void +unlisten_file_added (int (*callback)(ddb_fileadd_data_t *data, void *user_data), void *user_data) { +} + +DB_playItem_t * +plt_load2 (int visibility, playlist_t *plt, playItem_t *after, const char *fname, int *pabort) { + plt_load_int (visibility, plt, after, fname, pabort, NULL, NULL); +} + +int +plt_add_file2 (int visibility, playlist_t *plt, const char *fname) { + return plt_add_file_int (visibility, plt, fname, NULL, NULL); +} + +int +plt_add_dir2 (int visibility, playlist_t *plt, const char *dirname) { + follow_symlinks = conf_get_int ("add_folders_follow_symlinks", 0); + ignore_archives = conf_get_int ("ignore_archives", 1); + int abort = 0; + playItem_t *it = plt_insert_dir_int (visibility, plt, NULL, plt->tail[PL_MAIN], dirname, &abort, NULL, NULL); + if (it) { + // pl_insert_file doesn't hold reference, don't unref here + return 0; + } + return -1; +} + +playItem_t * +plt_insert_file2 (int visibility, playlist_t *playlist, playItem_t *after, const char *fname, int *pabort) { + return plt_insert_file_int (visibility, playlist, after, fname, pabort, NULL, NULL); +} + +playItem_t * +plt_insert_dir2 (int visibility, playlist_t *plt, playItem_t *after, const char *dirname, int *pabort) { + return plt_insert_dir_int (visibility, plt, NULL, after, dirname, pabort, NULL, NULL); +} -- cgit v1.2.3