diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2010-03-19 22:23:18 +0100 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2010-03-19 22:23:18 +0100 |
commit | a723a88e649bba5b8187bee0a7156beca31a1c8c (patch) | |
tree | c4615ee8090551b1e6b0c28f9086ab49e8e7f3e4 /plugins | |
parent | 2c6f50695af8b9dba7022cae891610e7285b5749 (diff) |
finished initial implementation of global hotkeys gui configuration
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/gtkui/callbacks.c | 1 | ||||
-rw-r--r-- | plugins/gtkui/callbacks.h | 4 | ||||
-rw-r--r-- | plugins/gtkui/deadbeef.glade | 12 | ||||
-rw-r--r-- | plugins/gtkui/interface.c | 7 | ||||
-rw-r--r-- | plugins/gtkui/prefwin.c | 112 | ||||
-rw-r--r-- | plugins/hotkeys/hotkeys.c | 82 | ||||
-rw-r--r-- | plugins/hotkeys/hotkeys.h | 30 | ||||
-rw-r--r-- | plugins/hotkeys/keysyms.inc | 2 |
8 files changed, 210 insertions, 40 deletions
diff --git a/plugins/gtkui/callbacks.c b/plugins/gtkui/callbacks.c index 369e9749..410e67e9 100644 --- a/plugins/gtkui/callbacks.c +++ b/plugins/gtkui/callbacks.c @@ -987,3 +987,4 @@ on_mainwin_realize (GtkWidget *widget, gtkui_init_theme_colors (); } + diff --git a/plugins/gtkui/callbacks.h b/plugins/gtkui/callbacks.h index 83139073..9abca77b 100644 --- a/plugins/gtkui/callbacks.h +++ b/plugins/gtkui/callbacks.h @@ -765,3 +765,7 @@ on_color_selected_text_color_set (GtkColorButton *colorbutton, void on_disable_playlist_theming_toggled (GtkToggleButton *togglebutton, gpointer user_data); + +void +on_addhotkey_activate (GtkButton *button, + gpointer user_data); diff --git a/plugins/gtkui/deadbeef.glade b/plugins/gtkui/deadbeef.glade index 85cf6cd6..3e9ca696 100644 --- a/plugins/gtkui/deadbeef.glade +++ b/plugins/gtkui/deadbeef.glade @@ -3955,6 +3955,18 @@ SOCKS5_HOSTNAME</property> <property name="focus_on_click">True</property> </widget> </child> + + <child> + <widget class="GtkButton" id="applyhotkeys"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Apply</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + </widget> + </child> </widget> <packing> <property name="padding">0</property> diff --git a/plugins/gtkui/interface.c b/plugins/gtkui/interface.c index cb33ff83..2f9534bf 100644 --- a/plugins/gtkui/interface.c +++ b/plugins/gtkui/interface.c @@ -1604,6 +1604,7 @@ create_prefwin (void) GtkWidget *hbuttonbox3; GtkWidget *addhotkey; GtkWidget *removehotkey; + GtkWidget *applyhotkeys; GtkWidget *label66; GtkWidget *dialog_action_area2; GtkWidget *closebutton1; @@ -2080,6 +2081,11 @@ create_prefwin (void) gtk_container_add (GTK_CONTAINER (hbuttonbox3), removehotkey); GTK_WIDGET_SET_FLAGS (removehotkey, GTK_CAN_DEFAULT); + applyhotkeys = gtk_button_new_with_mnemonic ("Apply"); + gtk_widget_show (applyhotkeys); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), applyhotkeys); + GTK_WIDGET_SET_FLAGS (applyhotkeys, GTK_CAN_DEFAULT); + label66 = gtk_label_new ("Global Hotkeys"); gtk_widget_show (label66); gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook2), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook2), 5), label66); @@ -2250,6 +2256,7 @@ create_prefwin (void) GLADE_HOOKUP_OBJECT (prefwin, hbuttonbox3, "hbuttonbox3"); GLADE_HOOKUP_OBJECT (prefwin, addhotkey, "addhotkey"); GLADE_HOOKUP_OBJECT (prefwin, removehotkey, "removehotkey"); + GLADE_HOOKUP_OBJECT (prefwin, applyhotkeys, "applyhotkeys"); GLADE_HOOKUP_OBJECT (prefwin, label66, "label66"); GLADE_HOOKUP_OBJECT_NO_REF (prefwin, dialog_action_area2, "dialog_action_area2"); GLADE_HOOKUP_OBJECT (prefwin, closebutton1, "closebutton1"); diff --git a/plugins/gtkui/prefwin.c b/plugins/gtkui/prefwin.c index 00c53515..efb407a3 100644 --- a/plugins/gtkui/prefwin.c +++ b/plugins/gtkui/prefwin.c @@ -24,6 +24,9 @@ #include "interface.h" #include "callbacks.h" #include "drawing.h" +#include "../hotkeys/hotkeys.h" + +#pragma GCC optimize("O0") static GtkWidget *prefwin; @@ -96,6 +99,9 @@ preferences_fill_soundcards (void) { void on_hk_slot_edited (GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data) { + if (!new_text || !new_text[0]) { + return; + } GtkListStore *store = GTK_LIST_STORE (user_data); GtkTreePath *treepath = gtk_tree_path_new_from_string (path); GtkTreeIter iter; @@ -120,16 +126,87 @@ on_hk_binding_edited (GtkCellRendererAccel *accel, gchar *path, guint accel_key, if (accel_mods & GDK_CONTROL_MASK) { strcat (new_value, "Ctrl "); } - if (accel_mods & GDK_MOD4_MASK) { + if (accel_mods & GDK_SUPER_MASK) { strcat (new_value, "Super "); } - if (accel_mods & GDK_META_MASK) { + if (accel_mods & GDK_MOD1_MASK) { strcat (new_value, "Alt "); } - char key[2] = {accel_key, 0}; - strcat (new_value, key); - gtk_list_store_set (store, &iter, 1, new_value, -1); + // find key name from hotkeys plugin + DB_plugin_t **plugs = deadbeef->plug_get_list (); + int i; + for (i = 0; plugs[i]; i++) { + if (plugs[i]->id && !strcmp (plugs[i]->id, "hotkeys")) { + const char *name = ((DB_hotkeys_plugin_t *)plugs[i])->get_name_for_keycode (accel_key); + strcat (new_value, name); + gtk_list_store_set (store, &iter, 1, new_value, -1); + break; + } + } +// if (!plugs[i]) { +// return; +// } +} + +void +on_addhotkey_clicked (GtkButton *button, gpointer user_data) { + GtkListStore *store = GTK_LIST_STORE (user_data); + GtkTreeIter iter; + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, "toggle_pause", 1, "", -1); +} + +void +on_removehotkey_clicked (GtkButton *button, gpointer user_data) { + GtkTreeView *tree = GTK_TREE_VIEW (user_data); + GtkTreeModel *model = gtk_tree_view_get_model (tree); + if (model) { + GtkTreeSelection *sel = gtk_tree_view_get_selection (tree); + if (sel) { + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (sel, NULL, &iter)) { + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + } + } + } +} + +static gboolean +add_hotkey_to_config (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { + int *counter = (int *)data; + GValue key = {0,}, value = {0,}; +// g_value_init (&key, G_TYPE_STRING); +// g_value_init (&value, G_TYPE_STRING); + gtk_tree_model_get_value (model, iter, 0, &key); + gtk_tree_model_get_value (model, iter, 1, &value); + const char *skey = g_value_get_string (&key); + const char *svalue = g_value_get_string (&value); + + char conf_name[100]; + char conf_value[100]; + snprintf (conf_name, sizeof (conf_name), "hotkeys.key%d", *counter); + (*counter)++; + snprintf (conf_value, sizeof (conf_value), "%s: %s", svalue, skey); + deadbeef->conf_set_str (conf_name, conf_value); +} + +void +on_applyhotkeys_clicked (GtkButton *button, gpointer user_data) { + DB_plugin_t **plugs = deadbeef->plug_get_list (); + int i; + for (i = 0; plugs[i]; i++) { + if (plugs[i]->id && !strcmp (plugs[i]->id, "hotkeys")) { + // rebuild config + deadbeef->conf_remove_items ("hotkeys.key"); + int counter = 1; + GtkTreeModel *model = GTK_TREE_MODEL (user_data); + gtk_tree_model_foreach (model, add_hotkey_to_config, &counter); + + ((DB_hotkeys_plugin_t *)plugs[i])->reset (); + break; + } + } } void @@ -277,16 +354,17 @@ on_preferences_activate (GtkMenuItem *menuitem, // model for hotkey slots const char *slots[] = { - "Toggle pause", - "Play", - "Prev", - "Next", - "Random", - "Seek forward", - "Seek backward", - "Volume up", - "Volume down", - "Toggle stop after current", + "toggle_pause", + "play", + "prev", + "next", + "stop", + "play_random", + "seek_fwd", + "seek_back", + "volume_up", + "volume_down", + "toggle_stop_after_current", NULL }; GtkListStore *slots_store = gtk_list_store_new (1, G_TYPE_STRING); @@ -345,6 +423,10 @@ on_preferences_activate (GtkMenuItem *menuitem, } gtk_tree_view_set_model (hktree, GTK_TREE_MODEL (hkstore)); + g_signal_connect ((gpointer)lookup_widget (prefwin, "addhotkey"), "clicked", G_CALLBACK (on_addhotkey_clicked), hkstore); + g_signal_connect ((gpointer)lookup_widget (prefwin, "removehotkey"), "clicked", G_CALLBACK (on_removehotkey_clicked), hktree); + g_signal_connect ((gpointer)lookup_widget (prefwin, "applyhotkeys"), "clicked", G_CALLBACK (on_applyhotkeys_clicked), hkstore); + gtk_dialog_run (GTK_DIALOG (prefwin)); gtk_widget_destroy (prefwin); prefwin = NULL; diff --git a/plugins/hotkeys/hotkeys.c b/plugins/hotkeys/hotkeys.c index 622fc5fb..959dbd30 100644 --- a/plugins/hotkeys/hotkeys.c +++ b/plugins/hotkeys/hotkeys.c @@ -22,13 +22,15 @@ #include <X11/Xlib.h> #include <ctype.h> +#include "hotkeys.h" #include "../../deadbeef.h" -static DB_misc_t plugin; +static DB_hotkeys_plugin_t plugin; static DB_functions_t *deadbeef; static int finished; static Display *disp; static intptr_t loop_tid; +static int need_reset = 0; #define MAX_COMMAND_COUNT 256 @@ -67,7 +69,7 @@ get_keycode (Display *disp, const char* name, KeySym *syms, int first_kk, int la for (i = 0; i < last_kk-first_kk; i++) { KeySym sym = * (syms + i*ks_per_kk); - for (ks = 0; ks < sizeof (keys) / sizeof (xkey_t); ks++) + for (ks = 0; keys[ks].name; ks++) { if ( (keys[ ks ].keysym == sym) && (0 == strcmp (name, keys[ ks ].name))) { @@ -257,6 +259,12 @@ read_config (Display *disp) item = deadbeef->conf_find ("hotkeys.", item); } XFree (syms); + int i; + // need to grab it here to prevent gdk_x_error from being called while we're + // doing it on other thread + for (i = 0; i < command_count; i++) { + XGrabKey (disp, commands[i].keycode, commands[i].modifier, DefaultRootWindow (disp), False, GrabModeAsync, GrabModeAsync); + } } DB_plugin_t * @@ -271,11 +279,29 @@ cleanup () { XCloseDisplay (disp); } +static int +x_err_handler (Display *d, XErrorEvent *evt) { + char buffer[1024]; + XGetErrorText (d, evt->error_code, buffer, sizeof (buffer)); + fprintf (stderr, "hotkeys: xlib error: %s\n", buffer); +} + static void hotkeys_event_loop (void *unused) { int i; while (!finished) { + if (need_reset) { + XSetErrorHandler (x_err_handler); + for (int i = 0; i < command_count; i++) { + XUngrabKey (disp, commands[i].keycode, commands[i].modifier, DefaultRootWindow (disp)); + } + memset (commands, 0, sizeof (commands)); + command_count = 0; + read_config (disp); + need_reset = 0; + } + XEvent event; while (XPending (disp)) { @@ -297,13 +323,6 @@ hotkeys_event_loop (void *unused) { } static int -x_err_handler (Display *d, XErrorEvent *evt) { - char buffer[1024]; - XGetErrorText (d, evt->error_code, buffer, sizeof (buffer)); - fprintf (stderr, "hotkeys: xlib error: %s\n", buffer); -} - -static int hotkeys_start (void) { finished = 0; loop_tid = 0; @@ -316,12 +335,6 @@ hotkeys_start (void) { XSetErrorHandler (x_err_handler); read_config (disp); - int i; - // need to grab it here to prevent gdk_x_error from being called while we're - // doing it on other thread - for (i = 0; i < command_count; i++) { - XGrabKey (disp, commands[i].keycode, commands[i].modifier, DefaultRootWindow (disp), False, GrabModeAsync, GrabModeAsync); - } XSync (disp, 0); if (command_count > 0) { loop_tid = deadbeef->thread_start (hotkeys_event_loop, 0); @@ -340,16 +353,35 @@ hotkeys_stop (void) { } } +const char * +hotkeys_get_name_for_keycode (int keycode) { + for (int i = 0; keys[i].name; i++) { + if (keycode == keys[i].keysym) { + return keys[i].name; + } + } + return NULL; +} + +void +hotkeys_reset (void) { + need_reset = 1; +} + // define plugin interface -static DB_misc_t plugin = { - DB_PLUGIN_SET_API_VERSION - .plugin.type = DB_PLUGIN_MISC, - .plugin.name = "Global hotkeys support", - .plugin.descr = "Allows to control player with global hotkeys", - .plugin.author = "Viktor Semykin", - .plugin.email = "thesame.ml@gmail.com", - .plugin.website = "http://deadbeef.sf.net", - .plugin.start = hotkeys_start, - .plugin.stop = hotkeys_stop +static DB_hotkeys_plugin_t plugin = { + .misc.plugin.api_vmajor = DB_API_VERSION_MAJOR, + .misc.plugin.api_vminor = DB_API_VERSION_MINOR, + .misc.plugin.type = DB_PLUGIN_MISC, + .misc.plugin.id = "hotkeys", + .misc.plugin.name = "Global hotkeys support", + .misc.plugin.descr = "Allows to control player with global hotkeys", + .misc.plugin.author = "Viktor Semykin", + .misc.plugin.email = "thesame.ml@gmail.com", + .misc.plugin.website = "http://deadbeef.sf.net", + .misc.plugin.start = hotkeys_start, + .misc.plugin.stop = hotkeys_stop, + .get_name_for_keycode = hotkeys_get_name_for_keycode, + .reset = hotkeys_reset, }; diff --git a/plugins/hotkeys/hotkeys.h b/plugins/hotkeys/hotkeys.h new file mode 100644 index 00000000..f520aa41 --- /dev/null +++ b/plugins/hotkeys/hotkeys.h @@ -0,0 +1,30 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2010 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 __HOTKEYS_H +#define __HOTKEYS_H + +#include "../../deadbeef.h" + +typedef struct DB_hotkeys_plugin_s { + DB_misc_t misc; + const char *(*get_name_for_keycode) (int keycode); + void (*reset) (void); +} DB_hotkeys_plugin_t; + +#endif diff --git a/plugins/hotkeys/keysyms.inc b/plugins/hotkeys/keysyms.inc index af164fef..1f66304b 100644 --- a/plugins/hotkeys/keysyms.inc +++ b/plugins/hotkeys/keysyms.inc @@ -2189,3 +2189,5 @@ KEY("XF86Ungrab", 0x1008FE20) KEY("XF86ClearGrab", 0x1008FE21) KEY("XF86Next_VMode", 0x1008FE22) KEY("XF86Prev_VMode", 0x1008FE23) + +KEY(NULL, 0) |