#include #include #include #include #include "gstmediaplay.h" #include "callbacks.h" static void gst_media_play_class_init (GstMediaPlayClass *klass); static void gst_media_play_init (GstMediaPlay *play); static void gst_media_play_set_arg (GtkObject *object, GtkArg *arg, guint id); static void gst_media_play_get_arg (GtkObject *object, GtkArg *arg, guint id); static void gst_media_play_frame_displayed (GstPlay *play, GstMediaPlay *mplay); static void gst_media_play_state_changed (GstPlay *play, GstPlayState state, GstMediaPlay *mplay); static void gst_media_play_slider_changed (GtkAdjustment *adj, GstMediaPlay *mplay); static void update_buttons (GstMediaPlay *mplay, GstPlayState state); static void update_slider (GstMediaPlay *mplay, GtkAdjustment *adjustment, gfloat value); gboolean fullscreen_active = FALSE; /* signals and args */ enum { LAST_SIGNAL }; enum { ARG_0, }; static void target_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint time, GstMediaPlay *play) { g_print ("Got: %s\n", data->data); gdk_threads_leave (); gst_media_play_start_uri (play, g_strchomp (data->data)); gdk_threads_enter (); } static GtkTargetEntry target_table[] = { { "text/plain", 0, 0 } }; static GtkObject *parent_class = NULL; //static guint gst_media_play_signals[LAST_SIGNAL] = { 0 }; GtkType gst_media_play_get_type (void) { static GtkType play_type = 0; if (!play_type) { static const GtkTypeInfo play_info = { "GstMediaPlay", sizeof (GstMediaPlay), sizeof (GstMediaPlayClass), (GtkClassInitFunc) gst_media_play_class_init, (GtkObjectInitFunc) gst_media_play_init, NULL, NULL, (GtkClassInitFunc) NULL, }; play_type = gtk_type_unique (gtk_object_get_type(), &play_info); } return play_type; } static void gst_media_play_class_init (GstMediaPlayClass *klass) { GtkObjectClass *object_class; parent_class = gtk_type_class (gtk_object_get_type ()); object_class = (GtkObjectClass*) klass; object_class->set_arg = gst_media_play_set_arg; object_class->get_arg = gst_media_play_get_arg; } typedef struct { GstMediaPlay *play; GModule *symbols; } connect_struct; /* we need more control here so... */ static void gst_media_play_connect_func (const gchar *handler_name, GtkObject *object, const gchar *signal_name, const gchar *signal_data, GtkObject *connect_object, gboolean after, gpointer user_data) { GtkSignalFunc func; connect_struct *data = (connect_struct *) user_data; if (!g_module_symbol (data->symbols, handler_name, (gpointer *)&func)) g_warning ("gsteditorproperty: could not find signal handler '%s'.", handler_name); else { if (after) gtk_signal_connect_after (object, signal_name, func, (gpointer) data->play); else gtk_signal_connect (object, signal_name, func, (gpointer) data->play); } } static void gst_media_play_init (GstMediaPlay *mplay) { GModule *symbols; connect_struct data; struct stat statbuf; /* load the interface */ if (stat (DATADIR"gstmediaplay.glade", &statbuf) == 0) { mplay->xml = glade_xml_new (DATADIR"gstmediaplay.glade", "gstplay"); } else { mplay->xml = glade_xml_new ("gstmediaplay.glade", "gstplay"); } g_assert (mplay->xml != NULL); mplay->slider = glade_xml_get_widget (mplay->xml, "slider"); g_assert (mplay->slider != NULL); { GtkArg arg; GtkRange *range; arg.name = "adjustment"; gtk_object_getv (GTK_OBJECT (mplay->slider), 1, &arg); range = GTK_RANGE (GTK_VALUE_POINTER (arg)); mplay->adjustment = gtk_range_get_adjustment (range); gtk_signal_connect (GTK_OBJECT (mplay->adjustment), "value_changed", GTK_SIGNAL_FUNC (gst_media_play_slider_changed), mplay); } mplay->play_button = glade_xml_get_widget (mplay->xml, "toggle_play"); g_assert (mplay->play_button != NULL); mplay->pause_button = glade_xml_get_widget (mplay->xml, "toggle_pause"); g_assert (mplay->pause_button != NULL); mplay->stop_button = glade_xml_get_widget (mplay->xml, "toggle_stop"); g_assert (mplay->stop_button != NULL); mplay->window = glade_xml_get_widget (mplay->xml, "gstplay"); g_assert (mplay->window != NULL); gtk_drag_dest_set (mplay->window, GTK_DEST_DEFAULT_ALL, target_table, 1, GDK_ACTION_COPY); gtk_signal_connect (GTK_OBJECT (mplay->window), "drag_data_received", GTK_SIGNAL_FUNC (target_drag_data_received), mplay); mplay->play = gst_play_new(); gtk_signal_connect (GTK_OBJECT (mplay->play), "frame_displayed", GTK_SIGNAL_FUNC (gst_media_play_frame_displayed), mplay); gtk_signal_connect (GTK_OBJECT (mplay->play), "audio_played", GTK_SIGNAL_FUNC (gst_media_play_frame_displayed), mplay); gtk_signal_connect (GTK_OBJECT (mplay->play), "playing_state_changed", GTK_SIGNAL_FUNC (gst_media_play_state_changed), mplay); gnome_dock_set_client_area (GNOME_DOCK (glade_xml_get_widget(mplay->xml, "dock1")), GTK_WIDGET (mplay->play)); gtk_widget_show (GTK_WIDGET (mplay->play)); mplay->status = (GstStatusArea *) glade_xml_get_widget (mplay->xml, "status_area"); gst_status_area_set_state (mplay->status, GST_STATUS_AREA_STATE_INIT); gst_status_area_set_playtime (mplay->status, "00:00 / 00:00"); symbols = g_module_open (NULL, 0); data.play = mplay; data.symbols = symbols; glade_xml_signal_autoconnect_full (mplay->xml, gst_media_play_connect_func, &data); mplay->last_time = 0; } GstMediaPlay * gst_media_play_new () { return GST_MEDIA_PLAY (gtk_type_new (GST_TYPE_MEDIA_PLAY)); } static void gst_media_play_play_item (GtkCList *clist, gint row, gint column, GdkEventButton *event, GstMediaPlay *mplay) { gchar *text; gtk_clist_get_text (clist, row, column, &text); gdk_threads_leave (); gst_media_play_start_uri (mplay, text); gdk_threads_enter (); } void gst_media_play_show_playlist (GstMediaPlay *mplay) { struct stat statbuf; /* load the interface */ if (stat (DATADIR"gstmediaplay.glade", &statbuf) == 0) { mplay->playlist_xml = glade_xml_new (DATADIR"gstmediaplay.glade", "playlist_window"); } else { mplay->playlist_xml = glade_xml_new ("gstmediaplay.glade", "playlist_window"); } g_assert (mplay->playlist_xml != NULL); mplay->playlist_window = glade_xml_get_widget (mplay->playlist_xml, "playlist_window"); mplay->playlist_clist = glade_xml_get_widget (mplay->playlist_xml, "playlist_clist"); gtk_signal_connect (GTK_OBJECT (mplay->playlist_clist), "select_row", GTK_SIGNAL_FUNC (gst_media_play_play_item), mplay); gtk_window_set_default_size (GTK_WINDOW (mplay->playlist_window), 215, 280); gtk_widget_show (mplay->playlist_window); } void gst_media_play_addto_playlist (GstMediaPlay *mplay, char *uri) { gchar *text[2]; text[0] = uri; gtk_clist_append (GTK_CLIST (mplay->playlist_clist), text); } static void gst_media_play_update_status_area (GstMediaPlay *mplay, gulong current_time, gulong total_time) { gchar time[14]; sprintf (time, "%02lu:%02lu / %02lu:%02lu", current_time / 60, current_time % 60, total_time / 60, total_time % 60); gst_status_area_set_playtime (mplay->status, time); } void gst_media_play_start_uri (GstMediaPlay *mplay, const guchar *uri) { GstPlayReturn ret; g_return_if_fail (mplay != NULL); g_return_if_fail (GST_IS_MEDIA_PLAY (mplay)); if (uri != NULL) { ret = gst_play_set_uri (mplay->play, uri); if (ret == GST_PLAY_CANNOT_PLAY) { printf ("*** Cannot load file: %s ***\n", uri); } else { if (!gst_play_media_can_seek (mplay->play)) { gtk_widget_set_sensitive (mplay->slider, FALSE); } gtk_window_set_title (GTK_WINDOW (mplay->window), g_strconcat ( "Gstplay - ", uri, NULL)); gst_play_play (mplay->play); } } } typedef struct { GtkWidget *selection; GstMediaPlay *play; } file_select; static void on_load_file_selected (GtkWidget *button, file_select *data) { GtkWidget *selector = data->selection; GstMediaPlay *play = data->play; gchar *file_name = gtk_file_selection_get_filename (GTK_FILE_SELECTION (selector)); gdk_threads_leave(); gst_media_play_start_uri (play, file_name); gdk_threads_enter(); //gst_media_play_addto_playlist (play, file_name); g_free (data); } void on_open2_activate (GtkWidget *widget, GstMediaPlay *play) { GtkWidget *file_selector; file_select *file_data = g_new0 (file_select, 1); file_selector = gtk_file_selection_new ("Please select a file to load."); file_data->selection = file_selector; file_data->play = play; gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_selector)->ok_button), "clicked", GTK_SIGNAL_FUNC (on_load_file_selected), file_data); /* Ensure that the dialog box is destroyed when the user clicks a button. */ gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (file_selector)->ok_button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) file_selector); gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (file_selector)->cancel_button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) file_selector); /* Display that dialog */ gtk_widget_show (file_selector); } static void gst_media_play_set_arg (GtkObject *object, GtkArg *arg, guint id) { GstMediaPlay *play; play = GST_MEDIA_PLAY (object); switch (id) { default: g_warning ("GstMediaPlay: unknown arg!"); break; } } static void gst_media_play_get_arg (GtkObject *object, GtkArg *arg, guint id) { GstMediaPlay *play; play = GST_MEDIA_PLAY (object); switch (id) { default: arg->type = GTK_TYPE_INVALID; break; } } static void gst_media_play_state_changed (GstPlay *play, GstPlayState state, GstMediaPlay *mplay) { GstStatusAreaState area_state; g_return_if_fail (GST_IS_PLAY (play)); g_return_if_fail (GST_IS_MEDIA_PLAY (mplay)); gdk_threads_enter (); update_buttons (mplay, state); switch (state) { case GST_PLAY_STOPPED: area_state = GST_STATUS_AREA_STATE_STOPPED; break; case GST_PLAY_PLAYING: area_state = GST_STATUS_AREA_STATE_PLAYING; break; case GST_PLAY_PAUSED: area_state = GST_STATUS_AREA_STATE_PAUSED; break; default: area_state = GST_STATUS_AREA_STATE_INIT; } gst_status_area_set_state (mplay->status, area_state); gdk_threads_leave (); } void on_gst_media_play_destroy (GtkWidget *widget, GstMediaPlay *mplay) { gst_main_quit (); } void on_exit_menu_activate (GtkWidget *widget, GstMediaPlay *mplay) { gdk_threads_leave (); gst_play_stop (mplay->play); gdk_threads_enter (); gst_main_quit (); } gint on_gst_media_play_delete_event (GtkWidget *widget, GdkEvent *event, GstMediaPlay *mplay) { gdk_threads_leave (); gst_play_stop (mplay->play); gdk_threads_enter (); return FALSE; } void on_extended1_activate (GtkCheckMenuItem *item, GstMediaPlay *mplay) { gdk_threads_leave (); gst_status_area_show_extended (mplay->status, item->active); gdk_threads_enter (); } void gst_media_play_set_original_size (GstMediaPlay *mplay) { GstPlay *play; GtkWidget *video_widget; gint width, height; play = mplay->play; if (fullscreen_active) gst_media_play_set_fullscreen (mplay); video_widget = gst_play_get_video_widget (play); width = gst_play_get_source_width (play); height = gst_play_get_source_height (play); gtk_widget_set_usize (video_widget, width, height); } void gst_media_play_set_double_size (GstMediaPlay *mplay) { GstPlay *play; GtkWidget *video_widget; gint width, height; play = mplay->play; if (fullscreen_active) gst_media_play_set_fullscreen (mplay); video_widget = gst_play_get_video_widget (play); width = gst_play_get_source_width (play); height = gst_play_get_source_height (play); gtk_widget_set_usize (video_widget, width * 1.5, height * 1.5); } static int fullscreen_key_press_event (GtkWidget *widget, GdkEventKey *event, GstMediaPlay *mplay) { switch (event->keyval) { case GDK_Escape: gst_media_play_set_fullscreen (mplay); break; } return TRUE; } void gst_media_play_set_fullscreen (GstMediaPlay *mplay) { GdkWindow *gdk_window; gint client_x, client_y, root_x, root_y; gint width, height, source_width, source_height; GstPlay *play; GtkWidget *video_widget; GdkCursor* cursor; GdkPixmap *source; GdkPixmap *mask; GdkColor fg = {0, 0, 0, 0}; GdkColor bg = {0, 0, 0, 0}; static unsigned char cursor_bits[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; static unsigned char cursormask_bits[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; gdk_window = mplay->window->window; play = mplay->play; video_widget = gst_play_get_video_widget (play); source_width = gst_play_get_source_width (play); source_height = gst_play_get_source_height (play); if (source_width || source_height) { if (!fullscreen_active) { gtk_widget_hide (glade_xml_get_widget (mplay->xml, "dockitem1")); gtk_widget_hide (glade_xml_get_widget (mplay->xml, "dockitem2")); gtk_widget_hide (glade_xml_get_widget (mplay->xml, "dockitem3")); gtk_widget_hide (glade_xml_get_widget (mplay->xml, "dockitem4")); gtk_widget_hide (GTK_WIDGET (mplay->status)); gdk_window_get_origin (gdk_window, &root_x, &root_y); gdk_window_get_geometry (gdk_window, &client_x, &client_y, &width, &height, NULL); gdk_window_move (gdk_window, -client_x, -client_y); gtk_widget_set_usize (video_widget, gdk_screen_width () + 1, gdk_screen_height () + 1); source = gdk_bitmap_create_from_data (NULL, cursor_bits, 16, 16); mask = gdk_bitmap_create_from_data (NULL, cursormask_bits, 16, 16); cursor = gdk_cursor_new_from_pixmap (source, mask, &fg, &bg, 8, 8); gdk_pixmap_unref (source); gdk_pixmap_unref (mask); gdk_window_set_cursor (mplay->window->window, cursor); mplay->x = root_x - client_x; mplay->y = root_y - client_y; mplay->width = width; mplay->height = height; fullscreen_active = TRUE; mplay->fullscreen_connection_id = gtk_signal_connect (GTK_OBJECT (mplay->window), "key_press_event", (GtkSignalFunc) fullscreen_key_press_event, mplay); } else { gtk_widget_show (glade_xml_get_widget (mplay->xml, "dockitem1")); gtk_widget_show (glade_xml_get_widget (mplay->xml, "dockitem2")); gtk_widget_show (glade_xml_get_widget (mplay->xml, "dockitem3")); gtk_widget_show (glade_xml_get_widget (mplay->xml, "dockitem4")); gtk_widget_show (GTK_WIDGET (mplay->status)); gtk_widget_queue_resize (glade_xml_get_widget (mplay->xml, "dock1")); gdk_window_move (gdk_window, mplay->x, mplay->y); gtk_widget_set_usize (video_widget, source_width, source_height); gdk_window_set_cursor (mplay->window->window, NULL); gtk_signal_disconnect (GTK_OBJECT (mplay->window), mplay->fullscreen_connection_id); fullscreen_active = FALSE; } } } static void gst_media_play_frame_displayed (GstPlay *play, GstMediaPlay *mplay) { gulong current_time; gulong total_time; gulong size, current_offset; g_return_if_fail (GST_IS_PLAY (play)); g_return_if_fail (GST_IS_MEDIA_PLAY (mplay)); current_time = gst_play_get_media_current_time (play); total_time = gst_play_get_media_total_time (play); size = gst_play_get_media_size (play); current_offset = gst_play_get_media_offset (play); //g_print ("%lu %lu %lu %lu\n", current_time, total_time, size, current_offset); if (current_time != mplay->last_time) { gdk_threads_enter (); gst_media_play_update_status_area (mplay, current_time, total_time); update_slider (mplay, mplay->adjustment, current_offset*100.0/size); mplay->last_time = current_time; gdk_threads_leave (); } } static void gst_media_play_slider_changed (GtkAdjustment *adj, GstMediaPlay *mplay) { gulong size; g_return_if_fail (GST_IS_MEDIA_PLAY (mplay)); size = gst_play_get_media_size (mplay->play); gst_play_media_seek (mplay->play, (int)(adj->value*size/100.0)); } void on_toggle_play_toggled (GtkToggleButton *togglebutton, GstMediaPlay *play) { gdk_threads_leave (); gst_play_play (play->play); gdk_threads_enter (); update_buttons (play, GST_PLAY_STATE(play->play)); } void on_toggle_pause_toggled (GtkToggleButton *togglebutton, GstMediaPlay *play) { gdk_threads_leave (); gst_play_pause (play->play); gdk_threads_enter (); update_buttons (play, GST_PLAY_STATE(play->play)); } void on_toggle_stop_toggled (GtkToggleButton *togglebutton, GstMediaPlay *play) { gdk_threads_leave (); gst_play_stop (play->play); gdk_threads_enter (); update_buttons (play, GST_PLAY_STATE(play->play)); } static void update_buttons (GstMediaPlay *mplay, GstPlayState state) { gtk_signal_handler_block_by_func (GTK_OBJECT (mplay->play_button), GTK_SIGNAL_FUNC (on_toggle_play_toggled), mplay); gtk_signal_handler_block_by_func (GTK_OBJECT (mplay->pause_button), GTK_SIGNAL_FUNC (on_toggle_pause_toggled), mplay); gtk_signal_handler_block_by_func (GTK_OBJECT (mplay->stop_button), GTK_SIGNAL_FUNC (on_toggle_stop_toggled), mplay); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mplay->play_button), FALSE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mplay->pause_button), FALSE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mplay->stop_button), FALSE); if (state == GST_PLAY_PLAYING) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mplay->play_button), TRUE); } else if (state == GST_PLAY_PAUSED) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mplay->pause_button), TRUE); } else if (state == GST_PLAY_STOPPED) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mplay->stop_button), TRUE); } gtk_signal_handler_unblock_by_func (GTK_OBJECT (mplay->play_button), GTK_SIGNAL_FUNC (on_toggle_play_toggled), mplay); gtk_signal_handler_unblock_by_func (GTK_OBJECT (mplay->pause_button), GTK_SIGNAL_FUNC (on_toggle_pause_toggled), mplay); gtk_signal_handler_unblock_by_func (GTK_OBJECT (mplay->stop_button), GTK_SIGNAL_FUNC (on_toggle_stop_toggled), mplay); } static void update_slider (GstMediaPlay *mplay, GtkAdjustment *adjustment, gfloat value) { gtk_signal_handler_block_by_func (GTK_OBJECT (adjustment), GTK_SIGNAL_FUNC (gst_media_play_slider_changed), mplay); gtk_adjustment_set_value (adjustment, value); gtk_signal_handler_unblock_by_func (GTK_OBJECT (adjustment), GTK_SIGNAL_FUNC (gst_media_play_slider_changed), mplay); }