2 * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 * SECTION:element-gsettingsvideosrc
22 * This element outputs sound to the videosrc that has been configured in
23 * GSettings by the user.
26 * <title>Example launch line</title>
28 * gst-launch gsettingsvideosrc ! ffmpegcolorspace ! videoscale ! autovideosink
29 * ]| Play from configured videosrc
40 #include "gstgsettingsvideosrc.h"
41 #include "gstgsettings.h"
43 GST_BOILERPLATE (GstGSettingsVideoSrc, gst_gsettings_video_src, GstSwitchSrc,
47 gst_gsettings_video_src_change_child (GstGSettingsVideoSrc * src)
53 GST_OBJECT_LOCK (src);
55 g_settings_get_string (src->settings, GST_GSETTINGS_KEY_VIDEOSRC);
57 if (new_string != NULL && src->gsettings_str != NULL &&
58 (strlen (new_string) == 0 ||
59 strcmp (src->gsettings_str, new_string) == 0)) {
61 GST_DEBUG_OBJECT (src,
62 "GSettings key was updated, but it didn't change. Ignoring");
63 GST_OBJECT_UNLOCK (src);
66 GST_OBJECT_UNLOCK (src);
68 GST_DEBUG_OBJECT (src, "GSettings key changed from '%s' to '%s'",
69 GST_STR_NULL (src->gsettings_str), GST_STR_NULL (new_string));
72 new_kid = gst_parse_bin_from_description (new_string, TRUE, &err);
74 GST_ERROR_OBJECT (src, "error creating bin '%s': %s", new_string,
82 if (new_kid == NULL) {
83 GST_ELEMENT_ERROR (src, LIBRARY, SETTINGS, (NULL),
84 ("Failed to render video src from GSettings"));
88 if (!gst_switch_src_set_child (GST_SWITCH_SRC (src), new_kid)) {
89 GST_WARNING_OBJECT (src, "Failed to update child element");
93 g_free (src->gsettings_str);
94 src->gsettings_str = new_string;
104 on_changed (GSettings * settings, gchar * key, GstGSettingsVideoSrc * src)
106 if (!g_str_equal (key, "videosrc"));
109 gst_gsettings_video_src_change_child (src);
113 gst_gsettings_video_src_start (GstGSettingsVideoSrc * src)
118 src->loop = g_main_loop_new (src->context, FALSE);
121 g_thread_create ((GThreadFunc) g_main_loop_run, src->loop, FALSE, &err);
123 GST_ELEMENT_ERROR (src, CORE, STATE_CHANGE, (NULL),
124 ("Failed to create new thread: %s", err->message));
126 g_main_loop_unref (src->loop);
131 g_main_context_push_thread_default (src->context);
132 src->settings = g_settings_new (GST_GSETTINGS_SCHEMA);
134 g_signal_connect_data (G_OBJECT (src->settings), "changed",
135 G_CALLBACK (on_changed), gst_object_ref (src),
136 (GClosureNotify) gst_object_unref, 0);
137 g_main_context_pop_thread_default (src->context);
143 gst_gsettings_video_src_reset (GstGSettingsVideoSrc * src)
145 gst_switch_src_set_child (GST_SWITCH_SRC (src), NULL);
147 if (src->changed_id) {
148 g_signal_handler_disconnect (src->settings, src->changed_id);
153 g_main_loop_quit (src->loop);
154 g_main_loop_unref (src->loop);
159 g_object_unref (src->settings);
160 src->settings = NULL;
163 GST_OBJECT_LOCK (src);
164 g_free (src->gsettings_str);
165 src->gsettings_str = NULL;
166 GST_OBJECT_UNLOCK (src);
172 gst_gsettings_video_src_finalize (GObject * object)
174 GstGSettingsVideoSrc *src = GST_GSETTINGS_VIDEO_SRC (object);
176 g_free (src->gsettings_str);
177 g_main_context_unref (src->context);
179 GST_CALL_PARENT (G_OBJECT_CLASS, finalize, ((GObject *) (src)));
182 static GstStateChangeReturn
183 gst_gsettings_video_src_change_state (GstElement * element,
184 GstStateChange transition)
186 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
187 GstGSettingsVideoSrc *src = GST_GSETTINGS_VIDEO_SRC (element);
189 switch (transition) {
190 case GST_STATE_CHANGE_NULL_TO_READY:
191 if (!gst_gsettings_video_src_start (src))
192 return GST_STATE_CHANGE_FAILURE;
194 if (!gst_gsettings_video_src_change_child (src)) {
195 gst_gsettings_video_src_reset (src);
196 return GST_STATE_CHANGE_FAILURE;
203 ret = GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state,
204 (element, transition), GST_STATE_CHANGE_SUCCESS);
206 switch (transition) {
207 case GST_STATE_CHANGE_READY_TO_NULL:
208 gst_gsettings_video_src_reset (src);
218 gst_gsettings_video_src_init (GstGSettingsVideoSrc * src,
219 GstGSettingsVideoSrcClass * g_class)
221 src->context = g_main_context_new ();
222 gst_gsettings_video_src_reset (src);
226 gst_gsettings_video_src_base_init (gpointer klass)
228 GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
230 gst_element_class_set_details_simple (eklass, "GSettings video src",
232 "Video src embedding the GSettings preferences for video input",
233 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
237 gst_gsettings_video_src_class_init (GstGSettingsVideoSrcClass * klass)
239 GObjectClass *oklass = G_OBJECT_CLASS (klass);
240 GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
242 oklass->finalize = gst_gsettings_video_src_finalize;
244 eklass->change_state = gst_gsettings_video_src_change_state;