Code cleanup and reorganization
authorJulien Moutte <julien@moutte.net>
Thu, 6 Feb 2003 23:17:37 +0000 (23:17 +0000)
committerJulien Moutte <julien@moutte.net>
Thu, 6 Feb 2003 23:17:37 +0000 (23:17 +0000)
Original commit message from CVS:
Code cleanup and reorganization
I ll now be able to make nice gtk-doc for this lib
Fixed latency bug on async_queue pop
X video window now comes immediatly

gst-libs/gst/play/play.old.c
gst-libs/gst/play/play.old.h
gst-libs/gst/play/playpipelines.c

index 560bed1..3ddd86d 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 1999,2000,2001,2002 Erik Walthinsen <omega@cse.ogi.edu>
  *                    2000,2001,2002 Wim Taymans <wtay@chello.be>
  *                              2002 Steve Baker <steve@stevebaker.org>
+ *                                                             2003 Julien Moutte <julien@moutte.net>
  *
  * play.c: GstPlay object code
  *
@@ -35,7 +36,9 @@ enum {
 };
 
 /* this struct is used to decouple signals coming out of threaded pipelines */
+
 typedef struct _GstPlaySignal    GstPlaySignal;
+
 struct _GstPlaySignal
 {
        gint signal_id;
@@ -69,36 +72,21 @@ enum
 
 static guint gst_play_signals [LAST_SIGNAL] = { 0 };
 
-static void         gst_play_init                  (GstPlay *play);
-static void         gst_play_class_init                    (GstPlayClass *klass);
-static void         gst_play_dispose               (GObject *object);
-
-static guint         gst_play_default_timeout_add    (guint interval, GSourceFunc function, gpointer data);
-static guint         gst_play_default_idle_add       (GSourceFunc function, gpointer data);
-
-static void         gst_play_set_property          (GObject *object, guint prop_id, 
-                                                    const GValue *value, GParamSpec *pspec);
-static void         gst_play_get_property          (GObject *object, guint prop_id, 
-                                                    GValue *value, GParamSpec *pspec);
-static void         callback_pipeline_error         (GObject *object, GstObject *orig, gchar *error, GstPlay* play);
-static void         callback_pipeline_state_change  (GstElement *element, GstElementState old, 
-                                                    GstElementState state, GstPlay *play);
-static void         callback_pipeline_deep_notify   (GstElement *element, GstElement *orig, 
-                                                    GParamSpec *param, GstPlay *play);
-static void         callback_audio_sink_eos         (GstElement *element, GstPlay *play);
-static void         callback_video_have_xid         (GstElement *element, gint xid, GstPlay *play);
-static void         callback_video_have_size        (GstElement *element, gint width, gint height, GstPlay *play);
+static GstElementClass *parent_class = NULL;
 
+/* ============================================================= */
+/*                                                               */
+/*                       Private Methods                         */
+/*                                                               */
+/* ============================================================= */
 
-static void         callback_bin_pre_iterate        (GstBin *bin, GMutex *mutex);
-static void         callback_bin_post_iterate       (GstBin *bin, GMutex *mutex);
+/* =========================================== */
+/*                                             */
+/*                  Tool Box                   */
+/*                                             */
+/* =========================================== */
 
-static gboolean     gst_play_idle_signal            (GstPlay *play);
-static gboolean     gst_play_idle_callback         (GstPlay *play);
-static gboolean     gst_play_get_length_callback    (GstPlay *play);
-static gboolean     gst_play_tick_callback          (GstPlay *play);
-
-GQuark
+static GQuark
 gst_play_error_quark (void)
 {
        static GQuark quark = 0;
@@ -109,11 +97,13 @@ gst_play_error_quark (void)
        return quark;
 }
 
-/* GError creation when plugin is missing */
-/* If we want to make error messages less generic and have more errors
- * than only plug-ins, move the message creation to the switch */
+/* GError creation when plugin is missing
+ * If we want to make error messages less
+ * generic and have more errors than only
+ * plug-ins, move the message creation to the switch */
 static void
-gst_play_error_plugin (GstPlayError type, GError **error)
+gst_play_error_plugin (        GstPlayError type,
+                                               GError **error)
 {
         gchar *name;
 
@@ -143,327 +133,168 @@ gst_play_error_plugin (GstPlayError type, GError **error)
                         name = g_strdup ("unknown");
                         break;
         }
-        *error = g_error_new (GST_PLAY_ERROR, type,
-                              "The %s plug-in could not be found. "
-                              "This plug-in is essential for gst-player. "
-                              "Please install it and verify that it works "
-                              "by running 'gst-inspect %s'",
-                              name, name);
+               
+        *error = g_error_new ( GST_PLAY_ERROR,
+                                                               type,
+                                                               "The %s plug-in could not be found. "
+                                                               "This plug-in is essential for gst-player. "
+                                                               "Please install it and verify that it works "
+                                                               "by running 'gst-inspect %s'",
+                                                               name, name);
         g_free (name);
         return;
 }
 
-/* split static pipeline functions to a seperate file */
-#include "playpipelines.c"
-
-static GstElementClass * parent_class = NULL;
-
-GType
-gst_play_get_type (void)
+static void
+gst_play_set_property (        GObject *object,
+                                               guint prop_id,
+                                               const GValue *value,
+                                               GParamSpec *pspec)
 {
-       static GType play_type = 0;
+       GstPlay *play = GST_PLAY (object);
+
+       g_return_if_fail (GST_IS_PLAY (play));
        
-       if (!play_type)
-       {
-               static const GTypeInfo play_info = {
-                       sizeof (GstPlayClass),
-                       (GBaseInitFunc) NULL,
-                       (GBaseFinalizeFunc) NULL,
-                       (GClassInitFunc) gst_play_class_init,
-                       NULL, NULL, sizeof (GstPlay),
-                       0, (GInstanceInitFunc) gst_play_init,
-                       NULL
-               };
-      
-               play_type = g_type_register_static (G_TYPE_OBJECT, "GstPlay", &play_info, 0);
+       switch (prop_id) {
+       case ARG_LOCATION:
+               gst_play_set_location(play, g_value_get_string (value));
+               break;
+       case ARG_VOLUME:
+               gst_play_set_volume(play, g_value_get_float (value));
+               break;
+       case ARG_MUTE:
+               gst_play_set_mute(play, g_value_get_boolean (value));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
        }
-
-       return play_type;
 }
 
 static void
-gst_play_class_init (GstPlayClass *klass)
+gst_play_get_property (        GObject *object,
+                                               guint prop_id,
+                                               GValue *value,
+                                               GParamSpec *pspec)
 {
-       GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  
-       parent_class = g_type_class_ref(GST_TYPE_OBJECT);
-
-       klass->information = NULL;
-       klass->state_changed = NULL;
-       klass->stream_end = NULL;
-  
-       gobject_class->dispose = gst_play_dispose;
-       gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_play_set_property);
-       gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_play_get_property);
-
-       g_object_class_install_property (gobject_class, ARG_LOCATION,
-               g_param_spec_string ("location", "location of file", 
-                                    "location of the file to play",
-                                    NULL, G_PARAM_READWRITE));
-       g_object_class_install_property (gobject_class, ARG_VOLUME,
-               g_param_spec_float ("volume", "Playing volume", 
-                                   "Playing volume", 
-                                                            0, 1.0, 0, G_PARAM_READWRITE));
-       g_object_class_install_property (gobject_class, ARG_MUTE,
-                                        g_param_spec_boolean ("mute", "Volume muted", "Playing volume muted",
-                                                              FALSE, G_PARAM_READWRITE));
-  
-       gst_play_signals [INFORMATION] = 
-               g_signal_new ("information", 
-                             G_TYPE_FROM_CLASS (klass), 
-                             G_SIGNAL_RUN_FIRST,
-                             G_STRUCT_OFFSET (GstPlayClass, information), 
-                             NULL, NULL,
-                             gst_marshal_VOID__OBJECT_PARAM, 
-                             G_TYPE_NONE, 2, 
-                             G_TYPE_OBJECT, G_TYPE_PARAM);
-       
-       gst_play_signals [STATE_CHANGE] = 
-               g_signal_new ("state_change", 
-                             G_TYPE_FROM_CLASS (klass), 
-                             G_SIGNAL_RUN_FIRST,
-                             G_STRUCT_OFFSET (GstPlayClass, state_changed), 
-                             NULL, NULL,
-                             gst_marshal_VOID__INT_INT,
-                             G_TYPE_NONE, 2, 
-                             G_TYPE_INT, G_TYPE_INT);
-       
-       gst_play_signals [STREAM_END] =
-               g_signal_new ("stream_end",
-                             G_TYPE_FROM_CLASS (klass),
-                             G_SIGNAL_RUN_FIRST,
-                             G_STRUCT_OFFSET (GstPlayClass, stream_end),
-                             NULL, NULL,
-                             gst_marshal_VOID__VOID,
-                             G_TYPE_NONE, 0);
-
-       gst_play_signals [TIME_TICK] = 
-               g_signal_new ("time_tick", 
-                             G_TYPE_FROM_CLASS (klass), 
-                             G_SIGNAL_RUN_FIRST,
-                             G_STRUCT_OFFSET (GstPlayClass, time_tick), 
-                             NULL, NULL,
-                             gst_marshal_VOID__INT64,
-                             G_TYPE_NONE, 1, 
-                             G_TYPE_INT64);
-
-       gst_play_signals [STREAM_LENGTH] = 
-               g_signal_new ("stream_length", 
-                             G_TYPE_FROM_CLASS (klass), 
-                             G_SIGNAL_RUN_FIRST,
-                             G_STRUCT_OFFSET (GstPlayClass, stream_length), 
-                             NULL, NULL,
-                             gst_marshal_VOID__INT64,
-                             G_TYPE_NONE, 1, 
-                             G_TYPE_INT64);
-
-       gst_play_signals [HAVE_XID] = 
-               g_signal_new ("have_xid", 
-                             G_TYPE_FROM_CLASS (klass), 
-                             G_SIGNAL_RUN_FIRST,
-                             G_STRUCT_OFFSET (GstPlayClass, have_xid), 
-                             NULL, NULL,
-                             gst_marshal_VOID__INT,
-                             G_TYPE_NONE, 1, 
-                             G_TYPE_INT);
+       GstPlay *play = GST_PLAY (object);
 
