From a031151153526ed6fd4390f05dfe40a411ca26e2 Mon Sep 17 00:00:00 2001 From: waker Date: Wed, 5 Jan 2011 22:15:34 +0100 Subject: added dsp preset functions to plugin api; added dsp preset management to gtkui preferences window --- Makefile.am | 3 +- deadbeef.h | 5 ++ dsppreset.c | 140 +++++++++++++++++++++++++++++++++++++++++++ dsppreset.h | 31 ++++++++++ plugins.c | 5 ++ plugins/gtkui/callbacks.h | 12 ++++ plugins/gtkui/deadbeef.glade | 87 +++++++++++++++++++++++++++ plugins/gtkui/dspconfig.c | 108 +++++++++++++++++++++++++++++++++ plugins/gtkui/interface.c | 39 ++++++++++++ 9 files changed, 429 insertions(+), 1 deletion(-) create mode 100644 dsppreset.c create mode 100644 dsppreset.h diff --git a/Makefile.am b/Makefile.am index 60d16bb2..86f75423 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,7 +32,8 @@ deadbeef_SOURCES =\ md5/md5.c md5/md5.h\ metacache.c metacache.h\ gettext.h\ - ringbuf.c ringbuf.h + ringbuf.c ringbuf.h\ + dsppreset.c dsppreset.h sdkdir = $(pkgincludedir) sdk_HEADERS = deadbeef.h diff --git a/deadbeef.h b/deadbeef.h index b3cf7d17..5a51b04f 100644 --- a/deadbeef.h +++ b/deadbeef.h @@ -540,6 +540,11 @@ typedef struct { // pcm utilities int (*pcm_convert) (const ddb_waveformat_t * inputfmt, const char *input, const ddb_waveformat_t *outputfmt, char *output, int inputsize); + + // dsp preset management + int (*dsp_preset_load) (const char *fname, struct ddb_dsp_context_s **head); + int (*dsp_preset_save) (const char *fname, struct ddb_dsp_context_s *head); + void (*dsp_preset_free) (struct ddb_dsp_context_s *head); } DB_functions_t; enum { diff --git a/dsppreset.c b/dsppreset.c new file mode 100644 index 00000000..840a7b29 --- /dev/null +++ b/dsppreset.c @@ -0,0 +1,140 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2011 Alexey Yakovenko + + 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. +*/ +#include +#include +#include + +#include "deadbeef.h" +#include "plugins.h" + +void +dsp_preset_free (ddb_dsp_context_t *head) { + while (head) { + ddb_dsp_context_t *next = head->next; + head->plugin->close (head); + head = next; + } +} + +int +dsp_preset_load (const char *fname, ddb_dsp_context_t **head) { + if (!head) { + return -1; + } + int err = 1; + FILE *fp = fopen (fname, "rt"); + if (!fp) { + return -1; + } + + ddb_dsp_context_t *tail = NULL; + + char temp[100]; + for (;;) { + // plugin { + int err = fscanf (fp, "%100s {\n", temp); + if (err == EOF) { + break; + } + else if (1 != err) { + fprintf (stderr, "error plugin name\n"); + goto error; + } + + DB_dsp_t *plug = (DB_dsp_t *)plug_get_for_id (temp); + if (!plug) { + fprintf (stderr, "ddb_dsp_preset_load: plugin %s not found. preset will not be loaded\n", temp); + goto error; + } + ddb_dsp_context_t *ctx = plug->open (); + if (!ctx) { + fprintf (stderr, "ddb_dsp_preset_load: failed to open ctxance of plugin %s\n", temp); + goto error; + } + + if (tail) { + tail->next = ctx; + tail = ctx; + } + else { + tail = *head = ctx; + } + + int n = 0; + for (;;) { + char value[1000]; + if (!fgets (temp, sizeof (temp), fp)) { + fprintf (stderr, "unexpected eof while reading plugin params\n"); + goto error; + } + if (!strcmp (temp, "}\n")) { + break; + } + else if (1 != sscanf (temp, "\t%1000[^\n]\n", value)) { + fprintf (stderr, "error loading param %d\n", n); + goto error; + } + if (plug->num_params) { + plug->set_param (ctx, n, value); + } + n++; + } + } + + err = 0; +error: + if (err) { + fprintf (stderr, "error loading %s\n", fname); + } + if (fp) { + fclose (fp); + } + if (err && *head) { + dsp_preset_free (*head); + *head = NULL; + } + return err ? -1 : 0; +} + +int +dsp_preset_save (const char *path, ddb_dsp_context_t *head) { + FILE *fp = fopen (path, "w+t"); + if (!fp) { + return -1; + } + + ddb_dsp_context_t *ctx = head; + while (ctx) { + fprintf (fp, "%s {\n", ctx->plugin->plugin.id); + if (ctx->plugin->num_params) { + int n = ctx->plugin->num_params (); + int i; + for (i = 0; i < n; i++) { + char v[1000]; + ctx->plugin->get_param (ctx, i, v, sizeof (v)); + fprintf (fp, "\t%s\n", v); + } + } + fprintf (fp, "}\n"); + ctx = ctx->next; + } + + fclose (fp); + return 0; +} diff --git a/dsppreset.h b/dsppreset.h new file mode 100644 index 00000000..37354f9f --- /dev/null +++ b/dsppreset.h @@ -0,0 +1,31 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2011 Alexey Yakovenko + + 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. +*/ +#ifndef __DSPPRESET_H +#define __DSPPRESET_H + +void +dsp_preset_free (ddb_dsp_context_t *head); + +int +dsp_preset_load (const char *fname, ddb_dsp_context_t **head); + +int +dsp_preset_save (const char *path, ddb_dsp_context_t *head); + +#endif diff --git a/plugins.c b/plugins.c index 2d6c3a23..1781c377 100644 --- a/plugins.c +++ b/plugins.c @@ -43,6 +43,7 @@ #include "junklib.h" #include "vfs.h" #include "premix.h" +#include "dsppreset.h" #define trace(...) { fprintf(stderr, __VA_ARGS__); } //#define trace(fmt,...) @@ -263,6 +264,10 @@ static DB_functions_t deadbeef_api = { .is_local_file = plug_is_local_file, // pcm utilities .pcm_convert = pcm_convert, + // dsp preset management + .dsp_preset_load = dsp_preset_load, + .dsp_preset_save = dsp_preset_save, + .dsp_preset_free = dsp_preset_free }; DB_functions_t *deadbeef = &deadbeef_api; diff --git a/plugins/gtkui/callbacks.h b/plugins/gtkui/callbacks.h index 5693dcbe..2de5e663 100644 --- a/plugins/gtkui/callbacks.h +++ b/plugins/gtkui/callbacks.h @@ -1046,3 +1046,15 @@ void on_auto_name_playlist_from_folder_toggled (GtkToggleButton *togglebutton, gpointer user_data); + +void +on_dsp_preset_changed (GtkComboBox *combobox, + gpointer user_data); + +void +on_dsp_preset_save_clicked (GtkButton *button, + gpointer user_data); + +void +on_dsp_preset_load_clicked (GtkButton *button, + gpointer user_data); diff --git a/plugins/gtkui/deadbeef.glade b/plugins/gtkui/deadbeef.glade index 71cb56b4..1b320bd6 100644 --- a/plugins/gtkui/deadbeef.glade +++ b/plugins/gtkui/deadbeef.glade @@ -2814,6 +2814,93 @@ Album True + + + + True + False + 8 + + + + True + DSP Chain Preset + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + True + True + + + + 0 + False + True + + + + + + True + True + gtk-save + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + True + _Load + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + 0 + False + True + + False diff --git a/plugins/gtkui/dspconfig.c b/plugins/gtkui/dspconfig.c index 7ea1f738..75f9999c 100644 --- a/plugins/gtkui/dspconfig.c +++ b/plugins/gtkui/dspconfig.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "callbacks.h" #include "interface.h" #include "support.h" @@ -62,6 +64,19 @@ fill_dsp_chain (GtkListStore *mdl) { } } +static int dirent_alphasort (const struct dirent **a, const struct dirent **b) { + return strcmp ((*a)->d_name, (*b)->d_name); +} + +static int +scandir_preset_filter (const struct dirent *ent) { + char *ext = strrchr (ent->d_name, '.'); + if (ext && !strcasecmp (ext, ".txt")) { + return 1; + } + return 0; +} + void dsp_setup_init (GtkWidget *_prefwin) { prefwin = _prefwin; @@ -92,6 +107,35 @@ dsp_setup_init (GtkWidget *_prefwin) { gtk_tree_view_set_model (GTK_TREE_VIEW (listview), GTK_TREE_MODEL (mdl)); fill_dsp_chain (mdl); + + // set last preset name + GtkWidget *combobox = lookup_widget (prefwin, "dsp_preset"); + GtkWidget *entry = gtk_bin_get_child (GTK_BIN (combobox)); + if (entry) { + gtk_entry_set_text (GTK_ENTRY (entry), deadbeef->conf_get_str ("gtkui.conf_dsp_preset", "")); + } + + // fill list of presets + mdl = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (combobox))); + struct dirent **namelist = NULL; + char path[1024]; + if (snprintf (path, sizeof (path), "%s/presets/dsp", deadbeef->get_config_dir ()) > 0) { + int n = scandir (path, &namelist, scandir_preset_filter, dirent_alphasort); + int i; + for (i = 0; i < n; i++) { + char title[100]; + strcpy (title, namelist[i]->d_name); + char *e = strrchr (title, '.'); + if (e) { + *e = 0; + } + GtkTreeIter iter; + gtk_list_store_append (mdl, &iter); + gtk_list_store_set (mdl, &iter, 0, title, -1); + free (namelist[i]); + } + free (namelist); + } } void @@ -370,3 +414,67 @@ on_dsp_down_clicked (GtkButton *button, update_streamer (); } +void +on_dsp_preset_changed (GtkComboBox *combobox, + gpointer user_data) +{ + GtkWidget *entry = gtk_bin_get_child (GTK_BIN (combobox)); + if (entry) { + deadbeef->conf_set_str ("gtkui.conf_dsp_preset", gtk_entry_get_text (GTK_ENTRY (entry))); + } +} + + +void +on_dsp_preset_save_clicked (GtkButton *button, + gpointer user_data) +{ + const char *confdir = deadbeef->get_config_dir (); + char path[1024]; + if (snprintf (path, sizeof (path), "%s/presets", confdir) < 0) { + return; + } + mkdir (path, 0755); + if (snprintf (path, sizeof (path), "%s/presets/dsp", confdir) < 0) { + return; + } + GtkWidget *combobox = lookup_widget (prefwin, "dsp_preset"); + GtkWidget *entry = gtk_bin_get_child (GTK_BIN (combobox)); + if (!entry) { + return; + } + + const char *text = gtk_entry_get_text (GTK_ENTRY (entry)); + mkdir (path, 0755); + if (snprintf (path, sizeof (path), "%s/presets/dsp/%s.txt", confdir, text) < 0) { + return; + } + deadbeef->dsp_preset_save (path, chain); +} + + +void +on_dsp_preset_load_clicked (GtkButton *button, + gpointer user_data) +{ + GtkWidget *combobox = lookup_widget (prefwin, "dsp_preset"); + GtkWidget *entry = gtk_bin_get_child (GTK_BIN (combobox)); + if (entry) { + const char *text = gtk_entry_get_text (GTK_ENTRY (entry)); + char path[PATH_MAX]; + if (snprintf (path, sizeof (path), "%s/presets/dsp/%s.txt", deadbeef->get_config_dir (), text) > 0) { + ddb_dsp_context_t *new_chain = NULL; + int res = deadbeef->dsp_preset_load (path, &new_chain); + if (!res) { + deadbeef->dsp_preset_free (chain); + chain = new_chain; + GtkWidget *list = lookup_widget (prefwin, "dsp_listview"); + GtkListStore *mdl = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW(list))); + gtk_list_store_clear (mdl); + fill_dsp_chain (mdl); + update_streamer (); + } + } + } +} + diff --git a/plugins/gtkui/interface.c b/plugins/gtkui/interface.c index c811718d..b694214a 100644 --- a/plugins/gtkui/interface.c +++ b/plugins/gtkui/interface.c @@ -1630,6 +1630,11 @@ create_prefwin (void) GtkWidget *vbox30; GtkWidget *dsp_up; GtkWidget *dsp_down; + GtkWidget *hbox86; + GtkWidget *label114; + GtkWidget *dsp_preset; + GtkWidget *dsp_preset_save; + GtkWidget *dsp_preset_load; GtkWidget *label110; GtkWidget *vbox9; GtkWidget *pref_close_send_to_tray; @@ -1913,6 +1918,26 @@ create_prefwin (void) gtk_widget_show (dsp_down); gtk_box_pack_start (GTK_BOX (vbox30), dsp_down, FALSE, FALSE, 0); + hbox86 = gtk_hbox_new (FALSE, 8); + gtk_widget_show (hbox86); + gtk_box_pack_start (GTK_BOX (vbox29), hbox86, FALSE, TRUE, 0); + + label114 = gtk_label_new (_("DSP Chain Preset")); + gtk_widget_show (label114); + gtk_box_pack_start (GTK_BOX (hbox86), label114, FALSE, FALSE, 0); + + dsp_preset = gtk_combo_box_entry_new_text (); + gtk_widget_show (dsp_preset); + gtk_box_pack_start (GTK_BOX (hbox86), dsp_preset, FALSE, TRUE, 0); + + dsp_preset_save = gtk_button_new_from_stock ("gtk-save"); + gtk_widget_show (dsp_preset_save); + gtk_box_pack_start (GTK_BOX (hbox86), dsp_preset_save, FALSE, FALSE, 0); + + dsp_preset_load = gtk_button_new_with_mnemonic (_("_Load")); + gtk_widget_show (dsp_preset_load); + gtk_box_pack_start (GTK_BOX (hbox86), dsp_preset_load, FALSE, FALSE, 0); + label110 = gtk_label_new (_("DSP")); gtk_widget_show (label110); gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 2), label110); @@ -2616,6 +2641,15 @@ create_prefwin (void) g_signal_connect ((gpointer) dsp_down, "clicked", G_CALLBACK (on_dsp_down_clicked), NULL); + g_signal_connect ((gpointer) dsp_preset, "changed", + G_CALLBACK (on_dsp_preset_changed), + NULL); + g_signal_connect ((gpointer) dsp_preset_save, "clicked", + G_CALLBACK (on_dsp_preset_save_clicked), + NULL); + g_signal_connect ((gpointer) dsp_preset_load, "clicked", + G_CALLBACK (on_dsp_preset_load_clicked), + NULL); g_signal_connect ((gpointer) pref_close_send_to_tray, "clicked", G_CALLBACK (on_pref_close_send_to_tray_clicked), NULL); @@ -2791,6 +2825,11 @@ create_prefwin (void) GLADE_HOOKUP_OBJECT (prefwin, vbox30, "vbox30"); GLADE_HOOKUP_OBJECT (prefwin, dsp_up, "dsp_up"); GLADE_HOOKUP_OBJECT (prefwin, dsp_down, "dsp_down"); + GLADE_HOOKUP_OBJECT (prefwin, hbox86, "hbox86"); + GLADE_HOOKUP_OBJECT (prefwin, label114, "label114"); + GLADE_HOOKUP_OBJECT (prefwin, dsp_preset, "dsp_preset"); + GLADE_HOOKUP_OBJECT (prefwin, dsp_preset_save, "dsp_preset_save"); + GLADE_HOOKUP_OBJECT (prefwin, dsp_preset_load, "dsp_preset_load"); GLADE_HOOKUP_OBJECT (prefwin, label110, "label110"); GLADE_HOOKUP_OBJECT (prefwin, vbox9, "vbox9"); GLADE_HOOKUP_OBJECT (prefwin, pref_close_send_to_tray, "pref_close_send_to_tray"); -- cgit v1.2.3