diff --git a/include/ocarina/header.h b/include/ocarina/header.h index c9db33d1..6a908c00 100644 --- a/include/ocarina/header.h +++ b/include/ocarina/header.h @@ -6,4 +6,6 @@ GtkWidget *get_header(); void put_header(); +bool entry_focused(); + #endif /* OCARINA_HEADER_H */ diff --git a/include/ocarina/shortcut.h b/include/ocarina/shortcut.h new file mode 100644 index 00000000..9106c65a --- /dev/null +++ b/include/ocarina/shortcut.h @@ -0,0 +1,12 @@ +#ifndef OCARINA_SHORTCUT_H +#define OCARINA_SHORTCUT_H + +#include + +#include +using namespace std; + +void register_shortcut(string, void (*)()); +gboolean handle_shortcut(GtkWidget *, GdkEvent *, gpointer); + +#endif /* OCARINA_SHORTCUT_H */ diff --git a/include/ocarina/window.h b/include/ocarina/window.h index 59633af1..28beb367 100644 --- a/include/ocarina/window.h +++ b/include/ocarina/window.h @@ -3,10 +3,14 @@ #include +#include +using namespace std; + void window_resize(int, int); void window_init(string, string); void window_add(GtkWidget *); void window_title(string); void window_icon(string); +void window_focus(); #endif diff --git a/ocarina/footer/controls.cpp b/ocarina/footer/controls.cpp index bb9cd13c..1a30c711 100644 --- a/ocarina/footer/controls.cpp +++ b/ocarina/footer/controls.cpp @@ -1,6 +1,9 @@ #include #include +#include +#include +#include #include "footer.h" static GtkWidget *controls = NULL; @@ -20,6 +23,29 @@ static GtkWidget *make_buttons() return buttons; } +static void toggle_pause_after() +{ + libsaria::set_pause_after(!libsaria::get_pause_after()); +} + +static void rewind() +{ + libsaria::audio::seek(-5); +} + +static void forward() +{ + libsaria::audio::seek(5); +} + +static void toggle_play() +{ + if (libsaria::audio::is_playing()) + libsaria::audio::pause(); + else + libsaria::audio::play(); +} + static void make_controls() { controls = gtk_vbox_new(FALSE, 0); @@ -29,6 +55,13 @@ static void make_controls() * expanding vertically to take up all the space. */ box_pack_start(controls, make_buttons(), TRUE, FALSE, 0); + + register_shortcut("Left", rewind); + register_shortcut("Right", forward); + register_shortcut("space", toggle_play); + register_shortcut("n", libsaria::next); + register_shortcut("s", libsaria::audio::stop); + register_shortcut("p", toggle_pause_after); } GtkWidget *get_controls() diff --git a/ocarina/header/entry.cpp b/ocarina/header/entry.cpp index 3f054416..265e61be 100644 --- a/ocarina/header/entry.cpp +++ b/ocarina/header/entry.cpp @@ -1,4 +1,6 @@ +#include +#include #include #include #include "header.h" @@ -11,10 +13,16 @@ static void do_filter(GtkWidget *entry) libsaria::library::filter(text); } +static void filter_focus() +{ + gtk_widget_grab_focus(entry); +} + static void make_entry() { entry = gtk_entry_new(); GTK_CONNECT(entry, "changed", do_filter, NULL); + register_shortcut("slash", filter_focus); } GtkWidget *get_entry() @@ -23,3 +31,8 @@ GtkWidget *get_entry() make_entry(); return entry; } + +bool entry_focused() +{ + return gtk_widget_is_focus(entry); +} diff --git a/ocarina/library.cpp b/ocarina/library.cpp index ff88e2d0..ac4e0b08 100644 --- a/ocarina/library.cpp +++ b/ocarina/library.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -16,7 +17,7 @@ static SongList library_list; static struct SongListFuncs library_funcs; static list library_menu; -static void add_to_queue(GtkMenuItem *menu, gpointer data) +static void add_to_queue() { list selected; list::iterator it; @@ -24,6 +25,11 @@ static void add_to_queue(GtkMenuItem *menu, gpointer data) libsaria::queue::add_ids(selected); } +static void add_to_queue_event(GtkMenuItem *menu, gpointer data) +{ + add_to_queue(); +} + namespace ocarina { @@ -40,10 +46,12 @@ namespace ocarina void library::init() { - library_menu.push_back(MenuItem("Add to Queue", add_to_queue)); + library_menu.push_back(MenuItem("Add to Queue", add_to_queue_event)); library_funcs.for_each = libsaria::library::for_each; library_funcs.size = libsaria::library::size; + register_shortcut("q", add_to_queue); + library_list.init("Library", &library_funcs, &library_menu, true); add_page(library_list.get_label(), library_list.get_window(), true); ocarina::library::refresh(); diff --git a/ocarina/shortcut.cpp b/ocarina/shortcut.cpp new file mode 100644 index 00000000..504a08ad --- /dev/null +++ b/ocarina/shortcut.cpp @@ -0,0 +1,46 @@ + +#include +#include +#include +#include +#include + +#include +#include +using namespace std; + +static map shortcut_map; + +void register_shortcut(string key, void (*func)()) +{ + shortcut_map[key] = func; +} + +/* + * Returns FALSE to allow other functions to run + * Returns TRUE if other handlers should not be run + */ +gboolean handle_shortcut(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + string key = gdk_keyval_name(event->key.keyval); + map::iterator it; + + if (key == "Escape") { + window_focus(); + return TRUE; + } + + /* Don't run shortcuts if user is filtering */ + if (entry_focused() == true) + return FALSE; + + it = shortcut_map.find(key); + if (it == shortcut_map.end()) { + print("No function registered for key: "); + println(key); + return FALSE; + } + + it->second(); + return TRUE; +} diff --git a/ocarina/window.cpp b/ocarina/window.cpp index bba1f4c5..98f5e5d1 100644 --- a/ocarina/window.cpp +++ b/ocarina/window.cpp @@ -5,6 +5,7 @@ using namespace std; #include #include #include +#include static GtkWidget *window; @@ -32,6 +33,7 @@ void window_init(string title, string icon) { window = gtk_window_new(GTK_WINDOW_TOPLEVEL); GTK_CONNECT(window, "destroy", destroy_window, NULL); + GTK_CONNECT(window, "key-press-event", handle_shortcut, NULL); window_resize(800, 600); gtk_widget_show(window); window_title(title); @@ -42,3 +44,8 @@ void window_add(GtkWidget *widget) { container_add(window, widget); } + +void window_focus() +{ + gtk_window_set_focus(GTK_WINDOW(window), NULL); +}