playback/player: GTK: Improvements to the GTK+ player

This patch contains a few improvements to the gtk-player:
* Uses unified play/pause button.
* Adds a Skip Previous/Next button.
* Volume control
* Takes multiple files/uri's as arguments.
* Switches to the next track (if any) when the current track
  reaches and end.

https://github.com/sdroege/gst-player/pull/1
This commit is contained in:
Parthasarathi Susarla 2014-08-06 17:37:33 +10:00 committed by Sebastian Dröge
parent 7cb352aaa6
commit a622cb0d2c

View file

@ -16,18 +16,35 @@
#include <gst/player/player.h>
#define APP_NAME "gtk-play"
typedef struct
{
GstPlayer *player;
gchar *uri;
GList *uris;
GtkWidget *window;
GtkWidget *play_button, *pause_button;
GtkWidget *play_pause_button;
GtkWidget *prev_button, *next_button;
GtkWidget *seekbar;
GtkWidget *video_area;
GtkWidget *volume_button;
gulong seekbar_value_changed_signal_id;
} GtkPlay;
static void
set_title (GtkPlay *play, const gchar *title)
{
if (title == NULL) {
gtk_window_set_title (GTK_WINDOW (play->window), APP_NAME);
} else {
gtk_window_set_title (GTK_WINDOW (play->window), title);
}
}
static void
delete_event_cb (GtkWidget * widget, GdkEvent * event, GtkPlay * play)
{
@ -55,15 +72,70 @@ video_area_realize_cb (GtkWidget * widget, GtkPlay * play)
}
static void
play_clicked_cb (GtkButton * button, GtkPlay * play)
play_pause_clicked_cb (GtkButton *button, GtkPlay *play)
{
gst_player_play (play->player);
GtkWidget *image;
if (gst_player_is_playing (play->player)) {
gst_player_pause (play->player);
image = gtk_image_new_from_icon_name ("media-playback-start", GTK_ICON_SIZE_BUTTON);
gtk_button_set_image (GTK_BUTTON(play->play_pause_button), image);
} else {
gchar *title;
gst_player_play (play->player);
image = gtk_image_new_from_icon_name ("media-playback-pause", GTK_ICON_SIZE_BUTTON);
gtk_button_set_image (GTK_BUTTON(play->play_pause_button), image);
title = gst_player_get_uri (play->player);
set_title (play, title);
g_free (title);
}
}
static void
pause_clicked_cb (GtkButton * button, GtkPlay * play)
skip_prev_clicked_cb (GtkButton *button, GtkPlay *play)
{
gst_player_pause (play->player);
GList *prev;
gchar *cur_uri;
prev = g_list_find_custom (play->uris,
gst_player_get_uri (play->player),
(GCompareFunc)strcmp);
if (prev != NULL) {
prev = g_list_previous (prev);
if (prev != NULL) {
gtk_widget_set_sensitive (play->next_button, TRUE);
gst_player_set_uri (play->player, prev->data);
gst_player_play (play->player);
set_title (play, prev->data);
} else {
gtk_widget_set_sensitive (play->prev_button, FALSE);
}
}
}
static void
skip_next_clicked_cb (GtkButton *button, GtkPlay *play)
{
GList *next, *l;
gchar *cur_uri;
next = g_list_find_custom (play->uris,
gst_player_get_uri (play->player),
(GCompareFunc)strcmp);
if (next != NULL) {
next = g_list_next (next);
if (next != NULL) {
gtk_widget_set_sensitive (play->prev_button, TRUE);
gst_player_set_uri (play->player, next->data);
gst_player_play (play->player);
set_title (play, next->data);
} else {
gtk_widget_set_sensitive (play->next_button, FALSE);
}
}
}
static void
@ -73,6 +145,14 @@ seekbar_value_changed_cb (GtkRange * range, GtkPlay * play)
gst_player_seek (play->player, gst_util_uint64_scale (value, GST_SECOND, 1));
}
void
volume_changed_cb (GtkScaleButton *button,
gdouble value,
GtkPlay *play)
{
gst_player_set_volume (play->player, value);
}
static void
create_ui (GtkPlay * play)
{
@ -81,23 +161,19 @@ create_ui (GtkPlay * play)
play->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (play->window), "delete-event",
G_CALLBACK (delete_event_cb), play);
set_title (play, APP_NAME);
play->video_area = gtk_drawing_area_new ();
gtk_widget_set_double_buffered (play->video_area, FALSE);
g_signal_connect (play->video_area, "realize",
G_CALLBACK (video_area_realize_cb), play);
play->play_button =
gtk_button_new_from_icon_name ("media-playback-start",
GTK_ICON_SIZE_BUTTON);
g_signal_connect (G_OBJECT (play->play_button), "clicked",
G_CALLBACK (play_clicked_cb), play);
play->pause_button =
/* 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->pause_button), "clicked",
G_CALLBACK (pause_clicked_cb), play);
g_signal_connect (G_OBJECT (play->play_pause_button), "clicked",
G_CALLBACK (play_pause_clicked_cb), play);
play->seekbar =
gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, 100, 1);
@ -106,10 +182,35 @@ create_ui (GtkPlay * play)
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);
/* 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);
controls = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start (GTK_BOX (controls), play->play_button, FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX (controls), play->pause_button, FALSE, FALSE, 2);
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->seekbar, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (controls), play->volume_button, FALSE, FALSE, 2);
main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start (GTK_BOX (main_hbox), play->video_area, TRUE, TRUE, 0);
@ -130,6 +231,7 @@ static void
play_clear (GtkPlay * play)
{
g_free (play->uri);
g_list_free_full (play->uris, g_free);
g_object_unref (play->player);
}
@ -160,19 +262,49 @@ video_dimensions_changed_cb (GstPlayer * unused, gint width, gint height,
gtk_widget_hide (play->video_area);
}
static void
eos_cb (GstPlayer * unused, GtkPlay * play)
{
if (gst_player_is_playing (play->player)) {
GList *next = NULL;
gchar *uri;
next = g_list_find_custom (play->uris,
gst_player_get_uri (play->player),
(GCompareFunc) strcmp);
if (next) {
next = g_list_next (next);
if (next) {
if (!gtk_widget_is_sensitive(play->prev_button))
gtk_widget_set_sensitive (play->prev_button, TRUE);
gst_player_set_uri (play->player, next->data);
gst_player_play (play->player);
set_title (play, next->data);
}
else
gst_player_stop (play->player);
}
}
}
int
main (gint argc, gchar ** argv)
{
GtkPlay play;
gchar **file_names = NULL;
GOptionContext *ctx;
GOptionEntry options[] = {
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &file_names,
"Files to play" },
{NULL}
};
guint list_length = 0;
GError *err = NULL;
GList *l;
memset (&play, 0, sizeof (play));
g_set_prgname ("gtk-play");
g_set_prgname (APP_NAME);
ctx = g_option_context_new ("FILE|URI");
g_option_context_add_main_entries (ctx, options, NULL);
@ -185,33 +317,49 @@ main (gint argc, gchar ** argv)
g_option_context_free (ctx);
// FIXME: Add support for playlists and stuff
play.uri = g_strdup (argv[1]);
if (!play.uri) {
g_print ("Usage: %s FILE|URI\n", argv[0]);
/* Parse the list of the file names we have to play. */
if (!file_names) {
g_print ("Usage: %s FILE(s)|URI(s)\n", APP_NAME);
return 1;
} else {
guint i;
list_length = g_strv_length (file_names);
for (i = 0; i < list_length; i++) {
play.uris =
g_list_append (play.uris,
gst_uri_is_valid (file_names[i]) ?
g_strdup (file_names[i]) :
gst_filename_to_uri (file_names[i], NULL));
}
g_strfreev (file_names);
file_names = NULL;
}
play.player = gst_player_new ();
g_object_set (play.player, "dispatch-to-main-context", TRUE, NULL);
if (!gst_uri_is_valid (play.uri)) {
gchar *uri = gst_filename_to_uri (play.uri, NULL);
g_free (play.uri);
play.uri = uri;
}
g_object_set (play.player, "uri", play.uri, NULL);
gst_player_set_uri (play.player, g_list_first (play.uris)->data);
create_ui (&play);
if (list_length > 1)
gtk_widget_set_sensitive (play.next_button, TRUE);
g_signal_connect (play.player, "position-updated",
G_CALLBACK (position_updated_cb), &play);
g_signal_connect (play.player, "duration-changed",
G_CALLBACK (duration_changed_cb), &play);
g_signal_connect (play.player, "video-dimensions-changed",
G_CALLBACK (video_dimensions_changed_cb), &play);
g_signal_connect (play.player, "end-of-stream",
G_CALLBACK (eos_cb), &play);
gst_player_pause (play.player);
/* We have file(s) that need playing. */
set_title (&play, g_list_first (play.uris)->data);
gst_player_play (play.player);
gtk_main ();