diff options
author | Lithopsian <deadbeef@nartowicz.co.uk> | 2014-06-22 22:39:47 +0100 |
---|---|---|
committer | Lithopsian <deadbeef@nartowicz.co.uk> | 2014-06-22 22:39:47 +0100 |
commit | 6cd87a40c3a3da1ff8ecdc0f8b980cec38de84aa (patch) | |
tree | 7d87af9dae15d6227edc3f0efebe16c49593a973 /plugins | |
parent | 579a1e72d3c96c2b04f127cc273f3641a56702fe (diff) | |
parent | d43b7c86b8fe7e5ef47a78becbca46b121d33d40 (diff) |
Merge pull request #7 from Alexey-Yakovenko/master
Resync
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/artwork/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/artwork/escape.h | 34 | ||||
-rw-r--r-- | plugins/converter/converter.c | 154 | ||||
-rw-r--r-- | plugins/converter/converter.glade | 16 | ||||
-rw-r--r-- | plugins/converter/converter.h | 3 | ||||
-rw-r--r-- | plugins/converter/convgui.c | 189 | ||||
-rw-r--r-- | plugins/converter/interface.c | 6 | ||||
-rw-r--r-- | plugins/flac/flac.c | 106 | ||||
-rw-r--r-- | plugins/gtkui/actionhandlers.c | 13 | ||||
-rw-r--r-- | plugins/gtkui/deadbeef.glade | 1 | ||||
-rw-r--r-- | plugins/gtkui/interface.c | 1 | ||||
-rw-r--r-- | plugins/gtkui/plcommon.c | 11 | ||||
-rw-r--r-- | plugins/m3u/m3u.c | 31 |
13 files changed, 345 insertions, 222 deletions
diff --git a/plugins/artwork/Makefile.am b/plugins/artwork/Makefile.am index 9fb8bea8..11f98e24 100644 --- a/plugins/artwork/Makefile.am +++ b/plugins/artwork/Makefile.am @@ -21,7 +21,7 @@ endif if HAVE_FLAC FLAC_DEPS=$(FLAC_LIBS) -flac_clags=-DUSE_METAFLAC $(FLAC_CFLAGS) +flac_cflags=-DUSE_METAFLAC $(FLAC_CFLAGS) endif AM_CFLAGS = $(CFLAGS) $(ARTWORK_CFLAGS) $(flac_cflags) $(artwork_net_cflags) -std=c99 diff --git a/plugins/artwork/escape.h b/plugins/artwork/escape.h index a8086a89..bd76f4d4 100644 --- a/plugins/artwork/escape.h +++ b/plugins/artwork/escape.h @@ -1,20 +1,24 @@ /* - DeaDBeeF - ultimate music player for GNU/Linux systems with X11 - Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net> + DeaDBeeF -- the music player + Copyright (C) 2009-2014 Alexey Yakovenko and other contributors - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. */ #ifndef __ESCAPE_H #define __ESCAPE_H diff --git a/plugins/converter/converter.c b/plugins/converter/converter.c index 41e896dd..a0e7a218 100644 --- a/plugins/converter/converter.c +++ b/plugins/converter/converter.c @@ -167,7 +167,7 @@ encoder_preset_save (ddb_encoder_preset_t *p, int overwrite) { return -1; } const char *confdir = deadbeef->get_config_dir (); - char path[1024]; + char path[PATH_MAX]; if (snprintf (path, sizeof (path), "%s/presets", confdir) < 0) { return -1; } @@ -371,7 +371,7 @@ dsp_preset_save (ddb_dsp_preset_t *p, int overwrite) { return -1; } const char *confdir = deadbeef->get_config_dir (); - char path[1024]; + char path[PATH_MAX]; if (snprintf (path, sizeof (path), "%s/presets", confdir) < 0) { return -1; } @@ -458,77 +458,69 @@ copy_file (const char *in, const char *out) { int load_encoder_presets (void) { // check if we need to install presets - char ppath[1024]; - char epath[1024]; - char fpath[1024]; + char ppath[PATH_MAX]; + char epath[PATH_MAX]; snprintf (ppath, sizeof (ppath), "%s/presets", deadbeef->get_config_dir ()); snprintf (epath, sizeof (epath), "%s/encoders", ppath); - snprintf (fpath, sizeof (fpath), "%s/.installed", epath); - struct stat stat_buf; - if (0 != stat (fpath, &stat_buf)) { - // file not found, install all presets from plugin_dir/convpresets/ - mkdir (ppath, 0755); - mkdir (epath, 0755); - char preset_src_dir[1024]; - snprintf (preset_src_dir, sizeof (preset_src_dir), "%s/convpresets", deadbeef->get_plugin_dir ()); - struct dirent **namelist = NULL; - int n = scandir (preset_src_dir, &namelist, NULL, dirent_alphasort); - for (int i = 0; i < n; i++) { - // replace _ with spaces - char new_name[1024]; - char *o = new_name; - char *in = namelist[i]->d_name; - while (*in) { - if (*in == '_') { - *o++ = ' '; - in++; - } - else { - *o++ = *in++; - } - } - *o = 0; - char in_name[1024]; - char out_name[1024]; - snprintf (in_name, sizeof (in_name), "%s/%s", preset_src_dir, namelist[i]->d_name); - snprintf (out_name, sizeof (out_name), "%s/%s", epath, new_name); - copy_file (in_name, out_name); - free (namelist[i]); - } - if (namelist) { - free (namelist); - } - FILE *fp = fopen (fpath, "w+b"); - if (fp) { - fclose (fp); - } - } - ddb_encoder_preset_t *tail = NULL; - char path[1024]; + char path[PATH_MAX]; if (snprintf (path, sizeof (path), "%s/presets/encoders", deadbeef->get_config_dir ()) < 0) { return -1; } - struct dirent **namelist = NULL; - int n = scandir (path, &namelist, scandir_preset_filter, dirent_alphasort); - int i; - for (i = 0; i < n; i++) { - char s[1024]; - if (snprintf (s, sizeof (s), "%s/%s", path, namelist[i]->d_name) > 0){ - ddb_encoder_preset_t *p = encoder_preset_load (s); - if (p) { - if (tail) { - tail->next = p; - tail = p; - } - else { - encoder_presets = tail = p; + + char syspath[PATH_MAX]; + if (snprintf (syspath, sizeof (syspath), "%s/convpresets", deadbeef->get_plugin_dir ()) < 0) { + return -1; + } + + const char *preset_dirs[] = { + syspath, path, NULL + }; + + ddb_encoder_preset_t *tail = NULL; + + for (int di = 0; preset_dirs[di]; di++) { + const char *path = preset_dirs[di]; + struct dirent **namelist = NULL; + int n = scandir (path, &namelist, scandir_preset_filter, dirent_alphasort); + int i; + for (i = 0; i < n; i++) { + char s[PATH_MAX]; + if (snprintf (s, sizeof (s), "%s/%s", path, namelist[i]->d_name) > 0){ + ddb_encoder_preset_t *p = encoder_preset_load (s); + if (p) { + if (path == syspath) { + // don't allow editing stock presets + p->readonly = 1; + } + else { + // check if the same RO preset exists + for (ddb_encoder_preset_t *pr = encoder_presets; pr; pr = pr->next) { + if (pr->readonly && !strcmp (pr->title, p->title)) { + encoder_preset_free (p); + p = NULL; + break; + } + } + if (!p) { + // NOTE: we don't delete duplicate presets in $HOME + // for compat with <=0.6.1 + continue; + } + } + if (tail) { + tail->next = p; + tail = p; + } + else { + encoder_presets = tail = p; + } } } + free (namelist[i]); } - free (namelist[i]); + free (namelist); } - free (namelist); return 0; } @@ -555,7 +547,7 @@ free_encoder_presets (void) { int load_dsp_presets (void) { ddb_dsp_preset_t *tail = NULL; - char path[1024]; + char path[PATH_MAX]; if (snprintf (path, sizeof (path), "%s/presets/dsp", deadbeef->get_config_dir ()) < 0) { return -1; } @@ -563,7 +555,7 @@ load_dsp_presets (void) { int n = scandir (path, &namelist, scandir_preset_filter, dirent_alphasort); int i; for (i = 0; i < n; i++) { - char s[1024]; + char s[PATH_MAX]; if (snprintf (s, sizeof (s), "%s/%s", path, namelist[i]->d_name) > 0){ ddb_dsp_preset_t *p = dsp_preset_load (s); if (p) { @@ -929,10 +921,10 @@ convert (DB_playItem_t *it, const char *out, int output_bps, int output_is_float // write wave header char wavehdr_int[] = { - 0x52, 0x49, 0x46, 0x46, 0x24, 0x70, 0x0d, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61 + 0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61 }; char wavehdr_float[] = { - 0x52, 0x49, 0x46, 0x46, 0x2a, 0xdf, 0x02, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, 0x28, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x02, 0x00, 0x40, 0x1f, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, 0x16, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71, 0x66, 0x61, 0x63, 0x74, 0x04, 0x00, 0x00, 0x00, 0xc5, 0x5b, 0x00, 0x00, 0x64, 0x61, 0x74, 0x61 + 0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, 0x28, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x02, 0x00, 0x40, 0x1f, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, 0x16, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71, 0x66, 0x61, 0x63, 0x74, 0x04, 0x00, 0x00, 0x00, 0xc5, 0x5b, 0x00, 0x00, 0x64, 0x61, 0x74, 0x61 }; char *wavehdr = output_is_float ? wavehdr_float : wavehdr_int; int wavehdr_size = output_is_float ? sizeof (wavehdr_float) : sizeof (wavehdr_int); @@ -1013,9 +1005,9 @@ convert (DB_playItem_t *it, const char *out, int output_bps, int output_is_float outsize += sz; if (!header_written) { - uint32_t size = (it->endsample-it->startsample) * outch * output_bps / 8; + uint64_t size = (int64_t)(it->endsample-it->startsample) * outch * output_bps / 8; if (!size) { - size = deadbeef->pl_get_item_duration (it) * fileinfo->fmt.samplerate * outch * output_bps / 8; + size = (double)deadbeef->pl_get_item_duration (it) * fileinfo->fmt.samplerate * outch * output_bps / 8; } @@ -1026,20 +1018,38 @@ convert (DB_playItem_t *it, const char *out, int output_bps, int output_is_float size = temp; } + uint64_t chunksize; + chunksize = size + 36; + + // for float, add 36 more + if (output_is_float) { + chunksize += 36; + } + + uint32_t size32 = 0xffffffff; + if (chunksize <= 0xffffffff) { + size32 = chunksize; + } + memcpy (&wavehdr[4], &size32, 4); memcpy (&wavehdr[22], &outch, 2); memcpy (&wavehdr[24], &outsr, 4); uint16_t blockalign = outch * output_bps / 8; memcpy (&wavehdr[32], &blockalign, 2); memcpy (&wavehdr[34], &output_bps, 2); + size32 = 0xffffffff; + if (size <= 0xffffffff) { + size32 = size; + } + if (wavehdr_size != write (temp_file, wavehdr, wavehdr_size)) { fprintf (stderr, "converter: wave header write error\n"); goto error; } if (encoder_preset->method == DDB_ENCODER_METHOD_PIPE) { - size = 0; + size32 = 0; } - if (write (temp_file, &size, sizeof (size)) != sizeof (size)) { + if (write (temp_file, &size32, sizeof (size32)) != sizeof (size32)) { fprintf (stderr, "converter: wave header size write error\n"); goto error; } @@ -1220,7 +1230,7 @@ static ddb_converter_t plugin = { .misc.plugin.api_vmajor = 1, .misc.plugin.api_vminor = 0, .misc.plugin.version_major = 1, - .misc.plugin.version_minor = 2, + .misc.plugin.version_minor = 3, .misc.plugin.type = DB_PLUGIN_MISC, .misc.plugin.name = "Converter", .misc.plugin.id = "converter", diff --git a/plugins/converter/converter.glade b/plugins/converter/converter.glade index af771399..a5f44643 100644 --- a/plugins/converter/converter.glade +++ b/plugins/converter/converter.glade @@ -1730,6 +1730,22 @@ Temporary file</property> </child> <child> + <widget class="GtkButton" id="copy"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-copy</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> <widget class="GtkButton" id="remove"> <property name="visible">True</property> <property name="can_focus">True</property> diff --git a/plugins/converter/converter.h b/plugins/converter/converter.h index 0adc5833..63aeb349 100644 --- a/plugins/converter/converter.h +++ b/plugins/converter/converter.h @@ -53,6 +53,9 @@ typedef struct ddb_encoder_preset_s { int tag_oggvorbis; int tag_mp3xing; int id3v2_version; + + // added in converter-1.3 + int readonly; // this means the preset cannot be edited } ddb_encoder_preset_t; typedef struct ddb_dsp_preset_s { diff --git a/plugins/converter/convgui.c b/plugins/converter/convgui.c index b461dcb7..e1ebdfb1 100644 --- a/plugins/converter/convgui.c +++ b/plugins/converter/convgui.c @@ -67,13 +67,24 @@ typedef struct { converter_ctx_t *current_ctx; -void -fill_presets (GtkListStore *mdl, ddb_preset_t *head) { +enum { + PRESET_TYPE_ENCODER, + PRESET_TYPE_DSP +}; + +static void +fill_presets (GtkListStore *mdl, ddb_preset_t *head, int type) { ddb_preset_t *p = head; while (p) { GtkTreeIter iter; gtk_list_store_append (mdl, &iter); - gtk_list_store_set (mdl, &iter, 0, p->title, -1); + const char *s = p->title; + if (type == PRESET_TYPE_ENCODER && ((ddb_encoder_preset_t *)p)->readonly) { + char stock[1000]; + snprintf (stock, sizeof (stock), _("[Built-in] %s"), p->title); + s = stock; + } + gtk_list_store_set (mdl, &iter, 0, s, -1); p = p->next; } } @@ -432,7 +443,7 @@ converter_show_cb (void *data) { // fill encoder presets combo = GTK_COMBO_BOX (lookup_widget (conv->converter, "encoder")); GtkListStore *mdl = GTK_LIST_STORE (gtk_combo_box_get_model (combo)); - fill_presets (mdl, (ddb_preset_t *)converter_plugin->encoder_preset_get_list ()); + fill_presets (mdl, (ddb_preset_t *)converter_plugin->encoder_preset_get_list (), PRESET_TYPE_ENCODER); gtk_combo_box_set_active (combo, deadbeef->conf_get_int ("converter.encoder_preset", 0)); // fill dsp presets @@ -441,7 +452,7 @@ converter_show_cb (void *data) { GtkTreeIter iter; gtk_list_store_append (mdl, &iter); gtk_list_store_set (mdl, &iter, 0, "Pass through", -1); - fill_presets (mdl, (ddb_preset_t *)converter_plugin->dsp_preset_get_list ()); + fill_presets (mdl, (ddb_preset_t *)converter_plugin->dsp_preset_get_list (), PRESET_TYPE_DSP); gtk_combo_box_set_active (combo, deadbeef->conf_get_int ("converter.dsp_preset", -1) + 1); @@ -693,13 +704,12 @@ init_encoder_preset_from_dlg (GtkWidget *dlg, ddb_encoder_preset_t *p) { } int -edit_encoder_preset (char *title, GtkWidget *toplevel, int overwrite) { +edit_encoder_preset (char *title, GtkWidget *toplevel) { GtkWidget *dlg = create_convpreset_editor (); gtk_window_set_title (GTK_WINDOW (dlg), title); gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_OK); gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (toplevel)); - ddb_encoder_preset_t *p = current_ctx->current_encoder_preset; if (p->title) { @@ -728,7 +738,19 @@ edit_encoder_preset (char *title, GtkWidget *toplevel, int overwrite) { ddb_encoder_preset_t *p = converter_plugin->encoder_preset_alloc (); if (p) { init_encoder_preset_from_dlg (dlg, p); - int err = converter_plugin->encoder_preset_save (p, overwrite); + int err = 0; + + ddb_encoder_preset_t *pp = converter_plugin->encoder_preset_get_list (); + for (; pp; pp = pp->next) { + if (pp != old && !strcmp (pp->title, p->title)) { + err = -2; + break; + } + } + + if (!err) { + err = converter_plugin->encoder_preset_save (p, 1); + } if (!err) { if (old->title && strcmp (p->title, old->title)) { char path[1024]; @@ -778,7 +800,7 @@ refresh_encoder_lists (GtkComboBox *combo, GtkTreeView *list) { } gtk_list_store_clear (mdl); - fill_presets (mdl, (ddb_preset_t *)converter_plugin->encoder_preset_get_list ()); + fill_presets (mdl, (ddb_preset_t *)converter_plugin->encoder_preset_get_list (), PRESET_TYPE_ENCODER); if (idx != -1) { path = gtk_tree_path_new_from_indices (idx, -1); gtk_tree_view_set_cursor (GTK_TREE_VIEW (list), path, col, FALSE); @@ -789,7 +811,7 @@ refresh_encoder_lists (GtkComboBox *combo, GtkTreeView *list) { int act = gtk_combo_box_get_active (combo); mdl = GTK_LIST_STORE (gtk_combo_box_get_model (combo)); gtk_list_store_clear (mdl); - fill_presets (mdl, (ddb_preset_t *)converter_plugin->encoder_preset_get_list ()); + fill_presets (mdl, (ddb_preset_t *)converter_plugin->encoder_preset_get_list (), PRESET_TYPE_ENCODER); gtk_combo_box_set_active (combo, act); } @@ -801,7 +823,7 @@ on_encoder_preset_add (GtkButton *button, current_ctx->current_encoder_preset = converter_plugin->encoder_preset_alloc (); - if (GTK_RESPONSE_OK == edit_encoder_preset (_("Add new encoder"), toplevel, 0)) { + if (GTK_RESPONSE_OK == edit_encoder_preset (_("Add new encoder"), toplevel)) { converter_plugin->encoder_preset_append (current_ctx->current_encoder_preset); GtkComboBox *combo = GTK_COMBO_BOX (lookup_widget (current_ctx->converter, "encoder")); GtkWidget *list = lookup_widget (toplevel, "presets"); @@ -831,7 +853,7 @@ on_encoder_preset_edit (GtkButton *button, ddb_encoder_preset_t *p = converter_plugin->encoder_preset_get_for_idx (idx); current_ctx->current_encoder_preset = p; - int r = edit_encoder_preset (_("Edit encoder"), toplevel, 1); + int r = edit_encoder_preset (_("Edit encoder"), toplevel); if (r == GTK_RESPONSE_OK) { GtkComboBox *combo = GTK_COMBO_BOX (lookup_widget (current_ctx->converter, "encoder")); refresh_encoder_lists (combo, GTK_TREE_VIEW (list)); @@ -884,6 +906,63 @@ on_encoder_preset_remove (GtkButton *button, } } +static void +on_encoder_preset_cursor_changed (GtkTreeView *treeview, + gpointer user_data) { + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (treeview)); + GtkWidget *edit = lookup_widget (toplevel, "edit"); + + GtkTreePath *path; + GtkTreeViewColumn *col; + gtk_tree_view_get_cursor (treeview, &path, &col); + if (!path || !col) { + // nothing selected + gtk_widget_set_sensitive (edit, FALSE); + return; + } + int *indices = gtk_tree_path_get_indices (path); + int idx = *indices; + g_free (indices); + + ddb_encoder_preset_t *p = converter_plugin->encoder_preset_get_for_idx (idx); + gtk_widget_set_sensitive (edit, !p->readonly); +} + + +void +on_encoder_preset_copy (GtkButton *button, gpointer user_data) +{ + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (button)); + + GtkTreeView *treeview = GTK_TREE_VIEW (lookup_widget (toplevel, "presets")); + + GtkTreePath *path; + GtkTreeViewColumn *col; + gtk_tree_view_get_cursor (treeview, &path, &col); + if (!path || !col) { + return; + } + int *indices = gtk_tree_path_get_indices (path); + int idx = *indices; + g_free (indices); + + ddb_encoder_preset_t *p = converter_plugin->encoder_preset_get_for_idx (idx); + + current_ctx->current_encoder_preset = converter_plugin->encoder_preset_alloc (); + if (!current_ctx->current_encoder_preset) { + return; + } + converter_plugin->encoder_preset_copy (current_ctx->current_encoder_preset, p); + + if (GTK_RESPONSE_OK == edit_encoder_preset (_("Add new encoder"), toplevel)) { + converter_plugin->encoder_preset_append (current_ctx->current_encoder_preset); + GtkComboBox *combo = GTK_COMBO_BOX (lookup_widget (current_ctx->converter, "encoder")); + refresh_encoder_lists (combo, treeview); + } + + current_ctx->current_encoder_preset = NULL; +} + void on_edit_encoder_presets_clicked (GtkButton *button, gpointer user_data) @@ -894,14 +973,16 @@ on_edit_encoder_presets_clicked (GtkButton *button, g_signal_connect ((gpointer)lookup_widget (dlg, "add"), "clicked", G_CALLBACK (on_encoder_preset_add), NULL); g_signal_connect ((gpointer)lookup_widget (dlg, "remove"), "clicked", G_CALLBACK (on_encoder_preset_remove), NULL); g_signal_connect ((gpointer)lookup_widget (dlg, "edit"), "clicked", G_CALLBACK (on_encoder_preset_edit), NULL); + g_signal_connect ((gpointer)lookup_widget (dlg, "copy"), "clicked", G_CALLBACK (on_encoder_preset_copy), NULL); GtkWidget *list = lookup_widget (dlg, "presets"); + g_signal_connect ((gpointer)list, "cursor-changed", G_CALLBACK (on_encoder_preset_cursor_changed), NULL); GtkCellRenderer *title_cell = gtk_cell_renderer_text_new (); GtkTreeViewColumn *col = gtk_tree_view_column_new_with_attributes (_("Title"), title_cell, "text", 0, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (list), GTK_TREE_VIEW_COLUMN (col)); GtkListStore *mdl = gtk_list_store_new (1, G_TYPE_STRING); gtk_tree_view_set_model (GTK_TREE_VIEW (list), GTK_TREE_MODEL (mdl)); - fill_presets (mdl, (ddb_preset_t *)converter_plugin->encoder_preset_get_list ()); + fill_presets (mdl, (ddb_preset_t *)converter_plugin->encoder_preset_get_list (), PRESET_TYPE_ENCODER); int curr = deadbeef->conf_get_int ("converter.encoder_preset", -1); if (curr != -1) { GtkTreePath *path = gtk_tree_path_new_from_indices (curr, -1); @@ -1181,7 +1262,7 @@ on_dsp_preset_plugin_down_clicked (GtkButton *button, int -edit_dsp_preset (const char *title, GtkWidget *toplevel, int overwrite) { +edit_dsp_preset (const char *title, GtkWidget *toplevel, ddb_dsp_preset_t *orig) { int r = GTK_RESPONSE_CANCEL; GtkWidget *dlg = create_dsppreset_editor (); @@ -1189,10 +1270,11 @@ edit_dsp_preset (const char *title, GtkWidget *toplevel, int overwrite) { gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (toplevel)); gtk_window_set_title (GTK_WINDOW (dlg), title); + ddb_dsp_preset_t *p = current_ctx->current_dsp_preset; // title - if (current_ctx->current_dsp_preset->title) { - gtk_entry_set_text (GTK_ENTRY (lookup_widget (dlg, "title")), current_ctx->current_dsp_preset->title); + if (p->title) { + gtk_entry_set_text (GTK_ENTRY (lookup_widget (dlg, "title")), p->title); } { @@ -1213,11 +1295,26 @@ edit_dsp_preset (const char *title, GtkWidget *toplevel, int overwrite) { r = gtk_dialog_run (GTK_DIALOG (dlg)); if (r == GTK_RESPONSE_OK) { - if (current_ctx->current_dsp_preset->title) { - free (current_ctx->current_dsp_preset->title); + const char *title = gtk_entry_get_text (GTK_ENTRY (lookup_widget (dlg, "title"))); + int err = 0; + + // don't allow duplicate title with existing presets + ddb_dsp_preset_t *pp = converter_plugin->dsp_preset_get_list (); + for (; pp; pp = pp->next) { + if (pp != orig && !strcmp (pp->title, title)) { + err = -2; + break; + } } - current_ctx->current_dsp_preset->title = strdup (gtk_entry_get_text (GTK_ENTRY (lookup_widget (dlg, "title")))); - int err = converter_plugin->dsp_preset_save (current_ctx->current_dsp_preset, overwrite); + + if (!err) { + if (current_ctx->current_dsp_preset->title) { + free (current_ctx->current_dsp_preset->title); + } + current_ctx->current_dsp_preset->title = strdup (title); + err = converter_plugin->dsp_preset_save (current_ctx->current_dsp_preset, 1); + } + if (err < 0) { GtkWidget *warndlg = gtk_message_dialog_new (GTK_WINDOW (gtkui_plugin->get_mainwin ()), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Failed to save DSP preset")); gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (warndlg), err == -1 ? _("Check preset folder permissions, try to pick different title, or free up some disk space") : _("Preset with the same name already exists. Try to pick another title.")); @@ -1255,7 +1352,7 @@ refresh_dsp_lists (GtkComboBox *combo, GtkTreeView *list) { } gtk_list_store_clear (mdl); - fill_presets (mdl, (ddb_preset_t *)converter_plugin->dsp_preset_get_list ()); + fill_presets (mdl, (ddb_preset_t *)converter_plugin->dsp_preset_get_list (), PRESET_TYPE_DSP); if (idx != -1) { path = gtk_tree_path_new_from_indices (idx, -1); gtk_tree_view_set_cursor (GTK_TREE_VIEW (list), path, col, FALSE); @@ -1269,7 +1366,7 @@ refresh_dsp_lists (GtkComboBox *combo, GtkTreeView *list) { GtkTreeIter iter; gtk_list_store_append (mdl, &iter); gtk_list_store_set (mdl, &iter, 0, "Pass through", -1); - fill_presets (mdl, (ddb_preset_t *)converter_plugin->dsp_preset_get_list ()); + fill_presets (mdl, (ddb_preset_t *)converter_plugin->dsp_preset_get_list (), PRESET_TYPE_DSP); gtk_combo_box_set_active (combo, act); } @@ -1283,7 +1380,7 @@ on_dsp_preset_add (GtkButton *button, GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (button)); - if (GTK_RESPONSE_OK == edit_dsp_preset (_("New DSP Preset"), toplevel, 0)) { + if (GTK_RESPONSE_OK == edit_dsp_preset (_("New DSP Preset"), toplevel, NULL)) { converter_plugin->dsp_preset_append (current_ctx->current_dsp_preset); GtkComboBox *combo = GTK_COMBO_BOX (lookup_widget (current_ctx->converter, "dsp_preset")); GtkWidget *list = lookup_widget (toplevel, "presets"); @@ -1297,6 +1394,43 @@ on_dsp_preset_add (GtkButton *button, } void +on_dsp_preset_copy (GtkButton *button, gpointer user_data) +{ + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (button)); + + GtkTreeView *treeview = GTK_TREE_VIEW (lookup_widget (toplevel, "presets")); + + GtkTreePath *path; + GtkTreeViewColumn *col; + gtk_tree_view_get_cursor (treeview, &path, &col); + if (!path || !col) { + return; + } + int *indices = gtk_tree_path_get_indices (path); + int idx = *indices; + g_free (indices); + + ddb_dsp_preset_t *p = converter_plugin->dsp_preset_get_for_idx (idx); + + current_ctx->current_dsp_preset = converter_plugin->dsp_preset_alloc (); + if (!current_ctx->current_dsp_preset) { + return; + } + converter_plugin->dsp_preset_copy (current_ctx->current_dsp_preset, p); + + if (GTK_RESPONSE_OK == edit_dsp_preset (_("New DSP Preset"), toplevel, NULL)) { + converter_plugin->dsp_preset_append (current_ctx->current_dsp_preset); + GtkComboBox *combo = GTK_COMBO_BOX (lookup_widget (current_ctx->converter, "dsp_preset")); + refresh_dsp_lists (combo, treeview); + } + else { + converter_plugin->dsp_preset_free (current_ctx->current_dsp_preset); + } + + current_ctx->current_dsp_preset = NULL; +} + +void on_dsp_preset_remove (GtkButton *button, gpointer user_data) { @@ -1368,7 +1502,7 @@ on_dsp_preset_edit (GtkButton *button, current_ctx->current_dsp_preset = converter_plugin->dsp_preset_alloc (); converter_plugin->dsp_preset_copy (current_ctx->current_dsp_preset, p); - int r = edit_dsp_preset (_("Edit DSP Preset"), toplevel, 1); + int r = edit_dsp_preset (_("Edit DSP Preset"), toplevel, p); if (r == GTK_RESPONSE_OK) { // replace preset converter_plugin->dsp_preset_replace (p, current_ctx->current_dsp_preset); @@ -1393,6 +1527,7 @@ on_edit_dsp_presets_clicked (GtkButton *button, g_signal_connect ((gpointer)lookup_widget (dlg, "add"), "clicked", G_CALLBACK (on_dsp_preset_add), NULL); g_signal_connect ((gpointer)lookup_widget (dlg, "remove"), "clicked", G_CALLBACK (on_dsp_preset_remove), NULL); g_signal_connect ((gpointer)lookup_widget (dlg, "edit"), "clicked", G_CALLBACK (on_dsp_preset_edit), NULL); + g_signal_connect ((gpointer)lookup_widget (dlg, "copy"), "clicked", G_CALLBACK (on_dsp_preset_copy), NULL); GtkWidget *list = lookup_widget (dlg, "presets"); GtkCellRenderer *title_cell = gtk_cell_renderer_text_new (); @@ -1400,7 +1535,7 @@ on_edit_dsp_presets_clicked (GtkButton *button, gtk_tree_view_append_column (GTK_TREE_VIEW (list), GTK_TREE_VIEW_COLUMN (col)); GtkListStore *mdl = gtk_list_store_new (1, G_TYPE_STRING); gtk_tree_view_set_model (GTK_TREE_VIEW (list), GTK_TREE_MODEL (mdl)); - fill_presets (mdl, (ddb_preset_t *)converter_plugin->dsp_preset_get_list ()); + fill_presets (mdl, (ddb_preset_t *)converter_plugin->dsp_preset_get_list (), PRESET_TYPE_DSP); int curr = deadbeef->conf_get_int ("converter.dsp_preset", -1); if (curr >= 0) { GtkTreePath *path = gtk_tree_path_new_from_indices (curr, -1); @@ -1463,8 +1598,8 @@ convgui_connect (void) { fprintf (stderr, "convgui: converter plugin not found\n"); return -1; } - if (!PLUG_TEST_COMPAT(&converter_plugin->misc.plugin, 1, 2)) { - fprintf (stderr, "convgui: need converter>=1.2, but found %d.%d\n", converter_plugin->misc.plugin.version_major, converter_plugin->misc.plugin.version_minor); + if (!PLUG_TEST_COMPAT(&converter_plugin->misc.plugin, 1, 3)) { + fprintf (stderr, "convgui: need converter>=1.3, but found %d.%d\n", converter_plugin->misc.plugin.version_major, converter_plugin->misc.plugin.version_minor); return -1; } return 0; diff --git a/plugins/converter/interface.c b/plugins/converter/interface.c index 4e693e3b..56b5bdcd 100644 --- a/plugins/converter/interface.c +++ b/plugins/converter/interface.c @@ -792,6 +792,7 @@ create_preset_list (void) GtkWidget *vbox33; GtkWidget *hbox94; GtkWidget *add; + GtkWidget *copy; GtkWidget *remove; GtkWidget *edit; GtkWidget *scrolledwindow8; @@ -821,6 +822,10 @@ create_preset_list (void) gtk_widget_show (add); gtk_box_pack_start (GTK_BOX (hbox94), add, FALSE, TRUE, 0); + copy = gtk_button_new_from_stock ("gtk-copy"); + gtk_widget_show (copy); + gtk_box_pack_start (GTK_BOX (hbox94), copy, FALSE, TRUE, 0); + remove = gtk_button_new_from_stock ("gtk-remove"); gtk_widget_show (remove); gtk_box_pack_start (GTK_BOX (hbox94), remove, FALSE, TRUE, 0); @@ -856,6 +861,7 @@ create_preset_list (void) GLADE_HOOKUP_OBJECT (preset_list, vbox33, "vbox33"); GLADE_HOOKUP_OBJECT (preset_list, hbox94, "hbox94"); GLADE_HOOKUP_OBJECT (preset_list, add, "add"); + GLADE_HOOKUP_OBJECT (preset_list, copy, "copy"); GLADE_HOOKUP_OBJECT (preset_list, remove, "remove"); GLADE_HOOKUP_OBJECT (preset_list, edit, "edit"); GLADE_HOOKUP_OBJECT (preset_list, scrolledwindow8, "scrolledwindow8"); diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c index 5deab23e..977298b0 100644 --- a/plugins/flac/flac.c +++ b/plugins/flac/flac.c @@ -988,6 +988,9 @@ cflac_write_metadata (DB_playItem_t *it) { if (data && data->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { break; } + else { + data = NULL; + } } while (FLAC__metadata_iterator_next (iter)); if (data) { @@ -1062,108 +1065,13 @@ cflac_write_metadata (DB_playItem_t *it) { deadbeef->pl_unlock (); -#if 0 // fetching covers is broken, disabling for 0.5.2 - // check if we have embedded cover - data = NULL; - while (FLAC__metadata_iterator_prev (iter)); - do { - data = FLAC__metadata_iterator_get_block (iter); - if (data && data->type == FLAC__METADATA_TYPE_PICTURE) { - break; - } - } while (FLAC__metadata_iterator_next (iter)); - - if (!coverart_plugin) { - DB_plugin_t **plugins = deadbeef->plug_get_list (); - for (int i = 0; plugins[i]; i++) { - DB_plugin_t *p = plugins[i]; - if (p->id && !strcmp (p->id, "artwork") && p->version_major == 1 && p->version_minor >= 1) { - coverart_plugin = (DB_artwork_plugin_t *)p; - break; - } - } - } - - // add coverart if the file doesn't have it - // FIXME: should have an option to overwrite it - if ((!data || data->type != FLAC__METADATA_TYPE_PICTURE) && coverart_plugin) { - deadbeef->pl_lock (); - const char *alb = deadbeef->pl_find_meta (it, "album"); - const char *art = deadbeef->pl_find_meta (it, "artist"); - if (!alb || !*alb) { - alb = deadbeef->pl_find_meta (it, "title"); - } - const char *fn = deadbeef->pl_find_meta (it, ":URI"); - - char *album = alb ? strdupa (alb) : NULL; - char *artist = art ? strdupa (art) : NULL; - char *fname = fn ? strdupa (fn) : NULL; - deadbeef->pl_unlock (); - - char *image_fname = coverart_plugin->get_album_art_sync (fname, artist, album, -1); - - if (image_fname && strcmp (image_fname, coverart_plugin->get_default_cover())) { - DB_FILE *fp = deadbeef->fopen (image_fname); - FLAC__byte *coverart_data = NULL; - FLAC__StreamMetadata *metadata = NULL; - if (!fp) { - fprintf (stderr, "flac: cannot open coverart %s\n", image_fname); - goto error2; - } - - int64_t len = deadbeef->fgetlength (fp); - if (len < 4) { - fprintf (stderr, "flac: cover image file %s is too small\n", image_fname); - goto error2; - } - coverart_data = malloc (len); - if (!coverart_data) { - fprintf (stderr, "flac: cannot allocate memory\n"); - goto error2; - } - if (!deadbeef->fread (coverart_data, len, 1, fp)) { - fprintf (stderr, "flac: cannot read from %s\n",image_fname); - goto error2; - } - - metadata = FLAC__metadata_object_new (FLAC__METADATA_TYPE_PICTURE); - if (!metadata) { - fprintf (stderr, "flac: failed to allocate new picture block\n"); - goto error2; - } - - FLAC__metadata_object_picture_set_description (metadata, "Cover", true); - FLAC__metadata_object_picture_set_data (metadata, coverart_data,len, true); - metadata->data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER; - - if (*(uint32_t *)coverart_data == 0x474e5089) { // png header - metadata->data.picture.mime_type = strdup ("image/png"); - } else { - metadata->data.picture.mime_type = strdup ("image/jpeg"); - } - - while (FLAC__metadata_iterator_next (iter)); - if (!FLAC__metadata_iterator_insert_block_after (iter, metadata)) { - fprintf (stderr, "flac: failed to append picture block to chain\n"); - goto error2; - } - -error2: - if (fp) { - deadbeef->fclose (fp); - } - if (coverart_data) { - free (coverart_data); - } - } - } -#endif - - if (!isogg) + if (!isogg) { res = FLAC__metadata_chain_write (chain, 1, 0); + } #if USE_OGGEDIT - else + else { res = cflac_write_metadata_ogg(it, &data->data.vorbis_comment); + } #endif if (res) { trace ("cflac_write_metadata: failed to write tags: code %d\n", res); diff --git a/plugins/gtkui/actionhandlers.c b/plugins/gtkui/actionhandlers.c index ad4bf04c..99a658bb 100644 --- a/plugins/gtkui/actionhandlers.c +++ b/plugins/gtkui/actionhandlers.c @@ -40,6 +40,9 @@ #include "callbacks.h" #include <sys/stat.h> +// disable custom title function, until we have new title formatting (0.7) +#define DISABLE_CUSTOM_TITLE + extern GtkWidget *mainwin; extern DB_functions_t *deadbeef; @@ -401,7 +404,6 @@ on_toggle_set_custom_title (GtkToggleButton *togglebutton, gpointer user_data) { deadbeef->conf_save (); } - gboolean action_add_location_handler_cb (void *user_data) { GtkWidget *dlg = create_addlocationdlg (); @@ -409,18 +411,23 @@ action_add_location_handler_cb (void *user_data) { GtkWidget *sct = lookup_widget (dlg, "set_custom_title"); GtkWidget *ct = lookup_widget (dlg, "custom_title"); +#ifndef DISABLE_CUSTOM_TITLE if (deadbeef->conf_get_int ("gtkui.location_set_custom_title", 0)) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sct), TRUE); gtk_widget_set_sensitive (ct, TRUE); } - else { + else +#endif + { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sct), FALSE); gtk_widget_set_sensitive (ct, FALSE); } +#ifndef DISABLE_CUSTOM_TITLE g_signal_connect ((gpointer) sct, "toggled", G_CALLBACK (on_toggle_set_custom_title), dlg); +#endif gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_OK); int res = gtk_dialog_run (GTK_DIALOG (dlg)); @@ -433,9 +440,11 @@ action_add_location_handler_cb (void *user_data) { if (!deadbeef->plt_add_files_begin (plt, 0)) { DB_playItem_t *tail = deadbeef->plt_get_last (plt, PL_MAIN); DB_playItem_t *it = deadbeef->plt_insert_file2 (0, plt, tail, text, NULL, NULL, NULL); +#ifndef DISABLE_CUSTOM_TITLE if (it && deadbeef->conf_get_int ("gtkui.location_set_custom_title", 0)) { deadbeef->pl_replace_meta (it, ":CUSTOM_TITLE", gtk_entry_get_text (GTK_ENTRY (ct))); } +#endif if (tail) { deadbeef->pl_item_unref (tail); } diff --git a/plugins/gtkui/deadbeef.glade b/plugins/gtkui/deadbeef.glade index 7828a9bf..57dd0cbe 100644 --- a/plugins/gtkui/deadbeef.glade +++ b/plugins/gtkui/deadbeef.glade @@ -6342,7 +6342,6 @@ if you don't press Apply.</property> <child> <widget class="GtkHBox" id="hbox122"> - <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">8</property> diff --git a/plugins/gtkui/interface.c b/plugins/gtkui/interface.c index 5cd3ce7e..c4c02b73 100644 --- a/plugins/gtkui/interface.c +++ b/plugins/gtkui/interface.c @@ -3223,7 +3223,6 @@ create_addlocationdlg (void) gtk_entry_set_activates_default (GTK_ENTRY (addlocation_entry), TRUE); hbox122 = gtk_hbox_new (FALSE, 8); - gtk_widget_show (hbox122); gtk_box_pack_start (GTK_BOX (vbox45), hbox122, TRUE, TRUE, 0); set_custom_title = gtk_check_button_new_with_mnemonic (_("Set custom title")); diff --git a/plugins/gtkui/plcommon.c b/plugins/gtkui/plcommon.c index a6077929..d7df4f62 100644 --- a/plugins/gtkui/plcommon.c +++ b/plugins/gtkui/plcommon.c @@ -38,6 +38,9 @@ //#define trace(...) { fprintf(stderr, __VA_ARGS__); } #define trace(fmt,...) +// disable custom title function, until we have new title formatting (0.7) +#define DISABLE_CUSTOM_TITLE + char group_by_str[MAX_GROUP_BY_STR]; extern GtkWidget *theme_treeview; @@ -478,6 +481,7 @@ on_toggle_set_custom_title (GtkToggleButton *togglebutton, gpointer user_data) { deadbeef->conf_save (); } +#ifndef DISABLE_CUSTOM_TITLE void on_set_custom_title_activate (GtkMenuItem *menuitem, gpointer user_data) { @@ -530,6 +534,7 @@ on_set_custom_title_activate (GtkMenuItem *menuitem, gpointer user_data) gtk_widget_destroy (dlg); lv->binding->unref (it); } +#endif void on_remove_from_disk_activate (GtkMenuItem *menuitem, @@ -624,7 +629,9 @@ list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) { GtkWidget *separator8; GtkWidget *properties1; GtkWidget *reload_metadata; +#ifndef DISABLE_CUSTOM_TITLE GtkWidget *set_custom_title; +#endif playlist_menu = gtk_menu_new (); add_to_playback_queue1 = gtk_menu_item_new_with_mnemonic (_("Add To Playback Queue")); @@ -795,6 +802,7 @@ list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) { gtk_widget_set_sensitive (separator8, FALSE); } +#ifndef DISABLE_CUSTOM_TITLE set_custom_title = gtk_menu_item_new_with_mnemonic (_("Set Custom Title")); gtk_widget_show (set_custom_title); gtk_container_add (GTK_CONTAINER (playlist_menu), set_custom_title); @@ -806,6 +814,7 @@ list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) { gtk_widget_show (separator); gtk_container_add (GTK_CONTAINER (playlist_menu), separator); gtk_widget_set_sensitive (separator, FALSE); +#endif properties1 = gtk_menu_item_new_with_mnemonic (_("Track Properties")); gtk_widget_show (properties1); @@ -829,9 +838,11 @@ list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) { G_CALLBACK (on_remove_from_disk_activate), NULL); } +#ifndef DISABLE_CUSTOM_TITLE g_signal_connect ((gpointer) set_custom_title, "activate", G_CALLBACK (on_set_custom_title_activate), listview); +#endif g_signal_connect ((gpointer) properties1, "activate", G_CALLBACK (main_properties_activate), NULL); diff --git a/plugins/m3u/m3u.c b/plugins/m3u/m3u.c index ea5a5fba..56602c4c 100644 --- a/plugins/m3u/m3u.c +++ b/plugins/m3u/m3u.c @@ -21,9 +21,16 @@ 3. This notice may not be removed or altered from any source distribution. */ +#ifdef HAVE_CONFIG_H +# include "../../config.h" +#endif #include <string.h> #include <stdlib.h> #include <math.h> // for ceil +#if HAVE_SYS_SYSLIMITS_H +#include <sys/syslimits.h> +#endif + #include "../../deadbeef.h" //#define trace(...) { fprintf(stderr, __VA_ARGS__); } @@ -235,18 +242,24 @@ load_m3u (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname, int *pab static DB_playItem_t * pls_insert_file (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname, const char *uri, int *pabort, int (*cb)(DB_playItem_t *it, void *data), void *user_data, const char *title, const char *length) { trace ("pls_insert_file uri: %s\n", uri); + trace ("pls_insert_file fname: %s\n", fname); DB_playItem_t *it = NULL; const char *slash = NULL; if (strrchr (uri, '/')) { + trace ("pls: inserting from uri: %s\n", uri); it = deadbeef->plt_insert_file2 (0, plt, after, uri, pabort, cb, user_data); } - else if (slash = strrchr (fname, '/')) { + + if (!it) { + slash = strrchr (fname, '/'); + } + if (slash) { int l = strlen (uri); char fullpath[slash - fname + l + 2]; memcpy (fullpath, fname, slash - fname + 1); strcpy (fullpath + (slash - fname + 1), uri); - trace ("pls_insert_file: adding file %s\n", fullpath); + trace ("pls: inserting from calculated relative path: %s\n", fullpath); it = deadbeef->plt_insert_file2 (0, plt, after, fullpath, pabort, cb, user_data); } if (it) { @@ -262,6 +275,7 @@ pls_insert_file (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname, c static DB_playItem_t * load_pls (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname, int *pabort, int (*cb)(DB_playItem_t *it, void *data), void *user_data) { + trace ("load_pls %s\n", fname); const char *slash = strrchr (fname, '/'); DB_FILE *fp = deadbeef->fopen (fname); if (!fp) { @@ -423,8 +437,11 @@ load_pls (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname, int *pab trace ("length%d=%s\n", idx, length); } else { - trace ("invalid entry in pls file: %s\n", p); - break; + trace ("pls: skipping unrecognized entry in pls file: %s\n", p); + e = p; + while (e < end && *e >= 0x20) { + e++; + } } while (e < end && *e < 0x20) { e++; @@ -443,6 +460,12 @@ load_pls (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname, int *pab static DB_playItem_t * m3uplug_load (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname, int *pabort, int (*cb)(DB_playItem_t *it, void *data), void *user_data) { + char resolved_fname[PATH_MAX]; + char *res = realpath (fname, resolved_fname); + if (res) { + fname = resolved_fname; + } + const char *ext = strrchr (fname, '.'); if (ext) { ext++; |