From 56f0e801f51842201a36fb9e7f1bc6d88f26eaa1 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Sun, 29 Jan 2012 10:24:07 -0500 Subject: [PATCH] ocarina: Give each page its own footer After listening to a long queue, I noticed that there were problems re-realizing widgets after moving the footer to a different page (the header might have the same problem?). I decided to fix this issue by creating a new footer instance for each notebook page. If I do the same thing for the page header then I can get rid of the "move this widget from page X to page Y" logic AND allow pages to use their own custom header AND allow for separate library and queue filters. Signed-off-by: Bryan Schumaker --- include/ocarina/footer.h | 2 +- ocarina/body/tabs.cpp | 6 +- ocarina/footer/controls.cpp | 17 ++--- ocarina/footer/footer.cpp | 30 ++++----- ocarina/footer/footer.h | 3 + ocarina/footer/now_playing.cpp | 118 ++++++++++++++++++++------------- ocarina/footer/progress.cpp | 76 ++++++++++++--------- ocarina/ocarina.cpp | 2 + 8 files changed, 142 insertions(+), 112 deletions(-) diff --git a/include/ocarina/footer.h b/include/ocarina/footer.h index ff9544d3..d0a70dec 100644 --- a/include/ocarina/footer.h +++ b/include/ocarina/footer.h @@ -4,8 +4,8 @@ #include #include +void footer_init(); GtkWidget *get_footer(); -void put_footer(); void change_footer(libsaria::Track *); #endif /* OCARINA_FOOTER */ diff --git a/ocarina/body/tabs.cpp b/ocarina/body/tabs.cpp index 1f1efa0d..355f8bbd 100644 --- a/ocarina/body/tabs.cpp +++ b/ocarina/body/tabs.cpp @@ -19,20 +19,15 @@ static int cur_page() static void switch_page(GtkWidget *notebook, GtkWidget *page, int pagenum) { GtkWidget *header = get_header(); - GtkWidget *footer = get_footer(); int cur = cur_page(); if (cur != -1) { pages[cur].remove_header(header); - pages[cur].remove_footer(footer); } if (pagenum != -1) { pages[pagenum].add_header(header); - pages[pagenum].add_footer(footer); } - if (footer != NULL) - put_footer(); if (header != NULL) put_header(); } @@ -66,6 +61,7 @@ unsigned int add_page(GtkWidget *label, GtkWidget *content, bool fill) TRUE, GTK_PACK_START); } + page.add_footer(get_footer()); return index; }; diff --git a/ocarina/footer/controls.cpp b/ocarina/footer/controls.cpp index c0bb628e..d8ecdd8f 100644 --- a/ocarina/footer/controls.cpp +++ b/ocarina/footer/controls.cpp @@ -6,8 +6,6 @@ #include #include "footer.h" -static GtkWidget *controls = NULL; - static GtkWidget *make_buttons() { GtkWidget *buttons = gtk_hbox_new(FALSE, 0); @@ -28,16 +26,20 @@ static void toggle_pause_after() libsaria::set_pause_after(!libsaria::get_pause_after()); } -static void make_controls() +GtkWidget *get_controls() { - controls = gtk_vbox_new(FALSE, 0); + GtkWidget *controls = gtk_vbox_new(FALSE, 0); gtk_widget_show(controls); /* * Putting the button hbox into a vbox will keep them from * expanding vertically to take up all the space. */ box_pack_start(controls, make_buttons(), TRUE, FALSE, 0); + return controls; +} +void controls_init() +{ register_shortcut("Left", libsaria::rewind); register_shortcut("Right", libsaria::forward); register_shortcut("space", libsaria::toggle_play); @@ -45,10 +47,3 @@ static void make_controls() register_shortcut("s", libsaria::audio::stop); register_shortcut("p", toggle_pause_after); } - -GtkWidget *get_controls() -{ - if (controls == NULL) - make_controls(); - return controls; -} diff --git a/ocarina/footer/footer.cpp b/ocarina/footer/footer.cpp index fd1d89b1..62eb6513 100644 --- a/ocarina/footer/footer.cpp +++ b/ocarina/footer/footer.cpp @@ -2,42 +2,36 @@ #include #include "footer.h" -static GtkWidget *footer = NULL; - -static void make_footer() +GtkWidget *get_footer() { - GtkWidget *sep = gtk_hseparator_new(); + GtkWidget *footer = gtk_vbox_new(FALSE, 0); + GtkWidget *sep = gtk_hseparator_new(); GtkWidget *content = gtk_hbox_new(FALSE, 5); - footer = gtk_vbox_new(FALSE, 0); box_pack_start(footer, sep, FALSE, FALSE, 0); box_pack_start(footer, get_progress(), FALSE, FALSE, 0); box_pack_start(footer, content, FALSE, FALSE, 0); + /* * The pause button begins life hidden, so show everything up until * this point, and then add the controls */ gtk_widget_show_all(footer); - box_pack_start(content, get_nowplaying(), TRUE, TRUE, 0); + box_pack_start(content, get_nowplaying(), TRUE, TRUE, 0); box_pack_start(content, get_controls(), FALSE, FALSE, 0); -} -GtkWidget *get_footer() -{ - if (footer == NULL) - make_footer(); - g_object_ref(footer); return footer; } -void put_footer() -{ - if (footer != NULL) - g_object_unref(footer); -} - void change_footer(libsaria::Track *track) { set_now_playing(track); } + +void footer_init() +{ + controls_init(); + progress_init(); + nowplaying_init(); +} diff --git a/ocarina/footer/footer.h b/ocarina/footer/footer.h index 97a10392..2d99e59a 100644 --- a/ocarina/footer/footer.h +++ b/ocarina/footer/footer.h @@ -7,6 +7,9 @@ GtkWidget *get_controls(); GtkWidget *get_nowplaying(); GtkWidget *get_progress(); +void progress_init(); +void controls_init(); +void nowplaying_init(); void set_now_playing(libsaria::Track *); #endif /* OCARINA_FOOTER_PRIVATE_H */ diff --git a/ocarina/footer/now_playing.cpp b/ocarina/footer/now_playing.cpp index 89a95a0a..40d6ee83 100644 --- a/ocarina/footer/now_playing.cpp +++ b/ocarina/footer/now_playing.cpp @@ -3,10 +3,16 @@ #include #include "footer.h" -static GtkWidget *now_playing = NULL; -static GtkWidget *title = NULL; -static GtkWidget *artist = NULL; -static GtkWidget *album = NULL; +#include +using namespace std; + +struct NowPlayingWidgets { + GtkWidget *title; + GtkWidget *artist; + GtkWidget *album; +}; + +static list nowplaying_widgets; static void set_label(GtkWidget *label, string text, string size) { @@ -15,19 +21,18 @@ static void set_label(GtkWidget *label, string text, string size) gtk_label_set_markup(GTK_LABEL(label), markup.c_str()); } -static void set_title(string new_title) +static void set_now_playing(struct NowPlayingWidgets *widgets, string title, + string artist, string album) { - set_label(title, new_title, "xx-large"); -} + if (artist != "") + artist = "by " + artist; -static void set_artist(string new_artist) -{ - set_label(artist, new_artist, "x-large"); -} + if (album != "") + album = "from " + album; -static void set_album(string new_album) -{ - set_label(album, new_album, "x-large"); + set_label(widgets->title, title, "xx-large"); + set_label(widgets->artist, artist, "x-large"); + set_label(widgets->album, album, "x-large"); } static GtkWidget *align(GtkWidget *label) @@ -37,51 +42,70 @@ static GtkWidget *align(GtkWidget *label) return alignment; } -static GtkWidget *setup_window() +static GtkWidget *setup_window(GtkWidget *box) { GtkWidget *viewport = gtk_viewport_new(NULL, NULL); - now_playing = gtk_scrolled_window_new(NULL, NULL); + GtkWidget *window = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(now_playing), + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(window), GTK_POLICY_AUTOMATIC, - GTK_POLICY_NEVER); + GTK_POLICY_AUTOMATIC); gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE); - container_add(now_playing, viewport); + container_add(viewport, box); + container_add(window, viewport); - return viewport; -} - -static void make_now_playing() -{ - GtkWidget *tag_box = gtk_vbox_new(FALSE, 0); - GtkWidget *container = setup_window(); - - title = gtk_label_new(""); - artist = gtk_label_new(""); - album = gtk_label_new(""); - - set_title(" "); - set_artist(" "); - set_album(" "); - - box_pack_start(tag_box, align(title), TRUE, FALSE, 0); - box_pack_start(tag_box, align(artist), TRUE, FALSE, 0); - box_pack_start(tag_box, align(album), TRUE, FALSE, 0); - - container_add(container, tag_box); - gtk_widget_show_all(now_playing); + return window; } GtkWidget *get_nowplaying() { - if (now_playing == NULL) - make_now_playing(); - return now_playing; + struct NowPlayingWidgets widgets; + GtkWidget *box = gtk_vbox_new(FALSE, 0); + GtkWidget *window = setup_window(box); + + widgets.title = gtk_label_new(""); + widgets.artist = gtk_label_new(""); + widgets.album = gtk_label_new(""); + + set_now_playing(&widgets, "", "", ""); + + box_pack_start(box, align(widgets.title), TRUE, FALSE, 0); + box_pack_start(box, align(widgets.artist), TRUE, FALSE, 0); + box_pack_start(box, align(widgets.album), TRUE, FALSE, 0); + + nowplaying_widgets.push_back(widgets); + gtk_widget_show_all(window); + return window; +} + +/* + * This takes some explanation, so... + * During startup, all the labels are set to the empty string. This + * causes them to initially be rendered blank. This normally isn't + * a problem BUT the three widgets placed on the settings tab don't have + * a call to gtk_widget_show() once the page is added to the notebook and + * for some reason switching tabs isn't enough to realize the widgets. + * As a result, only the very beginning of the widget gets updated (as in, + * you could see half of a "T" if you start ocarina, click "next" and then + * switch to the settings tab). Realizing just one of the widgets before + * trying to use them seems to fix the problem, so that's what I'm doing + * here. + */ +void nowplaying_init() +{ + list::iterator it; + for (it = nowplaying_widgets.begin(); it != nowplaying_widgets.end(); it++) + gtk_widget_realize(it->title); } void set_now_playing(libsaria::Track *track) { - set_title(track->get_title()); - set_artist("by " + track->get_artist()); - set_album("from " + track->get_album()); + list::iterator it; + + for (it = nowplaying_widgets.begin(); it != nowplaying_widgets.end(); it++) { + set_now_playing(&(*it), + track->get_title(), + track->get_artist(), + track->get_album()); + }; } diff --git a/ocarina/footer/progress.cpp b/ocarina/footer/progress.cpp index c7094e9b..4b32aa82 100644 --- a/ocarina/footer/progress.cpp +++ b/ocarina/footer/progress.cpp @@ -4,19 +4,24 @@ #include #include "footer.h" -static GtkWidget *progress_box = NULL; /* gtk hbox */ -static GtkWidget *position = NULL; /* gtk label */ -static GtkWidget *progress = NULL; /* gtk hscale */ -static GtkWidget *duration = NULL; /* gtk label */ +#include +using namespace std; -static gboolean update_progress(gpointer data) +struct ProgressWidgets { + GtkWidget *position; + GtkWidget *duration; + GtkWidget *progress; +}; + +static list widget_list; + +static gboolean update_progress(struct ProgressWidgets *widgets) { gint64 pos = libsaria::audio::position(); gint64 dur = libsaria::audio::duration() + 1; - gtk_label_set_text(GTK_LABEL(position), libsaria::audio::posstr().c_str()); - gtk_label_set_text(GTK_LABEL(duration), libsaria::audio::durstr().c_str()); - gtk_range_set_range(GTK_RANGE(progress), 0, dur); + gtk_label_set_text(GTK_LABEL(widgets->position), libsaria::audio::posstr().c_str()); + gtk_label_set_text(GTK_LABEL(widgets->duration), libsaria::audio::durstr().c_str()); /* * This happens when gstreamer's "about-to-finish" signal @@ -25,40 +30,51 @@ static gboolean update_progress(gpointer data) */ if (pos > dur) pos = 0; - gtk_range_set_value(GTK_RANGE(progress), pos); + gtk_range_set_range(GTK_RANGE(widgets->progress), 0, dur); + gtk_range_set_value(GTK_RANGE(widgets->progress), pos); return TRUE; } +static gboolean update_progress_widgets(gpointer data) +{ + list::iterator it; + for (it = widget_list.begin(); it != widget_list.end(); it++) + update_progress(&(*it)); + return TRUE; +} + +void progress_init() +{ + gtk_timeout_add(100, update_progress_widgets, NULL); +} + static void slider_changed(GtkWidget *slider, GtkScrollType scroll, gdouble value, gpointer data) { libsaria::audio::seek_to(value); } -static void make_scale() +static GtkWidget *make_scale() { - progress = gtk_hscale_new_with_range(0, 1, 1000000000); - gtk_scale_set_draw_value(GTK_SCALE(progress), FALSE); - gtk_timeout_add(100, update_progress, NULL); - GTK_CONNECT(progress, "change-value", slider_changed, NULL); -} - -static void make_progress() -{ - position = gtk_label_new(""); - progress_box = gtk_hbox_new(FALSE, 0); - duration = gtk_label_new(""); - make_scale(); - - box_pack_start(progress_box, position, FALSE, FALSE, 0); - box_pack_start(progress_box, progress, TRUE, TRUE, 0); - box_pack_start(progress_box, duration, FALSE, FALSE, 0); - gtk_widget_show_all(progress_box); + GtkWidget *scale = gtk_hscale_new_with_range(0, 1, 1000000000); + gtk_scale_set_draw_value(GTK_SCALE(scale), FALSE); + GTK_CONNECT(scale, "change-value", slider_changed, NULL); + return scale; } GtkWidget *get_progress() { - if (progress_box == NULL) - make_progress(); - return progress_box; + struct ProgressWidgets widgets; + GtkWidget *box = gtk_hbox_new(FALSE, 0); + widgets.position = gtk_label_new(""); + widgets.duration = gtk_label_new(""); + widgets.progress = make_scale(); + + box_pack_start(box, widgets.position, FALSE, FALSE, 0); + box_pack_start(box, widgets.progress, TRUE, TRUE, 0); + box_pack_start(box, widgets.duration, FALSE, FALSE, 0); + + gtk_widget_show_all(box); + widget_list.push_back(widgets); + return box; } diff --git a/ocarina/ocarina.cpp b/ocarina/ocarina.cpp index 344d9b19..9c9a7eec 100644 --- a/ocarina/ocarina.cpp +++ b/ocarina/ocarina.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,7 @@ namespace ocarina ocarina::queue::init(); ocarina::library::init(); settings_init(); + footer_init(); idle_add(); }