gst/playback/gstplay-marshal.list: Added marshal for streamselector Tags.

Original commit message from CVS:
* gst/playback/gstplay-marshal.list:
Added marshal for streamselector Tags.
* gst/playback/gstplaybasebin.c: (set_active_source):
Streamselector now selects pads based on the pad object instead of its
name.
* gst/playback/gstplaybin2.c: (gst_play_bin_class_init),
(init_group), (gst_play_bin_init), (get_group), (get_tags),
(gst_play_bin_get_video_tags), (gst_play_bin_get_audio_tags),
(gst_play_bin_get_text_tags),
(gst_play_bin_set_current_video_stream),
(gst_play_bin_set_current_audio_stream),
(gst_play_bin_set_current_text_stream),
(gst_play_bin_set_property), (gst_play_bin_get_property),
(pad_added_cb), (pad_removed_cb), (autoplug_select_cb):
Remove option to mute streams with the current-a/v/t property, we have
this functionality in the flags.
Add signals to notify when the number of A/V/T channels changed.
Add action signals to get tags for the A/V/T streams.
Implement setting the current A/V/T stream.
Rearrange some things to simplify stream selection.
Implement volume.
* gst/playback/gstplaysink.c: (gst_play_sink_set_volume),
(gst_play_sink_get_volume), (gst_play_sink_set_property),
(gst_play_sink_get_property), (gen_video_chain), (gen_audio_chain),
(activate_vis), (gst_play_sink_reconfigure):
* gst/playback/gstplaysink.h:
Add and implement volume setting methods.
* gst/playback/gststreamselector.c: (gst_selector_pad_class_init),
(gst_selector_pad_finalize), (gst_selector_pad_get_property),
(gst_selector_pad_event), (gst_stream_selector_class_init),
(gst_stream_selector_init), (gst_stream_selector_finalize),
(gst_stream_selector_set_property),
(gst_stream_selector_get_property),
(gst_stream_selector_get_linked_pad),
(gst_stream_selector_request_new_pad):
* gst/playback/gststreamselector.h:
Add pad properties for tags and status of pads.
Keep tags on pads.
Make active pad selection based on pad object instead of name.
This commit is contained in:
Wim Taymans 2008-02-08 17:47:37 +00:00
parent fcb1b6634b
commit c8bb67d0ca
9 changed files with 579 additions and 87 deletions

View file

@ -1,3 +1,49 @@
2008-02-08 Wim Taymans <wim.taymans@collabora.co.uk>
* gst/playback/gstplay-marshal.list:
Added marshal for streamselector Tags.
* gst/playback/gstplaybasebin.c: (set_active_source):
Streamselector now selects pads based on the pad object instead of its
name.
* gst/playback/gstplaybin2.c: (gst_play_bin_class_init),
(init_group), (gst_play_bin_init), (get_group), (get_tags),
(gst_play_bin_get_video_tags), (gst_play_bin_get_audio_tags),
(gst_play_bin_get_text_tags),
(gst_play_bin_set_current_video_stream),
(gst_play_bin_set_current_audio_stream),
(gst_play_bin_set_current_text_stream),
(gst_play_bin_set_property), (gst_play_bin_get_property),
(pad_added_cb), (pad_removed_cb), (autoplug_select_cb):
Remove option to mute streams with the current-a/v/t property, we have
this functionality in the flags.
Add signals to notify when the number of A/V/T channels changed.
Add action signals to get tags for the A/V/T streams.
Implement setting the current A/V/T stream.
Rearrange some things to simplify stream selection.
Implement volume.
* gst/playback/gstplaysink.c: (gst_play_sink_set_volume),
(gst_play_sink_get_volume), (gst_play_sink_set_property),
(gst_play_sink_get_property), (gen_video_chain), (gen_audio_chain),
(activate_vis), (gst_play_sink_reconfigure):
* gst/playback/gstplaysink.h:
Add and implement volume setting methods.
* gst/playback/gststreamselector.c: (gst_selector_pad_class_init),
(gst_selector_pad_finalize), (gst_selector_pad_get_property),
(gst_selector_pad_event), (gst_stream_selector_class_init),
(gst_stream_selector_init), (gst_stream_selector_finalize),
(gst_stream_selector_set_property),
(gst_stream_selector_get_property),
(gst_stream_selector_get_linked_pad),
(gst_stream_selector_request_new_pad):
* gst/playback/gststreamselector.h:
Add pad properties for tags and status of pads.
Keep tags on pads.
Make active pad selection based on pad object instead of name.
2008-02-08 Stefan Kost <ensonic@users.sf.net>
* configure.ac:

