1 #include <config.h>
3 #include <sys/stat.h>
4 #include <unistd.h>
6 #include <gnome.h>
7 #include "gstmediaplay.h"
8 #include "callbacks.h"
10 static void gst_media_play_class_init (GstMediaPlayClass *klass);
11 static void gst_media_play_init (GstMediaPlay *play);
13 static void gst_media_play_set_arg (GtkObject *object, GtkArg *arg, guint id);
14 static void gst_media_play_get_arg (GtkObject *object, GtkArg *arg, guint id);
16 static void gst_media_play_frame_displayed (GstPlay *play, GstMediaPlay *mplay);
17 static void gst_media_play_state_changed (GstPlay *play, GstPlayState state, GstMediaPlay *mplay);
18 static void gst_media_play_slider_changed (GtkAdjustment *adj, GstMediaPlay *mplay);
20 static void update_buttons (GstMediaPlay *mplay, GstPlayState state);
21 static void update_slider (GstMediaPlay *mplay, GtkAdjustment *adjustment, gfloat value);
23 /* signals and args */
24 enum {
25 LAST_SIGNAL
26 };
28 enum {
29 ARG_0,
30 };
32 static void
33 target_drag_data_received (GtkWidget *widget,
34 GdkDragContext *context,
35 gint x,
36 gint y,
37 GtkSelectionData *data,
38 guint info,
39 guint time,
40 GstMediaPlay *play)
41 {
42 g_print ("Got: %s\n", data->data);
43 gdk_threads_leave ();
44 gst_media_play_start_uri (play, g_strchomp (data->data));
45 gdk_threads_enter ();
47 }
49 static GtkTargetEntry target_table[] = {
50 { "text/plain", 0, 0 }
51 };
53 static GtkObject *parent_class = NULL;
54 //static guint gst_media_play_signals[LAST_SIGNAL] = { 0 };
56 GtkType
57 gst_media_play_get_type (void)
58 {
59 static GtkType play_type = 0;
61 if (!play_type) {
62 static const GtkTypeInfo play_info = {
63 "GstMediaPlay",
64 sizeof (GstMediaPlay),
65 sizeof (GstMediaPlayClass),
66 (GtkClassInitFunc) gst_media_play_class_init,
67 (GtkObjectInitFunc) gst_media_play_init,
68 NULL,
69 NULL,
70 (GtkClassInitFunc) NULL,
71 };
72 play_type = gtk_type_unique (gtk_object_get_type(), &play_info);
73 }
74 return play_type;
75 }
77 static void
78 gst_media_play_class_init (GstMediaPlayClass *klass)
79 {
80 GtkObjectClass *object_class;
82 parent_class = gtk_type_class (gtk_object_get_type ());
84 object_class = (GtkObjectClass*) klass;
86 object_class->set_arg = gst_media_play_set_arg;
87 object_class->get_arg = gst_media_play_get_arg;
88 }
90 typedef struct {
91 GstMediaPlay *play;
92 GModule *symbols;
93 } connect_struct;
95 /* we need more control here so... */
96 static void
97 gst_media_play_connect_func (const gchar *handler_name,
98 GtkObject *object,
99 const gchar *signal_name,
100 const gchar *signal_data,
101 GtkObject *connect_object,
102 gboolean after,
103 gpointer user_data)
104 {
105 GtkSignalFunc func;
106 connect_struct *data = (connect_struct *) user_data;
108 if (!g_module_symbol (data->symbols, handler_name, (gpointer *)&func))
109 g_warning ("gsteditorproperty: could not find signal handler '%s'.", handler_name);
110 else {
111 if (after)
112 gtk_signal_connect_after (object, signal_name, func, (gpointer) data->play);
113 else
114 gtk_signal_connect (object, signal_name, func, (gpointer) data->play);
115 }
116 }
119 static void
120 gst_media_play_init (GstMediaPlay *mplay)
121 {
122 GModule *symbols;
123 connect_struct data;
124 struct stat statbuf;
127 /* load the interface */
128 if (stat (DATADIR"gstmediaplay.glade", &statbuf) == 0) {
129 mplay->xml = glade_xml_new (DATADIR"gstmediaplay.glade", "gstplay");
130 }
131 else {
132 mplay->xml = glade_xml_new ("gstmediaplay.glade", "gstplay");
133 }
134 g_assert (mplay->xml != NULL);
136 mplay->slider = glade_xml_get_widget (mplay->xml, "slider");
137 g_assert (mplay->slider != NULL);
138 {
139 GtkArg arg;
140 GtkRange *range;
142 arg.name = "adjustment";
143 gtk_object_getv (GTK_OBJECT (mplay->slider), 1, &arg);
144 range = GTK_RANGE (GTK_VALUE_POINTER (arg));
145 mplay->adjustment = gtk_range_get_adjustment (range);
147 gtk_signal_connect (GTK_OBJECT (mplay->adjustment), "value_changed",
148 GTK_SIGNAL_FUNC (gst_media_play_slider_changed), mplay);
149 }
151 mplay->play_button = glade_xml_get_widget (mplay->xml, "toggle_play");
152 g_assert (mplay->play_button != NULL);
153 mplay->pause_button = glade_xml_get_widget (mplay->xml, "toggle_pause");
154 g_assert (mplay->pause_button != NULL);
155 mplay->stop_button = glade_xml_get_widget (mplay->xml, "toggle_stop");
156 g_assert (mplay->stop_button != NULL);
158 mplay->window = glade_xml_get_widget (mplay->xml, "gstplay");
159 g_assert (mplay->window != NULL);
161 gtk_drag_dest_set (mplay->window,
162 GTK_DEST_DEFAULT_ALL,
163 target_table, 1,
164 GDK_ACTION_COPY);
165 gtk_signal_connect (GTK_OBJECT (mplay->window), "drag_data_received",
166 GTK_SIGNAL_FUNC (target_drag_data_received),
167 mplay);
169 mplay->play = gst_play_new();
171 gtk_signal_connect (GTK_OBJECT (mplay->play), "frame_displayed",
172 GTK_SIGNAL_FUNC (gst_media_play_frame_displayed),
173 mplay);
175 gtk_signal_connect (GTK_OBJECT (mplay->play), "audio_played",
176 GTK_SIGNAL_FUNC (gst_media_play_frame_displayed),
177 mplay);
179 gtk_signal_connect (GTK_OBJECT (mplay->play), "playing_state_changed",
180 GTK_SIGNAL_FUNC (gst_media_play_state_changed),
181 mplay);
183 gnome_dock_set_client_area (GNOME_DOCK (glade_xml_get_widget(mplay->xml, "dock1")),
184 GTK_WIDGET (mplay->play));
186 gtk_widget_show (GTK_WIDGET (mplay->play));
188 mplay->status = (GstStatusArea *) glade_xml_get_widget (mplay->xml, "status_area");
189 gst_status_area_set_state (mplay->status, GST_STATUS_AREA_STATE_INIT);
190 gst_status_area_set_playtime (mplay->status, "00:00 / 00:00");
192 symbols = g_module_open (NULL, 0);
194 data.play = mplay;
195 data.symbols = symbols;
197 glade_xml_signal_autoconnect_full (mplay->xml, gst_media_play_connect_func, &data);
199 mplay->last_time = 0;
200 }
202 GstMediaPlay *
203 gst_media_play_new ()
204 {
205 return GST_MEDIA_PLAY (gtk_type_new (GST_TYPE_MEDIA_PLAY));
206 }
208 static void
209 gst_media_play_update_status_area (GstMediaPlay *play,
210 gulong current_time,
211 gulong total_time)
212 {
213 gchar time[14];
215 sprintf (time, "%02lu:%02lu / %02lu:%02lu",
216 current_time / 60, current_time % 60,
217 total_time / 60, total_time % 60);
219 gst_status_area_set_playtime (play->status, time);
220 }
222 void
223 gst_media_play_start_uri (GstMediaPlay *play,
224 const guchar *uri)
225 {
226 GstPlayReturn ret;
228 g_return_if_fail (play != NULL);
229 g_return_if_fail (GST_IS_MEDIA_PLAY (play));
231 if (uri != NULL) {
232 ret = gst_play_set_uri (play->play, uri);
234 if (!gst_play_media_can_seek (play->play)) {
235 gtk_widget_set_sensitive (play->slider, FALSE);
236 }
238 gtk_window_set_title (GTK_WINDOW (play->window),
239 g_strconcat ( "Gstplay - ", uri, NULL));
241 gst_play_play (play->play);
242 }
243 }
245 typedef struct {
246 GtkWidget *selection;
247 GstMediaPlay *play;
248 } file_select;
250 static void
251 on_load_file_selected (GtkWidget *button,
252 file_select *data)
253 {
254 GtkWidget *selector = data->selection;
255 GstMediaPlay *play = data->play;
257 gchar *file_name = gtk_file_selection_get_filename (GTK_FILE_SELECTION (selector));
258 gdk_threads_leave();
259 gst_media_play_start_uri (play, file_name);
260 gdk_threads_enter();
262 g_free (data);
263 }
265 void
266 on_open2_activate (GtkWidget *widget,
267 GstMediaPlay *play)
268 {
269 GtkWidget *file_selector;
270 file_select *file_data = g_new0 (file_select, 1);
272 file_selector = gtk_file_selection_new ("Please select a file to load.");
274 file_data->selection = file_selector;
275 file_data->play = play;
277 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_selector)->ok_button),
278 "clicked", GTK_SIGNAL_FUNC (on_load_file_selected),
279 file_data);
281 /* Ensure that the dialog box is destroyed when the user clicks a button. */
282 gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (file_selector)->ok_button),
283 "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
284 (gpointer) file_selector);
285 gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (file_selector)->cancel_button),
286 "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
287 (gpointer) file_selector);
289 /* Display that dialog */
290 gtk_widget_show (file_selector);
291 }
294 static void
295 gst_media_play_set_arg (GtkObject *object,
296 GtkArg *arg,
297 guint id)
298 {
299 GstMediaPlay *play;
300 play = GST_MEDIA_PLAY (object);
302 switch (id) {
303 default:
304 g_warning ("GstMediaPlay: unknown arg!");
305 break;
306 }
307 }
309 static void
310 gst_media_play_get_arg (GtkObject *object,
311 GtkArg *arg,
312 guint id)
313 {
314 GstMediaPlay *play;
316 play = GST_MEDIA_PLAY (object);
318 switch (id) {
319 default:
320 arg->type = GTK_TYPE_INVALID;
321 break;
322 }
323 }
325 static void
326 gst_media_play_state_changed (GstPlay *play,
327 GstPlayState state,
328 GstMediaPlay *mplay)
329 {
330 GstStatusAreaState area_state;
332 g_return_if_fail (GST_IS_PLAY (play));
333 g_return_if_fail (GST_IS_MEDIA_PLAY (mplay));
336 gdk_threads_enter ();
337 update_buttons (mplay, state);
339 switch (state) {
340 case GST_PLAY_STOPPED:
341 area_state = GST_STATUS_AREA_STATE_STOPPED;
342 break;
343 case GST_PLAY_PLAYING:
344 area_state = GST_STATUS_AREA_STATE_PLAYING;
345 break;
346 case GST_PLAY_PAUSED:
347 area_state = GST_STATUS_AREA_STATE_PAUSED;
348 break;
349 default:
350 area_state = GST_STATUS_AREA_STATE_INIT;
351 }
352 gst_status_area_set_state (mplay->status, area_state);
353 gdk_threads_leave ();
354 }
356 void
357 on_gst_media_play_destroy (GtkWidget *widget, GstMediaPlay *mplay)
358 {
359 gst_main_quit ();
360 }
362 void
363 on_exit_menu_activate (GtkWidget *widget, GstMediaPlay *mplay)
364 {
365 gdk_threads_leave ();
366 gst_play_stop (mplay->play);
367 gdk_threads_enter ();
368 gst_main_quit ();
369 }
371 gint
372 on_gst_media_play_delete_event (GtkWidget *widget,
373 GdkEvent *event,
374 GstMediaPlay *mplay)
375 {
376 gdk_threads_leave ();
377 gst_play_stop (mplay->play);
378 gdk_threads_enter ();
379 return FALSE;
380 }
382 void
383 on_extended1_activate (GtkCheckMenuItem *item, GstMediaPlay *mplay)
384 {
385 gdk_threads_leave ();
386 gst_status_area_show_extended (mplay->status, item->active);
387 gdk_threads_enter ();
388 }
390 static void
391 gst_media_play_frame_displayed (GstPlay *play, GstMediaPlay *mplay)
392 {
393 gulong current_time;
394 gulong total_time;
395 gulong size, current_offset;
397 g_return_if_fail (GST_IS_PLAY (play));
398 g_return_if_fail (GST_IS_MEDIA_PLAY (mplay));
400 current_time = gst_play_get_media_current_time (play);
401 total_time = gst_play_get_media_total_time (play);
402 size = gst_play_get_media_size (play);
403 current_offset = gst_play_get_media_offset (play);
405 //g_print ("%lu %lu %lu %lu\n", current_time, total_time, size, current_offset);
407 if (current_time != mplay->last_time) {
408 gdk_threads_enter ();
409 gst_media_play_update_status_area (mplay, current_time, total_time);
410 update_slider (mplay, mplay->adjustment, current_offset*100.0/size);
411 mplay->last_time = current_time;
412 gdk_threads_leave ();
413 }
414 }
416 static void
417 gst_media_play_slider_changed (GtkAdjustment *adj, GstMediaPlay *mplay)
418 {
419 gulong size;
421 g_return_if_fail (GST_IS_MEDIA_PLAY (mplay));
423 size = gst_play_get_media_size (mplay->play);
425 gst_play_media_seek (mplay->play, (int)(adj->value*size/100.0));
426 }
428 void
429 on_toggle_play_toggled (GtkToggleButton *togglebutton, GstMediaPlay *play)
430 {
431 gdk_threads_leave ();
432 gst_play_play (play->play);
433 gdk_threads_enter ();
434 update_buttons (play, GST_PLAY_STATE(play->play));
435 }
437 void
438 on_toggle_pause_toggled (GtkToggleButton *togglebutton, GstMediaPlay *play)
439 {
440 gdk_threads_leave ();
441 gst_play_pause (play->play);
442 gdk_threads_enter ();
443 update_buttons (play, GST_PLAY_STATE(play->play));
444 }
446 void
447 on_toggle_stop_toggled (GtkToggleButton *togglebutton, GstMediaPlay *play)
448 {
449 gdk_threads_leave ();
450 gst_play_stop (play->play);
451 gdk_threads_enter ();
452 update_buttons (play, GST_PLAY_STATE(play->play));
453 }
455 static void
456 update_buttons (GstMediaPlay *mplay, GstPlayState state)
457 {
458 gtk_signal_handler_block_by_func (GTK_OBJECT (mplay->play_button),
459 GTK_SIGNAL_FUNC (on_toggle_play_toggled),
460 mplay);
461 gtk_signal_handler_block_by_func (GTK_OBJECT (mplay->pause_button),
462 GTK_SIGNAL_FUNC (on_toggle_pause_toggled),
463 mplay);
464 gtk_signal_handler_block_by_func (GTK_OBJECT (mplay->stop_button),
465 GTK_SIGNAL_FUNC (on_toggle_stop_toggled),
466 mplay);
468 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mplay->play_button), FALSE);
469 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mplay->pause_button), FALSE);
470 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mplay->stop_button), FALSE);
472 if (state == GST_PLAY_PLAYING) {
473 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mplay->play_button), TRUE);
474 }
475 else if (state == GST_PLAY_PAUSED) {
476 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mplay->pause_button), TRUE);
477 }
478 else if (state == GST_PLAY_STOPPED) {
479 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mplay->stop_button), TRUE);
480 }
482 gtk_signal_handler_unblock_by_func (GTK_OBJECT (mplay->play_button),
483 GTK_SIGNAL_FUNC (on_toggle_play_toggled),
484 mplay);
485 gtk_signal_handler_unblock_by_func (GTK_OBJECT (mplay->pause_button),
486 GTK_SIGNAL_FUNC (on_toggle_pause_toggled),
487 mplay);
488 gtk_signal_handler_unblock_by_func (GTK_OBJECT (mplay->stop_button),
489 GTK_SIGNAL_FUNC (on_toggle_stop_toggled),
490 mplay);
491 }
493 static void
494 update_slider (GstMediaPlay *mplay,
495 GtkAdjustment *adjustment,
496 gfloat value)
497 {
498 gtk_signal_handler_block_by_func (GTK_OBJECT (adjustment),
499 GTK_SIGNAL_FUNC (gst_media_play_slider_changed),
500 mplay);
501 gtk_adjustment_set_value (adjustment, value);
502 gtk_signal_handler_unblock_by_func (GTK_OBJECT (adjustment),
503 GTK_SIGNAL_FUNC (gst_media_play_slider_changed),
504 mplay);
505 }