implement seek to, change rate, gui seek bar
[gst-scaletempo-demo-rj.git] / src / demo-gui.c
blob31e287c078cb9350d4e057230446612e4c134281
1 /* demo-gui.c
2 * Copyright (C) 2008 Rov Juvano <rovjuvano@users.sourceforge.net>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include <gtk/gtk.h>
19 #include <glib/gprintf.h>
20 #include "demo-gui.h"
22 #undef G_LOG_DOMAIN
23 #define G_LOG_DOMAIN "demo-gui"
25 enum
27 SIGNAL_ERROR,
28 SIGNAL_QUITING,
29 LAST_SIGNAL
31 static guint demo_gui_signals[LAST_SIGNAL] = { 0 };
33 enum
35 PROP_0,
38 typedef struct _DemoGuiPrivate
40 DemoPlayer *player;
41 GList *uris;
42 GList *now_playing;
43 gboolean is_playing;
44 GtkWidget *window;
45 GtkEntry *rate_entry;
46 GtkStatusbar *status_bar;
47 gint position_updater_id;
48 GtkRange *seek_range;
49 GtkLabel *amount_played;
50 GtkLabel *amount_to_play;
51 } DemoGuiPrivate;
53 #define DEMO_GUI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DEMO_TYPE_GUI, DemoGuiPrivate))
55 /* forward declarations */
56 static GValueArray * build_gvalue_array (guint n_values, ...);
58 /* Handlers for status bar and seek bar */
59 static int
60 pop_status_bar (gpointer data) {
61 GValueArray *gvalues = (GValueArray *)data;
62 GtkStatusbar *sb = GTK_STATUSBAR (g_value_get_object (g_value_array_get_nth (gvalues, 0)));
63 guint msg_id = g_value_get_uint (g_value_array_get_nth (gvalues, 1));
65 gtk_statusbar_remove (sb, 0, msg_id);
66 return FALSE;
69 static void
70 status_bar_printf (GtkStatusbar *sb,
71 gchar const *format, ...)
73 va_list args;
74 gchar msg[80];
75 va_start (args, format);
76 g_vsnprintf (msg, 80, format, args);
77 va_end (args);
78 guint msg_id = gtk_statusbar_push (sb, 0, msg);
79 g_timeout_add (2000, pop_status_bar,
80 build_gvalue_array (2, G_TYPE_OBJECT, sb, G_TYPE_UINT, msg_id));
83 #define PRINTF_TIME_FORMAT "u:%02u:%02u"
84 #define PRINTF_TIME_ARGS(t) \
85 (t >= 0) ? (guint) ((t) / (60 * 60)) : 99, \
86 (t >= 0) ? (guint) (((t) / (60)) % 60) : 99, \
87 (t >= 0) ? (guint) ((t) % 60) : 99
89 static gchar*
90 demo_gui_seek_bar_format (GtkScale *scale,
91 gdouble value,
92 gpointer data)
94 return g_strdup_printf ("%" PRINTF_TIME_FORMAT, PRINTF_TIME_ARGS ((gint64)value));
97 gboolean update_position (gpointer data) {
98 DemoGui *gui = DEMO_GUI (data);
99 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
100 gchar pos_str[16], dur_str[16];
102 gint pos = demo_player_get_position (priv->player);
103 if (pos > 0) {
104 g_snprintf (pos_str, 16, "%" PRINTF_TIME_FORMAT, PRINTF_TIME_ARGS (pos));
105 gint dur = demo_player_get_duration (priv->player);
106 if (dur > 0) {
107 g_snprintf (dur_str, 16, "-%" PRINTF_TIME_FORMAT, PRINTF_TIME_ARGS (dur - pos));
108 } else {
109 dur = pos;
110 g_sprintf (dur_str, "-??:??:??");
112 if (dur > 0)
113 gtk_range_set_range (GTK_RANGE (priv->seek_range), 0, (gdouble)dur);
114 gtk_range_set_value (GTK_RANGE (priv->seek_range), (gdouble)pos);
115 } else {
116 g_sprintf (pos_str, "??:??:??");
117 g_sprintf (dur_str, "-??:??:??");
119 gtk_label_set_text (GTK_LABEL (priv->amount_played), pos_str);
120 gtk_label_set_text (GTK_LABEL (priv->amount_to_play), dur_str);
122 return priv->is_playing;
126 gboolean
127 demo_gui_seek_bar_change (GtkRange *range,
128 GtkScrollType scroll,
129 gdouble value,
130 gpointer data)
132 DemoGui *gui = DEMO_GUI (data);
133 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
134 gint new_second = (gint)value;
136 status_bar_printf (priv->status_bar, "Seeking to %i second", new_second);
137 demo_player_seek_to (priv->player, new_second);
139 return FALSE;
143 /* Callbacks for actions */
144 static void
145 demo_gui_do_change_rate (GtkAction *action,
146 gpointer data)
148 GValueArray *gvalues = (GValueArray *)data;
149 DemoGui *gui = g_value_get_object (g_value_array_get_nth (gvalues, 0));
150 gdouble scale_amount = g_value_get_double (g_value_array_get_nth (gvalues, 1));
151 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
153 status_bar_printf (priv->status_bar, "Changing rate by %3.2lf", scale_amount);
155 demo_player_scale_rate (priv->player, scale_amount);
158 static void
159 demo_gui_do_rate_entered (GtkWidget *widget,
160 gpointer data)
162 DemoGui *gui = DEMO_GUI (data);
163 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
164 double new_rate;
166 sscanf (gtk_entry_get_text (GTK_ENTRY (widget)), "%lf", &new_rate);
168 status_bar_printf (priv->status_bar, "Setting rate to %3.2lf", new_rate);
170 demo_player_set_rate (priv->player, new_rate);
173 static void
174 demo_gui_do_seek (GtkAction *action,
175 gpointer data)
177 GValueArray *gvalues = (GValueArray *)data;
178 DemoGui *gui = g_value_get_object (g_value_array_get_nth (gvalues, 0));
179 gint seconds = g_value_get_int (g_value_array_get_nth (gvalues, 1));
181 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
183 status_bar_printf (priv->status_bar, "Seeking %i seconds", seconds);
185 demo_player_seek_by (priv->player, seconds);
188 static void
189 demo_gui_do_play (GtkAction *action,
190 gpointer data)
192 DemoGui *gui = DEMO_GUI (data);
193 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
195 if (priv->is_playing) {
196 g_signal_emit (gui, demo_gui_signals[SIGNAL_ERROR], 0, "Already playing");
197 return;
200 status_bar_printf (priv->status_bar, "Trying to start playing");
202 demo_player_play (priv->player);
205 static void
206 demo_gui_do_pause (GtkAction *action,
207 gpointer data)
209 DemoGui *gui = DEMO_GUI (data);
210 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
212 if (!priv->is_playing) {
213 g_signal_emit (gui, demo_gui_signals[SIGNAL_ERROR], 0, "Already paused");
214 return;
217 status_bar_printf (priv->status_bar, "Trying to pause playing");
219 demo_player_pause (priv->player);
222 static void
223 demo_gui_do_play_pause (GtkAction *action,
224 gpointer data)
226 DemoGui *gui = DEMO_GUI (data);
227 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
229 status_bar_printf (priv->status_bar, "Trying to toggle playing");
231 if (priv->is_playing)
232 demo_player_pause (priv->player);
233 else
234 demo_player_play (priv->player);
237 static void
238 demo_gui_do_quit (gpointer source,
239 gpointer data)
241 gtk_main_quit ();
242 g_signal_emit (DEMO_GUI (data), demo_gui_signals[SIGNAL_QUITING], 0, NULL);
246 /* Callbacks from signals */
247 static void
248 demo_gui_rate_changed (DemoPlayer *player,
249 gdouble new_rate,
250 gpointer data)
252 DemoGui *gui = DEMO_GUI (data);
253 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
254 status_bar_printf (priv->status_bar, "Rate changed to %3.2lf", new_rate);
256 gchar e[6];
257 snprintf (e, 6, "%3.2f", new_rate);
258 gtk_entry_set_text (GTK_ENTRY (priv->rate_entry), e);
261 static void
262 demo_gui_playing_started (DemoPlayer *player,
263 gpointer data)
265 DemoGui *gui = DEMO_GUI (data);
266 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
268 priv->is_playing = TRUE;
269 status_bar_printf (priv->status_bar, "Playing started");
271 if (priv->position_updater_id) {
272 g_source_remove (priv->position_updater_id);
273 priv->position_updater_id = 0;
275 update_position (gui);
276 priv->position_updater_id = g_timeout_add (1000, update_position, gui);
279 static void
280 demo_gui_playing_paused (DemoPlayer *player,
281 gpointer data)
283 DemoGui *gui = DEMO_GUI (data);
284 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
286 priv->is_playing = FALSE;
288 if (priv->position_updater_id)
289 g_source_remove (priv->position_updater_id);
290 priv->position_updater_id = 0;
291 update_position (gui);
293 status_bar_printf (priv->status_bar, "Playing paused");
296 static void
297 demo_gui_playing_ended (DemoPlayer *player,
298 gpointer data)
300 DemoGui *gui = DEMO_GUI (data);
301 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
302 status_bar_printf (priv->status_bar, "Playing ended");
306 /* method implementations */
307 static void
308 demo_gui_set_player_func (DemoGui *gui,
309 DemoPlayer *player)
311 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
312 if (priv->player) {
313 g_signal_handlers_disconnect_by_func (G_OBJECT (priv->player), G_CALLBACK (demo_gui_rate_changed), gui);
314 g_signal_handlers_disconnect_by_func (G_OBJECT (priv->player), G_CALLBACK (demo_gui_playing_started), gui);
315 g_signal_handlers_disconnect_by_func (G_OBJECT (priv->player), G_CALLBACK (demo_gui_playing_paused), gui);
316 g_signal_handlers_disconnect_by_func (G_OBJECT (priv->player), G_CALLBACK (demo_gui_playing_ended), gui);
318 priv->player = player;
319 g_signal_connect (G_OBJECT (priv->player), "rate-changed", G_CALLBACK (demo_gui_rate_changed), gui);
320 g_signal_connect (G_OBJECT (priv->player), "playing-started", G_CALLBACK (demo_gui_playing_started), gui);
321 g_signal_connect (G_OBJECT (priv->player), "playing-paused", G_CALLBACK (demo_gui_playing_paused), gui);
322 g_signal_connect (G_OBJECT (priv->player), "playing-ended", G_CALLBACK (demo_gui_playing_ended), gui);
324 if (priv->now_playing)
325 demo_player_load_uri (priv->player, priv->now_playing->data);
328 static void
329 demo_gui_set_playlist_func (DemoGui *gui,
330 GList *uris)
332 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
333 priv->uris = uris;
334 priv->now_playing = priv->uris;
335 if (priv->player && priv->now_playing)
336 demo_player_load_uri (priv->player, priv->now_playing->data);
339 typedef struct _ActionEntry {
340 GtkAction *action;
341 GtkWidget *button;
342 const gchar *accel;
343 const gchar *name;
344 const gchar *label;
345 const gchar *tooltip;
346 const gchar *stock_id;
347 GtkAccelGroup *accel_group;
348 GtkActionGroup *action_group;
349 GCallback callback;
350 gpointer data;
351 } ActionEntry;
353 static GValueArray *
354 build_gvalue_array (guint n_values,
355 ...)
357 va_list args;
358 va_start (args, n_values);
359 GValueArray *gva = g_value_array_new (n_values);
360 int i;
361 for (i=0; i<n_values; i++) {
362 GType type = va_arg (args, GType);
363 GValue *gval = g_new0 (GValue, 1);
364 if (type == G_TYPE_INT) {
365 gint value = va_arg (args, gint);
366 g_value_set_int (g_value_init (gval, G_TYPE_INT), value);
367 } else if (type == G_TYPE_UINT) {
368 guint value = va_arg (args, guint);
369 g_value_set_uint (g_value_init (gval, G_TYPE_UINT), value);
370 } else if (type == G_TYPE_DOUBLE) {
371 double value = va_arg (args, double);
372 g_value_set_double (g_value_init (gval, G_TYPE_DOUBLE), value);
373 } else if (type == G_TYPE_OBJECT) {
374 GObject *value = va_arg (args, GObject *);
375 g_value_set_object (g_value_init (gval, G_TYPE_OBJECT), value);
376 } else {
377 g_critical ("build_gvalue_array cannot handle type (%s)", g_type_name (type));
378 va_end (args);
379 return NULL;
381 g_value_array_append (gva, gval);
383 va_end (args);
384 return gva;
387 static void
388 create_action (ActionEntry *p)
390 p->action = gtk_action_new (p->name, p->label, p->tooltip, p->stock_id);
392 gtk_action_group_add_action_with_accel (p->action_group, p->action, p->accel);
393 gtk_action_set_accel_group (p->action, p->accel_group);
394 gtk_action_connect_accelerator (p->action);
396 p->button = gtk_button_new ();
397 gtk_action_connect_proxy (p->action, p->button);
398 gtk_button_set_image (GTK_BUTTON (p->button), gtk_action_create_icon (p->action, GTK_ICON_SIZE_BUTTON));
399 g_signal_connect (G_OBJECT (p->action), "activate", p->callback, p->data);
403 static void
404 demo_gui_show_func (DemoGui *gui) {
405 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
407 gtk_init (NULL, NULL);
408 GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
409 g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (demo_gui_do_quit), gui);
411 GtkAccelGroup *accel_group = gtk_accel_group_new ();
412 gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
413 GtkActionGroup *action_group = gtk_action_group_new ("toolbar");
415 ActionEntry *slower_lg = &(ActionEntry){
416 NULL, NULL,
417 "braceleft", "slower-large",
418 "2x Slower", "half playback rate",
419 GTK_STOCK_GO_DOWN, accel_group, action_group,
420 G_CALLBACK (demo_gui_do_change_rate),
421 build_gvalue_array (2, G_TYPE_OBJECT, gui, G_TYPE_DOUBLE, 0.5)
423 create_action (slower_lg);
425 ActionEntry *slower_sm = &(ActionEntry){
426 NULL, NULL,
427 "bracketleft", "slower-small",
428 "_Slower", "decrease playback rate",
429 GTK_STOCK_GO_DOWN, accel_group, action_group,
430 G_CALLBACK (demo_gui_do_change_rate),
431 build_gvalue_array (2, G_TYPE_OBJECT, gui, G_TYPE_DOUBLE, 0.943874312681694)
433 create_action (slower_sm);
435 ActionEntry *faster_sm = &(ActionEntry){
436 NULL, NULL,
437 "bracketright", "faster-small",
438 "_Faster", "increase playback rate",
439 GTK_STOCK_GO_UP, accel_group, action_group,
440 G_CALLBACK (demo_gui_do_change_rate),
441 build_gvalue_array (2, G_TYPE_OBJECT, gui, G_TYPE_DOUBLE, 1.0594630943593)
443 create_action (faster_sm);
445 ActionEntry *faster_lg = &(ActionEntry){
446 NULL, NULL,
447 "braceright", "faster-large",
448 "2X Faster", "double playback rate",
449 GTK_STOCK_GO_UP, accel_group, action_group,
450 G_CALLBACK (demo_gui_do_change_rate),
451 build_gvalue_array (2, G_TYPE_OBJECT, gui, G_TYPE_DOUBLE, 2.0)
453 create_action (faster_lg);
455 ActionEntry *rewind_lg = &(ActionEntry){
456 NULL, NULL,
457 "<ctrl><shift>Left", "seek-rewind-large",
458 "Rewind (large)", "seek -30 seconds",
459 GTK_STOCK_MEDIA_REWIND, accel_group, action_group,
460 G_CALLBACK (demo_gui_do_seek),
461 build_gvalue_array (2, G_TYPE_OBJECT, gui, G_TYPE_INT, -30)
463 create_action (rewind_lg);
465 ActionEntry *rewind_sm = &(ActionEntry){
466 NULL, NULL,
467 "<ctrl>Left", "seek-rewind-small",
468 "Rewind", "seek -15 seconds",
469 GTK_STOCK_MEDIA_REWIND, accel_group, action_group,
470 G_CALLBACK (demo_gui_do_seek),
471 build_gvalue_array (2, G_TYPE_OBJECT, gui, G_TYPE_INT, -5)
473 create_action (rewind_sm);
475 ActionEntry *forward_sm = &(ActionEntry){
476 NULL, NULL,
477 "<ctrl>Right", "seek-forward-small",
478 "Forward", "seek +5 seconds",
479 GTK_STOCK_MEDIA_FORWARD, accel_group, action_group,
480 G_CALLBACK (demo_gui_do_seek),
481 build_gvalue_array (2, G_TYPE_OBJECT, gui, G_TYPE_INT, 5)
483 create_action (forward_sm);
485 ActionEntry *forward_lg = &(ActionEntry){
486 NULL, NULL,
487 "<ctrl><shift>Right", "seek-forward-large",
488 "Forward (large)", "seek +30 seconds",
489 GTK_STOCK_MEDIA_FORWARD, accel_group, action_group,
490 G_CALLBACK (demo_gui_do_seek),
491 build_gvalue_array (2, G_TYPE_OBJECT, gui, G_TYPE_INT, 30)
493 create_action (forward_lg);
495 GValue *is_playing = g_new0 (GValue, 1);
496 g_value_set_boolean (g_value_init (is_playing, G_TYPE_BOOLEAN), TRUE);
497 ActionEntry *pause = &(ActionEntry){
498 NULL, NULL,
499 "p", "pause",
500 "Pause", "Pause playback",
501 GTK_STOCK_MEDIA_PAUSE, accel_group, action_group,
502 G_CALLBACK (demo_gui_do_pause), gui
504 create_action (pause);
506 ActionEntry *play = &(ActionEntry){
507 NULL, NULL,
508 "<ctrl>p", "play",
509 "Play", "Start Playback",
510 GTK_STOCK_MEDIA_PLAY, accel_group, action_group,
511 G_CALLBACK (demo_gui_do_play), gui
513 create_action (play);
514 GtkRequisition pause_size;
515 gtk_widget_size_request (pause->button, &pause_size);
516 gtk_widget_set_size_request (play->button, pause_size.width, -1);
518 ActionEntry *play_pause = &(ActionEntry){
519 NULL, NULL,
520 "space", "play-pause",
521 "Play/Pause", "Toggle playback",
522 NULL, accel_group, action_group,
523 G_CALLBACK (demo_gui_do_play_pause), gui
525 create_action (play_pause);
527 ActionEntry *quit = &(ActionEntry){
528 NULL, NULL,
529 "q", "quit",
530 "Quit", "Quit demo",
531 GTK_STOCK_MEDIA_STOP, accel_group, action_group,
532 G_CALLBACK (demo_gui_do_quit), gui
534 create_action (quit);
536 GtkWidget *rate_entry = gtk_entry_new ();
537 GtkWidget *rate_label = gtk_label_new ("Rate:");
538 gtk_entry_set_max_length (GTK_ENTRY (rate_entry), 5);
539 gtk_entry_set_text (GTK_ENTRY (rate_entry), "1.0");
540 gtk_entry_set_width_chars (GTK_ENTRY (rate_entry), 5);
541 g_signal_connect (G_OBJECT (rate_entry), "activate", G_CALLBACK (demo_gui_do_rate_entered), gui);
543 GtkWidget *menu = gtk_menu_new ();
544 gtk_menu_set_accel_group (GTK_MENU (menu), accel_group);
545 gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_action_create_menu_item (faster_lg->action));
546 gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_action_create_menu_item (faster_sm->action));
547 gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_action_create_menu_item (slower_sm->action));
548 gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_action_create_menu_item (slower_lg->action));
549 gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_action_create_menu_item (rewind_lg->action));
550 gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_action_create_menu_item (rewind_sm->action));
551 gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_action_create_menu_item (forward_sm->action));
552 gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_action_create_menu_item (forward_lg->action));
553 gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_action_create_menu_item (play->action));
554 gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_action_create_menu_item (pause->action));
555 gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_action_create_menu_item (play_pause->action));
556 gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_action_create_menu_item (quit->action));
557 GtkWidget *menu_button = GTK_WIDGET (gtk_menu_tool_button_new (NULL, "More"));
558 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (menu_button), menu);
560 GtkWidget *toolbox = gtk_hbox_new (FALSE, 0);
561 gtk_box_pack_start (GTK_BOX (toolbox), slower_sm->button, FALSE, FALSE, 2);
562 gtk_box_pack_start (GTK_BOX (toolbox), rate_label, FALSE, FALSE, 2);
563 gtk_box_pack_start (GTK_BOX (toolbox), rate_entry, FALSE, FALSE, 2);
564 gtk_box_pack_start (GTK_BOX (toolbox), faster_sm->button, FALSE, FALSE, 2);
565 gtk_box_pack_start (GTK_BOX (toolbox), pause->button, FALSE, FALSE, 2);
566 gtk_box_pack_start (GTK_BOX (toolbox), play->button, FALSE, FALSE, 2);
567 gtk_box_pack_start (GTK_BOX (toolbox), menu_button, FALSE, FALSE, 2);
569 GtkWidget *video_window = gtk_drawing_area_new ();
570 gtk_drawing_area_size (GTK_DRAWING_AREA (video_window), 640, 360);
572 GtkWidget *amount_played = gtk_label_new ("00:00:00.00");
573 GtkWidget *amount_to_play = gtk_label_new ("-00:00:00.00");
574 gtk_label_set_width_chars (GTK_LABEL (amount_played), 12);
575 gtk_label_set_width_chars (GTK_LABEL (amount_to_play), 12);
576 gtk_misc_set_alignment (GTK_MISC (amount_played), 1, 1);
577 gtk_misc_set_alignment (GTK_MISC (amount_to_play), 0, 1);
578 GtkWidget *seek_range = gtk_hscale_new (
579 GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 5.0, 30.0, 0.00)));
580 gtk_range_set_update_policy (GTK_RANGE (seek_range), GTK_UPDATE_DISCONTINUOUS);
581 GtkWidget *seek_bar = gtk_hbox_new (FALSE, 0);
582 gtk_box_pack_start (GTK_BOX (seek_bar), amount_played, FALSE, FALSE, 2);
583 gtk_box_pack_start (GTK_BOX (seek_bar), seek_range, TRUE, TRUE, 2);
584 gtk_box_pack_start (GTK_BOX (seek_bar), amount_to_play, FALSE, FALSE, 2);
585 g_signal_connect (G_OBJECT (seek_range), "format-value", G_CALLBACK (demo_gui_seek_bar_format), gui);
586 g_signal_connect (G_OBJECT (seek_range), "change-value", G_CALLBACK (demo_gui_seek_bar_change), gui);
588 GtkWidget *status_bar = gtk_statusbar_new ();
590 gtk_window_set_title (GTK_WINDOW (window), "Scaletempo Demo");
591 GtkWidget *toplevel_box = gtk_vbox_new (FALSE, 0);
592 gtk_container_set_border_width (GTK_CONTAINER (toplevel_box), 3);
593 gtk_container_add (GTK_CONTAINER (window), toplevel_box);
594 gtk_box_pack_start (GTK_BOX (toplevel_box), toolbox, FALSE, FALSE, 2);
595 gtk_box_pack_start (GTK_BOX (toplevel_box), video_window, TRUE, TRUE, 2);
596 gtk_box_pack_start (GTK_BOX (toplevel_box), seek_bar, FALSE, FALSE, 2);
597 gtk_box_pack_start (GTK_BOX (toplevel_box), status_bar, FALSE, FALSE, 2);
599 priv->window = window;
600 priv->rate_entry = GTK_ENTRY (rate_entry);
601 priv->status_bar = GTK_STATUSBAR (status_bar);
602 priv->seek_range = GTK_RANGE (seek_range);
603 priv->amount_played = GTK_LABEL (amount_played);
604 priv->amount_to_play = GTK_LABEL (amount_to_play);
606 gtk_widget_show_all (window);
607 status_bar_printf (GTK_STATUSBAR (status_bar), "Welcome to the Scaletempo demo.");
608 gtk_widget_grab_focus (seek_range);
610 GError *error;
611 if (!g_thread_create ((GThreadFunc)gtk_main, NULL, FALSE, &error)) {
612 g_signal_emit (gui, demo_gui_signals[SIGNAL_ERROR], 0, error->message);
617 /* Method wrappers */
618 void
619 demo_gui_set_player (DemoGui *gui,
620 DemoPlayer *player)
622 g_return_if_fail (DEMO_IS_GUI (gui));
623 g_return_if_fail (DEMO_IS_PLAYER (player));
625 DEMO_GUI_GET_CLASS (gui)->set_player (gui, player);
628 void
629 demo_gui_set_playlist (DemoGui *gui,
630 GList *uris)
632 g_return_if_fail (DEMO_IS_GUI (gui));
634 DEMO_GUI_GET_CLASS (gui)->set_playlist (gui, uris);
637 void
638 demo_gui_show (DemoGui *gui)
640 g_return_if_fail (DEMO_IS_GUI (gui));
642 DEMO_GUI_GET_CLASS (gui)->show (gui);
647 /* GObject overrides */
648 static void
649 demo_gui_get_property (GObject *object,
650 guint property_id,
651 GValue *value,
652 GParamSpec *pspec)
654 //DemoGui *gui = DEMO_GUI (object);
655 switch (property_id) {
656 default:
657 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
658 break;
662 static void
663 demo_gui_set_property (GObject *object,
664 guint property_id,
665 const GValue *value,
666 GParamSpec *pspec)
668 //DemoGui *gui = DEMO_GUI (object);
669 switch (property_id) {
670 default:
671 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
672 break;
677 /* GTypeInfo functions */
678 static void
679 demo_gui_init (GTypeInstance *instance,
680 gpointer klass)
682 DemoGui *gui = (DemoGui *)instance;
684 DemoGuiPrivate *priv = DEMO_GUI_GET_PRIVATE (gui);
685 priv->player = NULL;
686 priv->uris = NULL;
687 priv->now_playing = NULL;
688 priv->is_playing = FALSE;
689 priv->window = NULL;
690 priv->rate_entry = NULL;
691 priv->position_updater_id = 0;
692 priv->seek_range = NULL;
693 priv->amount_played = NULL;
694 priv->amount_to_play = NULL;
697 static void
698 demo_gui_class_init (gpointer klass,
699 gpointer class_data)
701 g_type_class_add_private (klass, sizeof (DemoGuiPrivate));
703 /* DemiPlayer */
704 DemoGuiClass *gui_class = (DemoGuiClass *)klass;
705 gui_class->set_player = demo_gui_set_player_func;
706 gui_class->set_playlist = demo_gui_set_playlist_func;
707 gui_class->show = demo_gui_show_func;
709 /* GObject */
710 GObjectClass *as_object_class = G_OBJECT_CLASS (klass);
711 as_object_class->get_property = demo_gui_get_property;
712 as_object_class->set_property = demo_gui_set_property;
714 /* Properties */
716 /* Signals */
717 GType type = G_TYPE_FROM_CLASS (klass);
718 demo_gui_signals[SIGNAL_ERROR] = g_signal_new ("error", type,
719 G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
720 g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
722 demo_gui_signals[SIGNAL_QUITING] = g_signal_new ("quiting", type,
723 G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
724 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
727 GType
728 demo_gui_get_type (void)
730 static GType type = 0;
731 if (G_UNLIKELY (type == 0)) {
732 static const GTypeInfo info = {
733 sizeof /* Class */ (DemoGuiClass),
734 (GBaseInitFunc) NULL,
735 (GBaseFinalizeFunc) NULL,
736 (GClassInitFunc) demo_gui_class_init,
737 (GClassFinalizeFunc) NULL,
738 (gconstpointer) NULL, /* class_data */
739 sizeof /* Instance */ (DemoGui),
740 /* n_preallocs */ 0,
741 (GInstanceInitFunc) demo_gui_init,
742 (const GTypeValueTable *) NULL
744 type = g_type_register_static (G_TYPE_OBJECT, "DemoGui", &info, 0);
746 return type;