#include <gst/pbutils/pbutils.h>
#include "gstplay-enum.h"
+#include "gstplay-marshal.h"
#include "gstplaysink.h"
#include "gstfactorylists.h"
#include "gststreaminfo.h"
GstPlaySinkType type; /* the sink pad type of the selector */
GstElement *selector; /* the selector */
- gint current; /* the currently selected stream */
+ GPtrArray *channels;
GstPad *srcpad; /* the source pad of the selector */
GstPad *sinkpad; /* the sinkpad of the sink when the selector is linked */
};
GstElement *source;
gchar *subencoding; /* encoding to propagate to the subtitle elements */
+ GPtrArray *video_channels; /* links to selector pads */
+ GPtrArray *audio_channels; /* links to selector pads */
+ GPtrArray *text_channels; /* links to selector pads */
+
/* uridecodebins for uri and subtitle uri */
GstElement *uridecodebin;
GstElement *suburidecodebin;
/* properties */
guint connection_speed; /* connection speed in bits/sec (0 = unknown) */
+ gint current_video; /* the currently selected stream */
+ gint current_audio; /* the currently selected stream */
+ gint current_text; /* the currently selected stream */
/* our play sink */
GstPlaySink *playsink;
{
GstPipelineClass parent_class;
- void (*about_to_finish) (void);
+ void (*about_to_finish) (GstPlayBin * playbin);
+
+ void (*video_changed) (GstPlayBin * playbin);
+ void (*audio_changed) (GstPlayBin * playbin);
+ void (*text_changed) (GstPlayBin * playbin);
+
+ GstTagList *(*get_video_tags) (GstPlayBin * playbin, gint stream);
+ GstTagList *(*get_audio_tags) (GstPlayBin * playbin, gint stream);
+ GstTagList *(*get_text_tags) (GstPlayBin * playbin, gint stream);
};
/* props */
enum
{
SIGNAL_ABOUT_TO_FINISH,
+ SIGNAL_VIDEO_CHANGED,
+ SIGNAL_AUDIO_CHANGED,
+ SIGNAL_TEXT_CHANGED,
+ SIGNAL_GET_VIDEO_TAGS,
+ SIGNAL_GET_AUDIO_TAGS,
+ SIGNAL_GET_TEXT_TAGS,
LAST_SIGNAL
};
static void gst_play_bin_handle_message (GstBin * bin, GstMessage * message);
+static GstStructure *gst_play_bin_get_video_tags (GstPlayBin * playbin,
+ gint stream);
+static GstStructure *gst_play_bin_get_audio_tags (GstPlayBin * playbin,
+ gint stream);
+static GstStructure *gst_play_bin_get_text_tags (GstPlayBin * playbin,
+ gint stream);
+
static gboolean setup_next_source (GstPlayBin * playbin);
static GstElementClass *parent_class;
*
* Get or set the currently playing video stream. By default the first video
* stream with data is played.
- *
- * Setting this property to -2 will disable the video stream.
*/
g_object_class_install_property (gobject_klass, PROP_CURRENT_VIDEO,
g_param_spec_int ("current-video", "Current Video",
- "Currently playing video stream (-1 = auto, -2 = none)",
- -2, G_MAXINT, -1, G_PARAM_READWRITE));
+ "Currently playing video stream (-1 = auto)",
+ -1, G_MAXINT, -1, G_PARAM_READWRITE));
/**
* GstPlayBin:n-audio
*
*
* Get or set the currently playing audio stream. By default the first audio
* stream with data is played.
- *
- * Setting this property to -2 will disable the audio stream.
*/
g_object_class_install_property (gobject_klass, PROP_CURRENT_AUDIO,
g_param_spec_int ("current-audio", "Current audio",
- "Currently playing audio stream (-1 = none, -2 = none)",
- -2, G_MAXINT, -1, G_PARAM_READWRITE));
+ "Currently playing audio stream (-1 = auto)",
+ -1, G_MAXINT, -1, G_PARAM_READWRITE));
/**
* GstPlayBin:n-text
*
/**
* GstPlayBin:current-text
*
- * Get or set the currently playing subtitle stream. By default the first audio
- * stream with data is played.
- *
- * Setting this property to -2 will disable the text stream.
+ * Get or set the currently playing subtitle stream. By default the first
+ * subtitle stream with data is played.
*/
g_object_class_install_property (gobject_klass, PROP_CURRENT_TEXT,
g_param_spec_int ("current-text", "Current Text",
- "Currently playing text stream (-1 = none, -2 = none)",
- -2, G_MAXINT, -1, G_PARAM_READWRITE));
+ "Currently playing text stream (-1 = auto)",
+ -1, G_MAXINT, -1, G_PARAM_READWRITE));
g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING,
g_param_spec_string ("subtitle-encoding", "subtitle encoding",
0, G_MAXUINT, DEFAULT_CONNECTION_SPEED, G_PARAM_READWRITE));
/**
* GstPlayBin::about-to-finish:
+ * @playbin: a #GstPlayBin
*
* This signal is emitted when the current uri is about to finish. You can
* set the next-uri and next-suburi to make sure that playback continues.
G_STRUCT_OFFSET (GstPlayBinClass, about_to_finish), NULL, NULL,
gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+ /**
+ * GstPlayBin::video-changed
+ * @playbin: a #GstPlayBin
+ *
+ * This signal is emited whenever the number or order of the video
+ * streams has changed. The application will most likely want to select
+ * a new video stream.
+ */
+ gst_play_bin_signals[SIGNAL_VIDEO_CHANGED] =
+ g_signal_new ("video-changed", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GstPlayBinClass, video_changed), NULL, NULL,
+ gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+ /**
+ * GstPlayBin::audio-changed
+ * @playbin: a #GstPlayBin
+ *
+ * This signal is emited whenever the number or order of the audio
+ * streams has changed. The application will most likely want to select
+ * a new audio stream.
+ */
+ gst_play_bin_signals[SIGNAL_AUDIO_CHANGED] =
+ g_signal_new ("audio-changed", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GstPlayBinClass, audio_changed), NULL, NULL,
+ gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+ /**
+ * GstPlayBin::text-changed
+ * @playbin: a #GstPlayBin
+ *
+ * This signal is emited whenever the number or order of the text
+ * streams has changed. The application will most likely want to select
+ * a new text stream.
+ */
+ gst_play_bin_signals[SIGNAL_TEXT_CHANGED] =
+ g_signal_new ("text-changed", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GstPlayBinClass, text_changed), NULL, NULL,
+ gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+
+ /**
+ * GstPlayBin::get-video-tags
+ * @playbin: a #GstPlayBin
+ * @stream: a video stream number
+ *
+ * Action signal to retrieve the tags of a specific video stream number.
+ * This information can be used to select a stream.
+ *
+ * Returns: a GstTagList with tags or NULL when the stream number does not
+ * exist.
+ */
+ gst_play_bin_signals[SIGNAL_GET_VIDEO_TAGS] =
+ g_signal_new ("get-video-tags", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GstPlayBinClass, get_video_tags), NULL, NULL,
+ gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
+ /**
+ * GstPlayBin::get-audio-tags
+ * @playbin: a #GstPlayBin
+ * @stream: an audio stream number
+ *
+ * Action signal to retrieve the tags of a specific audio stream number.
+ * This information can be used to select a stream.
+ *
+ * Returns: a GstTagList with tags or NULL when the stream number does not
+ * exist.
+ */
+ gst_play_bin_signals[SIGNAL_GET_AUDIO_TAGS] =
+ g_signal_new ("get-audio-tags", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GstPlayBinClass, get_audio_tags), NULL, NULL,
+ gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
+ /**
+ * GstPlayBin::get-text-tags
+ * @playbin: a #GstPlayBin
+ * @stream: a text stream number
+ *
+ * Action signal to retrieve the tags of a specific text stream number.
+ * This information can be used to select a stream.
+ *
+ * Returns: a GstTagList with tags or NULL when the stream number does not
+ * exist.
+ */
+ gst_play_bin_signals[SIGNAL_GET_TEXT_TAGS] =
+ g_signal_new ("get-text-tags", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GstPlayBinClass, get_text_tags), NULL, NULL,
+ gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
+
+ klass->get_video_tags = gst_play_bin_get_video_tags;
+ klass->get_audio_tags = gst_play_bin_get_audio_tags;
+ klass->get_text_tags = gst_play_bin_get_text_tags;
+
gst_element_class_set_details (gstelement_klass, &gst_play_bin_details);
gstelement_klass->change_state =
static void
init_group (GstPlayBin * playbin, GstSourceGroup * group)
{
+ /* store the array for the different channels */
+ group->video_channels = g_ptr_array_new ();
+ group->audio_channels = g_ptr_array_new ();
+ group->text_channels = g_ptr_array_new ();
/* init selectors */
group->playbin = playbin;
group->selector[0].media = "audio/x-raw-";
group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO_RAW;
+ group->selector[0].channels = group->audio_channels;
group->selector[1].media = "audio/";
group->selector[1].type = GST_PLAY_SINK_TYPE_AUDIO;
+ group->selector[1].channels = group->audio_channels;
group->selector[2].media = "video/x-raw-";
group->selector[2].type = GST_PLAY_SINK_TYPE_VIDEO_RAW;
+ group->selector[2].channels = group->video_channels;
group->selector[3].media = "video/";
group->selector[3].type = GST_PLAY_SINK_TYPE_VIDEO;
+ group->selector[3].channels = group->video_channels;
group->selector[4].media = "text/";
group->selector[4].type = GST_PLAY_SINK_TYPE_TEXT;
+ group->selector[4].channels = group->text_channels;
}
static void
gst_bin_add (GST_BIN_CAST (playbin), GST_ELEMENT_CAST (playbin->playsink));
gst_play_sink_set_flags (playbin->playsink, DEFAULT_FLAGS);
- /* get the caps */
+ playbin->current_video = DEFAULT_CURRENT_VIDEO;
+ playbin->current_audio = DEFAULT_CURRENT_AUDIO;
+ playbin->current_text = DEFAULT_CURRENT_TEXT;
}
static void
GST_OBJECT_UNLOCK (playbin);
}
+/* get the currently playing group or if nothing is playing, the next
+ * group. Must be called with the LOCK. */
+static GstSourceGroup *
+get_group (GstPlayBin * playbin)
+{
+ GstSourceGroup *result;
+
+ if (!(result = playbin->curr_group))
+ result = playbin->next_group;
+
+ return result;
+}
+
+static GstTagList *
+get_tags (GstPlayBin * playbin, GPtrArray * channels, gint stream)
+{
+ GstTagList *result;
+ GstPad *sinkpad;
+
+ if (!channels || channels->len < stream)
+ return NULL;
+
+ sinkpad = g_ptr_array_index (channels, stream);
+ g_object_get (sinkpad, "tags", &result, NULL);
+
+ return result;
+}
+
+static GstTagList *
+gst_play_bin_get_video_tags (GstPlayBin * playbin, gint stream)
+{
+ GstTagList *result;
+ GstSourceGroup *group;
+
+ GST_OBJECT_LOCK (playbin);
+ group = get_group (playbin);
+ result = get_tags (playbin, group->video_channels, stream);
+ GST_OBJECT_UNLOCK (playbin);
+
+ return result;
+}
+
+static GstTagList *
+gst_play_bin_get_audio_tags (GstPlayBin * playbin, gint stream)
+{
+ GstTagList *result;
+ GstSourceGroup *group;
+
+ GST_OBJECT_LOCK (playbin);
+ group = get_group (playbin);
+ result = get_tags (playbin, group->audio_channels, stream);
+ GST_OBJECT_UNLOCK (playbin);
+
+ return result;
+}
+
+static GstTagList *
+gst_play_bin_get_text_tags (GstPlayBin * playbin, gint stream)
+{
+ GstTagList *result;
+ GstSourceGroup *group;
+
+ GST_OBJECT_LOCK (playbin);
+ group = get_group (playbin);
+ result = get_tags (playbin, group->text_channels, stream);
+ GST_OBJECT_UNLOCK (playbin);
+
+ return result;
+}
+
+static gboolean
+gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream)
+{
+ GstSourceGroup *group;
+ GPtrArray *channels;
+ GstPad *sinkpad;
+
+ GST_OBJECT_LOCK (playbin);
+ group = get_group (playbin);
+ if (!(channels = group->video_channels))
+ goto no_channels;
+
+ if (stream == -1 || channels->len < stream) {
+ sinkpad = NULL;
+ } else {
+ /* take channel from selected stream */
+ sinkpad = g_ptr_array_index (channels, stream);
+ }
+
+ if (sinkpad)
+ gst_object_ref (sinkpad);
+ GST_OBJECT_UNLOCK (playbin);
+
+ if (sinkpad) {
+ GstObject *selector;
+
+ if ((selector = gst_pad_get_parent (sinkpad))) {
+ /* activate the selected pad */
+ g_object_set (selector, "active-pad", sinkpad, NULL);
+ gst_object_unref (selector);
+ }
+ gst_object_unref (sinkpad);
+ }
+ return TRUE;
+
+no_channels:
+ {
+ GST_OBJECT_UNLOCK (playbin);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_play_bin_set_current_audio_stream (GstPlayBin * playbin, gint stream)
+{
+ GstSourceGroup *group;
+ GPtrArray *channels;
+ GstPad *sinkpad;
+
+ GST_OBJECT_LOCK (playbin);
+ group = get_group (playbin);
+ if (!(channels = group->audio_channels))
+ goto no_channels;
+
+ if (stream == -1 || channels->len < stream) {
+ sinkpad = NULL;
+ } else {
+ /* take channel from selected stream */
+ sinkpad = g_ptr_array_index (channels, stream);
+ }
+
+ if (sinkpad)
+ gst_object_ref (sinkpad);
+ GST_OBJECT_UNLOCK (playbin);
+
+ if (sinkpad) {
+ GstObject *selector;
+
+ if ((selector = gst_pad_get_parent (sinkpad))) {
+ /* activate the selected pad */
+ g_object_set (selector, "active-pad", sinkpad, NULL);
+ gst_object_unref (selector);
+ }
+ gst_object_unref (sinkpad);
+ }
+ return TRUE;
+
+no_channels:
+ {
+ GST_OBJECT_UNLOCK (playbin);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream)
+{
+ GstSourceGroup *group;
+ GPtrArray *channels;
+ GstPad *sinkpad;
+
+ GST_OBJECT_LOCK (playbin);
+ group = get_group (playbin);
+ if (!(channels = group->text_channels))
+ goto no_channels;
+
+ if (stream == -1 || channels->len < stream) {
+ sinkpad = NULL;
+ } else {
+ /* take channel from selected stream */
+ sinkpad = g_ptr_array_index (channels, stream);
+ }
+
+ if (sinkpad)
+ gst_object_ref (sinkpad);
+ GST_OBJECT_UNLOCK (playbin);
+
+ if (sinkpad) {
+ GstObject *selector;
+
+ if ((selector = gst_pad_get_parent (sinkpad))) {
+ /* activate the selected pad */
+ g_object_set (selector, "active-pad", sinkpad, NULL);
+ gst_object_unref (selector);
+ }
+ gst_object_unref (sinkpad);
+ }
+ return TRUE;
+
+no_channels:
+ {
+ GST_OBJECT_UNLOCK (playbin);
+ return FALSE;
+ }
+}
+
static void
gst_play_bin_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
gst_play_sink_set_flags (playbin->playsink, g_value_get_flags (value));
break;
case PROP_CURRENT_VIDEO:
+ gst_play_bin_set_current_video_stream (playbin, g_value_get_int (value));
break;
case PROP_CURRENT_AUDIO:
+ gst_play_bin_set_current_audio_stream (playbin, g_value_get_int (value));
break;
case PROP_CURRENT_TEXT:
+ gst_play_bin_set_current_text_stream (playbin, g_value_get_int (value));
break;
case PROP_SUBTITLE_ENCODING:
break;
case PROP_VIS_PLUGIN:
break;
case PROP_VOLUME:
+ gst_play_sink_set_volume (playbin->playsink, g_value_get_double (value));
break;
case PROP_FONT_DESC:
break;
}
}
-/* get the currently playing group or if nothing is playing, the next
- * group. Must be called with the LOCK. */
-static GstSourceGroup *
-get_group (GstPlayBin * playbin)
-{
- GstSourceGroup *result;
-
- if (!(result = playbin->curr_group))
- result = playbin->next_group;
-
- return result;
-}
-
-static gint
-get_n_pads (GstSourceSelect * select)
-{
- gint res;
-
- if (select->selector == NULL)
- return 0;
-
- g_object_get (select->selector, "n-pads", &res, NULL);
-
- return res;
-}
-
static void
gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
case PROP_N_VIDEO:
{
GstSourceGroup *group;
- gint n_rawvideo, n_video;
+ gint n_video;
GST_OBJECT_LOCK (playbin);
group = get_group (playbin);
- n_rawvideo = get_n_pads (&group->selector[2]);
- n_video = get_n_pads (&group->selector[3]);
- g_value_set_int (value, n_rawvideo + n_video);
+ n_video = (group->video_channels ? group->video_channels->len : 0);
+ g_value_set_int (value, n_video);
GST_OBJECT_UNLOCK (playbin);
break;
}
case PROP_CURRENT_VIDEO:
+ GST_OBJECT_LOCK (playbin);
+ g_value_set_int (value, playbin->current_video);
+ GST_OBJECT_UNLOCK (playbin);
break;
case PROP_N_AUDIO:
{
GstSourceGroup *group;
- gint n_rawaudio, n_audio;
+ gint n_audio;
GST_OBJECT_LOCK (playbin);
group = get_group (playbin);
- n_rawaudio = get_n_pads (&group->selector[0]);
- n_audio = get_n_pads (&group->selector[1]);
- g_value_set_int (value, n_rawaudio + n_audio);
+ n_audio = (group->audio_channels ? group->audio_channels->len : 0);
+ g_value_set_int (value, n_audio);
GST_OBJECT_UNLOCK (playbin);
break;
}
- break;
case PROP_CURRENT_AUDIO:
+ GST_OBJECT_LOCK (playbin);
+ g_value_set_int (value, playbin->current_audio);
+ GST_OBJECT_UNLOCK (playbin);
break;
case PROP_N_TEXT:
+ {
+ GstSourceGroup *group;
+ gint n_text;
+
+ GST_OBJECT_LOCK (playbin);
+ group = get_group (playbin);
+ n_text = (group->text_channels ? group->text_channels->len : 0);
+ g_value_set_int (value, n_text);
+ GST_OBJECT_UNLOCK (playbin);
break;
+ }
case PROP_CURRENT_TEXT:
+ GST_OBJECT_LOCK (playbin);
+ g_value_set_int (value, playbin->current_text);
+ GST_OBJECT_UNLOCK (playbin);
break;
case PROP_SUBTITLE_ENCODING:
break;
case PROP_VIS_PLUGIN:
break;
case PROP_VOLUME:
+ g_value_set_double (value, gst_play_sink_get_volume (playbin->playsink));
break;
case PROP_FRAME:
break;
if (select == NULL)
goto unknown_type;
+ /* store the selector for the pad */
+ g_object_set_data (G_OBJECT (pad), "playbin2.select", select);
+
if (select->selector == NULL) {
/* no selector, create one */
GST_DEBUG_OBJECT (playbin, "creating new selector");
if ((sinkpad = gst_element_get_request_pad (select->selector, "sink%d"))) {
GST_DEBUG_OBJECT (playbin, "got pad %s:%s from selector",
GST_DEBUG_PAD_NAME (sinkpad));
+
+ /* store the pad in the array */
+ g_ptr_array_add (select->channels, sinkpad);
+
res = gst_pad_link (pad, sinkpad);
if (GST_PAD_LINK_FAILED (res))
goto link_failed;
/* store selector pad so we can release it */
- g_object_set_data (G_OBJECT (pad), "playbin2.selector", sinkpad);
+ g_object_set_data (G_OBJECT (pad), "playbin2.sinkpad", sinkpad);
}
GST_DEBUG_OBJECT (playbin, "linked pad %s:%s to selector %p",
GST_DEBUG_PAD_NAME (pad), select->selector);
GstPlayBin *playbin;
GstPad *peer;
GstElement *selector;
+ GstSourceSelect *select;
playbin = group->playbin;
GST_DEBUG_OBJECT (playbin,
"pad %s:%s removed from group %p", GST_DEBUG_PAD_NAME (pad), group);
+ if ((select = g_object_get_data (G_OBJECT (pad), "playbin2.select"))) {
+ /* remove the pad from the array */
+ g_ptr_array_remove (select->channels, pad);
+ }
+
/* get the selector sinkpad */
- peer = g_object_get_data (G_OBJECT (pad), "playbin2.selector");
- if (!peer)
+ if (!(peer = g_object_get_data (G_OBJECT (pad), "playbin2.sinkpad")))
goto not_linked;
/* unlink the pad now (can fail, the pad is unlinked before it's removed) */
gboolean eos;
gboolean segment_pending;
GstSegment segment;
+ GstTagList *tags;
};
struct _GstSelectorPadClass
static void gst_selector_pad_init (GstSelectorPad * pad);
static void gst_selector_pad_finalize (GObject * object);
+static void gst_selector_pad_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec);
+
static GstPadClass *selector_pad_parent_class = NULL;
static void gst_selector_pad_reset (GstSelectorPad * pad);
static GstFlowReturn gst_selector_pad_bufferalloc (GstPad * pad,
guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
+enum
+{
+ PROP_PAD_0,
+ PROP_PAD_TAGS,
+ PROP_PAD_ACTIVE,
+ PROP_PAD_LAST
+};
+
static GType
gst_selector_pad_get_type (void)
{
selector_pad_parent_class = g_type_class_peek_parent (klass);
gobject_class->finalize = gst_selector_pad_finalize;
+ gobject_class->get_property =
+ GST_DEBUG_FUNCPTR (gst_selector_pad_get_property);
+
+ g_object_class_install_property (gobject_class, PROP_PAD_TAGS,
+ g_param_spec_boxed ("tags", "Tags",
+ "The currently active tags on the pad", GST_TYPE_TAG_LIST,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_PAD_ACTIVE,
+ g_param_spec_boolean ("active", "Active",
+ "If the pad is currently active", FALSE, G_PARAM_READABLE));
}
static void
pad = GST_SELECTOR_PAD_CAST (object);
+ if (pad->tags)
+ gst_tag_list_free (pad->tags);
+
G_OBJECT_CLASS (selector_pad_parent_class)->finalize (object);
}
+static void
+gst_selector_pad_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ GstSelectorPad *pad;
+
+ pad = GST_SELECTOR_PAD (object);
+
+ switch (prop_id) {
+ case PROP_PAD_TAGS:
+ GST_OBJECT_LOCK (object);
+ g_value_set_boxed (value, pad->tags);
+ GST_OBJECT_UNLOCK (object);
+ break;
+ case PROP_PAD_ACTIVE:
+ {
+ GstStreamSelector *sel;
+
+ sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad));
+ g_value_set_boolean (value, gst_stream_selector_is_active_sinkpad (sel,
+ GST_PAD_CAST (pad)));
+ gst_object_unref (sel);
+ break;
+ }
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
static void
gst_selector_pad_reset (GstSelectorPad * pad)
{
selpad->segment_pending = TRUE;
break;
}
+ case GST_EVENT_TAG:
+ {
+ GstTagList *tags;
+
+ GST_OBJECT_LOCK (selpad);
+ if (selpad->tags)
+ gst_tag_list_free (selpad->tags);
+ gst_event_parse_tag (event, &tags);
+ if (tags)
+ tags = gst_tag_list_copy (tags);
+ selpad->tags = tags;
+ GST_DEBUG_OBJECT (sel, "received tags %" GST_PTR_FORMAT, selpad->tags);
+ GST_OBJECT_UNLOCK (selpad);
+ break;
+ }
case GST_EVENT_EOS:
selpad->eos = TRUE;
break;
}
static void gst_stream_selector_dispose (GObject * object);
+static void gst_stream_selector_finalize (GObject * object);
+
static void gst_stream_selector_init (GstStreamSelector * sel);
static void gst_stream_selector_base_init (GstStreamSelectorClass * klass);
static void gst_stream_selector_class_init (GstStreamSelectorClass * klass);
+
static void gst_stream_selector_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec);
static void gst_stream_selector_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec);
+
static GstPad *gst_stream_selector_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * unused);
static void gst_stream_selector_release_pad (GstElement * element,
GstPad * pad);
static GList *gst_stream_selector_get_linked_pads (GstPad * pad);
static GstCaps *gst_stream_selector_getcaps (GstPad * pad);
+
static GstElementClass *parent_class = NULL;
GType
parent_class = g_type_class_peek_parent (klass);
gobject_class->dispose = gst_stream_selector_dispose;
+ gobject_class->finalize = gst_stream_selector_finalize;
+
gobject_class->set_property =
GST_DEBUG_FUNCPTR (gst_stream_selector_set_property);
gobject_class->get_property =
GST_DEBUG_FUNCPTR (gst_stream_selector_get_property);
g_object_class_install_property (gobject_class, PROP_N_PADS,
- g_param_spec_int ("n-pads", "Number of Pads",
- "The number of sink pads", 0, G_MAXINT, 0, G_PARAM_READABLE));
+ g_param_spec_uint ("n-pads", "Number of Pads",
+ "The number of sink pads", 0, G_MAXUINT, 0, G_PARAM_READABLE));
g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD,
- g_param_spec_string ("active-pad", "Active pad",
- "Name of the currently" " active sink pad", NULL, G_PARAM_READWRITE));
+ g_param_spec_object ("active-pad", "Active Pad",
+ "The currently active sink pad", GST_TYPE_PAD, G_PARAM_READWRITE));
gstelement_class->request_new_pad = gst_stream_selector_request_new_pad;
gstelement_class->release_pad = gst_stream_selector_release_pad;
GST_DEBUG_FUNCPTR (gst_stream_selector_getcaps));
gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad);
/* sinkpad management */
- sel->active_sinkpad = NULL;
sel->padcount = 0;
- sel->n_pads = 0;
+ sel->active_sinkpad = NULL;
gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED);
}
G_OBJECT_CLASS (parent_class)->dispose (object);
}
+static void
+gst_stream_selector_finalize (GObject * object)
+{
+ GstStreamSelector *sel;
+
+ sel = GST_STREAM_SELECTOR (object);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
static void
gst_stream_selector_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
GstStreamSelector *sel = GST_STREAM_SELECTOR (object);
switch (prop_id) {
- case PROP_ACTIVE_PAD:{
- const gchar *pad_name = g_value_get_string (value);
+ case PROP_ACTIVE_PAD:
+ {
GstPad *pad = NULL;
GstPad **active_pad_p;
- if (strcmp (pad_name, "") != 0)
- pad = gst_element_get_pad (GST_ELEMENT (object), pad_name);
+ pad = g_value_get_object (value);
+
GST_OBJECT_LOCK (object);
if (pad != sel->active_sinkpad) {
GstSelectorPad *selpad;
}
}
GST_OBJECT_UNLOCK (object);
- if (pad)
- gst_object_unref (pad);
break;
}
default:
switch (prop_id) {
case PROP_N_PADS:
GST_OBJECT_LOCK (object);
- g_value_set_int (value, sel->n_pads);
+ g_value_set_uint (value, sel->n_pads);
GST_OBJECT_UNLOCK (object);
break;
case PROP_ACTIVE_PAD:{
GST_OBJECT_LOCK (object);
- if (sel->active_sinkpad != NULL) {
- g_value_take_string (value, gst_pad_get_name (sel->active_sinkpad));
- } else {
- g_value_set_string (value, "");
- }
+ g_value_set_object (value, sel->active_sinkpad);
GST_OBJECT_UNLOCK (object);
break;
}
GstPad *otherpad = NULL;
sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad));
+
GST_OBJECT_LOCK (sel);
if (pad == sel->srcpad)
otherpad = sel->active_sinkpad;
GST_LOG_OBJECT (sel, "Creating new pad %d", sel->padcount);
GST_OBJECT_LOCK (sel);
name = g_strdup_printf ("sink%d", sel->padcount++);
- sel->n_pads++;
sinkpad = g_object_new (GST_TYPE_SELECTOR_PAD,
"name", name, "direction", templ->direction, "template", templ, NULL);
g_free (name);
+ sel->n_pads++;
GST_OBJECT_UNLOCK (sel);
gst_pad_set_event_function (sinkpad,