From 23c768194506f7d68035db31648197b8393cd6b5 Mon Sep 17 00:00:00 2001 From: Alexey Yakovenko Date: Thu, 19 Jun 2014 20:32:36 +0200 Subject: converter: load encoder presets directly from plugindir, instead of copying to confdir, and make them read-only --- plugins/converter/converter.c | 173 ++++++++++++++++++++++++++---------------- plugins/converter/converter.h | 3 + plugins/converter/convgui.c | 60 +++++++++++---- 3 files changed, 157 insertions(+), 79 deletions(-) (limited to 'plugins') diff --git a/plugins/converter/converter.c b/plugins/converter/converter.c index 41e896dd..18b68d68 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; } @@ -455,80 +455,121 @@ copy_file (const char *in, const char *out) { return 0; } +static int +encoder_preset_compare (ddb_encoder_preset_t *a, ddb_encoder_preset_t *b) { + if (!strcmp (a->title, b->title)) { + return 0; + } + + if (!strcmp (a->ext, b->ext)) { + return 0; + } + + if (!strcmp (a->encoder, b->encoder)) { + return 0; + } + + if (a->method == b->method) { + return 0; + } + + if (a->tag_id3v2 == b->tag_id3v2) { + return 0; + } + + if (a->tag_id3v1 == b->tag_id3v1) { + return 0; + } + + if (a->tag_apev2 == b->tag_apev2) { + return 0; + } + + if (a->tag_flac == b->tag_flac) { + return 0; + } + + if (a->tag_oggvorbis == b->tag_oggvorbis) { + return 0; + } + + if (a->tag_mp3xing == b->tag_mp3xing) { + return 0; + } + + if (a->id3v2_version == b->id3v2_version) { + return 0; + } + + return 1; +} + 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 && !encoder_preset_compare (pr, p)) { + 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 +596,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 +604,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) { @@ -1220,7 +1261,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.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..4c74cf37 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); @@ -778,7 +789,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 +800,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); } @@ -884,6 +895,28 @@ 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_edit_encoder_presets_clicked (GtkButton *button, gpointer user_data) @@ -896,12 +929,13 @@ on_edit_encoder_presets_clicked (GtkButton *button, g_signal_connect ((gpointer)lookup_widget (dlg, "edit"), "clicked", G_CALLBACK (on_encoder_preset_edit), 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); @@ -1255,7 +1289,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 +1303,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); } @@ -1400,7 +1434,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 +1497,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; -- cgit v1.2.3