mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-13 12:51:16 +00:00
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:
parent
7cb352aaa6
commit
a622cb0d2c
1 changed files with 175 additions and 27 deletions
|
@ -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 ();
|
||||
|
||||
|
|
Loading…
Reference in a new issue