2
common

@ -1 +1 @@
Subproject commit aa24bcc28323422b29ba41874a4a98b6b6ddf63a
Subproject commit 961bb6bd997d7c8da6058534e86b4a1361c0fcea

View file

@ -5,3 +5,4 @@ VOID:OBJECT,BOOLEAN
ENUM:OBJECT,OBJECT,BOXED
ENUM:OBJECT,OBJECT,OBJECT
BOXED:OBJECT,OBJECT,BOXED
BOXED:INT

View file

@ -2443,8 +2443,7 @@ set_active_source (GstPlayBaseBin * play_base_bin,
"pb_sel_pad"));
if (sel && sel_pad != NULL) {
g_object_set (G_OBJECT (sel), "active-pad", GST_PAD_NAME (sel_pad),
NULL);
g_object_set (G_OBJECT (sel), "active-pad", sel_pad, NULL);
}
have_active = TRUE;
@ -2463,7 +2462,7 @@ set_active_source (GstPlayBaseBin * play_base_bin,
if (!have_active) {
GST_LOG ("Muting group type: %d", type);
g_object_set (sel, "active-pad", "", NULL);
g_object_set (sel, "active-pad", NULL, NULL);
} else {
GST_LOG ("Unmuting group type: %d", type);
}

View file

@ -249,6 +249,7 @@
#include <gst/pbutils/pbutils.h>
#include "gstplay-enum.h"
#include "gstplay-marshal.h"
#include "gstplaysink.h"
#include "gstfactorylists.h"
#include "gststreaminfo.h"
@ -277,7 +278,7 @@ struct _GstSourceSelect
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 */
};
@ -298,6 +299,10 @@ struct _GstSourceGroup
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;
@ -319,6 +324,9 @@ struct _GstPlayBin
/* 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;
@ -330,7 +338,15 @@ struct _GstPlayBinClass
{
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 */
@ -381,6 +397,12 @@ enum
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
};
@ -398,6 +420,13 @@ static GstStateChangeReturn gst_play_bin_change_state (GstElement * element,
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;
@ -495,13 +524,11 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
*
* 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
*
@ -515,13 +542,11 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
*
* 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
*
@ -533,15 +558,13 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
/**
* 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",
@ -582,6 +605,7 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
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.
@ -592,6 +616,99 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
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 =
@ -604,18 +721,27 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
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
@ -639,7 +765,9 @@ gst_play_bin_init (GstPlayBin * playbin)
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
@ -698,6 +826,202 @@ done:
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)
@ -717,10 +1041,13 @@ gst_play_bin_set_property (GObject * object, guint prop_id,
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;
@ -731,6 +1058,7 @@ gst_play_bin_set_property (GObject * object, guint prop_id,
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;
@ -745,32 +1073,6 @@ gst_play_bin_set_property (GObject * object, guint prop_id,
}
}
/* 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)
@ -808,37 +1110,53 @@ gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
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;
@ -849,6 +1167,7 @@ gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
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;
@ -929,6 +1248,9 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
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");
@ -948,12 +1270,16 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
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);
@ -990,15 +1316,20 @@ pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
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) */

View file

@ -33,7 +33,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_play_sink_debug);
#define GST_CAT_DEFAULT gst_play_sink_debug
#define VOLUME_MAX_DOUBLE 10.0
#define CONNECTION_SPEED_DEFAULT 0
/* holds the common data fields for the audio and video pipelines. We keep them
* in a structure to more easily have all the info available. */
@ -519,6 +518,39 @@ gst_play_sink_set_vis_plugin (GstPlaySink * playsink,
}
}
void
gst_play_sink_set_volume (GstPlaySink * playsink, gdouble volume)
{
GstPlayAudioChain *chain;
GST_PLAY_SINK_LOCK (playsink);
playsink->volume = volume;
chain = (GstPlayAudioChain *) playsink->audiochain;
if (chain && chain->volume) {
g_object_set (chain->volume, "volume", volume, NULL);
}
GST_PLAY_SINK_UNLOCK (playsink);
}
gdouble
gst_play_sink_get_volume (GstPlaySink * playsink)
{
gdouble result;
GstPlayAudioChain *chain;
GST_PLAY_SINK_LOCK (playsink);
chain = (GstPlayAudioChain *) playsink->audiochain;
if (chain && chain->volume) {
g_object_get (chain->volume, "volume", &result, NULL);
playsink->volume = result;
} else {
result = playsink->volume;
}
GST_PLAY_SINK_UNLOCK (playsink);
return result;
}
static void
gst_play_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
@ -538,9 +570,7 @@ gst_play_sink_set_property (GObject * object, guint prop_id,
gst_play_sink_set_vis_plugin (playsink, g_value_get_object (value));
break;
case PROP_VOLUME:
GST_OBJECT_LOCK (playsink);
playsink->volume = g_value_get_double (value);
GST_OBJECT_UNLOCK (playsink);
gst_play_sink_set_volume (playsink, g_value_get_double (value));
break;
case PROP_FONT_DESC:
GST_OBJECT_LOCK (playsink);
@ -583,9 +613,7 @@ gst_play_sink_get_property (GObject * object, guint prop_id, GValue * value,
GST_OBJECT_UNLOCK (playsink);
break;
case PROP_VOLUME:
GST_OBJECT_LOCK (playsink);
g_value_set_double (value, playsink->volume);
GST_OBJECT_UNLOCK (playsink);
g_value_set_double (value, gst_play_sink_get_volume (playsink));
break;
case PROP_FRAME:
{
@ -914,8 +942,11 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw)
res = gst_element_link_pads (chain->conv, "src", chain->resample, "sink");
/* FIXME check if the sink has the volume property */
if (playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME) {
chain->volume = gst_element_factory_make ("volume", "volume");
/* configure with the latest volume */
g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL);
gst_bin_add (bin, chain->volume);

View file

@ -69,6 +69,9 @@ void gst_play_sink_set_video_sink (GstPlaySink * playsink, GstElemen
void gst_play_sink_set_audio_sink (GstPlaySink * playsink, GstElement * sink);
void gst_play_sink_set_vis_plugin (GstPlaySink * playsink, GstElement * vis);
void gst_play_sink_set_volume (GstPlaySink *playsink, gdouble volume);
gdouble gst_play_sink_get_volume (GstPlaySink *playsink);
gboolean gst_play_sink_set_flags (GstPlaySink * playsink, GstPlayFlags flags);
GstPlayFlags gst_play_sink_get_flags (GstPlaySink * playsink);

View file

@ -91,6 +91,7 @@ struct _GstSelectorPad
gboolean eos;
gboolean segment_pending;
GstSegment segment;
GstTagList *tags;
};
struct _GstSelectorPadClass
@ -102,6 +103,9 @@ static void gst_selector_pad_class_init (GstSelectorPadClass * klass);
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);
@ -112,6 +116,14 @@ static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstBuffer * buf);
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)
{
@ -147,6 +159,17 @@ gst_selector_pad_class_init (GstSelectorPadClass * klass)
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
@ -162,9 +185,42 @@ gst_selector_pad_finalize (GObject * object)
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)
{
@ -232,6 +288,21 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event)
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;
@ -364,19 +435,24 @@ ignore:
}
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
@ -427,17 +503,19 @@ gst_stream_selector_class_init (GstStreamSelectorClass * klass)
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;
@ -453,9 +531,8 @@ gst_stream_selector_init (GstStreamSelector * sel)
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);
}
@ -472,6 +549,16 @@ gst_stream_selector_dispose (GObject * object)
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)
@ -479,13 +566,13 @@ gst_stream_selector_set_property (GObject * object, guint prop_id,
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;
@ -504,8 +591,6 @@ gst_stream_selector_set_property (GObject * object, guint prop_id,
}
}
GST_OBJECT_UNLOCK (object);
if (pad)
gst_object_unref (pad);
break;
}
default:
@ -523,16 +608,12 @@ gst_stream_selector_get_property (GObject * object, guint prop_id,
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;
}
@ -549,6 +630,7 @@ gst_stream_selector_get_linked_pad (GstPad * pad, gboolean strict)
GstPad *otherpad = NULL;
sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad));
GST_OBJECT_LOCK (sel);
if (pad == sel->srcpad)
otherpad = sel->active_sinkpad;
@ -653,10 +735,10 @@ gst_stream_selector_request_new_pad (GstElement * element,
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,

View file

@ -44,10 +44,9 @@ struct _GstStreamSelector {
GstPad *srcpad;
guint padcount;
GstPad *active_sinkpad;
guint n_pads;
guint padcount;
GstSegment segment;
};