-       gst_play_signals [HAVE_VIDEO_SIZE] = 
-               g_signal_new ("have_video_size", 
-                             G_TYPE_FROM_CLASS (klass), 
-                             G_SIGNAL_RUN_FIRST,
-                             G_STRUCT_OFFSET (GstPlayClass, have_video_size), 
-                             NULL, NULL,
-                             gst_marshal_VOID__INT_INT,
-                             G_TYPE_NONE, 2, 
-                             G_TYPE_INT, G_TYPE_INT);
+       g_return_if_fail (GST_IS_PLAY (play));
 
-       gst_control_init(NULL,NULL);
+       switch (prop_id) {
+       case ARG_LOCATION:
+               g_value_set_string (value, gst_play_get_location(play));
+               break;
+       case ARG_VOLUME:
+               g_value_set_float(value, gst_play_get_volume(play));
+               break;
+       case ARG_MUTE:
+               g_value_set_boolean (value, gst_play_get_mute(play));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
 }
 
+/* =========================================== */
+/*                                             */
+/*          Event Handlers, Callbacks          */
+/*                                             */
+/* =========================================== */
 
-
-static void 
-gst_play_init (GstPlay *play) 
-{
-       play->pipeline     = NULL;
-       play->source       = NULL;
-       play->autoplugger  = NULL;
-       play->audio_sink   = NULL;
-       play->audio_sink_element   = NULL;
-       play->video_sink   = NULL;
-       play->video_sink_element   = NULL;
-       play->volume       = NULL;
-       play->other_elements = g_hash_table_new(g_str_hash, g_str_equal);
-       play->audio_bin_mutex = g_mutex_new();
-       play->video_bin_mutex = g_mutex_new();
-       gst_play_set_idle_timeout_funcs(play, gst_play_default_timeout_add, gst_play_default_idle_add);
-       play->tick_timeout_id = play->idle_timeout_id = play->idle_signal_id = 0;
-}
-
-GstPlay *
-gst_play_new (GstPlayPipeType pipe_type, GError **error)
+static gboolean
+gst_play_get_length_callback (GstPlay *play)
 {
-       GstPlay *play;
-
-       play = g_object_new (GST_TYPE_PLAY, NULL);
+       gint64 value;
+       GstFormat format = GST_FORMAT_TIME;
+       gboolean query_worked = FALSE;
 
-       /* FIXME: looks like only VIDEO ever gets used ! */
-       switch (pipe_type){
-               case GST_PLAY_PIPE_VIDEO:
-                       play->setup_pipeline = gst_play_video_setup;
-                       play->teardown_pipeline = NULL;
-                       play->set_data_src = gst_play_video_set_data_src;
-                       play->set_autoplugger = gst_play_video_set_auto;
-                       play->set_video_sink = gst_play_video_set_video;
-                       play->set_audio_sink = gst_play_video_set_audio;
-                       break;
-               case GST_PLAY_PIPE_AUDIO:
-                       /* we can reuse the threaded set functions */
-                       play->setup_pipeline = gst_play_audio_setup;
-                       play->teardown_pipeline = NULL;
-                       play->set_data_src = gst_play_simple_set_data_src;
-                       play->set_autoplugger = gst_play_audiot_set_auto;
-                       play->set_video_sink = NULL;
-                       play->set_audio_sink = gst_play_audiot_set_audio;
-                       break;
-               case GST_PLAY_PIPE_AUDIO_THREADED:
-                       play->setup_pipeline = gst_play_audiot_setup;
-                       play->teardown_pipeline = NULL;
-                       play->set_data_src = gst_play_simple_set_data_src;
-                       play->set_autoplugger = gst_play_audiot_set_auto;
-                       play->set_video_sink = NULL;
-                       play->set_audio_sink = gst_play_audiot_set_audio;
-                       break;
-               case GST_PLAY_PIPE_AUDIO_HYPER_THREADED:
-                       play->setup_pipeline = gst_play_audioht_setup;
-                       play->teardown_pipeline = NULL;
-                       play->set_data_src = gst_play_simple_set_data_src;
-                       play->set_autoplugger = gst_play_audioht_set_auto;
-                       play->set_video_sink = NULL;
-                       play->set_audio_sink = gst_play_audioht_set_audio;
-                       break;
-               default:
-                       g_warning("unknown pipeline type: %d\n", pipe_type);
+       g_print("trying to get length\n");
+       if (play->audio_sink_element != NULL){
+               g_mutex_lock(play->audio_bin_mutex);
+               query_worked = gst_element_query (play->audio_sink_element, GST_QUERY_TOTAL, &format, &value);
+               g_mutex_unlock(play->audio_bin_mutex);
        }
-
-       /* init pipeline */
-       if ((play->setup_pipeline) &&
-           (! play->setup_pipeline (play, error)))
-       {
-               g_object_unref (play);
-               return NULL;
+       else if (play->video_sink_element != NULL){
+               g_mutex_lock(play->video_bin_mutex);
+               query_worked = gst_element_query (play->video_sink_element, GST_QUERY_TOTAL, &format, &value);
+               g_mutex_unlock(play->video_bin_mutex);
        }
-
-
-       if (play->pipeline){
-               /* connect to pipeline events */
-               g_signal_connect (G_OBJECT (play->pipeline), "deep_notify", G_CALLBACK (callback_pipeline_deep_notify), play);
-               g_signal_connect (G_OBJECT (play->pipeline), "state_change", G_CALLBACK (callback_pipeline_state_change), play);
-               g_signal_connect (G_OBJECT (play->pipeline), "error", G_CALLBACK (callback_pipeline_error), play);
+       if (query_worked){
+               g_print("got length %" G_GINT64_FORMAT "\n", value);
+               g_signal_emit (G_OBJECT (play), gst_play_signals [STREAM_LENGTH], 0, value);
+               play->length_nanos = value;
+               return FALSE;
        }
-
-       if (play->volume){
-               play->vol_dpman =  gst_dpman_get_manager(play->volume);
-               play->vol_dparam = gst_dpsmooth_new(G_TYPE_FLOAT);
-  
-               g_object_set(G_OBJECT(play->vol_dparam), "update_period", 2000000LL, NULL);
-  
-               g_object_set(G_OBJECT(play->vol_dparam), "slope_delta_float", 0.1F, NULL);
-               g_object_set(G_OBJECT(play->vol_dparam), "slope_time", 10000000LL, NULL); 
-               if (!gst_dpman_attach_dparam (play->vol_dpman, "volume", play->vol_dparam)){
-                       g_warning("could not attach dparam to volume element\n");
+       else {
+               if (play->get_length_attempt-- < 1){
+                       /* we've tried enough times, give up */
+                       return FALSE;
                }
-               gst_dpman_set_mode(play->vol_dpman, "asynchronous");
-               gst_play_set_volume(play, 0.9);
        }
+       return (gst_element_get_state(play->pipeline) == GST_STATE_PLAYING);
+}
+
+static gboolean
+gst_play_tick_callback (GstPlay *play)
+{
+       gint secs;
        
-       play->signal_queue = g_async_queue_new();
+       g_return_val_if_fail(GST_IS_PLAY(play), FALSE);
+       
+       play->clock = gst_bin_get_clock (GST_BIN (play->pipeline));
+       play->time_nanos = gst_clock_get_time(play->clock);
+       secs = (gint) (play->time_nanos / GST_SECOND);
+       if (secs != play->time_seconds){
+               play->time_seconds = secs;
+               g_signal_emit (G_OBJECT (play), gst_play_signals [TIME_TICK], 0, play->time_nanos);
+       }
 
-       return play;
+       return (gst_element_get_state(play->pipeline) == GST_STATE_PLAYING);
 }
 
-static void
-gst_play_dispose (GObject *object)
+static gboolean
+gst_play_default_idle (GstPlayIdleData *idle_data)
 {
-       GstPlay *play = GST_PLAY (object);
-       /* Before disposing, removing any callback that could
-       be called : time ticks, signal poller, etc...*/
-       if (play->tick_timeout_id)
-               if (!g_source_remove(play->tick_timeout_id))
-                       g_warning("failed to remove timetick timer %d", play->tick_timeout_id);
-       if (play->idle_timeout_id)
-               if (!g_source_remove(play->idle_timeout_id))
-                       g_warning("failed to remove idle timer %d", play->idle_timeout_id);
-       if (play->idle_signal_id)
-               if (!g_source_remove(play->idle_signal_id))
-                       g_warning("failed to remove signal idle timer %d", play->idle_signal_id);
-               
-       G_OBJECT_CLASS (parent_class)->dispose (object);
-       g_mutex_free(play->audio_bin_mutex);
-       g_mutex_free(play->video_bin_mutex);
-}
-
-static void
-callback_pipeline_error (GObject *object, GstObject *orig, gchar *error, GstPlay* play)
-{ 
-       g_print ("Pipeline error: %s\n", error);
-       if (gst_element_get_state(play->pipeline) == GST_STATE_PLAYING){
-               gst_element_set_state(play->pipeline, GST_STATE_READY);
+       if(idle_data->func(idle_data->data)){
+               /* call this function again in the future */
+               return TRUE;
        }
-} 
-
-static void
-callback_pipeline_deep_notify (GstElement *element, GstElement *orig, GParamSpec *param, GstPlay* play)
-{
-       GstPlaySignal *signal;
-       signal = g_new0(GstPlaySignal, 1);
-       signal->signal_id = INFORMATION;
-       signal->signal_data.info.element = orig;
-       signal->signal_data.info.param = param;
-       g_async_queue_push(play->signal_queue, signal);
-       /* If an idle callback has been added for signal polling
-       no need to put a new one */
-       if (!play->idle_signal_id)
-               play->idle_signal_id = play->idle_add_func ((GSourceFunc) gst_play_idle_signal, play);
+       /* this function should no longer be called */
+       g_free(idle_data);
+       return FALSE;
 }
 
-static void
-callback_pipeline_state_change (GstElement *element, GstElementState old, GstElementState state, GstPlay* play)
+static guint
+gst_play_default_timeout_add ( guint interval,
+                                                               GSourceFunc function,
+                                                               gpointer data)
 {
-       GstPlaySignal *signal;
+       GstPlayIdleData *idle_data = g_new0(GstPlayIdleData, 1);
+       idle_data->func = function;
+       idle_data->data = data;
 
-       g_return_if_fail (GST_IS_ELEMENT (element));
-       g_return_if_fail (GST_IS_PLAY (play));
-       g_return_if_fail (element == play->pipeline);
+       return g_timeout_add (interval, (GSourceFunc)gst_play_default_idle, idle_data);
+}
 
-       /*g_print ("got state change %s to %s\n", gst_element_state_get_name (old), gst_element_state_get_name (state));*/
+static guint
+gst_play_default_idle_add (    GSourceFunc function,
+                                                       gpointer data)
+{
+       GstPlayIdleData *idle_data = g_new0(GstPlayIdleData, 1);
+       idle_data->func = function;
+       idle_data->data = data;
+       
+       return g_idle_add ((GSourceFunc)gst_play_default_idle, idle_data);
+}
 
-       /* do additional stuff depending on state */
-       if (GST_IS_PIPELINE (play->pipeline)){
-               switch (state) {
-               case GST_STATE_PLAYING:
-                       play->idle_timeout_id = play->idle_add_func ((GSourceFunc) gst_play_idle_callback, play);
-                       play->tick_timeout_id = play->timeout_add_func (200, (GSourceFunc) gst_play_tick_callback, play);
-                       if (play->length_nanos == 0LL){
-                               /* try to get the length up to 16 times */
-                               play->get_length_attempt = 16;
-                               play->timeout_add_func (200, (GSourceFunc) gst_play_get_length_callback, play); 
-                       }
-                       break;
-               default:
-                       break;
-               }
-       }       
-       signal = g_new0(GstPlaySignal, 1);
-       signal->signal_id = STATE_CHANGE;
-       signal->signal_data.state.old_state = old;
-       signal->signal_data.state.new_state = state;
-       g_async_queue_push(play->signal_queue, signal);
-       /* If an idle callback has been added for signal polling
-       no need to put a new one */
-       if (!play->idle_signal_id)
-               play->idle_signal_id = play->idle_add_func ((GSourceFunc) gst_play_idle_signal, play);
+static gboolean
+gst_play_idle_callback (GstPlay *play)
+{
+       g_return_val_if_fail(GST_IS_PLAY(play), FALSE);
+       
+       return gst_bin_iterate (GST_BIN (play->pipeline));
 }
 
 static gboolean
@@ -502,13 +333,7 @@ gst_play_idle_signal (GstPlay *play)
 
        g_free(signal);
        queue_length = g_async_queue_length (play->signal_queue);
-       
-       /* If queue length is zero the idle callback will be
-       destroyed */
-       
-       if (!queue_length)
-               play->idle_signal_id = 0;
-       
+               
        return (queue_length > 0);
 }
 
@@ -520,161 +345,305 @@ gst_play_idle_eos (GstPlay* play)
 }
 
 static void
-callback_audio_sink_eos (GstElement *element, GstPlay *play)
+callback_audio_sink_eos (      GstElement *element,
+                                                       GstPlay *play)
 {
        play->idle_add_func ((GSourceFunc) gst_play_idle_eos, play);
 }
 
 static void
-callback_video_have_xid (GstElement *element, gint xid, GstPlay *play)
+callback_video_have_xid (      GstElement *element,
+                                                       gint xid,
+                                                       GstPlay *play)
 {
        GstPlaySignal *signal;
+       
        signal = g_new0(GstPlaySignal, 1);
        signal->signal_id = HAVE_XID;
        signal->signal_data.video_xid.xid = xid;
+       
        g_async_queue_push(play->signal_queue, signal);
-       /* If an idle callback has been added for signal polling
-       no need to put a new one */
-       if (!play->idle_signal_id)
-               play->idle_signal_id = play->idle_add_func ((GSourceFunc) gst_play_idle_signal, play);
-       /*g_print("have xid %d\n", xid);*/
+       
+       play->idle_add_func ((GSourceFunc) gst_play_idle_signal, play);
 }
 
 static void
-callback_video_have_size (GstElement *element, gint width, gint height, GstPlay *play)
+callback_video_have_size (     GstElement *element,
+                                                       gint width,
+                                                       gint height,
+                                                       GstPlay *play)
 {
        GstPlaySignal *signal;
+       
        signal = g_new0(GstPlaySignal, 1);
        signal->signal_id = HAVE_VIDEO_SIZE;
        signal->signal_data.video_size.width = width;
        signal->signal_data.video_size.height = height;
+       
        g_async_queue_push(play->signal_queue, signal);
-       /* If an idle callback has been added for signal polling
-       no need to put a new one */
-       if (!play->idle_signal_id)
-               play->idle_signal_id = play->idle_add_func ((GSourceFunc) gst_play_idle_signal, play);
-       /*g_print("have size %d x %d\n", width, height);*/
+       
+       play->idle_add_func ((GSourceFunc) gst_play_idle_signal, play);
 }
 
 static void 
-callback_bin_pre_iterate (GstBin *bin, GMutex *mutex)
+callback_bin_pre_iterate (     GstBin *bin,
+                                                       GMutex *mutex)
 {
        g_mutex_lock(mutex);
 }
 
 static void 
-callback_bin_post_iterate (GstBin *bin, GMutex *mutex)
+callback_bin_post_iterate (    GstBin *bin,
+                                                       GMutex *mutex)
 {
        g_mutex_unlock(mutex);
 }
 
-static gboolean
-gst_play_get_length_callback (GstPlay *play)
-{
-       gint64 value;
-       GstFormat format = GST_FORMAT_TIME;
-       gboolean query_worked = FALSE;
-
-       g_print("trying to get length\n");
-       if (play->audio_sink_element != NULL){
-               g_mutex_lock(play->audio_bin_mutex);
-               query_worked = gst_element_query (play->audio_sink_element, GST_QUERY_TOTAL, &format, &value);
-               g_mutex_unlock(play->audio_bin_mutex);
-       }
-       else if (play->video_sink_element != NULL){
-               g_mutex_lock(play->video_bin_mutex);
-               query_worked = gst_element_query (play->video_sink_element, GST_QUERY_TOTAL, &format, &value);
-               g_mutex_unlock(play->video_bin_mutex);
-       }
-       if (query_worked){
-               g_print("got length %" G_GINT64_FORMAT "\n", value);
-               g_signal_emit (G_OBJECT (play), gst_play_signals [STREAM_LENGTH], 0, value);
-               play->length_nanos = value;
-               return FALSE;
-       }
-       else {
-               if (play->get_length_attempt-- < 1){
-                       /* we've tried enough times, give up */
-                       return FALSE;
-               }
-       }
-       return (gst_element_get_state(play->pipeline) == GST_STATE_PLAYING);
-}
+static void
+callback_pipeline_error (      GObject *object,
+                                                       GstObject *orig,
+                                                       gchar *error,
+                                                       GstPlay* play)
+{ 
+       g_print ("Pipeline error: %s\n", error);
+       if (gst_element_get_state(play->pipeline) == GST_STATE_PLAYING)
+               gst_element_set_state(play->pipeline, GST_STATE_READY);
+} 
 
-static gboolean
-gst_play_tick_callback (GstPlay *play)
+static void
+callback_pipeline_deep_notify (        GstElement *element,
+                                                               GstElement *orig,
+                                                               GParamSpec *param,
+                                                               GstPlay* play)
 {
-       gint secs;
+       GstPlaySignal *signal;
        
-       g_return_val_if_fail(GST_IS_PLAY(play), FALSE);
+       signal = g_new0(GstPlaySignal, 1);
+       signal->signal_id = INFORMATION;
+       signal->signal_data.info.element = orig;
+       signal->signal_data.info.param = param;
        
-       play->clock = gst_bin_get_clock (GST_BIN (play->pipeline));
-       play->time_nanos = gst_clock_get_time(play->clock);
-       secs = (gint) (play->time_nanos / GST_SECOND);
-       if (secs != play->time_seconds){
-               play->time_seconds = secs;
-               g_signal_emit (G_OBJECT (play), gst_play_signals [TIME_TICK], 0, play->time_nanos);
-       }
-
-       return (gst_element_get_state(play->pipeline) == GST_STATE_PLAYING);
+       g_async_queue_push(play->signal_queue, signal);
+       
+       play->idle_add_func ((GSourceFunc) gst_play_idle_signal, play);
 }
 
-static gboolean
-gst_play_idle_callback (GstPlay *play)
+static void
+callback_pipeline_state_change (       GstElement *element,
+                                                                       GstElementState old,
+                                                                       GstElementState state,
+                                                                       GstPlay* play)
 {
-       g_return_val_if_fail(GST_IS_PLAY(play), FALSE);
-       
-       return gst_bin_iterate (GST_BIN (play->pipeline));
+       GstPlaySignal *signal;
+
+       g_return_if_fail (GST_IS_ELEMENT (element));
+       g_return_if_fail (GST_IS_PLAY (play));
+       g_return_if_fail (element == play->pipeline);
+
+       /*g_print ("got state change %s to %s\n", gst_element_state_get_name (old), gst_element_state_get_name (state));*/
+
+       /* do additional stuff depending on state */
+       if (GST_IS_PIPELINE (play->pipeline)){
+               switch (state) {
+               case GST_STATE_PLAYING:
+                       play->idle_add_func (   (GSourceFunc) gst_play_idle_callback,
+                                                                       play);
+                       play->timeout_add_func (        200,
+                                                                               (GSourceFunc) gst_play_tick_callback,
+                                                                               play);
+                       if (play->length_nanos == 0LL){
+                               /* try to get the length up to 16 times */
+                               play->get_length_attempt = 16;
+                               play->timeout_add_func (200, (GSourceFunc) gst_play_get_length_callback, play); 
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }       
+       signal = g_new0(GstPlaySignal, 1);
+       signal->signal_id = STATE_CHANGE;
+       signal->signal_data.state.old_state = old;
+       signal->signal_data.state.new_state = state;
+
+       g_async_queue_push(play->signal_queue, signal);
+
+       play->idle_add_func ((GSourceFunc) gst_play_idle_signal, play);
 }
 
+/* split static pipeline functions to a seperate file */
+#include "playpipelines.c"
+
+/* =========================================== */
+/*                                             */
+/*              Init & Class init              */
+/*                                             */
+/* =========================================== */
+
 static void
-gst_play_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+gst_play_dispose (GObject *object)
 {
        GstPlay *play = GST_PLAY (object);
 
-       g_return_if_fail (GST_IS_PLAY (play));
-       
-       switch (prop_id) {
-       case ARG_LOCATION:
-               gst_play_set_location(play, g_value_get_string (value));
-               break;
-       case ARG_VOLUME:
-               gst_play_set_volume(play, g_value_get_float (value));
-               break;
-       case ARG_MUTE:
-               gst_play_set_mute(play, g_value_get_boolean (value));
-               break;
-       default:
-               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-               break;
-       }
+       /* Removing all sources */
+       while (g_source_remove_by_user_data (play));
+               
+       G_OBJECT_CLASS (parent_class)->dispose (object);
+       g_mutex_free(play->audio_bin_mutex);
+       g_mutex_free(play->video_bin_mutex);
 }
 
 static void
-gst_play_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+gst_play_class_init (GstPlayClass *klass)
 {
-       GstPlay *play = GST_PLAY (object);
+       GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  
+       parent_class = g_type_class_ref(GST_TYPE_OBJECT);
+
+       klass->information = NULL;
+       klass->state_changed = NULL;
+       klass->stream_end = NULL;
+  
+       gobject_class->dispose = gst_play_dispose;
+       gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_play_set_property);
+       gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_play_get_property);
+
+       g_object_class_install_property (
+                       gobject_class,
+                       ARG_LOCATION,
+                       g_param_spec_string (
+                                               "location",
+                                               "location of file", 
+                                               "location of the file to play",
+                                               NULL, G_PARAM_READWRITE));
+       
+       g_object_class_install_property (
+                       gobject_class,
+                       ARG_VOLUME,
+                       g_param_spec_float (
+                                               "volume",
+                                               "Playing volume", 
+                                   "Playing volume", 
+                                               0, 1.0, 0, G_PARAM_READWRITE));
+                                               
+       g_object_class_install_property (
+                       gobject_class,
+                       ARG_MUTE,
+                       g_param_spec_boolean (
+                                               "mute",
+                                               "Volume muted",
+                                               "Playing volume muted",
+                                               FALSE, G_PARAM_READWRITE));
+  
+       gst_play_signals [INFORMATION] = 
+               g_signal_new ("information", 
+                             G_TYPE_FROM_CLASS (klass), 
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (GstPlayClass, information), 
+                             NULL, NULL,
+                             gst_marshal_VOID__OBJECT_PARAM, 
+                             G_TYPE_NONE, 2, 
+                             G_TYPE_OBJECT, G_TYPE_PARAM);
+       
+       gst_play_signals [STATE_CHANGE] = 
+               g_signal_new ("state_change", 
+                             G_TYPE_FROM_CLASS (klass), 
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (GstPlayClass, state_changed), 
+                             NULL, NULL,
+                             gst_marshal_VOID__INT_INT,
+                             G_TYPE_NONE, 2, 
+                             G_TYPE_INT, G_TYPE_INT);
+       
+       gst_play_signals [STREAM_END] =
+               g_signal_new ("stream_end",
+                             G_TYPE_FROM_CLASS (klass),
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (GstPlayClass, stream_end),
+                             NULL, NULL,
+                             gst_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+
+       gst_play_signals [TIME_TICK] = 
+               g_signal_new ("time_tick", 
+                             G_TYPE_FROM_CLASS (klass), 
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (GstPlayClass, time_tick), 
+                             NULL, NULL,
+                             gst_marshal_VOID__INT64,
+                             G_TYPE_NONE, 1, 
+                             G_TYPE_INT64);
+
+       gst_play_signals [STREAM_LENGTH] = 
+               g_signal_new ("stream_length", 
+                             G_TYPE_FROM_CLASS (klass), 
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (GstPlayClass, stream_length), 
+                             NULL, NULL,
+                             gst_marshal_VOID__INT64,
+                             G_TYPE_NONE, 1, 
+                             G_TYPE_INT64);
+
+       gst_play_signals [HAVE_XID] = 
+               g_signal_new ("have_xid", 
+                             G_TYPE_FROM_CLASS (klass), 
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (GstPlayClass, have_xid), 
+                             NULL, NULL,
+                             gst_marshal_VOID__INT,
+                             G_TYPE_NONE, 1, 
+                             G_TYPE_INT);
+
+       gst_play_signals [HAVE_VIDEO_SIZE] = 
+               g_signal_new ("have_video_size", 
+                             G_TYPE_FROM_CLASS (klass), 
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (GstPlayClass, have_video_size), 
+                             NULL, NULL,
+                             gst_marshal_VOID__INT_INT,
+                             G_TYPE_NONE, 2, 
+                             G_TYPE_INT, G_TYPE_INT);
+
+       gst_control_init(NULL,NULL);
+}
+
+
+
+static void 
+gst_play_init (GstPlay *play) 
+{
+       play->pipeline                          = NULL;
+       play->source                            = NULL;
+       play->autoplugger                       = NULL;
+       play->audio_sink                        = NULL;
+       play->audio_sink_element        = NULL;
+       play->video_sink                        = NULL;
+       play->video_sink_element        = NULL;
+       play->volume                            = NULL;
+       play->other_elements            = g_hash_table_new(g_str_hash, g_str_equal);
+       play->audio_bin_mutex           = g_mutex_new();
+       play->video_bin_mutex           = g_mutex_new();
+       
+       gst_play_set_idle_timeout_funcs(        play,
+                                                                               gst_play_default_timeout_add,
+                                                                               gst_play_default_idle_add);
+}
 
-       g_return_if_fail (GST_IS_PLAY (play));
+/* ============================================================= */
+/*                                                               */
+/*                       Public Methods                          */
+/*                                                               */
+/* ============================================================= */
 
-       switch (prop_id) {
-       case ARG_LOCATION:
-               g_value_set_string (value, gst_play_get_location(play));
-               break;
-       case ARG_VOLUME:
-               g_value_set_float(value, gst_play_get_volume(play));
-               break;
-       case ARG_MUTE:
-               g_value_set_boolean (value, gst_play_get_mute(play));
-               break;
-       default:
-               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-               break;
-       }
-}
+/* =========================================== */
+/*                                             */
+/*                   Toolbox                   */
+/*                                             */
+/* =========================================== */
 
 void
-gst_play_seek_to_time (GstPlay *play, gint64 time_nanos)
+gst_play_seek_to_time (        GstPlay *play,
+                                               gint64 time_nanos)
 {
        GstEvent *s_event;
         guint8   prev_state;
@@ -717,48 +686,19 @@ gst_play_seek_to_time (GstPlay *play, gint64 time_nanos)
 }
 
 void
-gst_play_need_new_video_window(GstPlay *play)
+gst_play_need_new_video_window (GstPlay *play)
 {
        g_return_if_fail (GST_IS_PLAY (play));
        if (GST_IS_ELEMENT(play->video_sink_element)){
-               g_object_set(G_OBJECT(play->video_sink_element), "need_new_window", TRUE, NULL);
-       }
-}
-
-static gboolean
-gst_play_default_idle (GstPlayIdleData *idle_data)
-{
-       if(idle_data->func(idle_data->data)){
-               /* call this function again in the future */
-               return TRUE;
+               g_object_set(   G_OBJECT(play->video_sink_element),
+                                               "need_new_window", TRUE, NULL);
        }
-       /* this function should no longer be called */
-       g_free(idle_data);
-       return FALSE;
-}
-
-static guint
-gst_play_default_timeout_add (guint interval, GSourceFunc function, gpointer data)
-{
-       GstPlayIdleData *idle_data = g_new0(GstPlayIdleData, 1);
-       idle_data->func = function;
-       idle_data->data = data;
-
-       return g_timeout_add (interval, (GSourceFunc)gst_play_default_idle, idle_data);
-}
-
-static guint
-gst_play_default_idle_add (GSourceFunc function, gpointer data)
-{
-       GstPlayIdleData *idle_data = g_new0(GstPlayIdleData, 1);
-       idle_data->func = function;
-       idle_data->data = data;
-       
-       return g_idle_add ((GSourceFunc)gst_play_default_idle, idle_data);
 }
 
 void
-gst_play_set_idle_timeout_funcs (GstPlay *play, GstPlayTimeoutAdd timeout_add_func, GstPlayIdleAdd idle_add_func)
+gst_play_set_idle_timeout_funcs (      GstPlay *play,
+                                                                       GstPlayTimeoutAdd timeout_add_func,
+                                                                       GstPlayIdleAdd idle_add_func)
 {
        g_return_if_fail (GST_IS_PLAY (play));
        play->timeout_add_func = timeout_add_func;
@@ -766,7 +706,9 @@ gst_play_set_idle_timeout_funcs (GstPlay *play, GstPlayTimeoutAdd timeout_add_fu
 }
 
 GstElement*
-gst_play_get_sink_element (GstPlay *play, GstElement *element){
+gst_play_get_sink_element (    GstPlay *play,
+                                                       GstElement *element)
+{
        GstPad *pad = NULL;
        GList *elements = NULL;
        const GList *pads = NULL;
@@ -804,62 +746,15 @@ gst_play_get_sink_element (GstPlay *play, GstElement *element){
        return NULL;
 }
 
-gboolean
-gst_play_set_data_src (GstPlay *play, GstElement *data_src)
-{
-       g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
-       g_return_val_if_fail (GST_IS_ELEMENT (data_src), FALSE);
-
-       if (gst_play_get_state (play) != GST_STATE_READY){
-               gst_play_set_state (play, GST_STATE_READY);
-       }
-
-       if (play->set_data_src){
-               return play->set_data_src(play, data_src);
-       }
-
-       /* if there is no set_data_src func, fail quietly */
-       return FALSE;
-}
-
-gboolean
-gst_play_set_video_sink (GstPlay *play, GstElement *video_sink)
-{
-       g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
-       g_return_val_if_fail (GST_IS_ELEMENT (video_sink), FALSE);
-
-       if (gst_play_get_state (play) != GST_STATE_READY){
-               gst_play_set_state (play, GST_STATE_READY);
-       }
-
-       if (play->set_video_sink){
-               return play->set_video_sink(play, video_sink);
-       }
-
-       /* if there is no set_video_sink func, fail quietly */
-       return FALSE;
-}
-
-gboolean
-gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
-{
-       g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
-       g_return_val_if_fail (GST_IS_ELEMENT (audio_sink), FALSE);
-
-       if (gst_play_get_state (play) != GST_STATE_READY){
-               gst_play_set_state (play, GST_STATE_READY);
-       }
-
-       if (play->set_audio_sink){
-               return play->set_audio_sink(play, audio_sink);
-       }
-
-       /* if there is no set_audio_sink func, fail quietly */
-       return FALSE;
-}
+/* =========================================== */
+/*                                             */
+/*      State, Mute, Volume, Location          */
+/*                                             */
+/* =========================================== */
 
 GstElementStateReturn
-gst_play_set_state (GstPlay *play, GstElementState state)
+gst_play_set_state (   GstPlay *play,
+                                               GstElementState state)
 {
        g_return_val_if_fail (GST_IS_PLAY (play), GST_STATE_FAILURE);
        g_return_val_if_fail (GST_IS_ELEMENT(play->pipeline), GST_STATE_FAILURE);
@@ -878,7 +773,8 @@ gst_play_get_state (GstPlay *play)
 }
 
 gboolean
-gst_play_set_location (GstPlay *play, const gchar *location)
+gst_play_set_location (        GstPlay *play,
+                                               const gchar *location)
 {
        GstElementState current_state;
        g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
@@ -922,7 +818,8 @@ gst_play_get_location (GstPlay *play)
 
 
 void
-gst_play_set_volume (GstPlay *play, gfloat volume)
+gst_play_set_volume (  GstPlay *play,
+                                               gfloat volume)
 {
        g_return_if_fail (GST_IS_PLAY (play));
 
@@ -942,7 +839,8 @@ gst_play_get_volume (GstPlay *play)
 }
 
 void
-gst_play_set_mute (GstPlay *play, gboolean mute)
+gst_play_set_mute (    GstPlay *play,
+                                       gboolean mute)
 {
        g_return_if_fail (GST_IS_PLAY (play));
 
@@ -961,6 +859,202 @@ gst_play_get_mute (GstPlay *play)
        return mute;
 }
 
-/* modelines */
-/* vim:set ts=8:sw=8:noet */
+/* =========================================== */
+/*                                             */
+/*    Audio sink, Video sink, Data src         */
+/*                                             */
+/* =========================================== */
+
+gboolean
+gst_play_set_data_src (        GstPlay *play,
+                                               GstElement *data_src)
+{
+       g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
+       g_return_val_if_fail (GST_IS_ELEMENT (data_src), FALSE);
+
+       if (gst_play_get_state (play) != GST_STATE_READY){
+               gst_play_set_state (play, GST_STATE_READY);
+       }
+
+       if (play->set_data_src){
+               return play->set_data_src(play, data_src);
+       }
+
+       /* if there is no set_data_src func, fail quietly */
+       return FALSE;
+}
+
+gboolean
+gst_play_set_video_sink (      GstPlay *play,
+                                                       GstElement *video_sink)
+{
+       g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
+       g_return_val_if_fail (GST_IS_ELEMENT (video_sink), FALSE);
+
+       if (gst_play_get_state (play) != GST_STATE_READY){
+               gst_play_set_state (play, GST_STATE_READY);
+       }
+
+       if (play->set_video_sink){
+               return play->set_video_sink(play, video_sink);
+       }
+
+       /* if there is no set_video_sink func, fail quietly */
+       return FALSE;
+}
+
+gboolean
+gst_play_set_audio_sink (      GstPlay *play,
+                                                       GstElement *audio_sink)
+{
+       g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
+       g_return_val_if_fail (GST_IS_ELEMENT (audio_sink), FALSE);
+
+       if (gst_play_get_state (play) != GST_STATE_READY){
+               gst_play_set_state (play, GST_STATE_READY);
+       }
+
+       if (play->set_audio_sink){
+               return play->set_audio_sink(play, audio_sink);
+       }
+
+       /* if there is no set_audio_sink func, fail quietly */
+       return FALSE;
+}
+
+/* =========================================== */
+/*                                             */
+/*          Object typing & Creation           */
+/*                                             */
+/* =========================================== */
+
+GType
+gst_play_get_type (void)
+{
+       static GType play_type = 0;
+       
+       if (!play_type)
+       {
+               static const GTypeInfo play_info = {
+                       sizeof (GstPlayClass),
+                       (GBaseInitFunc) NULL,
+                       (GBaseFinalizeFunc) NULL,
+                       (GClassInitFunc) gst_play_class_init,
+                       NULL, NULL, sizeof (GstPlay),
+                       0, (GInstanceInitFunc) gst_play_init,
+                       NULL
+               };
+      
+               play_type = g_type_register_static (G_TYPE_OBJECT, "GstPlay", &play_info, 0);
+       }
+
+       return play_type;
+}
+
+
+GstPlay *
+gst_play_new ( GstPlayPipeType pipe_type,
+                               GError **error)
+{
+       GstPlay *play;
+
+       play = g_object_new (GST_TYPE_PLAY, NULL);
+
+       /* FIXME: looks like only VIDEO ever gets used ! */
+       switch (pipe_type){
+               case GST_PLAY_PIPE_VIDEO:
+                       play->setup_pipeline = gst_play_video_setup;
+                       play->teardown_pipeline = NULL;
+                       play->set_data_src = gst_play_video_set_data_src;
+                       play->set_autoplugger = gst_play_video_set_auto;
+                       play->set_video_sink = gst_play_video_set_video;
+                       play->set_audio_sink = gst_play_video_set_audio;
+                       break;
+               case GST_PLAY_PIPE_AUDIO:
+                       /* we can reuse the threaded set functions */
+                       play->setup_pipeline = gst_play_audio_setup;
+                       play->teardown_pipeline = NULL;
+                       play->set_data_src = gst_play_simple_set_data_src;
+                       play->set_autoplugger = gst_play_audiot_set_auto;
+                       play->set_video_sink = NULL;
+                       play->set_audio_sink = gst_play_audiot_set_audio;
+                       break;
+               case GST_PLAY_PIPE_AUDIO_THREADED:
+                       play->setup_pipeline = gst_play_audiot_setup;
+                       play->teardown_pipeline = NULL;
+                       play->set_data_src = gst_play_simple_set_data_src;
+                       play->set_autoplugger = gst_play_audiot_set_auto;
+                       play->set_video_sink = NULL;
+                       play->set_audio_sink = gst_play_audiot_set_audio;
+                       break;
+               case GST_PLAY_PIPE_AUDIO_HYPER_THREADED:
+                       play->setup_pipeline = gst_play_audioht_setup;
+                       play->teardown_pipeline = NULL;
+                       play->set_data_src = gst_play_simple_set_data_src;
+                       play->set_autoplugger = gst_play_audioht_set_auto;
+                       play->set_video_sink = NULL;
+                       play->set_audio_sink = gst_play_audioht_set_audio;
+                       break;
+               default:
+                       g_warning("unknown pipeline type: %d\n", pipe_type);
+       }
+
+       /* init pipeline */
+       if ((play->setup_pipeline) &&
+           (! play->setup_pipeline (play, error)))
+       {
+               g_object_unref (play);
+               return NULL;
+       }
+
+
+       if (play->pipeline) {
+               /* connect to pipeline events */
+               g_signal_connect (      G_OBJECT (play->pipeline),
+                                                       "deep_notify",
+                                                       G_CALLBACK (callback_pipeline_deep_notify),
+                                                       play);
+               g_signal_connect (      G_OBJECT (play->pipeline),
+                                                       "state_change",
+                                                       G_CALLBACK (callback_pipeline_state_change),
+                                                       play);
+               g_signal_connect (      G_OBJECT (play->pipeline),
+                                                       "error",
+                                                       G_CALLBACK (callback_pipeline_error),
+                                                       play);
+       }
+
+       if (play->volume) {
+               play->vol_dpman =  gst_dpman_get_manager(play->volume);
+               play->vol_dparam = gst_dpsmooth_new(G_TYPE_FLOAT);
+  
+               g_object_set(   G_OBJECT(play->vol_dparam),
+                                               "update_period", 2000000LL, NULL);
+  
+               g_object_set(   G_OBJECT(play->vol_dparam),
+                                               "slope_delta_float", 0.1F, NULL);
+               g_object_set(   G_OBJECT(play->vol_dparam),
+                                               "slope_time", 10000000LL, NULL); 
+               if (!gst_dpman_attach_dparam (  play->vol_dpman,
+                                                                               "volume",
+                                                                               play->vol_dparam))
+                       g_warning("could not attach dparam to volume element\n");
+               
+               gst_dpman_set_mode(play->vol_dpman, "asynchronous");
+               gst_play_set_volume(play, 0.9);
+       }
+       
+       play->signal_queue = g_async_queue_new();
+
+       return play;
+}
+
+
+
+
+
+
+
+
 
index acf777c..f9b1411 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 1999,2000,2001,2002 Erik Walthinsen <omega@cse.ogi.edu>
  *                    2000,2001,2002 Wim Taymans <wtay@chello.be>
  *                              2002 Steve Baker <steve@stevebaker.org>
+ *                                                             2003 Julien Moutte <julien@moutte.net>
  *
  * play.h: GstPlay object code
  *
@@ -76,7 +77,9 @@ typedef struct _GstPlay          GstPlay;
 typedef struct _GstPlayClass     GstPlayClass;
 typedef struct _GstPlayIdleData  GstPlayIdleData;
 
-typedef guint (*GstPlayTimeoutAdd) (guint interval, GSourceFunc function, gpointer data);
+typedef guint (*GstPlayTimeoutAdd) (   guint interval,
+                                                                               GSourceFunc function,
+                                                                               gpointer data);
 typedef guint (*GstPlayIdleAdd)    (GSourceFunc function, gpointer data);
 
 struct _GstPlay
@@ -117,10 +120,6 @@ struct _GstPlay
        gint64 time_nanos;
        gint64 length_nanos;
        
-       guint tick_timeout_id;
-       guint idle_timeout_id;
-       guint idle_signal_id;
-
        GAsyncQueue *signal_queue;
 
        GstPlayTimeoutAdd timeout_add_func;
@@ -132,13 +131,22 @@ struct _GstPlayClass
        GObjectClass parent_class;
        
        /* signals */
-       void (*information)    (GstPlay* play, GstElement* element, GParamSpec *param);
-       void (*state_changed)  (GstPlay* play, GstElementState old_state, GstElementState new_state);
-       void (*stream_end)     (GstPlay* play);
-       void (*time_tick)    (GstPlay* play, gint64 time_nanos);
-       void (*stream_length)  (GstPlay* play, gint64 length_nanos);
-       void (*have_xid)  (GstPlay* play, gint xid);
-       void (*have_video_size)  (GstPlay* play, gint width, gint height);
+       void (*information)             (       GstPlay* play,
+                                                               GstElement* element,
+                                                               GParamSpec *param);
+       void (*state_changed)   (       GstPlay* play,
+                                                               GstElementState old_state,
+                                                               GstElementState new_state);
+       void (*stream_end)              (       GstPlay* play);
+       void (*time_tick)               (       GstPlay* play,
+                                                               gint64 time_nanos);
+       void (*stream_length)   (       GstPlay* play,
+                                                               gint64 length_nanos);
+       void (*have_xid)                (       GstPlay* play,
+                                                               gint xid);
+       void (*have_video_size) (       GstPlay* play,
+                                                               gint width,
+                                                               gint height);
 };
 
 struct _GstPlayIdleData
@@ -147,35 +155,71 @@ struct _GstPlayIdleData
        gpointer data;
 };
 
-GType    gst_play_get_type        (void);
 
-GstPlay*  gst_play_new            (GstPlayPipeType pipe_type, GError **error);
+void
+gst_play_seek_to_time (        GstPlay *play,
+                                               gint64 time_nanos);
 
-void      gst_play_seek_to_time (GstPlay *play, gint64 time_nanos);
+void
+gst_play_need_new_video_window (GstPlay *play);
 
-GstElement*       gst_play_get_sink_element (GstPlay *play, GstElement *element);
+void
+gst_play_set_idle_timeout_funcs (      GstPlay *play,
+                                                                       GstPlayTimeoutAdd timeout_add_func,
+                                                                       GstPlayIdleAdd idle_add_func);
+GstElement*
+gst_play_get_sink_element (    GstPlay *play,
+                                                       GstElement *element);
 
-gboolean         gst_play_set_data_src (GstPlay *play, GstElement *data_src);
-gboolean         gst_play_set_video_sink  (GstPlay *play, GstElement *element);
-gboolean         gst_play_set_audio_sink  (GstPlay *play, GstElement *element);
-void             gst_play_need_new_video_window  (GstPlay *play);
+/* Set/Get state */
 
-GstElementStateReturn gst_play_set_state       (GstPlay *play, GstElementState state);
-GstElementState gst_play_get_state (GstPlay *play);
+GstElementStateReturn
+gst_play_set_state (   GstPlay *play,
+                                               GstElementState state);
+GstElementState
+gst_play_get_state (GstPlay *play);
 
-gboolean  gst_play_set_location    (GstPlay *play, const gchar *location);
-gchar*    gst_play_get_location    (GstPlay *play);
+/* Set/Get location */
 
-void      gst_play_set_volume      (GstPlay *play, gfloat volume);
-gfloat     gst_play_get_volume      (GstPlay *play);
+gboolean
+gst_play_set_location (        GstPlay *play,
+                                               const gchar *location);
+gchar*
+gst_play_get_location (GstPlay *play);
 
-void      gst_play_set_mute        (GstPlay *play, gboolean mute);
-gboolean  gst_play_get_mute        (GstPlay *play);
+/* Set/Get volume */
 
-void      gst_play_set_idle_timeout_funcs (GstPlay *play, GstPlayTimeoutAdd timeout_add_func, GstPlayIdleAdd idle_add_func);
+void
+gst_play_set_volume (  GstPlay *play,
+                                               gfloat volume);
+gfloat
+gst_play_get_volume (GstPlay *play);
 
-#endif /* __GSTPLAY_H__ */
+/* Set/Get mute */
+
+void
+gst_play_set_mute (    GstPlay *play,
+                                       gboolean mute);
+gboolean
+gst_play_get_mute (GstPlay *play);
+
+/* Set sinks and data src */
 
-/* modelines */
-/* vim:set ts=8:sw=8:noet */
+gboolean
+gst_play_set_data_src (        GstPlay *play,
+                                               GstElement *data_src);
+gboolean
+gst_play_set_video_sink (      GstPlay *play,
+                                                       GstElement *video_sink);
+gboolean
+gst_play_set_audio_sink (      GstPlay *play,
+                                                       GstElement *audio_sink);
 
+GType
+gst_play_get_type (void);
+
+GstPlay *
+gst_play_new ( GstPlayPipeType pipe_type,
+                               GError **error);
+
+#endif /* __GSTPLAY_H__ */
index 527ea43..ace3462 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 1999,2000,2001,2002 Erik Walthinsen <omega@cse.ogi.edu>
  *                    2000,2001,2002 Wim Taymans <wtay@chello.be>
  *                              2002 Steve Baker <steve@stevebaker.org>
+ *                                                             2003 Julien Moutte <julien@moutte.net>
  *
  * playpipelines.c: Set up pipelines for playback
  *
  */
 
 static gboolean
-gst_play_default_set_data_src (GstPlay *play, GstElement *datasrc, GstElement* parent)
+gst_play_default_set_data_src (        GstPlay *play,
+                                                               GstElement *datasrc,
+                                                               GstElement* parent)
 {
        g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
        g_return_val_if_fail (GST_IS_ELEMENT (datasrc), FALSE);
        
        if (GST_IS_ELEMENT(play->source)) {
-               /* we need to remove the existing data source before creating a new one */
+               /* we need to remove the existing data
+                       source before creating a new one */
                if (GST_IS_ELEMENT(play->autoplugger)){
                        gst_element_unlink (play->autoplugger, play->source);
                }
@@ -51,7 +55,8 @@ gst_play_default_set_data_src (GstPlay *play, GstElement *datasrc, GstElement* p
  */
 
 static gboolean 
-gst_play_audio_setup (GstPlay *play, GError **error)
+gst_play_audio_setup ( GstPlay *play,
+                                               GError **error)
 {
        
        /* creating gst_bin */
@@ -105,7 +110,8 @@ gst_play_audio_setup (GstPlay *play, GError **error)
 }
 
 static gboolean
-gst_play_simple_set_data_src (GstPlay *play, GstElement *datasrc)
+gst_play_simple_set_data_src ( GstPlay *play,
+                                                               GstElement *datasrc)
 {
        return gst_play_default_set_data_src(play, datasrc, play->pipeline);
 }
@@ -116,7 +122,8 @@ gst_play_simple_set_data_src (GstPlay *play, GstElement *datasrc)
  */
  
 static gboolean 
-gst_play_audiot_setup (GstPlay *play, GError **error)
+gst_play_audiot_setup (        GstPlay *play,
+                                               GError **error)
 {
        
        g_return_val_if_fail (GST_IS_PLAY(play), FALSE);
@@ -173,7 +180,8 @@ gst_play_audiot_setup (GstPlay *play, GError **error)
 
 
 static gboolean
-gst_play_audiot_set_audio (GstPlay *play, GstElement *audio_sink)
+gst_play_audiot_set_audio (    GstPlay *play,
+                                                       GstElement *audio_sink)
 {
        g_return_val_if_fail (GST_IS_PLAY(play), FALSE);
        g_return_val_if_fail (GST_IS_ELEMENT (audio_sink), FALSE);
@@ -200,14 +208,16 @@ gst_play_audiot_set_audio (GstPlay *play, GstElement *audio_sink)
 
 
 static gboolean
-gst_play_audiot_set_auto (GstPlay *play, GstElement *autoplugger)
+gst_play_audiot_set_auto (     GstPlay *play,
+                                                       GstElement *autoplugger)
 {
 
        g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
        g_return_val_if_fail (GST_IS_ELEMENT (autoplugger), FALSE);
        
        if (play->autoplugger) {
-               /* we need to remove the existing autoplugger before creating a new one */
+               /* we need to remove the existing autoplugger
+                       before creating a new one */
                gst_element_unlink (play->autoplugger, play->volume);
                gst_element_unlink (play->autoplugger, play->source);
                gst_bin_remove (GST_BIN (play->pipeline), play->autoplugger);
@@ -228,7 +238,8 @@ gst_play_audiot_set_auto (GstPlay *play, GstElement *autoplugger)
  */
 
 static gboolean 
-gst_play_audioht_setup (GstPlay *play, GError **error)
+gst_play_audioht_setup (       GstPlay *play,
+                                                       GError **error)
 {
        GstElement *audio_thread, *audio_queue;
 
@@ -313,7 +324,8 @@ gst_play_audioht_setup (GstPlay *play, GError **error)
 
 
 static gboolean
-gst_play_audioht_set_audio (GstPlay *play, GstElement *audio_sink)
+gst_play_audioht_set_audio (   GstPlay *play,
+                                                               GstElement *audio_sink)
 {
        GstElement *audio_thread;
        
@@ -344,7 +356,8 @@ gst_play_audioht_set_audio (GstPlay *play, GstElement *audio_sink)
 
 
 static gboolean
-gst_play_audioht_set_auto (GstPlay *play, GstElement *autoplugger)
+gst_play_audioht_set_auto (    GstPlay *play,
+                                                       GstElement *autoplugger)
 {
        GstElement *audio_thread;
        
@@ -354,7 +367,8 @@ gst_play_audioht_set_auto (GstPlay *play, GstElement *autoplugger)
        audio_thread = g_hash_table_lookup(play->other_elements, "audio_thread");
 
        if (play->autoplugger) {
-               /* we need to remove the existing autoplugger before creating a new one */
+               /* we need to remove the existing autoplugger
+                       before creating a new one */
                gst_element_unlink (play->autoplugger, audio_thread);
                gst_element_unlink (play->autoplugger, play->source);
                gst_bin_remove (GST_BIN (play->pipeline), play->autoplugger);
@@ -376,7 +390,8 @@ gst_play_audioht_set_auto (GstPlay *play, GstElement *autoplugger)
  */
 
 static gboolean 
-gst_play_video_setup (GstPlay *play, GError **error)
+gst_play_video_setup ( GstPlay *play,
+                                               GError **error)
 {
        GstElement *audio_bin, *audio_queue;
        GstElement *video_queue, *video_bin;
@@ -523,7 +538,8 @@ gst_play_video_setup (GstPlay *play, GError **error)
 }
 
 static gboolean
-gst_play_video_set_data_src (GstPlay *play, GstElement *datasrc)
+gst_play_video_set_data_src (  GstPlay *play,
+                                                               GstElement *datasrc)
 {
        GstElement *work_thread;
        g_return_val_if_fail (GST_IS_PLAY(play), FALSE);
@@ -533,7 +549,8 @@ gst_play_video_set_data_src (GstPlay *play, GstElement *datasrc)
 }
 
 static gboolean
-gst_play_video_set_auto (GstPlay *play, GstElement *autoplugger)
+gst_play_video_set_auto (      GstPlay *play,
+                                                       GstElement *autoplugger)
 {
 
        GstElement *audio_bin, *video_bin, *work_thread;
@@ -546,7 +563,8 @@ gst_play_video_set_auto (GstPlay *play, GstElement *autoplugger)
        work_thread = g_hash_table_lookup(play->other_elements, "work_thread");
 
        if (play->autoplugger) {
-               /* we need to remove the existing autoplugger before creating a new one */
+               /* we need to remove the existing autoplugger
+                       before creating a new one */
                gst_element_unlink (play->autoplugger, audio_bin);
                gst_element_unlink (play->autoplugger, play->source);
                gst_element_unlink (play->autoplugger, video_bin);
@@ -567,7 +585,8 @@ gst_play_video_set_auto (GstPlay *play, GstElement *autoplugger)
 
 
 static gboolean
-gst_play_video_set_video (GstPlay *play, GstElement *video_sink)
+gst_play_video_set_video (     GstPlay *play,
+                                                       GstElement *video_sink)
 {
        GstElement *video_mate, *video_bin;
        
@@ -588,18 +607,27 @@ gst_play_video_set_video (GstPlay *play, GstElement *video_sink)
        play->video_sink_element = gst_play_get_sink_element (play, video_sink);
 
        if (play->video_sink_element != NULL) {
-               g_signal_connect (G_OBJECT (play->video_sink_element), "have_xid",
-                                 G_CALLBACK (callback_video_have_xid), play);
-               g_signal_connect (G_OBJECT (play->video_sink_element), "have_size",
-                                 G_CALLBACK (callback_video_have_size), play);
-               g_object_set(G_OBJECT(play->video_sink_element), "need_new_window", TRUE, "toplevel", FALSE, NULL);
+               g_signal_connect (      G_OBJECT (play->video_sink_element),
+                                                       "have_xid",
+                                                       G_CALLBACK (callback_video_have_xid),
+                                                       play);
+               g_signal_connect (      G_OBJECT (play->video_sink_element),
+                                                       "have_size",
+                                                       G_CALLBACK (callback_video_have_size),
+                                                       play);
+               g_object_set(   G_OBJECT(play->video_sink_element),
+                                               "need_new_window",
+                                               TRUE,
+                                               "toplevel",
+                                               FALSE, NULL);
        }
        return TRUE;
 }
 
 
 static gboolean
-gst_play_video_set_audio (GstPlay *play, GstElement *audio_sink)
+gst_play_video_set_audio (     GstPlay *play,
+                                                       GstElement *audio_sink)
 {
        GstElement *audio_bin;