diff --git a/gst/elements/gstqueue.c b/gst/elements/gstqueue.c index 302388b1b5..0b635c6a18 100644 --- a/gst/elements/gstqueue.c +++ b/gst/elements/gstqueue.c @@ -57,8 +57,12 @@ static void gst_queue_init(GstQueue *queue); static void gst_queue_set_arg(GtkObject *object,GtkArg *arg,guint id); static void gst_queue_get_arg(GtkObject *object,GtkArg *arg,guint id); -void gst_queue_push(GstConnection *connection); -void gst_queue_chain(GstPad *pad,GstBuffer *buf); +static void gst_queue_push(GstConnection *connection); +static void gst_queue_chain(GstPad *pad,GstBuffer *buf); + +static void gst_queue_flush(GstQueue *queue); + +static GstElementStateReturn gst_queue_change_state(GstElement *element); static GstConnectionClass *parent_class = NULL; //static guint gst_queue_signals[LAST_SIGNAL] = { 0 }; @@ -85,9 +89,11 @@ gst_queue_get_type(void) { static void gst_queue_class_init(GstQueueClass *klass) { GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; GstConnectionClass *gstconnection_class; gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; gstconnection_class = (GstConnectionClass*)klass; parent_class = gtk_type_class(GST_TYPE_CONNECTION); @@ -101,6 +107,8 @@ static void gst_queue_class_init(GstQueueClass *klass) { gtkobject_class->set_arg = gst_queue_set_arg; gtkobject_class->get_arg = gst_queue_get_arg; + + gstelement_class->change_state = gst_queue_change_state; } static void gst_queue_init(GstQueue *queue) { @@ -137,7 +145,14 @@ static void gst_queue_cleanup_buffers(gpointer data, gpointer user_data) gst_buffer_unref(GST_BUFFER(data)); } -void gst_queue_chain(GstPad *pad,GstBuffer *buf) { +static void gst_queue_flush(GstQueue *queue) { + g_slist_foreach(queue->queue, gst_queue_cleanup_buffers, gst_element_get_name(GST_ELEMENT(queue))); + g_slist_free(queue->queue); + queue->queue = NULL; + queue->level_buffers = 0; +} + +static void gst_queue_chain(GstPad *pad,GstBuffer *buf) { GstQueue *queue; gboolean tosignal = FALSE; guchar *name; @@ -157,13 +172,9 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) { DEBUG("queue: have queue lock\n"); if (GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLUSH)) { - g_slist_foreach(queue->queue, gst_queue_cleanup_buffers, name); - g_slist_free(queue->queue); - queue->queue = NULL; - queue->level_buffers = 0; + gst_queue_flush(queue); } - DEBUG("queue: %s: chain %d %p\n", name, queue->level_buffers, buf); while (queue->level_buffers >= queue->max_buffers) { @@ -199,7 +210,7 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) { } } -void gst_queue_push(GstConnection *connection) { +static void gst_queue_push(GstConnection *connection) { GstQueue *queue = GST_QUEUE(connection); GstBuffer *buf = NULL; GSList *front; @@ -248,6 +259,26 @@ void gst_queue_push(GstConnection *connection) { /* unlock now */ } +static GstElementStateReturn gst_queue_change_state(GstElement *element) { + GstQueue *queue; + g_return_val_if_fail(GST_IS_QUEUE(element),GST_STATE_FAILURE); + + queue = GST_QUEUE(element); + DEBUG("gstqueue: state pending %d\n", GST_STATE_PENDING(element)); + + /* if going down into NULL state, clear out buffers*/ + if (GST_STATE_PENDING(element) == GST_STATE_READY) { + /* otherwise (READY or higher) we need to open the file */ + gst_queue_flush(queue); + } + + /* if we haven't failed already, give the parent class a chance to ;-) */ + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element); + + return GST_STATE_SUCCESS; +} + static void gst_queue_set_arg(GtkObject *object,GtkArg *arg,guint id) { GstQueue *queue; diff --git a/gst/gstbin.c b/gst/gstbin.c index d3a0d1e140..cd537eecf6 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -720,7 +720,7 @@ void gst_bin_iterate_func(GstBin *bin) { gst_element_get_name(GST_ELEMENT(bin->children->data))); } else { if (bin->numentries <= 0) { - printf("gstbin: no entries in bin \"%s\" trying children...\n", gst_element_get_name(GST_ELEMENT(bin))); + //printf("gstbin: no entries in bin \"%s\" trying children...\n", gst_element_get_name(GST_ELEMENT(bin))); // we will try loop over the elements then... entries = bin->children; } diff --git a/gst/gstthread.c b/gst/gstthread.c index 6c2c2b444f..5c230ee441 100644 --- a/gst/gstthread.c +++ b/gst/gstthread.c @@ -170,6 +170,7 @@ GstElement *gst_thread_new(guchar *name) { thread = gtk_type_new(gst_thread_get_type()); gst_element_set_name(GST_ELEMENT(thread),name); + GST_FLAG_UNSET(thread,GST_THREAD_STATE_REAPING); return GST_ELEMENT(thread); } @@ -205,7 +206,6 @@ static GstElementStateReturn gst_thread_change_state(GstElement *element) { // set the state to idle GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING); - GST_FLAG_UNSET(thread,GST_THREAD_STATE_REAPING); // create the thread if that's what we're supposed to do gst_info("gstthread: flags are 0x%08x\n",GST_FLAGS(thread)); if (GST_FLAG_IS_SET(thread,GST_THREAD_CREATE)) { @@ -224,14 +224,12 @@ static GstElementStateReturn gst_thread_change_state(GstElement *element) { gst_info("gstthread: starting thread \"%s\"\n", gst_element_get_name(GST_ELEMENT(element))); GST_FLAG_SET(thread,GST_THREAD_STATE_SPINNING); - GST_FLAG_UNSET(thread,GST_THREAD_STATE_REAPING); gst_thread_signal_thread(thread); break; case GST_STATE_PAUSED: gst_info("gstthread: pausing thread \"%s\"\n", gst_element_get_name(GST_ELEMENT(element))); GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING); - GST_FLAG_UNSET(thread,GST_THREAD_STATE_REAPING); gst_thread_signal_thread(thread); break; case GST_STATE_NULL: diff --git a/gstplay/.gitignore b/gstplay/.gitignore index fd40a01393..e1ca49e2f7 100644 --- a/gstplay/.gitignore +++ b/gstplay/.gitignore @@ -5,4 +5,4 @@ Makefile.in *.la .deps .libs -gstplay +gstmediaplay diff --git a/gstplay/Makefile.am b/gstplay/Makefile.am index b8783c8c6a..caec689be5 100644 --- a/gstplay/Makefile.am +++ b/gstplay/Makefile.am @@ -4,21 +4,24 @@ INCLUDES = $(GLIB_CFLAGS) $(GTK_CFLAGS) -I$(top_srcdir) \ $(shell gnome-config --cflags gnomeui) $(shell gstreamer-config --cflags) -bin_PROGRAMS = gstplay +bin_PROGRAMS = gstmediaplay -gladedir = $(datadir)/gstplay -glade_DATA = gstplay.glade play.xpm stop.xpm pause.xpm +gladedir = $(datadir)/gstmediaplay +glade_DATA = gstmediaplay.glade play.xpm stop.xpm pause.xpm -gstplay_SOURCES = \ - gstplay.c \ - interface.c interface.h \ - callbacks.c callbacks.h +gstmediaplay_SOURCES = \ + gstplay.c main.c \ + gstmediaplay.c gstmediaplay.h \ + gststatusarea.c gststatusarea.h \ + callbacks.c callbacks.h + +# interface.c interface.h CFLAGS += -O2 -Wall -DDATADIR=\""$(gladedir)/"\" -gstplay_CFLAGS = $(shell gnome-config --cflags gnomeui) $(shell libglade-config --cflags gnome) \ +gstmediaplay_CFLAGS = $(shell gnome-config --cflags gnomeui) $(shell libglade-config --cflags gnome) \ $(shell gstreamer-config --cflags ) -gstplay_LDFLAGS = $(shell gnome-config --libs gnomeui) $(shell libglade-config --libs gnome) \ +gstmediaplay_LDFLAGS = $(shell gnome-config --libs gnomeui) $(shell libglade-config --libs gnome) \ $(shell gstreamer-config --libs ) if HAVE_LIBXV @@ -27,7 +30,7 @@ else xvlibs= endif -gstplay_LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(top_builddir)/gst/libgst.la \ +gstmediaplay_LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(top_builddir)/gst/libgst.la \ $(top_builddir)/plugins/videosink/gdkxvimage.lo ${xvlibs} -lXxf86vm diff --git a/gstplay/callbacks.c b/gstplay/callbacks.c index c1bd000d52..b84796c982 100644 --- a/gstplay/callbacks.c +++ b/gstplay/callbacks.c @@ -10,12 +10,7 @@ #include "callbacks.h" #include "interface.h" -extern GstElement *src; -extern gboolean picture_shown; -extern GstPlayState state; -extern guchar statusline[]; -extern guchar *statustext; -extern GtkFileSelection *open_file_selection; +GtkFileSelection *open_file_selection; void on_save1_activate (GtkMenuItem *menuitem, @@ -53,75 +48,35 @@ on_open2_activate (GtkMenuItem *menuitem, gpointer user_data) { GladeXML *xml; - xml = glade_xml_new(DATADIR "gstplay.glade", "fileselection1"); + xml = glade_xml_new(DATADIR "gstmediaplay.glade", "fileselection1"); /* connect the signals in the interface */ glade_xml_signal_autoconnect(xml); - open_file_selection = glade_xml_get_widget(xml, "fileselection1"); -} - -void -on_toggle_play_toggled (GtkToggleButton *togglebutton, - gpointer user_data) -{ - update_buttons(0); - change_state(GSTPLAY_PLAYING); - -} - -void -on_toggle_pause_toggled (GtkToggleButton *togglebutton, - gpointer user_data) -{ - update_buttons(1); - change_state(GSTPLAY_PAUSE); - -} - -void -on_toggle_stop_toggled (GtkToggleButton *togglebutton, - gpointer user_data) -{ - update_buttons(2); - change_state(GSTPLAY_STOPPED); + open_file_selection = GTK_FILE_SELECTION(glade_xml_get_widget(xml, "fileselection1")); } void on_hscale1_value_changed (GtkAdjustment *adj, gpointer user_data) { - int size = gst_util_get_int_arg(GTK_OBJECT(src),"size"); + //int size = gst_util_get_int_arg(GTK_OBJECT(src),"size"); - gtk_object_set(GTK_OBJECT(src),"offset",(int)(adj->value*size/100.0),NULL); + //gtk_object_set(GTK_OBJECT(src),"offset",(int)(adj->value*size/100.0),NULL); - if (state != GSTPLAY_PLAYING) { - show_next_picture(); - } -} - -void -on_drawingarea1_configure_event (GtkWidget *widget, GdkEventConfigure *event, - gpointer user_data) -{ - gdk_draw_rectangle(widget->window, - widget->style->black_gc, - TRUE, 0,0, - widget->allocation.width, - widget->allocation.height); - - gdk_draw_string(widget->window,widget->style->font,widget->style->white_gc, 8, 15, statustext); - gdk_draw_string(widget->window,widget->style->font,widget->style->white_gc, widget->allocation.width-100, 15, statusline); + //if (state != GSTPLAY_PLAYING) { + // show_next_picture(); + //} } void on_about_activate(GtkWidget *widget, gpointer data) { GladeXML *xml; - xml = glade_xml_new(DATADIR "gstplay.glade", "about"); + xml = glade_xml_new(DATADIR "gstmediaplay.glade", "about"); /* connect the signals in the interface */ glade_xml_signal_autoconnect(xml); } void on_gstplay_destroy(GtkWidget *widget, gpointer data) { - gtk_main_quit(); + gst_main_quit(); } diff --git a/gstplay/callbacks.h b/gstplay/callbacks.h index 032fb24f4f..acaa086abd 100644 --- a/gstplay/callbacks.h +++ b/gstplay/callbacks.h @@ -40,14 +40,3 @@ void on_drawingarea1_configure_event (GtkWidget *widget, GdkEventConfigure *event, gpointer user_data); -void -on_toggle_play_toggled (GtkToggleButton *togglebutton, - gpointer user_data); - -void -on_toggle_pause_toggled (GtkToggleButton *togglebutton, - gpointer user_data); - -void -on_toggle_stop_toggled (GtkToggleButton *togglebutton, - gpointer user_data); diff --git a/gstplay/codecs.h b/gstplay/codecs.h deleted file mode 100644 index 88fb26a56a..0000000000 --- a/gstplay/codecs.h +++ /dev/null @@ -1,12 +0,0 @@ - -/* mpeg1.c */ -void mpeg1_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline); -void mpeg1_setup_video_thread(GstPad *pad, GstElement *show, GstElement *pipeline); -void mpeg1_setup_audio_thread(GstPad *pad, GstElement *show, GstElement *pipeline); - -/* mpeg2.c */ -void mpeg2_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline); -void mpeg2_setup_video_thread(GstPad *pad, GstElement *show, GstElement *pipeline); - -/* avi.c */ -void avi_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline); diff --git a/gstplay/gstmediaplay.c b/gstplay/gstmediaplay.c new file mode 100644 index 0000000000..a3b9fad8d1 --- /dev/null +++ b/gstplay/gstmediaplay.c @@ -0,0 +1,297 @@ +/* + * Initial main.c file generated by Glade. Edit as required. + * Glade will not overwrite this file. + */ + +#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 update_buttons (GstMediaPlay *mplay, GstPlayState state); +static void update_slider (GtkAdjustment *adjustment, gfloat value); + +/* 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) +{ + if (strstr (data->data, "file:")) { + g_print ("Got: %s\n",data->data); + } +} + +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) +{ + GtkWidget *gstplay; + GModule *symbols; + connect_struct data; + + glade_init(); + glade_gnome_init(); + + g_print("using %s\n", DATADIR"gstmediaplay.glade"); + /* load the interface */ + mplay->xml = glade_xml_new (DATADIR "gstmediaplay.glade", "gstplay"); + + mplay->play_button = glade_xml_get_widget (mplay->xml, "toggle_play"); + mplay->pause_button = glade_xml_get_widget (mplay->xml, "toggle_pause"); + mplay->stop_button = glade_xml_get_widget (mplay->xml, "toggle_stop"); + + gstplay = glade_xml_get_widget (mplay->xml, "gstplay"); + gtk_drag_dest_set (gstplay, + GTK_DEST_DEFAULT_ALL, + target_table, 1, + GDK_ACTION_COPY); + gtk_signal_connect (GTK_OBJECT (gstplay), "drag_data_received", + GTK_SIGNAL_FUNC (target_drag_data_received), + NULL); + + mplay->play = gst_play_new(); + + 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 = gst_status_area_new(); + 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); + + gtk_container_add (GTK_CONTAINER (glade_xml_get_widget (mplay->xml, "dockitem4")), + GTK_WIDGET (mplay->status)); + gtk_widget_show (GTK_WIDGET (mplay->status)); + +} + +GstMediaPlay * +gst_media_play_new () +{ + return GST_MEDIA_PLAY (gtk_type_new (GST_TYPE_MEDIA_PLAY)); +} + +void +gst_media_play_start_uri (GstMediaPlay *play, + const guchar *uri) +{ + GstPlayReturn ret; + + g_return_if_fail (play != NULL); + g_return_if_fail (GST_IS_MEDIA_PLAY (play)); + + if (uri != NULL) { + ret = gst_play_set_uri (play->play, uri); + gst_status_area_set_state (play->status, GST_STATUS_AREA_STATE_PLAYING); + gst_play_play (play->play); + update_buttons (play, GST_PLAY_STATE (play->play)); + } +} + +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; + } +} + +void +on_toggle_play_toggled (GtkToggleButton *togglebutton, + GstMediaPlay *play) +{ + gst_status_area_set_state (play->status, GST_STATUS_AREA_STATE_PLAYING); + gst_play_play (play->play); + update_buttons (play, GST_PLAY_STATE (play->play)); +} + +void +on_toggle_pause_toggled (GtkToggleButton *togglebutton, + GstMediaPlay *play) +{ + gst_status_area_set_state (play->status, GST_STATUS_AREA_STATE_PAUSED); + gst_play_pause (play->play); + update_buttons (play, GST_PLAY_STATE (play->play)); +} + +void +on_toggle_stop_toggled (GtkToggleButton *togglebutton, + GstMediaPlay *play) +{ + gst_status_area_set_state (play->status, GST_STATUS_AREA_STATE_STOPPED); + gst_play_stop (play->play); + 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 (GtkAdjustment *adjustment, + gfloat value) +{ + gtk_signal_handler_block_by_func (GTK_OBJECT (adjustment), + GTK_SIGNAL_FUNC (on_hscale1_value_changed), + NULL); + gtk_adjustment_set_value (adjustment, value); + gtk_signal_handler_unblock_by_func (GTK_OBJECT (adjustment), + GTK_SIGNAL_FUNC (on_hscale1_value_changed), + NULL); +} + diff --git a/gstplay/gstplay.glade b/gstplay/gstmediaplay.glade similarity index 97% rename from gstplay/gstplay.glade rename to gstplay/gstmediaplay.glade index f0248a6e85..d2cab82dda 100644 --- a/gstplay/gstplay.glade +++ b/gstplay/gstmediaplay.glade @@ -2,8 +2,8 @@ - Gstplay - gstplay + GstMediaPlay + gstmediaplay src pixmaps @@ -369,14 +369,7 @@ GTK_SHADOW_OUT - GtkDrawingArea - status_area - 21 - - configure_event - on_drawingarea1_configure_event - Sun, 06 Aug 2000 11:27:09 GMT - + Placeholder diff --git a/gstplay/gstmediaplay.h b/gstplay/gstmediaplay.h new file mode 100644 index 0000000000..d14c3abfd4 --- /dev/null +++ b/gstplay/gstmediaplay.h @@ -0,0 +1,55 @@ +/* + * Initial main.c file generated by Glade. Edit as required. + * Glade will not overwrite this file. + */ + +#ifndef __GST_MEDIA_PLAY_H__ +#define __GST_MEDIA_PLAY_H__ + + +#include + +#include "gstplay.h" +#include "gststatusarea.h" + +typedef struct _GstMediaPlay GstMediaPlay; +typedef struct _GstMediaPlayClass GstMediaPlayClass; + +#define GST_TYPE_MEDIA_PLAY \ + (gst_media_play_get_type()) +#define GST_MEDIA_PLAY(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_MEDIA_PLAY,GstMediaPlay)) +#define GST_MEDIA_PLAY_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_MEDIA_PLAY,GstMediaPlayClass)) +#define GST_IS_MEDIA_PLAY(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_MEDIA_PLAY)) +#define GST_IS_MEDIA_PLAY_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_MEDIA_PLAY)) + +struct _GstMediaPlay { + GtkObject parent; + + GladeXML *xml; + GstPlay *play; + + GtkWidget *play_button; + GtkWidget *pause_button; + GtkWidget *stop_button; + + GstStatusArea *status; +}; + +struct _GstMediaPlayClass { + GtkObjectClass parent_class; + +}; + + +GtkType gst_media_play_get_type (void); + +/* setup the player */ +GstMediaPlay* gst_media_play_new (void); + +void gst_media_play_start_uri (GstMediaPlay *play, const guchar *uri); + +#endif /* __GST_MEDIA_PLAY_H__ */ diff --git a/gstplay/gstplay.c b/gstplay/gstplay.c index 5f54cf6978..5482471168 100644 --- a/gstplay/gstplay.c +++ b/gstplay/gstplay.c @@ -5,298 +5,359 @@ #include -//#define DEBUG_ENABLED - -#include -#include - #include "gstplay.h" +#include "gstplayprivate.h" -#include "callbacks.h" -#include "interface.h" +static void gst_play_class_init (GstPlayClass *klass); +static void gst_play_init (GstPlay *play); -#define MUTEX_STATUS() (g_mutex_trylock(gdk_threads_mutex)? g_mutex_unlock(gdk_threads_mutex), "was not locked" : "was locked") +static void gst_play_set_arg (GtkObject *object,GtkArg *arg,guint id); +static void gst_play_get_arg (GtkObject *object,GtkArg *arg,guint id); -#define BUFFER 20 +static void gst_play_realize (GtkWidget *play); -static gboolean idle_func(gpointer data); -static gint start_from_file(guchar *filename); +static void gst_play_frame_displayed (GstElement *element, GstPlay *play); +static void gst_play_audio_handoff (GstElement *element, GstPlay *play); -GstElement *show; -GstElement *audio_play; -GstElement *src; -GstElement *parse; -GstElement *pipeline; -GstPlayState state; -gboolean picture_shown = FALSE; -guchar statusline[200]; -guchar *statustext = "stopped"; -GtkWidget *status_area; -GtkWidget *video; -GtkAdjustment *adjustment; -GtkWidget *play_button; -GtkWidget *pause_button; -GtkWidget *stop_button; -GtkFileSelection *open_file_selection; - -static void frame_displayed(GstSrc *asrc) -{ - int size, time, frame_time = 0, src_pos; - guint mux_rate; - static int prev_time = -1; - - if (!parse) return; - DEBUG("gstplay: frame displayed %s\n", MUTEX_STATUS()); - - mux_rate = gst_util_get_int_arg(GTK_OBJECT(parse),"mux_rate"); - size = gst_util_get_int_arg(GTK_OBJECT(src),"size"); - time = (size*8)/mux_rate; - frame_time = gst_util_get_int_arg(GTK_OBJECT(show),"frame_time"); - src_pos = gst_util_get_int_arg(GTK_OBJECT(src),"offset"); - frame_time = (src_pos*8)/mux_rate; - - if (frame_time >= prev_time) { - - g_snprintf(statusline, 200, "%02d:%02d / %02d:%02d\n", - frame_time/60, frame_time%60, - time/60, time%60); - - //printf("%d %d %g\n", frame_time, size, frame_time*100.0/size); - - update_status_area(status_area); - if (state == GSTPLAY_PLAYING) - update_slider(adjustment, src_pos*100.0/size); - } - picture_shown = TRUE; - - prev_time = frame_time; - DEBUG("gstplay: frame displayed end %s\n", MUTEX_STATUS()); -} - -static gboolean idle_func(gpointer data) { - DEBUG("idle start %s\n",MUTEX_STATUS()); - gst_bin_iterate(GST_BIN(data)); - DEBUG("idle stop %s\n",MUTEX_STATUS()); - return TRUE; -} - -static void eof(GstSrc *src) { - change_state(GSTPLAY_PAUSE); - picture_shown = TRUE; -} - -void show_next_picture() { - picture_shown = FALSE; - DEBUG("gstplay: next picture %s\n", MUTEX_STATUS()); - while (!picture_shown) { - gdk_threads_leave(); - gst_src_push(GST_SRC(src)); - gdk_threads_enter(); - } - DEBUG("gstplay: next found %s\n", MUTEX_STATUS()); -} - -static void mute_audio(gboolean mute) { - gtk_object_set(GTK_OBJECT(audio_play),"mute",mute,NULL); -} - -static void gstplay_tear_down() -{ - g_print("setting to NULL state\n"); - gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_NULL); -} - -static void -target_drag_data_received (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *data, - guint info, - guint time) -{ - if (strstr(data->data, "file:")) { - g_print("Got: %s\n",data->data); - start_from_file(g_strchomp(&data->data[5])); - } -} - -void -on_exit_menu_activate (GtkMenuItem *menuitem, - gpointer user_data) -{ - gdk_threads_leave(); - gstplay_tear_down(); - gdk_threads_enter(); - gst_main_quit(); -} - -void on_ok_button1_clicked (GtkButton *button, - GtkFileSelection *sel) -{ - gchar *selected_filename; - - selected_filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION(open_file_selection)); - start_from_file(selected_filename); -} - -gint on_gstplay_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - gdk_threads_leave(); - gstplay_tear_down(); - gdk_threads_enter(); - return FALSE; -} - -void change_state(GstPlayState new_state) { - - if (new_state == state) return; - switch (new_state) { - case GSTPLAY_PLAYING: - mute_audio(FALSE); - statustext = "playing"; - update_status_area(status_area); - gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_READY); - gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING); - gtk_idle_add(idle_func, pipeline); - state = GSTPLAY_PLAYING; - update_buttons(0); - break; - case GSTPLAY_PAUSE: - statustext = "paused"; - update_status_area(status_area); - if (state != GSTPLAY_STOPPED) gtk_idle_remove_by_data(pipeline); - //gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED); - mute_audio(TRUE); - state = GSTPLAY_PAUSE; - update_buttons(1); - break; - case GSTPLAY_STOPPED: - if (state != GSTPLAY_PAUSE) gtk_idle_remove_by_data(pipeline); - //gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_NULL); - statustext = "stopped"; - update_status_area(status_area); - mute_audio(TRUE); - state = GSTPLAY_STOPPED; - gtk_object_set(GTK_OBJECT(src),"offset",0,NULL); - update_buttons(2); - update_slider(adjustment, 0.0); - //show_next_picture(); - break; - } -} - -static gint start_from_file(guchar *filename) -{ - src = gst_elementfactory_make("disksrc", "disk_src"); - g_return_val_if_fail(src != NULL, -1); - g_print("should be using file '%s'\n",filename); - gtk_object_set(GTK_OBJECT(src),"location",filename,NULL); - - gst_pipeline_add_src(GST_PIPELINE(pipeline),GST_ELEMENT(src)); - gtk_signal_connect(GTK_OBJECT(src),"eos", - GTK_SIGNAL_FUNC(eof),NULL); - - if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) { - g_print("unable to handle stream\n"); - exit(-1); - } - - if (GST_PAD_CONNECTED(gst_element_get_pad(show, "sink"))) { - gtk_widget_show(video); - } - g_print("setting to READY state\n"); - gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_READY); - - state = GSTPLAY_STOPPED; - - change_state(GSTPLAY_PLAYING); - - return 0; -} - -static GtkTargetEntry target_table[] = { - { "text/plain", 0, 0 } +/* signals and args */ +enum { + SIGNAL_STATE_CHANGED, + SIGNAL_FRAME_DISPLAYED, + SIGNAL_AUDIO_PLAYED, + LAST_SIGNAL }; -int -main (int argc, char *argv[]) +enum { + ARG_0, + ARG_URI, + ARG_MUTE, + ARG_STATE, + ARG_MEDIA_SIZE, + ARG_MEDIA_OFFSET, + ARG_MEDIA_TOTAL_TIME, + ARG_MEDIA_CURRENT_TIME, +}; + +static GtkObject *parent_class = NULL; +static guint gst_play_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_play_get_type (void) { - GladeXML *xml; - GtkWidget *slider, *gstplay; + static GtkType play_type = 0; - bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR); - textdomain (PACKAGE); - - gst_init(&argc,&argv); - gnome_init ("gstreamer", VERSION, argc, argv); - glade_init(); - glade_gnome_init(); - - g_print("using %s\n", DATADIR"gstplay.glade"); - /* load the interface */ - xml = glade_xml_new(DATADIR "gstplay.glade", "gstplay"); - - status_area = glade_xml_get_widget(xml, "status_area"); - slider = glade_xml_get_widget(xml, "slider"); - { - GtkArg arg; - GtkRange *range; - arg.name = "adjustment"; - gtk_object_getv(GTK_OBJECT(slider),1,&arg); - range = GTK_RANGE(GTK_VALUE_POINTER(arg)); - adjustment = gtk_range_get_adjustment(range); - gtk_signal_connect(GTK_OBJECT(adjustment),"value_changed", - GTK_SIGNAL_FUNC(on_hscale1_value_changed),NULL); + if (!play_type) { + static const GtkTypeInfo play_info = { + "GstPlay", + sizeof(GstPlay), + sizeof(GstPlayClass), + (GtkClassInitFunc)gst_play_class_init, + (GtkObjectInitFunc)gst_play_init, + NULL, + NULL, + (GtkClassInitFunc)NULL, + }; + play_type = gtk_type_unique (gtk_hbox_get_type (),&play_info); + } + return play_type; +} + +static void +gst_play_class_init (GstPlayClass *klass) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + parent_class = gtk_type_class (gtk_hbox_get_type ()); + + object_class = (GtkObjectClass*)klass; + widget_class = (GtkWidgetClass*)klass; + + gst_play_signals[SIGNAL_STATE_CHANGED] = + gtk_signal_new ("playing_state_changed",GTK_RUN_FIRST,object_class->type, + GTK_SIGNAL_OFFSET (GstPlayClass,state_changed), + gtk_marshal_NONE__INT,GTK_TYPE_NONE,1, + GTK_TYPE_INT); + + gst_play_signals[SIGNAL_FRAME_DISPLAYED] = + gtk_signal_new ("frame_displayed",GTK_RUN_FIRST,object_class->type, + GTK_SIGNAL_OFFSET (GstPlayClass,frame_displayed), + gtk_marshal_NONE__INT,GTK_TYPE_NONE,0); + + gst_play_signals[SIGNAL_AUDIO_PLAYED] = + gtk_signal_new ("audio_played",GTK_RUN_FIRST,object_class->type, + GTK_SIGNAL_OFFSET (GstPlayClass,audio_played), + gtk_marshal_NONE__INT,GTK_TYPE_NONE,0); + + gtk_object_class_add_signals (object_class,gst_play_signals,LAST_SIGNAL); + gtk_object_add_arg_type ("GstPlay::uri",GTK_TYPE_STRING, + GTK_ARG_READABLE, ARG_URI); + gtk_object_add_arg_type ("GstPlay::mute",GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_MUTE); + gtk_object_add_arg_type ("GstPlay::state",GTK_TYPE_INT, + GTK_ARG_READABLE, ARG_STATE); + gtk_object_add_arg_type ("GstPlay::media_size",GTK_TYPE_ULONG, + GTK_ARG_READABLE, ARG_MEDIA_SIZE); + gtk_object_add_arg_type ("GstPlay::media_offset",GTK_TYPE_ULONG, + GTK_ARG_READABLE, ARG_MEDIA_OFFSET); + gtk_object_add_arg_type ("GstPlay::media_total_time",GTK_TYPE_ULONG, + GTK_ARG_READABLE, ARG_MEDIA_TOTAL_TIME); + gtk_object_add_arg_type ("GstPlay::media_current_time",GTK_TYPE_ULONG, + GTK_ARG_READABLE, ARG_MEDIA_CURRENT_TIME); + + object_class->set_arg = gst_play_set_arg; + object_class->get_arg = gst_play_get_arg; + + widget_class->realize = gst_play_realize; + +} + +static void +gst_play_init (GstPlay *play) +{ + + GstPlayPrivate *private = g_new0 (GstPlayPrivate, 1); + + play->private = private; + + /* create a new bin to hold the elements */ + private->thread = gst_thread_new ("main_thread"); + g_assert (private->thread != NULL); + private->pipeline = gst_pipeline_new ("main_pipeline"); + g_assert (private->pipeline != NULL); + + /* and an audio sink */ + private->audio_play = gst_elementfactory_make ("audiosink","play_audio"); + g_return_if_fail (private->audio_play != NULL); + gtk_signal_connect (GTK_OBJECT (private->audio_play), "handoff", + GTK_SIGNAL_FUNC (gst_play_audio_handoff), play); + + /* and a video sink */ + private->video_show = gst_elementfactory_make ("videosink","show"); + g_return_if_fail (private->video_show != NULL); + gtk_object_set (GTK_OBJECT (private->video_show),"xv_enabled",FALSE,NULL); + gtk_signal_connect (GTK_OBJECT (private->video_show), "frame_displayed", + GTK_SIGNAL_FUNC (gst_play_frame_displayed), play); + + gst_pipeline_add_sink (GST_PIPELINE (private->pipeline), private->audio_play); + gst_pipeline_add_sink (GST_PIPELINE (private->pipeline), private->video_show); + + gst_bin_add (GST_BIN (private->thread), private->pipeline); + + play->state = GST_PLAY_STOPPED; + private->src = NULL; + play->flags = 0; + private->muted = FALSE; + private->uri = NULL; +} + +GstPlay * +gst_play_new () +{ + return GST_PLAY (gtk_type_new (GST_TYPE_PLAY)); +} + +static void +gst_play_eos (GstElement *element, + GstPlay *play) +{ + gst_play_stop(play); +} + +static void +gst_play_frame_displayed (GstElement *element, + GstPlay *play) +{ + gtk_signal_emit (GTK_OBJECT (play), gst_play_signals[SIGNAL_FRAME_DISPLAYED], + NULL); +} + +static void +gst_play_audio_handoff (GstElement *element, + GstPlay *play) +{ + gtk_signal_emit (GTK_OBJECT (play), gst_play_signals[SIGNAL_AUDIO_PLAYED], + NULL); +} + +GstPlayReturn +gst_play_set_uri (GstPlay *play, + const guchar *uri) +{ + GstPlayPrivate *private; + + g_return_val_if_fail (play != NULL, GST_PLAY_ERROR); + g_return_val_if_fail (GST_IS_PLAY (play), GST_PLAY_ERROR); + g_return_val_if_fail (uri != NULL, GST_PLAY_ERROR); + + private = (GstPlayPrivate *)play->private; + + if (private->src) { + } + + if (private->uri) g_free (private->uri); + + private->uri = g_strdup (uri); + + private->src = gst_elementfactory_make ("disksrc", "disk_src"); + g_return_val_if_fail (private->src != NULL, -1); + gtk_object_set (GTK_OBJECT (private->src),"location",uri,NULL); + gtk_signal_connect (GTK_OBJECT (private->src), "eos", GTK_SIGNAL_FUNC (gst_play_eos), play); + + gst_pipeline_add_src (GST_PIPELINE (private->pipeline),GST_ELEMENT (private->src)); + + if (!gst_pipeline_autoplug (GST_PIPELINE (private->pipeline))) { + return GST_PLAY_UNKNOWN_MEDIA; + } + + if (GST_PAD_CONNECTED (gst_element_get_pad (private->video_show, "sink"))) { + play->flags |= GST_PLAY_TYPE_VIDEO; + } + if (GST_PAD_CONNECTED (gst_element_get_pad (private->audio_play, "sink"))) { + play->flags |= GST_PLAY_TYPE_AUDIO; + } + + return GST_PLAY_OK; +} + +static void +gst_play_realize (GtkWidget *widget) +{ + GstPlay *play; + GtkWidget *video_widget; + GstPlayPrivate *private; + + g_return_if_fail (GST_IS_PLAY (widget)); + + play = GST_PLAY (widget); + private = (GstPlayPrivate *)play->private; + + video_widget = gst_util_get_widget_arg (GTK_OBJECT (private->video_show),"widget"); + + if (video_widget) { + gtk_container_add (GTK_CONTAINER (widget), video_widget); + gtk_widget_show (video_widget); + } + + if (GTK_WIDGET_CLASS (parent_class)->realize) { + GTK_WIDGET_CLASS (parent_class)->realize (widget); + } +} + +void +gst_play_play (GstPlay *play) +{ + GstPlayPrivate *private; + + g_return_if_fail (play != NULL); + g_return_if_fail (GST_IS_PLAY (play)); + + private = (GstPlayPrivate *)play->private; + + if (play->state == GST_PLAY_PLAYING) return; + + if (play->state == GST_PLAY_STOPPED) + gst_element_set_state (GST_ELEMENT (private->thread),GST_STATE_READY); + gst_element_set_state (GST_ELEMENT (private->thread),GST_STATE_PLAYING); + + play->state = GST_PLAY_PLAYING; + + gtk_signal_emit (GTK_OBJECT (play), gst_play_signals[SIGNAL_STATE_CHANGED], + play->state); +} + +void +gst_play_pause (GstPlay *play) +{ + GstPlayPrivate *private; + + g_return_if_fail (play != NULL); + g_return_if_fail (GST_IS_PLAY (play)); + + private = (GstPlayPrivate *)play->private; + + if (play->state == GST_PLAY_PAUSED) return; + + gst_element_set_state (GST_ELEMENT (private->thread),GST_STATE_PAUSED); + + play->state = GST_PLAY_PAUSED; + + gtk_signal_emit (GTK_OBJECT (play), gst_play_signals[SIGNAL_STATE_CHANGED], + play->state); +} + +void +gst_play_stop (GstPlay *play) +{ + GstPlayPrivate *private; + + g_return_if_fail (play != NULL); + g_return_if_fail (GST_IS_PLAY (play)); + + if (play->state == GST_PLAY_STOPPED) return; + + private = (GstPlayPrivate *)play->private; + + gst_element_set_state (GST_ELEMENT (private->thread),GST_STATE_NULL); + gtk_object_set (GTK_OBJECT (private->src),"offset",0,NULL); + + play->state = GST_PLAY_STOPPED; + + gtk_signal_emit (GTK_OBJECT (play), gst_play_signals[SIGNAL_STATE_CHANGED], + play->state); +} + +static void +gst_play_set_arg (GtkObject *object, + GtkArg *arg, + guint id) +{ + GstPlay *play; + play = GST_PLAY (object); + + switch (id) { + case ARG_MUTE: + break; + default: + g_warning ("GstPlay: unknown arg!"); + break; + } +} + +static void +gst_play_get_arg (GtkObject *object, + GtkArg *arg, + guint id) +{ + GstPlay *play; + GstPlayPrivate *private; + + play = GST_PLAY (object); + private = (GstPlayPrivate *)play->private; + + switch (id) { + case ARG_URI: + GTK_VALUE_STRING (*arg) = private->uri; + break; + case ARG_MUTE: + GTK_VALUE_BOOL (*arg) = private->muted; + break; + case ARG_STATE: + GTK_VALUE_INT (*arg) = play->state; + break; + case ARG_MEDIA_SIZE: + GTK_VALUE_LONG (*arg) = gst_util_get_long_arg (GTK_OBJECT (private->src), "size"); + break; + case ARG_MEDIA_OFFSET: + GTK_VALUE_LONG (*arg) = gst_util_get_long_arg (GTK_OBJECT (private->src), "offset"); + break; + case ARG_MEDIA_TOTAL_TIME: + break; + case ARG_MEDIA_CURRENT_TIME: + break; + default: + arg->type = GTK_TYPE_INVALID; + break; } - play_button = glade_xml_get_widget(xml, "toggle_play"); - pause_button = glade_xml_get_widget(xml, "toggle_pause"); - stop_button = glade_xml_get_widget(xml, "toggle_stop"); - - gstplay = glade_xml_get_widget(xml, "gstplay"); - gtk_drag_dest_set (gstplay, - GTK_DEST_DEFAULT_ALL, - target_table, 1, - GDK_ACTION_COPY); - gtk_signal_connect (GTK_OBJECT (gstplay), "drag_data_received", - GTK_SIGNAL_FUNC (target_drag_data_received), - NULL); - - g_snprintf(statusline, 200, "seeking"); - - /* create a new bin to hold the elements */ - pipeline = gst_pipeline_new("pipeline"); - g_assert(pipeline != NULL); - - /* and an audio sink */ - audio_play = gst_elementfactory_make("audiosink","play_audio"); - g_return_val_if_fail(audio_play != NULL, -1); - - /* and a video sink */ - show = gst_elementfactory_make("videosink","show"); - g_return_val_if_fail(show != NULL, -1); - gtk_object_set(GTK_OBJECT(show),"xv_enabled",FALSE,NULL); - gtk_signal_connect(GTK_OBJECT(show),"frame_displayed", - GTK_SIGNAL_FUNC(frame_displayed),NULL); - - video = gst_util_get_widget_arg(GTK_OBJECT(show),"widget"); - gnome_dock_set_client_area(GNOME_DOCK(glade_xml_get_widget(xml, "dock1")), - video); - - gst_pipeline_add_sink(GST_PIPELINE(pipeline), audio_play); - gst_pipeline_add_sink(GST_PIPELINE(pipeline), show); - - /* connect the signals in the interface */ - glade_xml_signal_autoconnect(xml); - - if (argc > 1) { - gint ret; - - ret = start_from_file(argv[1]); - if (ret < 0) exit(ret); - } - - gst_main(); - return 0; } diff --git a/gstplay/gstplay.h b/gstplay/gstplay.h index 101101655c..186bb53556 100644 --- a/gstplay/gstplay.h +++ b/gstplay/gstplay.h @@ -6,20 +6,84 @@ #ifndef __GSTPLAY_H__ #define __GSTPLAY_H__ -#ifdef HAVE_CONFIG_H -# include -#endif - -#include #include +typedef struct _GstPlay GstPlay; +typedef struct _GstPlayClass GstPlayClass; + +#define GST_TYPE_PLAY \ + (gst_play_get_type()) +#define GST_PLAY(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_PLAY,GstPlay)) +#define GST_PLAY_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_PLAY,GstPlayClass)) +#define GST_IS_PLAY(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_PLAY)) +#define GST_IS_PLAY_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_PLAY)) + typedef enum { - GSTPLAY_PLAYING, - GSTPLAY_STOPPED, - GSTPLAY_PAUSE, + GST_PLAY_STOPPED, + GST_PLAY_PLAYING, + GST_PLAY_PAUSED, } GstPlayState; -void change_state(GstPlayState new_state); -void show_next_picture(); +typedef enum { + GST_PLAY_OK, + GST_PLAY_UNKNOWN_MEDIA, + GST_PLAY_ERROR, +} GstPlayReturn; + +typedef enum { + GST_PLAY_TYPE_AUDIO = (1 << 0), + GST_PLAY_TYPE_VIDEO = (1 << 1), +} GstPlayMediaTypeFlags; + +struct _GstPlay { + GtkHBox parent; + + GstPlayState state; + GstPlayMediaTypeFlags flags; + + gpointer private; +}; + +#define GST_PLAY_STATE(play) ((play)->state) +#define GST_PLAY_MEDIA_TYPE(play) ((play)->flags) +#define GST_PLAY_IS_AUDIO_TYPE(play) ((play)->flags & GST_PLAY_TYPE_AUDIO) +#define GST_PLAY_IS_VIDEO_TYPE(play) ((play)->flags & GST_PLAY_TYPE_VIDEO) + +struct _GstPlayClass { + GtkHBoxClass parent_class; + + void (*state_changed) (GstPlay *play, GstPlayState state); + void (*frame_displayed) (GstPlay *play); + void (*audio_played) (GstPlay *play); +}; + + +GtkType gst_play_get_type (void); + +/* setup the player */ +GstPlay* gst_play_new (void); +GstPlayReturn gst_play_set_uri (GstPlay *play, const guchar *uri); + +/* control the player */ +void gst_play_play (GstPlay *play); +void gst_play_pause (GstPlay *play); +void gst_play_stop (GstPlay *play); + +void gst_play_mute (GstPlay *play, gboolean mute); + +/* information about the media stream */ +gulong gst_play_get_media_size (GstPlay *play); +gulong gst_play_get_media_offset (GstPlay *play); +void gst_play_media_seek (GstPlay *play, gulong offset); + +gulong gst_play_get_media_total_time (GstPlay *play); +gulong gst_play_get_media_current_time (GstPlay *play); + +/* the autoplugged pipeline */ +GstElement* gst_play_get_pipeline (GstPlay *play); #endif /* __GSTPLAY_H__ */ diff --git a/gstplay/gstplayprivate.h b/gstplay/gstplayprivate.h new file mode 100644 index 0000000000..a0ac3cab24 --- /dev/null +++ b/gstplay/gstplayprivate.h @@ -0,0 +1,24 @@ +/* + * Initial main.c file generated by Glade. Edit as required. + * Glade will not overwrite this file. + */ + +#ifndef __GSTPLAY_PRIVATE_H__ +#define __GSTPLAY_PRIVATE_H__ + +#include + +typedef struct _GstPlayPrivate GstPlayPrivate; + +struct _GstPlayPrivate { + GstElement *thread; + GstElement *pipeline; + GstElement *audio_play; + GstElement *video_show; + GstElement *src; + + guchar *uri; + gboolean muted; +}; + +#endif /* __GSTPLAY_PRIVATE_H__ */ diff --git a/gstplay/gststatusarea.c b/gstplay/gststatusarea.c new file mode 100644 index 0000000000..f88a6b3919 --- /dev/null +++ b/gstplay/gststatusarea.c @@ -0,0 +1,240 @@ +/* + * Initial main.c file generated by Glade. Edit as required. + * Glade will not overwrite this file. + */ + +#include + +#include "gststatusarea.h" + +static void gst_status_area_class_init(GstStatusAreaClass *klass); +static void gst_status_area_init(GstStatusArea *status_area); + +static void gst_status_area_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_status_area_get_arg(GtkObject *object,GtkArg *arg,guint id); + +static void gst_status_area_realize(GtkWidget *status_area); +static gint gst_status_area_expose(GtkWidget *widget, GdkEventExpose *event); + +#define DEFAULT_HEIGHT 20 + +/* signals and args */ +enum { + LAST_SIGNAL +}; + +enum { + ARG_0, +}; + +static GtkDrawingArea *parent_class = NULL; +static guint gst_status_area_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_status_area_get_type (void) +{ + static GtkType status_area_type = 0; + + if (!status_area_type) { + static const GtkTypeInfo status_area_info = { + "GstStatusArea", + sizeof(GstStatusArea), + sizeof(GstStatusAreaClass), + (GtkClassInitFunc)gst_status_area_class_init, + (GtkObjectInitFunc)gst_status_area_init, + NULL, + NULL, + (GtkClassInitFunc)NULL, + }; + status_area_type = gtk_type_unique (gtk_widget_get_type (),&status_area_info); + } + return status_area_type; +} + +static void +gst_status_area_class_init (GstStatusAreaClass *klass) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + parent_class = gtk_type_class (gtk_widget_get_type ()); + + object_class = (GtkObjectClass*)klass; + widget_class = (GtkWidgetClass*)klass; + + object_class->set_arg = gst_status_area_set_arg; + object_class->get_arg = gst_status_area_get_arg; + + widget_class->realize = gst_status_area_realize; + widget_class->expose_event = gst_status_area_expose; +} + +static void +gst_status_area_init (GstStatusArea *status_area) +{ + GTK_WIDGET(status_area)->requisition.height = DEFAULT_HEIGHT; + + status_area->state = GST_STATUS_AREA_STATE_INIT; +} + +GstStatusArea * +gst_status_area_new (void) +{ + return GST_STATUS_AREA (gtk_type_new (GST_TYPE_STATUS_AREA)); +} + +static void +gst_status_area_realize (GtkWidget *widget) +{ + GdkWindowAttr attributes; + gint attributes_mask; + GstStatusArea *status_area; + + g_return_if_fail (widget != NULL); + g_return_if_fail(GST_IS_STATUS_AREA(widget)); + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + status_area = GST_STATUS_AREA(widget); + + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.event_mask = gtk_widget_get_events (widget) + | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK; + + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask); + + widget->style = gtk_style_attach (widget->style, widget->window); +} + +static gint +gst_status_area_expose(GtkWidget *widget, + GdkEventExpose *event) +{ + GstStatusArea *status_area; + guchar *statustext; + + g_return_val_if_fail (GST_IS_STATUS_AREA (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + status_area = GST_STATUS_AREA (widget); + + if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget)) { + gdk_draw_rectangle (widget->window, + widget->style->black_gc, + TRUE, + 0, 0, + widget->allocation.width, + widget->allocation.height); + + switch (status_area->state) { + case GST_STATUS_AREA_STATE_INIT: + statustext = "Initializing"; + break; + case GST_STATUS_AREA_STATE_PLAYING: + statustext = "Playing"; + break; + case GST_STATUS_AREA_STATE_PAUSED: + statustext = "Paused"; + break; + case GST_STATUS_AREA_STATE_STOPPED: + statustext = "Stopped"; + break; + default: + statustext = ""; + break; + } + + gdk_draw_string (widget->window, + widget->style->font, + widget->style->white_gc, + 8, 15, statustext); + + if (status_area->playtime) { + gdk_draw_string (widget->window, + widget->style->font, + widget->style->white_gc, + widget->allocation.width-100, 15, status_area->playtime); + } + } + return FALSE; +} + +void +gst_status_area_set_state (GstStatusArea *area, + GstStatusAreaState state) +{ + g_return_if_fail(area != NULL); + g_return_if_fail(GST_IS_STATUS_AREA(area)); + + area->state = state; + + if (GTK_WIDGET_VISIBLE(area)) + gtk_widget_queue_draw(GTK_WIDGET(area)); +} + +void +gst_status_area_set_playtime (GstStatusArea *area, + const guchar *time) +{ + g_return_if_fail(area != NULL); + g_return_if_fail(GST_IS_STATUS_AREA(area)); + g_return_if_fail(time != NULL); + + if (area->playtime) g_free (area->playtime); + + area->playtime = g_strdup (time); +} + +void +gst_status_area_set_streamtype (GstStatusArea *area, + const guchar *type) +{ +} + +void +gst_status_area_show_extended (GstStatusArea *area, + gboolean show) +{ +} + +static void +gst_status_area_set_arg(GtkObject *object, + GtkArg *arg, + guint id) +{ + GstStatusArea *status_area; + + status_area = GST_STATUS_AREA(object); + + switch (id) { + default: + g_warning("GstStatusArea: unknown arg!"); + break; + } +} + +static void +gst_status_area_get_arg(GtkObject *object, + GtkArg *arg, + guint id) +{ + GstStatusArea *status_area; + + status_area = GST_STATUS_AREA(object); + + switch (id) { + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + diff --git a/gstplay/gststatusarea.h b/gstplay/gststatusarea.h new file mode 100644 index 0000000000..ba3a2e7acc --- /dev/null +++ b/gstplay/gststatusarea.h @@ -0,0 +1,51 @@ +#ifndef __GST_STATUS_AREA_H__ +#define __GST_STATUS_AREA_H__ + +#include +#include + +typedef struct _GstStatusArea GstStatusArea; +typedef struct _GstStatusAreaClass GstStatusAreaClass; + +#define GST_TYPE_STATUS_AREA \ + (gst_status_area_get_type()) +#define GST_STATUS_AREA(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_STATUS_AREA,GstStatusArea)) +#define GST_STATUS_AREA_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_STATUS_AREA,GstStatusAreaClass)) +#define GST_IS_STATUS_AREA(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_STATUS_AREA)) +#define GST_IS_STATUS_AREA_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_STATUS_AREA)) + +typedef enum { + GST_STATUS_AREA_STATE_INIT, + GST_STATUS_AREA_STATE_PLAYING, + GST_STATUS_AREA_STATE_PAUSED, + GST_STATUS_AREA_STATE_STOPPED, +} GstStatusAreaState; + +struct _GstStatusArea { + GtkWidget parent; + + GstStatusAreaState state; + guchar *playtime; +}; + +struct _GstStatusAreaClass { + GtkWidgetClass parent_class; + +}; + + +GtkType gst_status_area_get_type (void); + +GstStatusArea* gst_status_area_new (void); + +void gst_status_area_set_state (GstStatusArea *area, GstStatusAreaState state); +void gst_status_area_set_playtime (GstStatusArea *area, const guchar *time); +void gst_status_area_set_streamtype (GstStatusArea *area, const guchar *type); + +void gst_status_area_show_extended (GstStatusArea *area, gboolean show); + +#endif /* __GST_STATUS_AREA_H__ */ diff --git a/gstplay/interface.c b/gstplay/interface.c index 150f814291..1ee3ea3851 100644 --- a/gstplay/interface.c +++ b/gstplay/interface.c @@ -22,7 +22,7 @@ extern GtkWidget *stop_button; extern guchar statusline[]; extern guchar *statustext; -void update_buttons(int active) +void update_buttons(GstPlayState state) { gtk_signal_handler_block_by_func(GTK_OBJECT(play_button), GTK_SIGNAL_FUNC (on_toggle_play_toggled), @@ -38,13 +38,13 @@ void update_buttons(int active) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pause_button), FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(stop_button), FALSE); - if (active == 0) { + if (state == GST_PLAY_PLAYING) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(play_button), TRUE); } - else if (active == 1) { + else if (state == GST_PLAY_PAUSED) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pause_button), TRUE); } - else if (active == 2) { + else if (state == GST_PLAY_STOPPED) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(stop_button), TRUE); } @@ -70,17 +70,3 @@ void update_slider(GtkAdjustment *adjustment, gfloat value) NULL); } -void update_status_area(GtkWidget *widget) -{ - - gdk_draw_rectangle(widget->window, - widget->style->black_gc, - TRUE, 0, - 0, - widget->allocation.width, - widget->allocation.height); - - gdk_draw_string(widget->window,widget->style->font,widget->style->white_gc, 8, 15, statustext); - gdk_draw_string(widget->window,widget->style->font,widget->style->white_gc, widget->allocation.width-100, 15, statusline); - -} diff --git a/gstplay/interface.h b/gstplay/interface.h index df5c635385..15f020370d 100644 --- a/gstplay/interface.h +++ b/gstplay/interface.h @@ -2,6 +2,8 @@ * DO NOT EDIT THIS FILE - it is generated by Glade. */ +#include "gstplay.h" + void update_status_area(GtkWidget *area); void update_slider(GtkAdjustment *adjustment, gfloat value); -void update_buttons(int active); +void update_buttons(GstPlayState state); diff --git a/gstplay/main.c b/gstplay/main.c new file mode 100644 index 0000000000..6f9f78d459 --- /dev/null +++ b/gstplay/main.c @@ -0,0 +1,34 @@ +/* + * Initial main.c file generated by Glade. Edit as required. + * Glade will not overwrite this file. + */ + +#include + +//#define DEBUG_ENABLED + +#include +#include + +#include "gstmediaplay.h" + + +int +main (int argc, char *argv[]) +{ + GstMediaPlay *play; + + gst_init(&argc,&argv); + gnome_init ("gstreamer", VERSION, argc, argv); + + play = gst_media_play_new(); + + if (argc > 1) { + gst_media_play_start_uri(play, argv[1]); + } + + gst_main(); + + return 0; +} + diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index 302388b1b5..0b635c6a18 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -57,8 +57,12 @@ static void gst_queue_init(GstQueue *queue); static void gst_queue_set_arg(GtkObject *object,GtkArg *arg,guint id); static void gst_queue_get_arg(GtkObject *object,GtkArg *arg,guint id); -void gst_queue_push(GstConnection *connection); -void gst_queue_chain(GstPad *pad,GstBuffer *buf); +static void gst_queue_push(GstConnection *connection); +static void gst_queue_chain(GstPad *pad,GstBuffer *buf); + +static void gst_queue_flush(GstQueue *queue); + +static GstElementStateReturn gst_queue_change_state(GstElement *element); static GstConnectionClass *parent_class = NULL; //static guint gst_queue_signals[LAST_SIGNAL] = { 0 }; @@ -85,9 +89,11 @@ gst_queue_get_type(void) { static void gst_queue_class_init(GstQueueClass *klass) { GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; GstConnectionClass *gstconnection_class; gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; gstconnection_class = (GstConnectionClass*)klass; parent_class = gtk_type_class(GST_TYPE_CONNECTION); @@ -101,6 +107,8 @@ static void gst_queue_class_init(GstQueueClass *klass) { gtkobject_class->set_arg = gst_queue_set_arg; gtkobject_class->get_arg = gst_queue_get_arg; + + gstelement_class->change_state = gst_queue_change_state; } static void gst_queue_init(GstQueue *queue) { @@ -137,7 +145,14 @@ static void gst_queue_cleanup_buffers(gpointer data, gpointer user_data) gst_buffer_unref(GST_BUFFER(data)); } -void gst_queue_chain(GstPad *pad,GstBuffer *buf) { +static void gst_queue_flush(GstQueue *queue) { + g_slist_foreach(queue->queue, gst_queue_cleanup_buffers, gst_element_get_name(GST_ELEMENT(queue))); + g_slist_free(queue->queue); + queue->queue = NULL; + queue->level_buffers = 0; +} + +static void gst_queue_chain(GstPad *pad,GstBuffer *buf) { GstQueue *queue; gboolean tosignal = FALSE; guchar *name; @@ -157,13 +172,9 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) { DEBUG("queue: have queue lock\n"); if (GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLUSH)) { - g_slist_foreach(queue->queue, gst_queue_cleanup_buffers, name); - g_slist_free(queue->queue); - queue->queue = NULL; - queue->level_buffers = 0; + gst_queue_flush(queue); } - DEBUG("queue: %s: chain %d %p\n", name, queue->level_buffers, buf); while (queue->level_buffers >= queue->max_buffers) { @@ -199,7 +210,7 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) { } } -void gst_queue_push(GstConnection *connection) { +static void gst_queue_push(GstConnection *connection) { GstQueue *queue = GST_QUEUE(connection); GstBuffer *buf = NULL; GSList *front; @@ -248,6 +259,26 @@ void gst_queue_push(GstConnection *connection) { /* unlock now */ } +static GstElementStateReturn gst_queue_change_state(GstElement *element) { + GstQueue *queue; + g_return_val_if_fail(GST_IS_QUEUE(element),GST_STATE_FAILURE); + + queue = GST_QUEUE(element); + DEBUG("gstqueue: state pending %d\n", GST_STATE_PENDING(element)); + + /* if going down into NULL state, clear out buffers*/ + if (GST_STATE_PENDING(element) == GST_STATE_READY) { + /* otherwise (READY or higher) we need to open the file */ + gst_queue_flush(queue); + } + + /* if we haven't failed already, give the parent class a chance to ;-) */ + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element); + + return GST_STATE_SUCCESS; +} + static void gst_queue_set_arg(GtkObject *object,GtkArg *arg,guint id) { GstQueue *queue; diff --git a/test/avi2mpg.c b/test/avi2mpg.c index 09b98757d7..37a63d0c42 100644 --- a/test/avi2mpg.c +++ b/test/avi2mpg.c @@ -75,11 +75,11 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) { median = gst_elementfactory_make("median","median"); g_return_if_fail(median != NULL); gtk_object_set(GTK_OBJECT(median),"filtersize",5,NULL); - gtk_object_set(GTK_OBJECT(median),"active",FALSE,NULL); + gtk_object_set(GTK_OBJECT(median),"active",TRUE,NULL); gtk_object_set(GTK_OBJECT(smooth),"filtersize",16,NULL); gtk_object_set(GTK_OBJECT(smooth),"tolerance",16,NULL); - gtk_object_set(GTK_OBJECT(smooth),"active",TRUE,NULL); + gtk_object_set(GTK_OBJECT(smooth),"active",FALSE,NULL); encode = gst_elementfactory_make("mpeg2enc","encode"); g_return_if_fail(encode != NULL); diff --git a/test/mp2tomp1.c b/test/mp2tomp1.c index 144027a008..1340edb66a 100644 --- a/test/mp2tomp1.c +++ b/test/mp2tomp1.c @@ -158,6 +158,7 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { gtk_object_set(GTK_OBJECT(smooth),"active",FALSE,NULL); encode = gst_elementfactory_make("mpeg2enc","encode"); g_return_if_fail(encode != NULL); + //gtk_object_set(GTK_OBJECT(encode),"frames_per_second",25.0,NULL); gtk_object_set(GTK_OBJECT(encode),"frames_per_second",29.97,NULL); //encode = gst_elementfactory_make("mpeg1encoder","encode"); //gtk_object_set(GTK_OBJECT(show),"width",640, "height", 480,NULL);