summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar waker <wakeroid@gmail.com>2011-01-05 22:15:34 +0100
committerGravatar waker <wakeroid@gmail.com>2011-01-05 22:16:20 +0100
commita031151153526ed6fd4390f05dfe40a411ca26e2 (patch)
treebefba9abab10d09063eb17fd4ed1f972ca5a6c57
parent7f45bdddac21422cfb7e6380707f87c86a4e5a65 (diff)
added dsp preset functions to plugin api;
added dsp preset management to gtkui preferences window
-rw-r--r--Makefile.am3
-rw-r--r--deadbeef.h5
-rw-r--r--dsppreset.c140
-rw-r--r--dsppreset.h31
-rw-r--r--plugins.c5
-rw-r--r--plugins/gtkui/callbacks.h12
-rw-r--r--plugins/gtkui/deadbeef.glade87
-rw-r--r--plugins/gtkui/dspconfig.c108
-rw-r--r--plugins/gtkui/interface.c39
9 files changed, 429 insertions, 1 deletions
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 <waker@users.sourceforge.net>
+
+ 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#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 <waker@users.sourceforge.net>
+
+ 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</property>
<property name="fill">True</property>
</packing>
</child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox86">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">8</property>
+
+ <child>
+ <widget class="GtkLabel" id="label114">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">DSP Chain Preset</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBoxEntry" id="dsp_preset">
+ <property name="visible">True</property>
+ <property name="add_tearoffs">False</property>
+ <property name="has_frame">True</property>
+ <property name="focus_on_click">True</property>
+ <signal name="changed" handler="on_dsp_preset_changed" last_modification_time="Wed, 05 Jan 2011 19:38:28 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="dsp_preset_save">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-save</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_dsp_preset_save_clicked" last_modification_time="Wed, 05 Jan 2011 19:38:10 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="dsp_preset_load">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">_Load</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_dsp_preset_load_clicked" last_modification_time="Wed, 05 Jan 2011 19:38:13 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="tab_expand">False</property>
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 <string.h>
#include <unistd.h>
#include <assert.h>
+#include <dirent.h>
+#include <sys/stat.h>
#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");