diff options
author | Brijesh Singh <brijesh.ksingh@gmail.com> | 2015-06-26 20:42:31 -0500 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2015-07-07 23:49:09 +0300 |
commit | b59a893da7c2e431e4d676b940adcd2bc7018e8a (patch) | |
tree | 1c23c89e1be571b8c4972464c726de936280259e /playback | |
parent | cce3ab6381bf291d1fde96aede8ad4a42ac38c39 (diff) |
playback/player: gtk-play: add support to build UI through gtkbuilder
- build toolbar ui from glade generated xml files
- build media info dialog from glade generated xml files
- add support to apply css style on widget
- multiple cleanups
Diffstat (limited to 'playback')
-rw-r--r-- | playback/player/gtk/Makefile.am | 34 | ||||
-rw-r--r-- | playback/player/gtk/gtk-play.c | 868 | ||||
-rw-r--r-- | playback/player/gtk/resources/gresources.xml | 11 | ||||
-rw-r--r-- | playback/player/gtk/resources/media_info_dialog.ui | 108 | ||||
-rw-r--r-- | playback/player/gtk/resources/toolbar.css | 26 | ||||
-rw-r--r-- | playback/player/gtk/resources/toolbar.ui | 341 |
6 files changed, 874 insertions, 514 deletions
diff --git a/playback/player/gtk/Makefile.am b/playback/player/gtk/Makefile.am index df03555..f7e6d0f 100644 --- a/playback/player/gtk/Makefile.am +++ b/playback/player/gtk/Makefile.am @@ -1,10 +1,36 @@ bin_PROGRAMS = gtk-play -gtk_play_SOURCES = gtk-play.c +gtk-play-resources.c: resources/gresources.xml \ + resources/media_info_dialog.ui \ + resources/toolbar.css \ + resources/toolbar.ui + $(AM_V_GEN) \ + glib-compile-resources \ + --sourcedir=$(srcdir)/resources \ + --target=$@ \ + --generate-source \ + --c-name as \ + $(srcdir)/resources/gresources.xml + +gtk-play-resources.h: resources/gresources.xml \ + resources/media_info_dialog.ui \ + resources/toolbar.css \ + resources/toolbar.ui + $(AM_V_GEN) \ + glib-compile-resources \ + --sourcedir=$(srcdir)/resources \ + --target=$@ \ + --generate-header \ + --c-name as \ + $(srcdir)/resources/gresources.xml + +BUILT_SOURCES: gtk-play-resources.c gtk-play-resources.h + +gtk_play_SOURCES = gtk-play.c gtk-play-resources.c LDADD = $(top_builddir)/lib/gst/player/.libs/libgstplayer-@GST_PLAYER_API_VERSION@.la \ - $(GSTREAMER_LIBS) $(GTK_LIBS) $(GTK_X11_LIBS) $(GLIB_LIBS) $(LIBM) + $(GSTREAMER_LIBS) $(GTK_LIBS) $(GTK_X11_LIBS) $(GLIB_LIBS) $(LIBM) $(GMODULE_LIBS) -AM_CFLAGS = -I$(top_srcdir)/lib -I$(top_builddir)/lib $(GSTREAMER_CFLAGS) $(GTK_CFLAGS) $(GTK_X11_CFLAGS) $(GLIB_CFLAGS) +AM_CFLAGS = -I$(top_srcdir)/lib -I$(top_builddir)/lib $(GSTREAMER_CFLAGS) $(GTK_CFLAGS) $(GTK_X11_CFLAGS) $(GLIB_CFLAGS) $(GMODULE_CFLAGS) -noinst_HEADERS = +noinst_HEADERS = gtk-play-resources.h diff --git a/playback/player/gtk/gtk-play.c b/playback/player/gtk/gtk-play.c index 2a8cfa5..32973af 100644 --- a/playback/player/gtk/gtk-play.c +++ b/playback/player/gtk/gtk-play.c @@ -42,6 +42,12 @@ #define APP_NAME "gtk-play" +#define TOOLBAR_GET_OBJECT(x) \ + (GtkWidget *)gtk_builder_get_object (play->toolbar_ui, #x) + +#define TOOLBAR_GET_LABEL(x) \ + (GtkLabel *) gtk_builder_get_object (play->toolbar_ui, #x) + typedef GtkApplication GtkPlayApp; typedef GtkApplicationClass GtkPlayAppClass; @@ -63,20 +69,22 @@ typedef struct GtkWidget *prev_button, *next_button; GtkWidget *seekbar; GtkWidget *video_area; - GtkWidget *image_area; GtkWidget *volume_button; - GtkWidget *media_info_button; - GtkWidget *repeat_button; GtkWidget *fullscreen_button; GtkWidget *toolbar; + GtkWidget *toolbar_overlay; + GtkWidget *media_info_dialog; + GtkLabel *title_label; + GtkLabel *elapshed_label; + GtkLabel *remain_label; + GtkLabel *rate_label; GdkCursor *default_cursor; - gulong seekbar_value_changed_signal_id; - GdkPixbuf *image_pixbuf; gboolean playing; gboolean loop; gboolean fullscreen; - gboolean visual; gint toolbar_hide_timeout; + + GtkBuilder *toolbar_ui; } GtkPlay; typedef GtkApplicationWindowClass GtkPlayClass; @@ -88,7 +96,6 @@ enum PROP_0, PROP_LOOP, PROP_FULLSCREEN, - PROP_VISUAL, PROP_URIS, LAST_PROP @@ -124,8 +131,6 @@ enum SUBTITLE_INFO_END, }; -static void display_cover_art (GtkPlay * play, GstPlayerMediaInfo * media_info); - static void set_title (GtkPlay * play, const gchar * title) { @@ -136,6 +141,25 @@ set_title (GtkPlay * play, const gchar * title) } } +static GtkBuilder * +load_from_builder (const gchar * filename, gboolean register_sig_handler, + GtkPlay * play) +{ + GtkBuilder *builder; + + builder = gtk_builder_new_from_resource (filename); + if (builder == NULL) { + g_print ("ERROR: failed to load %s \n", filename); + return NULL; + } + + if (register_sig_handler) + gtk_builder_connect_signals (builder, play); + + return builder; +} + + static void delete_event_cb (GtkWidget * widget, GdkEvent * event, GtkPlay * play) { @@ -162,15 +186,47 @@ video_area_realize_cb (GtkWidget * widget, GtkPlay * play) } static void -play_pause_clicked_cb (GtkButton * button, GtkPlay * play) +gtk_play_set_rate (GtkPlay * play, gdouble step) +{ + gdouble val; + + val = gst_player_get_rate (play->player); + val += step; + if (val == 0.0) + val = step; + gst_player_set_rate (play->player, val); + + if (val == 1.0) + gtk_label_set_label (play->rate_label, NULL); + else { + gchar *data; + + data = g_strdup_printf ("%.2fx", val); + gtk_label_set_label (play->rate_label, data); + g_free (data); + } +} + +G_MODULE_EXPORT void +rewind_button_clicked_cb (GtkButton * button, GtkPlay * play) +{ + gtk_play_set_rate (play, -0.5); +} + +G_MODULE_EXPORT void +forward_button_clicked_cb (GtkButton * button, GtkPlay * play) +{ + gtk_play_set_rate (play, 0.5); +} + +G_MODULE_EXPORT void +play_pause_button_clicked_cb (GtkButton * button, GtkPlay * play) { GtkWidget *image; if (play->playing) { gst_player_pause (play->player); - image = - gtk_image_new_from_icon_name ("media-playback-start", - GTK_ICON_SIZE_BUTTON); + image = TOOLBAR_GET_OBJECT (play_image); gtk_button_set_image (GTK_BUTTON (play->play_pause_button), image); play->playing = FALSE; @@ -187,9 +243,7 @@ play_pause_clicked_cb (GtkButton * button, GtkPlay * play) GTK_WINDOW (play), GTK_APPLICATION_INHIBIT_IDLE, "Playing media"); gst_player_play (play->player); - image = - gtk_image_new_from_icon_name ("media-playback-pause", - GTK_ICON_SIZE_BUTTON); + image = TOOLBAR_GET_OBJECT (pause_image); gtk_button_set_image (GTK_BUTTON (play->play_pause_button), image); play->playing = TRUE; } @@ -199,13 +253,10 @@ static void play_current_uri (GtkPlay * play, GList * uri, const gchar * ext_suburi) { /* reset the button/widget state to default */ - if (play->image_pixbuf) - g_object_unref (play->image_pixbuf); - play->image_pixbuf = NULL; - gtk_widget_set_sensitive (play->media_info_button, FALSE); gtk_range_set_range (GTK_RANGE (play->seekbar), 0, 0); gtk_widget_set_sensitive (play->prev_button, g_list_previous (uri) != NULL); gtk_widget_set_sensitive (play->next_button, g_list_next (uri) != NULL); + gtk_label_set_label (play->rate_label, NULL); /* set uri or suburi */ if (ext_suburi) @@ -231,8 +282,8 @@ play_current_uri (GtkPlay * play, GList * uri, const gchar * ext_suburi) set_title (play, uri->data); } -static void -skip_prev_clicked_cb (GtkButton * button, GtkPlay * play) +G_MODULE_EXPORT void +prev_button_clicked_cb (GtkButton * button, GtkPlay * play) { GList *prev; @@ -388,8 +439,8 @@ open_file_clicked_cb (GtkWidget * unused, GtkPlay * play) } } -static void -skip_next_clicked_cb (GtkButton * button, GtkPlay * play) +G_MODULE_EXPORT void +next_button_clicked_cb (GtkButton * button, GtkPlay * play) { GList *next; @@ -519,51 +570,14 @@ stream_info_get_string (GstPlayerStreamInfo * stream, gint type, gboolean label) } } -static gboolean -is_current_stream (GtkPlay * play, GstPlayerStreamInfo * stream) -{ - gboolean ret = FALSE; - GstPlayerStreamInfo *s; - GstPlayerVideoInfo *video = gst_player_get_current_video_track (play->player); - GstPlayerAudioInfo *audio = gst_player_get_current_audio_track (play->player); - GstPlayerSubtitleInfo *sub = - gst_player_get_current_subtitle_track (play->player); - - if (GST_IS_PLAYER_VIDEO_INFO (stream)) - s = (GstPlayerStreamInfo *) video; - else if (GST_IS_PLAYER_AUDIO_INFO (stream)) - s = (GstPlayerStreamInfo *) audio; - else - s = (GstPlayerStreamInfo *) sub; - - if (s) - if (gst_player_stream_info_get_index (stream) == - gst_player_stream_info_get_index (s)) - ret = TRUE; - - if (audio) - g_object_unref (audio); - - if (video) - g_object_unref (video); - - if (sub) - g_object_unref (sub); - - return ret; -} - -static GtkTreeModel * -create_and_fill_model (GtkPlay * play, GstPlayerMediaInfo * info) +static void +fill_tree_model (GtkTreeStore * tree, GtkPlay * play, GstPlayerMediaInfo * info) { GList *l; guint count; - GtkTreeStore *tree; GtkTreeIter child, parent; count = 0; - tree = gtk_tree_store_new (COL_NUM, G_TYPE_STRING); - for (l = gst_player_media_info_get_stream_list (info); l != NULL; l = l->next) { gchar *buffer; gint i, start, end; @@ -581,8 +595,7 @@ create_and_fill_model (GtkPlay * play, GstPlayerMediaInfo * info) end = SUBTITLE_INFO_END; } - buffer = g_strdup_printf ("Stream %u %s", count++, - is_current_stream (play, stream) ? "(current)" : ""); + buffer = g_strdup_printf ("Stream %u", count++); gtk_tree_store_append (tree, &parent, NULL); gtk_tree_store_set (tree, &parent, COL_TEXT, buffer, -1); g_free (buffer); @@ -602,131 +615,74 @@ create_and_fill_model (GtkPlay * play, GstPlayerMediaInfo * info) } } } +} - return GTK_TREE_MODEL (tree); +G_MODULE_EXPORT void +media_info_dialog_button_clicked_cb (GtkButton * button, GtkPlay * play) +{ + gtk_widget_destroy (GTK_WIDGET (play->media_info_dialog)); + play->media_info_dialog = NULL; } -static GtkWidget * -create_view_and_model (GtkPlay * play, GstPlayerMediaInfo * info) +static void +media_info_dialog (GtkPlay * play, GstPlayerMediaInfo * media_info) { + GtkBuilder *dialog_ui; GtkWidget *view; + GtkTreeStore *tree; GtkTreeModel *model; GtkTreeViewColumn *col; GtkCellRenderer *renderer; - view = gtk_tree_view_new (); - col = gtk_tree_view_column_new (); - gtk_tree_view_append_column (GTK_TREE_VIEW (view), col); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE); + dialog_ui = load_from_builder ("/ui/media_info_dialog.ui", TRUE, play); + if (!dialog_ui) + return; + + play->media_info_dialog = + (GtkWidget *) gtk_builder_get_object (dialog_ui, "media_info_dialog"); + gtk_window_set_transient_for (GTK_WINDOW (play->media_info_dialog), + GTK_WINDOW (play)); + + view = (GtkWidget *) gtk_builder_get_object (dialog_ui, "view"); + col = (GtkTreeViewColumn *) gtk_builder_get_object (dialog_ui, "col"); + /* TODO: use glade cell renderer (not working for me) */ renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (col, renderer, TRUE); gtk_tree_view_column_add_attribute (col, renderer, "text", COL_TEXT); - model = create_and_fill_model (play, info); - gtk_tree_view_set_model (GTK_TREE_VIEW (view), model); - g_object_unref (model); - - return view; -} + tree = (GtkTreeStore *) gtk_builder_get_object (dialog_ui, "tree"); + fill_tree_model (tree, play, media_info); -static void -delete_media_info_window (GtkWidget * button, GtkWindow * window) -{ - gtk_window_close (window); -} - -static void -create_media_info_window (GtkPlay * play, GstPlayerMediaInfo * info) -{ - GtkWidget *sw; - GtkWidget *vbox; - GtkWidget *label; - GtkWidget *view; - GtkWidget *hbox; - GtkWidget *uri; - GtkWidget *loc; - GtkTextIter iter; - GtkWidget *window; - GtkTextBuffer *buffer; - GtkWidget *hbox_close; - GtkWidget *button_close; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (window), "Media information"); - gtk_window_set_default_size (GTK_WINDOW (window), 550, 450); - gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER); - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (play)); - - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8); - gtk_container_add (GTK_CONTAINER (window), vbox); - - label = gtk_label_new (NULL); - gtk_label_set_markup (GTK_LABEL (label), - "Information about all the streams contains in your media. \n" - "Current selected streams are marked as (current)."); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 2); - - sw = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), - GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0); - - view = create_view_and_model (play, info); - gtk_container_add (GTK_CONTAINER (sw), view); g_signal_connect (view, "realize", G_CALLBACK (gtk_tree_view_expand_all), NULL); + + gtk_widget_set_size_request (play->media_info_dialog, 550, 450); - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2); - - loc = gtk_label_new ("Location : "); - gtk_box_pack_start (GTK_BOX (hbox), loc, FALSE, FALSE, 2); - - buffer = gtk_text_buffer_new (NULL); - gtk_text_buffer_get_start_iter (buffer, &iter); - gtk_text_buffer_insert (buffer, &iter, - gst_player_media_info_get_uri (info), -1); - uri = gtk_text_view_new_with_buffer (buffer); - gtk_box_pack_start (GTK_BOX (hbox), uri, FALSE, FALSE, 2); - gtk_text_view_set_editable (GTK_TEXT_VIEW (uri), FALSE); - g_object_unref (buffer); - - hbox_close = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8); - gtk_box_pack_start (GTK_BOX (vbox), hbox_close, FALSE, FALSE, 2); - button_close = gtk_button_new_with_label (" Close "); - g_signal_connect (button_close, "clicked", - G_CALLBACK (delete_media_info_window), window); - gtk_box_pack_end (GTK_BOX (hbox_close), button_close, FALSE, FALSE, 3); - - gtk_widget_show_all (window); + gtk_widget_show_all (play->media_info_dialog); + gtk_dialog_run (GTK_DIALOG (play->media_info_dialog)); } static void media_info_clicked_cb (GtkButton * button, GtkPlay * play) { - GstPlayerMediaInfo *info; + GstPlayerMediaInfo *media_info; - info = gst_player_get_media_info (play->player); - if (!info) + media_info = gst_player_get_media_info (play->player); + if (!media_info) return; - create_media_info_window (play, info); - - g_object_unref (info); + media_info_dialog (play, media_info); + g_object_unref (media_info); } static gboolean -toolbar_hide_func (GtkPlay * play) +toolbar_hide_cb (GtkPlay * play) { GdkCursor *cursor; - /* TODO: add some animation while hiding the toolbar. */ + /* hide mouse pointer and toolbar */ gtk_widget_hide (play->toolbar); - - /* hide the mouse pointer */ cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (play)), GDK_BLANK_CURSOR); @@ -739,43 +695,59 @@ toolbar_hide_func (GtkPlay * play) } static void -fullscreen_toggle_cb (GtkToggleButton * widget, GtkPlay * play) +toolbar_show (GtkPlay * play) +{ + /* if timer is running then kill it */ + if (play->toolbar_hide_timeout) { + g_source_remove (play->toolbar_hide_timeout); + play->toolbar_hide_timeout = 0; + } + + /* show toolbar and mouse pointer */ + gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET + (play->video_area)), play->default_cursor); + gtk_widget_show (play->toolbar); +} + +static void +start_toolbar_hide_timer (GtkPlay * play) +{ + /* hide toolbar only if its playing */ + if (!play->playing) + return; + + /* start timer to hide toolbar */ + if (play->toolbar_hide_timeout) + g_source_remove (play->toolbar_hide_timeout); + play->toolbar_hide_timeout = g_timeout_add_seconds (5, + (GSourceFunc) toolbar_hide_cb, play); +} + +G_MODULE_EXPORT void +fullscreen_button_toggled_cb (GtkToggleButton * widget, GtkPlay * play) { GtkWidget *image; if (gtk_toggle_button_get_active (widget)) { - image = gtk_image_new_from_icon_name ("view-restore", GTK_ICON_SIZE_BUTTON); + image = TOOLBAR_GET_OBJECT (restore_image); gtk_window_fullscreen (GTK_WINDOW (play)); gtk_button_set_image (GTK_BUTTON (play->fullscreen_button), image); - - /* start timer to hide toolbar */ - if (play->toolbar_hide_timeout) - g_source_remove (play->toolbar_hide_timeout); - play->toolbar_hide_timeout = g_timeout_add_seconds (5, - (GSourceFunc) toolbar_hide_func, play); } else { - /* if toolbar hide timer is running then kill it */ - if (play->toolbar_hide_timeout) { - g_source_remove (play->toolbar_hide_timeout); - play->toolbar_hide_timeout = 0; - } - - image = gtk_image_new_from_icon_name ("view-fullscreen", - GTK_ICON_SIZE_BUTTON); + image = TOOLBAR_GET_OBJECT (fullscreen_image); gtk_window_unfullscreen (GTK_WINDOW (play)); gtk_button_set_image (GTK_BUTTON (play->fullscreen_button), image); } } -static void +G_MODULE_EXPORT void seekbar_value_changed_cb (GtkRange * range, GtkPlay * play) { gdouble value = gtk_range_get_value (GTK_RANGE (play->seekbar)); gst_player_seek (play->player, gst_util_uint64_scale (value, GST_SECOND, 1)); } -void -volume_changed_cb (GtkScaleButton * button, gdouble value, GtkPlay * play) +G_MODULE_EXPORT void +volume_button_value_changed_cb (GtkScaleButton * button, gdouble value, GtkPlay * play) { gst_player_set_volume (play->player, value); } @@ -860,7 +832,6 @@ disable_track (GtkPlay * play, GType type) { if (type == GST_TYPE_PLAYER_VIDEO_INFO) { gst_player_set_video_track_enabled (play->player, FALSE); - display_cover_art (play, NULL); /* display cover art */ } else if (type == GST_TYPE_PLAYER_AUDIO_INFO) gst_player_set_audio_track_enabled (play->player, FALSE); else @@ -873,11 +844,6 @@ change_track (GtkPlay * play, gint index, GType type) if (type == GST_TYPE_PLAYER_VIDEO_INFO) { gst_player_set_video_track (play->player, index); gst_player_set_video_track_enabled (play->player, TRUE); - /* if video area widget is not visible then make it visible */ - if (!gtk_widget_is_visible (play->video_area)) { - gtk_widget_hide (play->image_area); - gtk_widget_show (play->video_area); - } } else if (type == GST_TYPE_PLAYER_AUDIO_INFO) { gst_player_set_audio_track (play->player, index); gst_player_set_audio_track_enabled (play->player, TRUE); @@ -912,18 +878,9 @@ visualization_changed_cb (GtkWidget * widget, GtkPlay * play) gchar *name; if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) { - - /* video_area is window-id is shared with playbin hence - * video_area widget will be used by visualization elements to - * render the visuals. If visualization is enabled then hide - * image widget and show video widget and similiarly when visualization - * is disabled then hide video widget and show imag widget. - */ name = g_object_get_data (G_OBJECT (widget), "name"); if (g_strcmp0 (name, "disable") == 0) { gst_player_set_visualization_enabled (play->player, FALSE); - gtk_widget_hide (play->video_area); - gtk_widget_show (play->image_area); } else { const gchar *vis_name; @@ -932,8 +889,6 @@ visualization_changed_cb (GtkWidget * widget, GtkPlay * play) if (!(vis_name = gst_player_get_current_visualization (play->player))) { gst_player_set_visualization_enabled (play->player, TRUE); } - gtk_widget_hide (play->image_area); - gtk_widget_show (play->video_area); } } } @@ -1058,41 +1013,6 @@ player_set_rate_cb (GtkSpinButton * button, GtkPlay * play) } static void -player_speed_clicked_cb (GtkButton * button, GtkPlay * play) -{ - GtkWidget *box; - GtkWidget *label; - GtkWidget *dialog; - GtkWidget *content; - GtkWidget *rate_spinbutton; - - dialog = - gtk_dialog_new_with_buttons ("Playback speed control", GTK_WINDOW (play), - GTK_DIALOG_DESTROY_WITH_PARENT, "_Close", GTK_RESPONSE_CLOSE, NULL); - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (play)); - - content = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1); - gtk_box_pack_start (GTK_BOX (content), box, TRUE, TRUE, 0); - - label = gtk_label_new ("Playback rate"); - rate_spinbutton = gtk_spin_button_new_with_range (-64, 64, 0.1); - gtk_spin_button_set_digits (GTK_SPIN_BUTTON (rate_spinbutton), 2); - gtk_spin_button_set_value (GTK_SPIN_BUTTON (rate_spinbutton), - gst_player_get_rate (play->player)); - - gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 2); - gtk_box_pack_start (GTK_BOX (box), rate_spinbutton, TRUE, TRUE, 2); - g_signal_connect (rate_spinbutton, "value-changed", - G_CALLBACK (player_set_rate_cb), play); - - gtk_widget_show_all (dialog); - gtk_dialog_run (GTK_DIALOG (dialog)); - - gtk_widget_destroy (dialog); -} - -static void player_quit_clicked_cb (GtkButton * button, GtkPlay * play) { gtk_widget_destroy (GTK_WIDGET (play)); @@ -1113,7 +1033,6 @@ gtk_player_popup_menu_create (GtkPlay * play, GdkEventButton * event) GtkWidget *submenu; GtkWidget *vis; GtkWidget *cb; - GtkWidget *speed; GstPlayerMediaInfo *media_info; menu = gtk_menu_new (); @@ -1127,7 +1046,6 @@ gtk_player_popup_menu_create (GtkPlay * play, GdkEventButton * event) quit = gtk_menu_item_new_with_label ("Quit"); vis = gtk_menu_item_new_with_label ("Visualization"); cb = gtk_menu_item_new_with_label ("Color Balance"); - speed = gtk_menu_item_new_with_label ("Playback Speed"); media_info = gst_player_get_media_info (play->player); @@ -1182,13 +1100,11 @@ gtk_player_popup_menu_create (GtkPlay * play, GdkEventButton * event) g_signal_connect (G_OBJECT (cb), "activate", G_CALLBACK (color_balance_clicked_cb), play); g_signal_connect (G_OBJECT (next), "activate", - G_CALLBACK (skip_next_clicked_cb), play); + G_CALLBACK (next_button_clicked_cb), play); g_signal_connect (G_OBJECT (prev), "activate", - G_CALLBACK (skip_prev_clicked_cb), play); + G_CALLBACK (prev_button_clicked_cb), play); g_signal_connect (G_OBJECT (info), "activate", G_CALLBACK (media_info_clicked_cb), play); - g_signal_connect (G_OBJECT (speed), "activate", - G_CALLBACK (player_speed_clicked_cb), play); g_signal_connect (G_OBJECT (quit), "activate", G_CALLBACK (player_quit_clicked_cb), play); @@ -1201,7 +1117,6 @@ gtk_player_popup_menu_create (GtkPlay * play, GdkEventButton * event) gtk_menu_shell_append (GTK_MENU_SHELL (menu), sub); gtk_menu_shell_append (GTK_MENU_SHELL (menu), info); gtk_menu_shell_append (GTK_MENU_SHELL (menu), cb); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), speed); gtk_menu_shell_append (GTK_MENU_SHELL (menu), quit); gtk_widget_show_all (menu); @@ -1233,68 +1148,108 @@ mouse_button_pressed_cb (GtkWidget * unused, GdkEventButton * event, } static gboolean -image_area_draw_cb (GtkWidget * widget, cairo_t * cr, GtkPlay * play) -{ - if (play->image_pixbuf) { - gint width, height; - gint pix_width, pix_height; - gint x = 0, y = 0; - gdouble scalex = 0.0, scaley = 0.0; - - width = gtk_widget_get_allocated_width (widget); - height = gtk_widget_get_allocated_height (widget); - pix_width = gdk_pixbuf_get_width (play->image_pixbuf); - pix_height = gdk_pixbuf_get_height (play->image_pixbuf); - - /* if image is bigger than widget then scale down otherwise center it. */ - if (width <= pix_width) - scalex = (gdouble) width / (gdouble) pix_width; - else - x = (width - pix_width) / 2; - if (height <= pix_height) - scaley = (gdouble) height / (gdouble) pix_height; - else - y = (height - pix_height) / 2; +video_area_leave_notify_cb (GtkWidget * widget, GdkEvent * event, GtkPlay * play) +{ + start_toolbar_hide_timer (play); - /* fill background with black */ - cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); - cairo_rectangle (cr, 0, 0, width, height); - cairo_fill (cr); + return TRUE; +} - if (scalex > 0.0 && scaley > 0.0) - cairo_scale (cr, scalex, scaley); +static gboolean +video_area_toolbar_show_cb (GtkWidget * widget, GdkEvent * event, GtkPlay * play) +{ + toolbar_show (play); - gdk_cairo_set_source_pixbuf (cr, play->image_pixbuf, x, y); - cairo_paint (cr); - } else { - /* fill background with black */ - cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); - cairo_paint (cr); - } + start_toolbar_hide_timer (play); - return FALSE; + return TRUE; } static gboolean -gtk_show_toolbar_cb (GtkWidget * widget, GdkEvent * event, GtkPlay * play) +overlay_leave_notify_event_cb (GtkWidget * widget, GdkEvent * event, GtkPlay * play) { - if (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON (play->fullscreen_button))) { + start_toolbar_hide_timer (play); - /* if timer is running then kill it */ - if (play->toolbar_hide_timeout) { - g_source_remove (play->toolbar_hide_timeout); - play->toolbar_hide_timeout = 0; - } + return TRUE; +} + +static gboolean +overlay_enter_notify_event_cb (GtkWidget * widget, GdkEvent * event, GtkPlay * play) +{ + toolbar_show (play); + + return TRUE; +} + +static void +apply_css (GtkWidget *widget, GtkStyleProvider *provider) +{ + gtk_style_context_add_provider (gtk_widget_get_style_context (widget), + provider, G_MAXUINT); + if (GTK_IS_CONTAINER (widget)) { + gtk_container_forall (GTK_CONTAINER (widget), + (GtkCallback) apply_css, provider); + } +} + +static void +gtk_widget_apply_css (GtkWidget * widget, const gchar * filename) +{ + GBytes *bytes; + gsize data_size; + const guint8 *data; + GError *err = NULL; + GtkStyleProvider *provider; - /* show mouse pointer */ - gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET - (play->video_area)), play->default_cursor); + if (widget == NULL) + return; - gtk_widget_show (play->toolbar); - play->toolbar_hide_timeout = g_timeout_add_seconds (5, - (GSourceFunc) toolbar_hide_func, play); + provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ()); + bytes = g_resources_lookup_data (filename, 0, &err); + if (err) { + g_print ("ERROR: failed to apply css %s '%s' \n", filename, err->message); + return; } + data = g_bytes_get_data (bytes, &data_size); + gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider), + (gchar *)data, data_size, NULL); + g_bytes_unref (bytes); + + apply_css (widget, provider); +} + +static gboolean +get_child_position (GtkOverlay * overlay, GtkWidget * widget, + GtkAllocation * alloc, GtkPlay * play) +{ + GtkRequisition req; + GtkWidget *child; + GtkAllocation main_alloc; + gint x, y; + GtkWidget * relative = play->video_area; + + child = gtk_bin_get_child (GTK_BIN (overlay)); + gtk_widget_translate_coordinates (relative, child, 0, 0, &x, &y); + main_alloc.x = x; + main_alloc.y = y; + main_alloc.width = gtk_widget_get_allocated_width (relative); + main_alloc.height = gtk_widget_get_allocated_height (relative); + + gtk_widget_get_preferred_size (widget, NULL, &req); + + alloc->x = (main_alloc.width - req.width) / 2; + if (alloc->x < 0) + alloc->x = 0; + alloc->width = MIN (main_alloc.width, req.width); + if (gtk_widget_get_halign (widget) == GTK_ALIGN_END) + alloc->x += main_alloc.width - req.width; + + alloc->y = main_alloc.height - req.height - 20; + if (alloc->y < 0) + alloc->y = 0; + alloc->height = MIN (main_alloc.height, req.height); + if (gtk_widget_get_valign (widget) == GTK_ALIGN_END) + alloc->y += main_alloc.height - req.height; return TRUE; } @@ -1303,7 +1258,7 @@ static void create_ui (GtkPlay * play) { GtkWidget *image; - GtkWidget *controls, *main_hbox, *main_vbox; + GtkWidget *main_hbox, *main_vbox; GstElement *playbin, *gtk_sink; gtk_window_set_default_size (GTK_WINDOW (play), 640, 480); @@ -1336,140 +1291,123 @@ create_ui (GtkPlay * play) g_signal_connect (play->video_area, "realize", G_CALLBACK (video_area_realize_cb), play); } - g_signal_connect (play->video_area, "button-press-event", - G_CALLBACK (mouse_button_pressed_cb), play); - g_signal_connect (play->video_area, "motion-notify-event", - G_CALLBACK (gtk_show_toolbar_cb), play); - g_signal_connect (play->video_area, "scroll-event", - G_CALLBACK (gtk_show_toolbar_cb), play); gtk_widget_set_events (play->video_area, GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_ENTER_NOTIFY_MASK); - - play->image_area = gtk_drawing_area_new (); - g_signal_connect (play->image_area, "button-press-event", + g_signal_connect (play->video_area, "motion-notify-event", + G_CALLBACK (video_area_toolbar_show_cb), play); + g_signal_connect (play->video_area, "scroll-event", + G_CALLBACK (video_area_toolbar_show_cb), play); + g_signal_connect (play->video_area, "button-press-event", G_CALLBACK (mouse_button_pressed_cb), play); - g_signal_connect (play->image_area, "draw", - G_CALLBACK (image_area_draw_cb), play); - g_signal_connect (play->image_area, "motion-notify-event", - G_CALLBACK (gtk_show_toolbar_cb), play); - g_signal_connect (play->image_area, "scroll-event", - G_CALLBACK (gtk_show_toolbar_cb), play); - gtk_widget_set_events (play->image_area, GDK_EXPOSURE_MASK - | GDK_LEAVE_NOTIFY_MASK - | GDK_BUTTON_PRESS_MASK - | GDK_POINTER_MOTION_MASK - | GDK_POINTER_MOTION_HINT_MASK | GDK_ENTER_NOTIFY_MASK); + g_signal_connect (play->video_area, "leave-notify-event", + G_CALLBACK (video_area_leave_notify_cb), play); - /* Unified play/pause button */ - play->play_pause_button = - gtk_button_new_from_icon_name ("media-playback-pause", - GTK_ICON_SIZE_BUTTON); - g_signal_connect (G_OBJECT (play->play_pause_button), "clicked", - G_CALLBACK (play_pause_clicked_cb), play); + /* load toolbar UI */ + play->toolbar_ui = load_from_builder ("/ui/toolbar.ui", TRUE, play); + if (!play->toolbar_ui) + return; - play->seekbar = - gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, 100, 1); - gtk_scale_set_draw_value (GTK_SCALE (play->seekbar), 0); - gtk_range_set_range (GTK_RANGE (play->seekbar), 0, 0); - play->seekbar_value_changed_signal_id = - g_signal_connect (G_OBJECT (play->seekbar), "value-changed", - G_CALLBACK (seekbar_value_changed_cb), play); - - /* Skip backward button */ - play->prev_button = - gtk_button_new_from_icon_name ("media-skip-backward", - GTK_ICON_SIZE_BUTTON); - g_signal_connect (G_OBJECT (play->prev_button), "clicked", - G_CALLBACK (skip_prev_clicked_cb), play); - gtk_widget_set_sensitive (play->prev_button, FALSE); - - /* Skip forward button */ - play->next_button = - gtk_button_new_from_icon_name ("media-skip-forward", - GTK_ICON_SIZE_BUTTON); - g_signal_connect (G_OBJECT (play->next_button), "clicked", - G_CALLBACK (skip_next_clicked_cb), play); - gtk_widget_set_sensitive (play->next_button, FALSE); - - /* Playlist repeat button */ - play->repeat_button = gtk_toggle_button_new (); - image = gtk_image_new_from_icon_name ("media-playlist-repeat", - GTK_ICON_SIZE_BUTTON); - gtk_button_set_image (GTK_BUTTON (play->repeat_button), image); - if (play->loop) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (play->repeat_button), - TRUE); - - /* Volume control button */ - play->volume_button = gtk_volume_button_new (); - gtk_scale_button_set_value (GTK_SCALE_BUTTON (play->volume_button), - gst_player_get_volume (play->player)); - g_signal_connect (G_OBJECT (play->volume_button), "value-changed", - G_CALLBACK (volume_changed_cb), play); - - /* media information button */ - play->media_info_button = gtk_button_new_from_icon_name ("dialog-information", - GTK_ICON_SIZE_BUTTON); - g_signal_connect (G_OBJECT (play->media_info_button), "clicked", - G_CALLBACK (media_info_clicked_cb), play); - gtk_widget_set_sensitive (play->media_info_button, FALSE); - - /* Full screen button */ - play->fullscreen_button = gtk_toggle_button_new (); - image = gtk_image_new_from_icon_name ("view-fullscreen", - GTK_ICON_SIZE_BUTTON); - gtk_button_set_image (GTK_BUTTON (play->fullscreen_button), image); - g_signal_connect (G_OBJECT (play->fullscreen_button), "toggled", - G_CALLBACK (fullscreen_toggle_cb), play); - if (play->fullscreen) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (play->fullscreen_button), - TRUE); - - play->toolbar = controls = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); - gtk_box_pack_start (GTK_BOX (controls), play->prev_button, FALSE, FALSE, 2); - gtk_box_pack_start (GTK_BOX (controls), play->play_pause_button, FALSE, - FALSE, 2); - gtk_box_pack_start (GTK_BOX (controls), play->next_button, FALSE, FALSE, 2); - gtk_box_pack_start (GTK_BOX (controls), play->repeat_button, FALSE, FALSE, 2); - gtk_box_pack_start (GTK_BOX (controls), play->seekbar, TRUE, TRUE, 2); - gtk_box_pack_start (GTK_BOX (controls), play->volume_button, FALSE, FALSE, 2); - gtk_box_pack_start (GTK_BOX (controls), play->media_info_button, - FALSE, FALSE, 2); - gtk_box_pack_start (GTK_BOX (controls), play->fullscreen_button, - FALSE, FALSE, 2); + play->toolbar = TOOLBAR_GET_OBJECT (toolbar); + play->play_pause_button = TOOLBAR_GET_OBJECT (play_pause_button); + play->seekbar = TOOLBAR_GET_OBJECT (seekbar); + play->next_button = TOOLBAR_GET_OBJECT (next_button); + play->prev_button = TOOLBAR_GET_OBJECT (prev_button); + play->fullscreen_button = TOOLBAR_GET_OBJECT (fullscreen_button); + play->volume_button = TOOLBAR_GET_OBJECT (volume_button); + play->elapshed_label = TOOLBAR_GET_LABEL (elapshed_time); + play->remain_label = TOOLBAR_GET_LABEL (remain_time); + play->rate_label = TOOLBAR_GET_LABEL (rate_label); + play->title_label = TOOLBAR_GET_LABEL (title_label); main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (main_hbox), play->video_area, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (main_hbox), play->image_area, TRUE, TRUE, 0); - main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), main_hbox, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), controls, FALSE, FALSE, 0); - gtk_container_add (GTK_CONTAINER (play), main_vbox); + /* set minimum window size */ + gtk_widget_set_size_request (main_hbox, 320, 240); + + /* set the toolbar size */ + gtk_widget_set_size_request (play->toolbar, 500, 50); + + play->toolbar_overlay = gtk_overlay_new (); + gtk_overlay_add_overlay (GTK_OVERLAY (play->toolbar_overlay), play->toolbar); + gtk_container_add (GTK_CONTAINER (play->toolbar_overlay), main_hbox); + gtk_container_add (GTK_CONTAINER (play), play->toolbar_overlay); + gtk_widget_set_events (play->toolbar_overlay, GDK_EXPOSURE_MASK + | GDK_LEAVE_NOTIFY_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK | GDK_ENTER_NOTIFY_MASK); + + g_signal_connect (play->toolbar_overlay, "get-child-position", + G_CALLBACK (get_child_position), play); + g_signal_connect (play->toolbar_overlay, "leave-notify-event", + G_CALLBACK (overlay_leave_notify_event_cb), play); + g_signal_connect (play->toolbar_overlay, "enter-notify-event", + G_CALLBACK (overlay_enter_notify_event_cb), play); + + /* apply css on widgets */ + gtk_widget_apply_css (play->toolbar, "/css/toolbar.css"); if (!gtk_sink) gtk_widget_realize (play->video_area); gtk_widget_hide (play->video_area); + + /* start toolbar autohide timer */ + start_toolbar_hide_timer (play); + + /* check if we need to enable fullscreen */ + if (play->fullscreen) + gtk_toggle_button_set_active + (GTK_TOGGLE_BUTTON (play->fullscreen_button), TRUE); + + /* enable visualization (by default laybin uses goom) */ + /* if visualization is enabled then use the first element */ + gst_player_set_visualization_enabled (play->player, TRUE); } static void duration_changed_cb (GstPlayer * unused, GstClockTime duration, GtkPlay * play) { - gtk_range_set_range (GTK_RANGE (play->seekbar), 0, + gtk_range_set_range (GTK_RANGE (play->seekbar), 0.0, (gdouble) duration / GST_SECOND); } static void +update_position_label (GtkLabel * label, guint64 seconds) +{ + gchar *data; + gint hrs, mins; + + hrs = seconds / 3600; + seconds -= hrs * 3600; + mins = seconds / 60; + seconds -= mins * 60; + + if (hrs) + data = g_strdup_printf ("%02d:%02d", hrs, mins); + else + data = g_strdup_printf ("%02d:%02ld", mins, seconds); + + gtk_label_set_label (label, data); + g_free (data); +} + +static void position_updated_cb (GstPlayer * unused, GstClockTime position, GtkPlay * play) { - g_signal_handler_block (play->seekbar, play->seekbar_value_changed_signal_id); + g_signal_handlers_block_by_func (play->seekbar, + seekbar_value_changed_cb, play); gtk_range_set_value (GTK_RANGE (play->seekbar), (gdouble) position / GST_SECOND); - g_signal_handler_unblock (play->seekbar, - play->seekbar_value_changed_signal_id); + update_position_label (play->elapshed_label, position / GST_SECOND); + update_position_label (play->remain_label, + GST_CLOCK_DIFF (position, gst_player_get_duration (play->player)) / + GST_SECOND); + g_signal_handlers_unblock_by_func (play->seekbar, + seekbar_value_changed_cb, play); } static void @@ -1479,8 +1417,7 @@ eos_cb (GstPlayer * unused, GtkPlay * play) GList *next = NULL; next = g_list_next (play->current_uri); - if (!next && gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON (play->repeat_button))) + if (!next && play->loop) next = g_list_first (play->uris); if (next) { @@ -1489,9 +1426,7 @@ eos_cb (GstPlayer * unused, GtkPlay * play) GtkWidget *image; gst_player_pause (play->player); - image = - gtk_image_new_from_icon_name ("media-playback-start", - GTK_ICON_SIZE_BUTTON); + image = TOOLBAR_GET_OBJECT (play_image); gtk_button_set_image (GTK_BUTTON (play->play_pause_button), image); play->playing = FALSE; if (play->inhibit_cookie) @@ -1502,31 +1437,23 @@ eos_cb (GstPlayer * unused, GtkPlay * play) } } -static gboolean -_has_active_stream (GtkPlay * play, void *(*func) (GstPlayer * player)) -{ - void *obj; - - obj = func (play->player); - if (obj) { - g_object_unref (obj); - return TRUE; - } - - return FALSE; -} - static GdkPixbuf * -gst_sample_to_pixbuf (GtkPlay * play, GstSample * sample) +gtk_play_get_cover_image (GstPlayerMediaInfo * media_info) { - GdkPixbufLoader *loader; - GdkPixbuf *pixbuf = NULL; - GError *err = NULL; + GstSample *sample; GstMapInfo info; GstBuffer *buffer; + GError *err = NULL; + GdkPixbufLoader *loader; + GdkPixbuf *pixbuf = NULL; const GstStructure *caps_struct; GstTagImageType type = GST_TAG_IMAGE_TYPE_UNDEFINED; + /* get image sample buffer from media */ + sample = gst_player_media_info_get_image_sample (media_info); + if (!sample) + return NULL; + buffer = gst_sample_get_buffer (sample); caps_struct = gst_sample_get_info (sample); @@ -1566,84 +1493,27 @@ gst_sample_to_pixbuf (GtkPlay * play, GstSample * sample) return pixbuf; } - -static void -display_cover_art (GtkPlay * play, GstPlayerMediaInfo * media_info) -{ - GstSample *sample; - GstPlayerMediaInfo *temp_media_info = NULL; - - /* hide the video widget and show image widget */ - gtk_widget_hide (play->video_area); - gtk_widget_show (play->image_area); - - /* if media information is not passed then get it from player */ - if (!media_info) - temp_media_info = media_info = gst_player_get_media_info (play->player); - - sample = gst_player_media_info_get_image_sample (media_info); - if (!sample) - goto cleanup; - - if (play->image_pixbuf) - g_object_unref (play->image_pixbuf); - - play->image_pixbuf = gst_sample_to_pixbuf (play, sample); - -cleanup: - gtk_widget_queue_draw (play->image_area); /* send expose event to widget */ - - if (temp_media_info) - g_object_unref (temp_media_info); -} - -static gboolean -has_active_stream (GtkPlay * play, GType type) -{ - if (type == GST_TYPE_PLAYER_VIDEO_INFO) - return _has_active_stream (play, - (void *) gst_player_get_current_video_track); - else if (type == GST_TYPE_PLAYER_AUDIO_INFO) - return _has_active_stream (play, - (void *) gst_player_get_current_audio_track); - else - return _has_active_stream (play, - (void *) gst_player_get_current_subtitle_track); -} - static void media_info_updated_cb (GstPlayer * player, GstPlayerMediaInfo * media_info, GtkPlay * play) { - if (!gtk_widget_is_sensitive (play->media_info_button)) { - const gchar *title; - const gchar *vis; + const gchar *title; + GdkPixbuf *pixbuf; - title = gst_player_media_info_get_title (media_info); - if (title) - set_title (play, title); + title = gst_player_media_info_get_title (media_info); + if (!title) + title = g_path_get_basename (gst_player_media_info_get_uri (media_info)); - gtk_widget_set_sensitive (play->media_info_button, TRUE); + pixbuf = gtk_play_get_cover_image (media_info); - /* if we have active video stream then hide image widget - * and show video widget otherwise show the cover art. - */ - if (has_active_stream (play, GST_TYPE_PLAYER_VIDEO_INFO)) { - gtk_widget_hide (play->image_area); - gtk_widget_show (play->video_area); - } else { - display_cover_art (play, media_info); - } + if (title) { + gtk_label_set_label (play->title_label, title); + set_title (play, title); + } - /* if we have audio only stream and visualization is enabled - * then show video widget. - */ - vis = gst_player_get_current_visualization (play->player); - if (!has_active_stream (play, GST_TYPE_PLAYER_VIDEO_INFO) && - has_active_stream (play, GST_TYPE_PLAYER_AUDIO_INFO) && vis) { - gtk_widget_show (play->video_area); - gtk_widget_hide (play->image_area); - } + if (pixbuf) { + gtk_window_set_icon (GTK_WINDOW (play), pixbuf); + g_object_unref (pixbuf); } } @@ -1657,11 +1527,11 @@ player_volume_changed_cb (GstPlayer * player, GtkPlay * play) if (fabs (cur_val - new_val) > 0.001) { g_signal_handlers_block_by_func (play->volume_button, - volume_changed_cb, play); + volume_button_value_changed_cb, play); gtk_scale_button_set_value (GTK_SCALE_BUTTON (play->volume_button), new_val); g_signal_handlers_unblock_by_func (play->volume_button, - volume_changed_cb, play); + volume_button_value_changed_cb, play); } } @@ -1678,9 +1548,6 @@ gtk_play_set_property (GObject * object, guint prop_id, const GValue * value, case PROP_FULLSCREEN: self->fullscreen = g_value_get_boolean (value); break; - case PROP_VISUAL: - self->visual = g_value_get_boolean (value); - break; case PROP_URIS: self->uris = g_value_get_pointer (value); break; @@ -1725,19 +1592,6 @@ gtk_play_constructor (GType type, guint n_construct_params, create_ui (self); - /* if visualization is enabled then use the first element */ - if (self->visual) { - GstPlayerVisualization **viss; - viss = gst_player_visualizations_get (); - - if (viss && *viss) { - gst_player_set_visualization (self->player, (*viss)->name); - gst_player_set_visualization_enabled (self->player, TRUE); - } - if (viss) - gst_player_visualizations_free (viss); - } - g_signal_connect (self->player, "position-updated", G_CALLBACK (position_updated_cb), self); g_signal_connect (self->player, "duration-changed", @@ -1801,9 +1655,6 @@ gtk_play_class_init (GtkPlayClass * klass) g_param_spec_boolean ("fullscreen", "Fullscreen", "Fullscreen mode", FALSE, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - gtk_play_properties[PROP_VISUAL] = - g_param_spec_boolean ("visual", "Visual", "Use Visualizations", FALSE, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); gtk_play_properties[PROP_URIS] = g_param_spec_pointer ("uris", "URIs", "URIs to play", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); @@ -1819,13 +1670,12 @@ gtk_play_app_command_line (GApplication * application, GVariantDict *options; GtkPlay *play; GList *uris = NULL; - gboolean loop = FALSE, visual = FALSE, fullscreen = FALSE; + gboolean loop = FALSE, fullscreen = FALSE; gchar **uris_array = NULL; options = g_application_command_line_get_options_dict (command_line); g_variant_dict_lookup (options, "loop", "b", &loop); - g_variant_dict_lookup (options, "visual", "b", &visual); g_variant_dict_lookup (options, "fullscreen", "b", &fullscreen); g_variant_dict_lookup (options, G_OPTION_REMAINING, "^a&ay", &uris_array); @@ -1850,7 +1700,7 @@ gtk_play_app_command_line (GApplication * application, play = g_object_new (gtk_play_get_type (), "loop", loop, "fullscreen", - fullscreen, "visual", visual, "uris", uris, NULL); + fullscreen, "uris", uris, NULL); gtk_widget_show_all (GTK_WIDGET (play)); return @@ -1881,8 +1731,6 @@ gtk_play_app_new (void) {"loop", 'l', 0, G_OPTION_ARG_NONE, NULL, "Repeat all"}, {"fullscreen", 'f', 0, G_OPTION_ARG_NONE, NULL, "Show the player in fullscreen"}, - {"visual", 'v', 0, G_OPTION_ARG_NONE, NULL, - "Show visualization when there is no video stream"}, {NULL} }; diff --git a/playback/player/gtk/resources/gresources.xml b/playback/player/gtk/resources/gresources.xml new file mode 100644 index 0000000..90b3c43 --- /dev/null +++ b/playback/player/gtk/resources/gresources.xml @@ -0,0 +1,11 @@ +<? xml version="1.0" encoding="UTF-8" ?> +<gresources> + <gresource prefix="/ui"> + <file>toolbar.ui</file> + <file>media_info_dialog.ui</file> + </gresource> + <gresource prefix="/css"> + <file>toolbar.css</file> + </gresource> +</gresources> + diff --git a/playback/player/gtk/resources/media_info_dialog.ui b/playback/player/gtk/resources/media_info_dialog.ui new file mode 100644 index 0000000..fe25cf1 --- /dev/null +++ b/playback/player/gtk/resources/media_info_dialog.ui @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.18.3 --> +<interface> + <requires lib="gtk+" version="3.10"/> + <object class="GtkTreeStore" id="tree"> + <columns> + <!-- column-name gchararray1 --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkDialog" id="media_info_dialog"> + <property name="name">media_info_dialog</property> + <property name="can_focus">False</property> + <property name="window_position">center-on-parent</property> + <property name="type_hint">dialog</property> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog-vbox1"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog-action_area1"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="media_info_dialog_button"> + <property name="label" translatable="yes">Close</property> + <property name="name">media_info_dialog_button</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="media_info_dialog_button_clicked_cb" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_bottom">5</property> + <property name="label" translatable="yes">Information about all the streams contains in your media. </property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow" id="sw"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="margin_top">5</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkTreeView" id="view"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="model">tree</property> + <property name="headers_visible">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="treeview-selection2"/> + </child> + <child> + <object class="GtkTreeViewColumn" id="col"> + <property name="sizing">autosize</property> + <property name="title" translatable="yes">col</property> + <child> + <object class="GtkCellRendererText" id="cellrenderertext1"/> + </child> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> +</interface> diff --git a/playback/player/gtk/resources/toolbar.css b/playback/player/gtk/resources/toolbar.css new file mode 100644 index 0000000..b967454 --- /dev/null +++ b/playback/player/gtk/resources/toolbar.css @@ -0,0 +1,26 @@ +* { + background-color: rgba(43,56,54,0.0); + padding: 0px; +} + +GtkLabel { + font-size: 10px; + color: #ffffff; +} + +#toolbar { + border-radius: 25px; + border: 3px solid #212B2A; + background: rgba(43,56,54,0.6); +} + +GtkButton:hover { + border-radius: 45px; + background: rgba(43,56,54,1.0); + border: 1px solid #212B2A; +} + +#title_label { + font-size: 12px; +} + diff --git a/playback/player/gtk/resources/toolbar.ui b/playback/player/gtk/resources/toolbar.ui new file mode 100644 index 0000000..c185795 --- /dev/null +++ b/playback/player/gtk/resources/toolbar.ui @@ -0,0 +1,341 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.18.3 --> +<interface> + <requires lib="gtk+" version="3.12"/> + <!-- interface-css-provider-path controls.css --> + <object class="GtkImage" id="forward_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="pixel_size">30</property> + <property name="icon_name">gtk-media-forward</property> + <property name="icon_size">0</property> + </object> + <object class="GtkImage" id="fullscreen_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="pixel_size">25</property> + <property name="icon_name">view-fullscreen</property> + <property name="icon_size">0</property> + </object> + <object class="GtkImage" id="next_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="pixel_size">30</property> + <property name="icon_name">gtk-media-next</property> + <property name="icon_size">0</property> + </object> + <object class="GtkImage" id="pause_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="pixel_size">35</property> + <property name="icon_name">media-playback-pause</property> + <property name="icon_size">0</property> + </object> + <object class="GtkImage" id="play_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="pixel_size">35</property> + <property name="icon_name">gtk-media-play</property> + <property name="icon_size">0</property> + </object> + <object class="GtkImage" id="prev_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="pixel_size">30</property> + <property name="icon_name">gtk-media-previous</property> + </object> + <object class="GtkImage" id="restore_image"> + <property name="name">restore_image</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="pixel_size">25</property> + <property name="icon_name">view-restore</property> + <property name="icon_size">0</property> + </object> + <object class="GtkImage" id="rewind_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="pixel_size">30</property> + <property name="icon_name">gtk-media-rewind</property> + </object> + <object class="GtkBox" id="toolbar"> + <property name="name">toolbar</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_bottom">5</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkBox" id="box1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">20</property> + <property name="margin_right">20</property> + <property name="spacing">9</property> + <child> + <object class="GtkLabel" id="elapshed_time"> + <property name="name">elapshed_time</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">center</property> + <property name="label" translatable="yes">00:00</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkScale" id="seekbar"> + <property name="name">seekbar</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="valign">center</property> + <property name="round_digits">1</property> + <property name="draw_value">False</property> + <signal name="value-changed" handler="seekbar_value_changed_cb" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="remain_time"> + <property name="name">remain_time</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">center</property> + <property name="label" translatable="yes">00:00</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkVolumeButton" id="volume_button"> + <property name="name">volume_button</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="valign">center</property> + <property name="relief">none</property> + <property name="focus_on_click">False</property> + <property name="orientation">vertical</property> + <property name="icons">audio-volume-muted +audio-volume-high +audio-volume-low +audio-volume-medium</property> + <signal name="value-changed" handler="volume_button_value_changed_cb" swapped="no"/> + <child internal-child="plus_button"> + <object class="GtkButton" id="volumebutton-plus_button1"> + <property name="label" translatable="yes">+</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="relief">none</property> + </object> + </child> + <child internal-child="minus_button"> + <object class="GtkButton" id="volumebutton-minus_button1"> + <property name="label" translatable="yes">-</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="relief">none</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="fullscreen_button"> + <property name="name">fullscreen_button</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="image">fullscreen_image</property> + <property name="relief">none</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <signal name="toggled" handler="fullscreen_button_toggled_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">-1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="title_label"> + <property name="name">title_label</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">5</property> + <property name="justify">center</property> + <property name="wrap">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="box2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">center</property> + <property name="margin_left">20</property> + <property name="margin_right">20</property> + <property name="margin_bottom">10</property> + <child> + <object class="GtkBox" id="box4"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="spacing">5</property> + <child> + <object class="GtkButton" id="prev_button"> + <property name="name">prev_button</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="valign">center</property> + <property name="image">prev_image</property> + <property name="relief">none</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <signal name="clicked" handler="prev_button_clicked_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="rewind_button"> + <property name="name">rewind_button</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="image">rewind_image</property> + <property name="relief">none</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <signal name="clicked" handler="rewind_button_clicked_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="play_pause_button"> + <property name="name">play_pause_button</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="valign">center</property> + <property name="image">pause_image</property> + <property name="relief">none</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <signal name="clicked" handler="play_pause_button_clicked_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="forward_button"> + <property name="name">forward_button</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="valign">center</property> + <property name="image">forward_image</property> + <property name="relief">none</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <signal name="clicked" handler="forward_button_clicked_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkButton" id="next_button"> + <property name="name">next_button</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="valign">center</property> + <property name="image">next_image</property> + <property name="relief">none</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <signal name="clicked" handler="next_button_clicked_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="rate_label"> + <property name="name">rate_label</property> + <property name="width_request">40</property> + <property name="can_focus">False</property> + <property name="valign">center</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="justify">right</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> +</interface> |