+static void
+gst_play_sink_overlay_expose (GstVideoOverlay * overlay)
+{
+ GstPlaySink *playsink = GST_PLAY_SINK (overlay);
+ GstVideoOverlay *overlay_element;
+
+ GST_OBJECT_LOCK (playsink);
+ if (playsink->overlay_element)
+ overlay_element =
+ GST_VIDEO_OVERLAY (gst_object_ref (playsink->overlay_element));
+ else
+ overlay_element = NULL;
+ GST_OBJECT_UNLOCK (playsink);
+
+ if (overlay_element) {
+ gst_video_overlay_expose (overlay_element);
+ gst_object_unref (overlay_element);
+ }
+}
+
+static void
+gst_play_sink_overlay_handle_events (GstVideoOverlay * overlay,
+ gboolean handle_events)
+{
+ GstPlaySink *playsink = GST_PLAY_SINK (overlay);
+ GstVideoOverlay *overlay_element;
+
+ GST_OBJECT_LOCK (playsink);
+ if (playsink->overlay_element)
+ overlay_element =
+ GST_VIDEO_OVERLAY (gst_object_ref (playsink->overlay_element));
+ else
+ overlay_element = NULL;
+ GST_OBJECT_UNLOCK (playsink);
+
+ playsink->overlay_handle_events_set = TRUE;
+ playsink->overlay_handle_events = handle_events;
+
+ if (overlay_element) {
+ gst_video_overlay_handle_events (overlay_element, handle_events);
+ gst_object_unref (overlay_element);
+ }
+}
+
+static void
+gst_play_sink_overlay_set_render_rectangle (GstVideoOverlay * overlay, gint x,
+ gint y, gint width, gint height)
+{
+ GstPlaySink *playsink = GST_PLAY_SINK (overlay);
+ GstVideoOverlay *overlay_element;
+
+ GST_OBJECT_LOCK (playsink);
+ if (playsink->overlay_element)
+ overlay_element =
+ GST_VIDEO_OVERLAY (gst_object_ref (playsink->overlay_element));
+ else
+ overlay_element = NULL;
+ GST_OBJECT_UNLOCK (playsink);
+
+ playsink->overlay_render_rectangle_set = TRUE;
+ playsink->overlay_x = x;
+ playsink->overlay_y = y;
+ playsink->overlay_width = width;
+ playsink->overlay_height = height;
+
+ if (overlay_element) {
+ gst_video_overlay_set_render_rectangle (overlay_element, x, y, width,
+ height);
+ gst_object_unref (overlay_element);
+ }
+}
+
+static void
+gst_play_sink_overlay_set_window_handle (GstVideoOverlay * overlay,
+ guintptr handle)
+{
+ GstPlaySink *playsink = GST_PLAY_SINK (overlay);
+ GstVideoOverlay *overlay_element;
+
+ GST_OBJECT_LOCK (playsink);
+ if (playsink->overlay_element)
+ overlay_element =
+ GST_VIDEO_OVERLAY (gst_object_ref (playsink->overlay_element));
+ else
+ overlay_element = NULL;
+ GST_OBJECT_UNLOCK (playsink);
+
+ playsink->overlay_handle_set = TRUE;
+ playsink->overlay_handle = handle;
+
+ if (overlay_element) {
+ gst_video_overlay_set_window_handle (overlay_element, handle);
+ gst_object_unref (overlay_element);
+ }
+}
+
+static void
+gst_play_sink_overlay_init (gpointer g_iface, gpointer g_iface_data)
+{
+ GstVideoOverlayInterface *iface = (GstVideoOverlayInterface *) g_iface;
+ iface->expose = gst_play_sink_overlay_expose;
+ iface->handle_events = gst_play_sink_overlay_handle_events;
+ iface->set_render_rectangle = gst_play_sink_overlay_set_render_rectangle;
+ iface->set_window_handle = gst_play_sink_overlay_set_window_handle;
+}
+
+static void
+gst_play_sink_navigation_send_event (GstNavigation * navigation,
+ GstStructure * structure)
+{
+ GstPlaySink *playsink = GST_PLAY_SINK (navigation);
+ GstBin *bin = NULL;
+
+ GST_PLAY_SINK_LOCK (playsink);
+ if (playsink->videochain && playsink->videochain->chain.bin)
+ bin = GST_BIN (gst_object_ref (playsink->videochain->chain.bin));
+ GST_PLAY_SINK_UNLOCK (playsink);
+
+ if (bin) {
+ GstElement *nav = gst_bin_get_by_interface (bin, GST_TYPE_NAVIGATION);
+
+ if (nav) {
+ gst_navigation_send_event (GST_NAVIGATION (nav), structure);
+ structure = NULL;
+ gst_object_unref (nav);
+ }
+
+ gst_object_unref (bin);
+ }
+
+ if (structure)
+ gst_structure_free (structure);
+}
+
+static void
+gst_play_sink_navigation_init (gpointer g_iface, gpointer g_iface_data)
+{
+ GstNavigationInterface *iface = (GstNavigationInterface *) g_iface;
+
+ iface->send_event = gst_play_sink_navigation_send_event;
+}
+
+static const GList *
+gst_play_sink_colorbalance_list_channels (GstColorBalance * balance)
+{
+ GstPlaySink *playsink = GST_PLAY_SINK (balance);
+
+ return playsink->colorbalance_channels;
+}
+
+static void
+gst_play_sink_colorbalance_set_value (GstColorBalance * balance,
+ GstColorBalanceChannel * proxy, gint value)
+{
+ GstPlaySink *playsink = GST_PLAY_SINK (balance);
+ GList *l;
+ gint i;
+ GstColorBalance *balance_element = NULL;
+
+ GST_OBJECT_LOCK (playsink);
+ if (playsink->colorbalance_element)
+ balance_element =
+ GST_COLOR_BALANCE (gst_object_ref (playsink->colorbalance_element));
+ GST_OBJECT_UNLOCK (playsink);
+
+ for (i = 0, l = playsink->colorbalance_channels; l; l = l->next, i++) {
+ GstColorBalanceChannel *proxy_tmp = l->data;
+ gdouble new_val;
+
+ if (proxy_tmp != proxy)
+ continue;
+
+ playsink->colorbalance_values[i] = value;
+
+ if (balance_element) {
+ GstColorBalanceChannel *channel = NULL;
+ const GList *channels, *k;
+
+ channels = gst_color_balance_list_channels (balance_element);
+ for (k = channels; k; k = k->next) {
+ GstColorBalanceChannel *tmp = l->data;
+
+ if (g_strrstr (tmp->label, proxy->label)) {
+ channel = tmp;
+ break;
+ }
+ }
+
+ g_assert (channel);
+
+ /* Convert to [0, 1] range */
+ new_val =
+ ((gdouble) value -
+ (gdouble) proxy->min_value) / ((gdouble) proxy->max_value -
+ (gdouble) proxy->min_value);
+ /* Convert to channel range */
+ new_val =
+ channel->min_value + new_val * ((gdouble) channel->max_value -
+ (gdouble) channel->min_value);
+
+ gst_color_balance_set_value (balance_element, channel,
+ (gint) (new_val + 0.5));
+
+ gst_object_unref (balance_element);
+ }
+
+ gst_color_balance_value_changed (balance, proxy, value);
+ break;
+ }
+}
+
+static gint
+gst_play_sink_colorbalance_get_value (GstColorBalance * balance,
+ GstColorBalanceChannel * proxy)
+{
+ GstPlaySink *playsink = GST_PLAY_SINK (balance);
+ GList *l;
+ gint i;
+
+ for (i = 0, l = playsink->colorbalance_channels; l; l = l->next, i++) {
+ GstColorBalanceChannel *proxy_tmp = l->data;
+
+ if (proxy_tmp != proxy)
+ continue;
+
+ return playsink->colorbalance_values[i];
+ }
+
+ g_return_val_if_reached (0);
+}
+
+static GstColorBalanceType
+gst_play_sink_colorbalance_get_balance_type (GstColorBalance * balance)
+{
+ GstPlaySink *playsink = GST_PLAY_SINK (balance);
+ GstColorBalance *balance_element = NULL;
+ GstColorBalanceType t = GST_COLOR_BALANCE_SOFTWARE;
+
+ GST_OBJECT_LOCK (playsink);
+ if (playsink->colorbalance_element)
+ balance_element =
+ GST_COLOR_BALANCE (gst_object_ref (playsink->colorbalance_element));
+ GST_OBJECT_UNLOCK (playsink);
+
+ if (balance_element) {
+ t = gst_color_balance_get_balance_type (balance_element);
+ gst_object_unref (balance_element);
+ }
+
+ return t;
+}
+
+static void
+gst_play_sink_colorbalance_init (gpointer g_iface, gpointer g_iface_data)
+{
+ GstColorBalanceInterface *iface = (GstColorBalanceInterface *) g_iface;
+
+ iface->list_channels = gst_play_sink_colorbalance_list_channels;
+ iface->set_value = gst_play_sink_colorbalance_set_value;
+ iface->get_value = gst_play_sink_colorbalance_get_value;
+ iface->get_balance_type = gst_play_sink_colorbalance_get_balance_type;
+}