renatofilho@787
|
1 |
/* GStreamer
|
renatofilho@797
|
2 |
* Copyright (C) <2007> Renato Araujo Oliveira Filho <renato.filho@indt.org.br>
|
renatofilho@787
|
3 |
*
|
renatofilho@787
|
4 |
* This library is free software; you can redistribute it and/or
|
renatofilho@787
|
5 |
* modify it under the terms of the GNU Library General Public
|
renatofilho@787
|
6 |
* License as published by the Free Software Foundation; either
|
renatofilho@787
|
7 |
* version 2 of the License, or (at your option) any later version.
|
renatofilho@787
|
8 |
*
|
renatofilho@787
|
9 |
* This library is distributed in the hope that it will be useful,
|
renatofilho@787
|
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
renatofilho@787
|
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
renatofilho@787
|
12 |
* Library General Public License for more details.
|
renatofilho@787
|
13 |
*
|
renatofilho@787
|
14 |
* You should have received a copy of the GNU Library General Public
|
renatofilho@787
|
15 |
* License along with this library; if not, write to the
|
renatofilho@787
|
16 |
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
renatofilho@787
|
17 |
* Boston, MA 02111-1307, USA.
|
renatofilho@787
|
18 |
*/
|
renatofilho@787
|
19 |
|
renatofilho@787
|
20 |
#ifdef HAVE_CONFIG_H
|
renatofilho@787
|
21 |
#include "config.h"
|
renatofilho@787
|
22 |
#endif
|
renatofilho@787
|
23 |
|
renatofilho@787
|
24 |
#include <glib/gi18n.h>
|
renatofilho@787
|
25 |
#include <string.h>
|
renatofilho@787
|
26 |
#include <gst/gst.h>
|
renatofilho@787
|
27 |
#include <gst/gsterror.h>
|
renatofilho@787
|
28 |
#include <gst/gstplugin.h>
|
renatofilho@787
|
29 |
#include <gst/interfaces/xoverlay.h>
|
renatofilho@787
|
30 |
#include <X11/Xlib.h>
|
renatofilho@787
|
31 |
//#include <gst/pbutils/pbutils.h>
|
renatofilho@787
|
32 |
#include "gstplaybinmaemo.h"
|
renatofilho@787
|
33 |
|
renatofilho@787
|
34 |
|
renatofilho@787
|
35 |
GST_DEBUG_CATEGORY_STATIC (gst_play_bin_maemo_debug);
|
renatofilho@787
|
36 |
#define GST_CAT_DEFAULT gst_play_bin_maemo_debug
|
renatofilho@787
|
37 |
|
leo_sobral@811
|
38 |
#define DEFAULT_VOLUME 1.0
|
renatofilho@787
|
39 |
#define DEFAULT_XID -1
|
renatofilho@787
|
40 |
|
renatofilho@787
|
41 |
/* props */
|
renatofilho@787
|
42 |
enum
|
renatofilho@787
|
43 |
{
|
renatofilho@787
|
44 |
ARG_0,
|
renatofilho@787
|
45 |
ARG_URI,
|
renatofilho@787
|
46 |
ARG_QUEUE_SIZE,
|
renatofilho@787
|
47 |
ARG_QUEUE_MIN_THRESHOLD,
|
renatofilho@787
|
48 |
ARG_SOURCE,
|
renatofilho@787
|
49 |
ARG_VOLUME,
|
renatofilho@788
|
50 |
ARG_PARSE_METADATA,
|
renatofilho@787
|
51 |
ARG_XID
|
renatofilho@787
|
52 |
};
|
renatofilho@787
|
53 |
|
renatofilho@787
|
54 |
static const GstElementDetails gst_play_bin_maemo_details =
|
leo_sobral@796
|
55 |
GST_ELEMENT_DETAILS("playbinmaemo",
|
renatofilho@787
|
56 |
"Generic/Bin/Player",
|
renatofilho@787
|
57 |
"Autoplug and play media from an uri used on maemo plataform",
|
renatofilho@787
|
58 |
"Renato Araujo Oliveira Filho <renato.filho@indt.org.br>");
|
renatofilho@787
|
59 |
|
renatofilho@787
|
60 |
static void gst_play_bin_maemo_dispose (GObject * object);
|
renatofilho@787
|
61 |
static void gst_play_bin_maemo_finalize (GObject * object);
|
renatofilho@787
|
62 |
static void gst_play_bin_maemo_set_property (GObject * object, guint prop_id,
|
renatofilho@787
|
63 |
const GValue * value, GParamSpec * spec);
|
renatofilho@787
|
64 |
static void gst_play_bin_maemo_get_property (GObject * object, guint prop_id,
|
renatofilho@787
|
65 |
GValue * value, GParamSpec * spec);
|
renatofilho@787
|
66 |
static GstStateChangeReturn
|
renatofilho@787
|
67 |
gst_play_bin_maemo_change_state (GstElement *element,
|
renatofilho@787
|
68 |
GstStateChange transition);
|
renatofilho@787
|
69 |
static gboolean factory_filter_sinks (GstPluginFeature *feature,
|
renatofilho@787
|
70 |
GstPlayBinMaemo *pbm);
|
renatofilho@787
|
71 |
static gint compare_ranks (GstPluginFeature * f1,
|
renatofilho@787
|
72 |
GstPluginFeature * f2);
|
renatofilho@787
|
73 |
static GList *find_compatibles (GstPlayBinMaemo *pbm,
|
renatofilho@787
|
74 |
const GstCaps *caps);
|
renatofilho@787
|
75 |
static GstPad *find_sink_pad (GstElement * element);
|
leo_sobral@811
|
76 |
static void update_volume (GstPlayBinMaemo *pbm,
|
leo_sobral@811
|
77 |
gfloat volume);
|
renatofilho@787
|
78 |
static void update_xid (GstPlayBinMaemo *pbm);
|
renatofilho@787
|
79 |
static void new_decoded_pad_cb (GstElement *object,
|
renatofilho@787
|
80 |
GstPad* pad,
|
renatofilho@787
|
81 |
gboolean arg,
|
renatofilho@787
|
82 |
gpointer user_data);
|
leo_sobral@811
|
83 |
static void removed_decoded_pad_cb (GstElement *object,
|
leo_sobral@811
|
84 |
GstPad* pad,
|
leo_sobral@811
|
85 |
gpointer user_data);
|
renatofilho@787
|
86 |
static void unknown_type_cb (GstElement *object,
|
renatofilho@787
|
87 |
GstPad *pad,
|
renatofilho@787
|
88 |
GstCaps *casp,
|
renatofilho@787
|
89 |
gpointer user_data);
|
renatofilho@787
|
90 |
static gboolean autoplug_continue_cb (GstElement* object,
|
renatofilho@787
|
91 |
GstCaps* caps,
|
renatofilho@787
|
92 |
gpointer user_data);
|
renatofilho@792
|
93 |
static gboolean add_element (GstPlayBinMaemo *pbm,
|
renatofilho@792
|
94 |
GstElement *child);
|
renatofilho@792
|
95 |
static void clear_elements (GstPlayBinMaemo *pbm);
|
leo_sobral@808
|
96 |
static int x_error_handler (Display *display,
|
leo_sobral@808
|
97 |
XErrorEvent *event);
|
renatofilho@787
|
98 |
|
renatofilho@787
|
99 |
GST_BOILERPLATE(GstPlayBinMaemo, gst_play_bin_maemo, GstPipeline, GST_TYPE_PIPELINE)
|
renatofilho@787
|
100 |
|
renatofilho@787
|
101 |
|
renatofilho@787
|
102 |
static void
|
renatofilho@787
|
103 |
gst_play_bin_maemo_base_init (gpointer klass)
|
renatofilho@787
|
104 |
{
|
renatofilho@787
|
105 |
GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
|
renatofilho@787
|
106 |
|
renatofilho@787
|
107 |
gst_element_class_set_details (element_class, &gst_play_bin_maemo_details);
|
renatofilho@787
|
108 |
}
|
renatofilho@787
|
109 |
|
renatofilho@787
|
110 |
static void
|
renatofilho@787
|
111 |
gst_play_bin_maemo_class_init (GstPlayBinMaemoClass * klass)
|
renatofilho@787
|
112 |
{
|
renatofilho@787
|
113 |
GObjectClass *gobject_klass;
|
renatofilho@787
|
114 |
GstElementClass *gstelement_klass;
|
renatofilho@787
|
115 |
GstBinClass *gstbin_klass;
|
renatofilho@787
|
116 |
|
renatofilho@787
|
117 |
gobject_klass = (GObjectClass *) klass;
|
renatofilho@787
|
118 |
gstelement_klass = (GstElementClass *) klass;
|
renatofilho@787
|
119 |
gstbin_klass = (GstBinClass *) klass;
|
renatofilho@787
|
120 |
|
renatofilho@787
|
121 |
parent_class = g_type_class_peek_parent (klass);
|
renatofilho@787
|
122 |
|
renatofilho@787
|
123 |
gobject_klass->set_property = gst_play_bin_maemo_set_property;
|
renatofilho@787
|
124 |
gobject_klass->get_property = gst_play_bin_maemo_get_property;
|
renatofilho@787
|
125 |
|
renatofilho@787
|
126 |
g_object_class_install_property (gobject_klass, ARG_URI,
|
renatofilho@787
|
127 |
g_param_spec_string ("uri", "URI", "URI of the media to play",
|
renatofilho@787
|
128 |
NULL, G_PARAM_READWRITE));
|
renatofilho@787
|
129 |
|
renatofilho@787
|
130 |
g_object_class_install_property (gobject_klass, ARG_VOLUME,
|
renatofilho@793
|
131 |
g_param_spec_double ("volume", "Audio volume", "volume",
|
leo_sobral@811
|
132 |
0.0, 10.0, DEFAULT_VOLUME, G_PARAM_READWRITE));
|
renatofilho@787
|
133 |
|
renatofilho@787
|
134 |
g_object_class_install_property (gobject_klass, ARG_XID,
|
renatofilho@787
|
135 |
g_param_spec_long ("xid", "xid", "X windown ID",
|
renatofilho@787
|
136 |
-1, G_MAXLONG, DEFAULT_XID, G_PARAM_READWRITE));
|
renatofilho@787
|
137 |
|
renatofilho@787
|
138 |
g_object_class_install_property (gobject_klass, ARG_SOURCE,
|
renatofilho@787
|
139 |
g_param_spec_object ("source", "Source", "Source element",
|
renatofilho@787
|
140 |
GST_TYPE_ELEMENT, G_PARAM_READABLE));
|
renatofilho@787
|
141 |
|
renatofilho@788
|
142 |
g_object_class_install_property (gobject_klass, ARG_PARSE_METADATA,
|
renatofilho@788
|
143 |
g_param_spec_boolean ("parse-metadata", "Parse Metadata", "Parse metadata info",
|
renatofilho@788
|
144 |
TRUE, G_PARAM_READWRITE));
|
renatofilho@788
|
145 |
|
renatofilho@788
|
146 |
|
renatofilho@787
|
147 |
GST_DEBUG_CATEGORY_INIT (gst_play_bin_maemo_debug, "playbinmaemo", 0,
|
renatofilho@787
|
148 |
"playbinmaemo");
|
renatofilho@787
|
149 |
|
renatofilho@787
|
150 |
gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_dispose);
|
renatofilho@787
|
151 |
gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_finalize);
|
renatofilho@787
|
152 |
|
renatofilho@787
|
153 |
gstelement_klass->change_state =
|
renatofilho@787
|
154 |
GST_DEBUG_FUNCPTR (gst_play_bin_maemo_change_state);
|
renatofilho@787
|
155 |
}
|
renatofilho@787
|
156 |
|
renatofilho@787
|
157 |
static void
|
renatofilho@787
|
158 |
gst_play_bin_maemo_init (GstPlayBinMaemo * play_bin_maemo, GstPlayBinMaemoClass *class)
|
renatofilho@787
|
159 |
{
|
renatofilho@787
|
160 |
GList *factories;
|
renatofilho@787
|
161 |
|
renatofilho@787
|
162 |
play_bin_maemo->uri = NULL;
|
renatofilho@787
|
163 |
play_bin_maemo->source = NULL;
|
renatofilho@787
|
164 |
|
leo_sobral@811
|
165 |
play_bin_maemo->volume = DEFAULT_VOLUME;
|
renatofilho@787
|
166 |
play_bin_maemo->xid = DEFAULT_XID;
|
renatofilho@788
|
167 |
play_bin_maemo->parse_metadata = TRUE;
|
renatofilho@787
|
168 |
|
leo_sobral@811
|
169 |
factories = gst_default_registry_feature_filter (
|
leo_sobral@811
|
170 |
(GstPluginFeatureFilter) factory_filter_sinks,
|
leo_sobral@811
|
171 |
FALSE, play_bin_maemo);
|
renatofilho@787
|
172 |
|
leo_sobral@811
|
173 |
play_bin_maemo->factories = g_list_sort (factories,
|
leo_sobral@811
|
174 |
(GCompareFunc) compare_ranks);
|
renatofilho@787
|
175 |
}
|
renatofilho@787
|
176 |
|
renatofilho@787
|
177 |
static void
|
renatofilho@787
|
178 |
gst_play_bin_maemo_dispose (GObject * object)
|
renatofilho@787
|
179 |
{
|
renatofilho@787
|
180 |
GstPlayBinMaemo *play_bin_maemo;
|
renatofilho@787
|
181 |
|
renatofilho@787
|
182 |
play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
|
renatofilho@787
|
183 |
g_free (play_bin_maemo->uri);
|
renatofilho@787
|
184 |
play_bin_maemo->uri = NULL;
|
renatofilho@787
|
185 |
|
renatofilho@787
|
186 |
G_OBJECT_CLASS (parent_class)->dispose (object);
|
renatofilho@787
|
187 |
}
|
renatofilho@787
|
188 |
|
renatofilho@787
|
189 |
static void
|
renatofilho@787
|
190 |
gst_play_bin_maemo_finalize (GObject * object)
|
renatofilho@787
|
191 |
{
|
renatofilho@792
|
192 |
clear_elements (GST_PLAY_BIN_MAEMO (object));
|
renatofilho@787
|
193 |
G_OBJECT_CLASS (parent_class)->finalize (object);
|
renatofilho@787
|
194 |
}
|
renatofilho@787
|
195 |
|
renatofilho@787
|
196 |
static gboolean
|
renatofilho@787
|
197 |
array_has_value (const gchar * values[], const gchar * value)
|
renatofilho@787
|
198 |
{
|
renatofilho@787
|
199 |
gint i;
|
renatofilho@787
|
200 |
|
renatofilho@787
|
201 |
for (i = 0; values[i]; i++) {
|
renatofilho@787
|
202 |
if (g_str_has_prefix (value, values[i]))
|
renatofilho@787
|
203 |
return TRUE;
|
renatofilho@787
|
204 |
}
|
renatofilho@787
|
205 |
return FALSE;
|
renatofilho@787
|
206 |
}
|
renatofilho@787
|
207 |
|
renatofilho@787
|
208 |
/* list of URIs that we consider to be streams and that need buffering.
|
renatofilho@787
|
209 |
* We have no mechanism yet to figure this out with a query. */
|
renatofilho@787
|
210 |
static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://",
|
renatofilho@787
|
211 |
"mmsu://", "mmst://", NULL
|
renatofilho@787
|
212 |
};
|
renatofilho@787
|
213 |
|
renatofilho@787
|
214 |
/* blacklisted URIs, we know they will always fail. */
|
renatofilho@787
|
215 |
static const gchar *blacklisted_uris[] = { NULL };
|
renatofilho@787
|
216 |
|
renatofilho@787
|
217 |
/* mime types that we don't consider to be media types */
|
renatofilho@793
|
218 |
/*
|
renatofilho@787
|
219 |
static const gchar *no_media_mimes[] = {
|
renatofilho@787
|
220 |
"application/x-executable", "application/x-bzip", "application/x-gzip",
|
renatofilho@787
|
221 |
"application/zip", "application/x-compress", NULL
|
renatofilho@787
|
222 |
};
|
renatofilho@793
|
223 |
*/
|
renatofilho@787
|
224 |
|
renatofilho@787
|
225 |
/* mime types we consider raw media */
|
renatofilho@787
|
226 |
static const gchar *raw_mimes[] = {
|
renatofilho@787
|
227 |
"audio/x-raw", "video/x-raw", NULL
|
renatofilho@787
|
228 |
};
|
renatofilho@787
|
229 |
|
renatofilho@787
|
230 |
#define IS_STREAM_URI(uri) (array_has_value (stream_uris, uri))
|
renatofilho@787
|
231 |
#define IS_BLACKLISTED_URI(uri) (array_has_value (blacklisted_uris, uri))
|
renatofilho@787
|
232 |
#define IS_NO_MEDIA_MIME(mime) (array_has_value (no_media_mimes, mime))
|
renatofilho@787
|
233 |
#define IS_RAW_MIME(mime) (array_has_value (raw_mimes, mime))
|
renatofilho@787
|
234 |
|
renatofilho@787
|
235 |
/*
|
renatofilho@787
|
236 |
* Generate and configure a source element.
|
renatofilho@787
|
237 |
*/
|
renatofilho@787
|
238 |
static GstElement *
|
renatofilho@787
|
239 |
gen_source_element (GstPlayBinMaemo * play_bin_maemo)
|
renatofilho@787
|
240 |
{
|
renatofilho@787
|
241 |
GstElement *source;
|
renatofilho@787
|
242 |
|
renatofilho@787
|
243 |
if (!play_bin_maemo->uri)
|
renatofilho@787
|
244 |
goto no_uri;
|
renatofilho@787
|
245 |
|
renatofilho@787
|
246 |
if (!gst_uri_is_valid (play_bin_maemo->uri))
|
renatofilho@787
|
247 |
goto invalid_uri;
|
renatofilho@787
|
248 |
|
renatofilho@787
|
249 |
if (IS_BLACKLISTED_URI (play_bin_maemo->uri))
|
renatofilho@787
|
250 |
goto uri_blacklisted;
|
renatofilho@787
|
251 |
|
renatofilho@792
|
252 |
source = gst_element_make_from_uri (GST_URI_SRC, play_bin_maemo->uri, "source");
|
renatofilho@787
|
253 |
if (!source)
|
renatofilho@787
|
254 |
goto no_source;
|
renatofilho@787
|
255 |
|
renatofilho@787
|
256 |
play_bin_maemo->is_stream = IS_STREAM_URI (play_bin_maemo->uri);
|
renatofilho@787
|
257 |
|
renatofilho@787
|
258 |
/* make HTTP sources send extra headers so we get icecast
|
renatofilho@787
|
259 |
* metadata in case the stream is an icecast stream */
|
renatofilho@787
|
260 |
if (!strncmp (play_bin_maemo->uri, "http://", 7) &&
|
renatofilho@787
|
261 |
g_object_class_find_property (G_OBJECT_GET_CLASS (source),
|
renatofilho@787
|
262 |
"iradio-mode")) {
|
renatofilho@787
|
263 |
g_object_set (source, "iradio-mode", TRUE, NULL);
|
renatofilho@787
|
264 |
}
|
renatofilho@787
|
265 |
return source;
|
renatofilho@787
|
266 |
|
renatofilho@787
|
267 |
/* ERRORS */
|
renatofilho@787
|
268 |
no_uri:
|
renatofilho@787
|
269 |
{
|
renatofilho@787
|
270 |
GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
|
renatofilho@787
|
271 |
(_("No URI specified to play from.")), (NULL));
|
renatofilho@787
|
272 |
return NULL;
|
renatofilho@787
|
273 |
}
|
renatofilho@787
|
274 |
invalid_uri:
|
renatofilho@787
|
275 |
{
|
renatofilho@787
|
276 |
GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
|
renatofilho@787
|
277 |
(_("Invalid URI \"%s\"."), play_bin_maemo->uri), (NULL));
|
renatofilho@787
|
278 |
return NULL;
|
renatofilho@787
|
279 |
}
|
renatofilho@787
|
280 |
uri_blacklisted:
|
renatofilho@787
|
281 |
{
|
renatofilho@787
|
282 |
GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, FAILED,
|
renatofilho@787
|
283 |
(_("RTSP streams cannot be played yet.")), (NULL));
|
renatofilho@787
|
284 |
return NULL;
|
renatofilho@787
|
285 |
}
|
renatofilho@787
|
286 |
no_source:
|
renatofilho@787
|
287 |
{
|
renatofilho@787
|
288 |
gchar *prot = gst_uri_get_protocol (play_bin_maemo->uri);
|
renatofilho@787
|
289 |
|
renatofilho@787
|
290 |
/* whoops, could not create the source element, dig a little deeper to
|
renatofilho@787
|
291 |
* figure out what might be wrong. */
|
renatofilho@787
|
292 |
if (prot) {
|
renatofilho@793
|
293 |
/*
|
renatofilho@787
|
294 |
gchar *desc;
|
renatofilho@787
|
295 |
|
renatofilho@787
|
296 |
gst_element_post_message (GST_ELEMENT (play_bin_maemo),
|
renatofilho@787
|
297 |
gst_missing_uri_source_message_new (GST_ELEMENT (play_bin_maemo),
|
renatofilho@787
|
298 |
prot));
|
renatofilho@787
|
299 |
|
renatofilho@787
|
300 |
desc = gst_pb_utils_get_source_description (prot);
|
renatofilho@787
|
301 |
GST_ELEMENT_ERROR (play_bin_maemo, CORE, MISSING_PLUGIN,
|
renatofilho@787
|
302 |
(_("A %s plugin is required to play this stream, but not installed."),
|
renatofilho@787
|
303 |
desc), ("No URI handler for %s", prot));
|
renatofilho@787
|
304 |
g_free (desc);
|
renatofilho@793
|
305 |
*/
|
renatofilho@787
|
306 |
g_free (prot);
|
renatofilho@787
|
307 |
} else
|
renatofilho@787
|
308 |
goto invalid_uri;
|
renatofilho@787
|
309 |
|
renatofilho@787
|
310 |
return NULL;
|
renatofilho@787
|
311 |
}
|
renatofilho@787
|
312 |
}
|
renatofilho@787
|
313 |
|
renatofilho@787
|
314 |
static void
|
renatofilho@787
|
315 |
prepare_elements (GstPlayBinMaemo *pbm)
|
renatofilho@787
|
316 |
{
|
leo_sobral@805
|
317 |
GstElement *decoder;
|
leo_sobral@805
|
318 |
GstElement *queue;
|
renatofilho@787
|
319 |
|
leo_sobral@805
|
320 |
decoder = gst_element_factory_make ("decodebin2", "decode");
|
leo_sobral@805
|
321 |
add_element (pbm, decoder);
|
leo_sobral@805
|
322 |
g_signal_connect (G_OBJECT (decoder),
|
leo_sobral@805
|
323 |
"autoplug-continue",
|
leo_sobral@805
|
324 |
G_CALLBACK (autoplug_continue_cb),
|
leo_sobral@805
|
325 |
pbm);
|
renatofilho@787
|
326 |
|
leo_sobral@805
|
327 |
g_signal_connect (G_OBJECT (decoder),
|
leo_sobral@805
|
328 |
"unknown-type",
|
leo_sobral@805
|
329 |
G_CALLBACK (unknown_type_cb),
|
leo_sobral@805
|
330 |
pbm);
|
renatofilho@792
|
331 |
|
leo_sobral@805
|
332 |
g_signal_connect (G_OBJECT (decoder),
|
leo_sobral@805
|
333 |
"new-decoded-pad",
|
leo_sobral@805
|
334 |
G_CALLBACK (new_decoded_pad_cb),
|
leo_sobral@805
|
335 |
pbm);
|
renatofilho@792
|
336 |
|
leo_sobral@811
|
337 |
g_signal_connect (G_OBJECT (decoder),
|
leo_sobral@811
|
338 |
"removed-decoded-pad",
|
leo_sobral@811
|
339 |
G_CALLBACK (removed_decoded_pad_cb),
|
leo_sobral@811
|
340 |
pbm);
|
leo_sobral@811
|
341 |
|
leo_sobral@811
|
342 |
|
leo_sobral@805
|
343 |
queue = gst_element_factory_make ("queue", NULL);
|
leo_sobral@805
|
344 |
add_element (pbm, queue);
|
renatofilho@792
|
345 |
|
leo_sobral@805
|
346 |
if (gst_element_link_many (pbm->source, queue, decoder, NULL) == FALSE) {
|
leo_sobral@811
|
347 |
GST_WARNING ("FAIL TO LINK SRC WITH DECODEBIN2");
|
leo_sobral@805
|
348 |
}
|
renatofilho@787
|
349 |
}
|
renatofilho@787
|
350 |
|
renatofilho@787
|
351 |
static gboolean
|
renatofilho@787
|
352 |
setup_source (GstPlayBinMaemo *pbm)
|
renatofilho@787
|
353 |
{
|
leo_sobral@805
|
354 |
if (!pbm->need_rebuild)
|
leo_sobral@805
|
355 |
return TRUE;
|
renatofilho@787
|
356 |
|
leo_sobral@805
|
357 |
clear_elements (pbm);
|
renatofilho@792
|
358 |
|
leo_sobral@805
|
359 |
GST_DEBUG_OBJECT (pbm, "setup source");
|
renatofilho@787
|
360 |
|
leo_sobral@805
|
361 |
pbm->has_metadata = FALSE;
|
renatofilho@788
|
362 |
|
leo_sobral@805
|
363 |
/* create and configure an element that can handle the uri */
|
leo_sobral@805
|
364 |
if (!(pbm->source = gen_source_element (pbm)))
|
leo_sobral@805
|
365 |
goto no_source;
|
renatofilho@787
|
366 |
|
leo_sobral@805
|
367 |
add_element (pbm, pbm->source);
|
renatofilho@787
|
368 |
|
renatofilho@787
|
369 |
|
renatofilho@787
|
370 |
#if 0
|
renatofilho@787
|
371 |
if (verify_src_have_sink (pbm)) {
|
renatofilho@787
|
372 |
/* source can be linked with sinks directly */
|
renatofilho@787
|
373 |
return TRUE;
|
renatofilho@787
|
374 |
}
|
renatofilho@787
|
375 |
#endif
|
renatofilho@787
|
376 |
|
leo_sobral@805
|
377 |
prepare_elements (pbm);
|
renatofilho@787
|
378 |
|
leo_sobral@805
|
379 |
return TRUE;
|
renatofilho@787
|
380 |
|
renatofilho@787
|
381 |
no_source:
|
leo_sobral@805
|
382 |
return FALSE;
|
renatofilho@787
|
383 |
}
|
renatofilho@787
|
384 |
|
renatofilho@787
|
385 |
static void
|
renatofilho@787
|
386 |
gst_play_bin_maemo_set_property (GObject *object,
|
renatofilho@787
|
387 |
guint prop_id,
|
renatofilho@787
|
388 |
const GValue *value,
|
renatofilho@787
|
389 |
GParamSpec *pspec)
|
renatofilho@787
|
390 |
{
|
renatofilho@787
|
391 |
GstPlayBinMaemo *play_bin_maemo;
|
renatofilho@787
|
392 |
|
renatofilho@787
|
393 |
g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
|
renatofilho@787
|
394 |
|
renatofilho@787
|
395 |
play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
|
renatofilho@787
|
396 |
|
renatofilho@787
|
397 |
switch (prop_id) {
|
renatofilho@787
|
398 |
case ARG_URI:
|
renatofilho@787
|
399 |
{
|
renatofilho@787
|
400 |
const gchar *uri = g_value_get_string (value);
|
renatofilho@787
|
401 |
|
renatofilho@787
|
402 |
if (uri == NULL) {
|
leo_sobral@811
|
403 |
GST_WARNING ("cannot set NULL uri");
|
renatofilho@787
|
404 |
return;
|
renatofilho@787
|
405 |
}
|
renatofilho@787
|
406 |
/* if we have no previous uri, or the new uri is different from the
|
renatofilho@787
|
407 |
* old one, replug */
|
renatofilho@787
|
408 |
if (play_bin_maemo->uri == NULL || strcmp (play_bin_maemo->uri, uri) != 0) {
|
renatofilho@787
|
409 |
g_free (play_bin_maemo->uri);
|
renatofilho@787
|
410 |
play_bin_maemo->uri = g_strdup (uri);
|
renatofilho@787
|
411 |
|
renatofilho@787
|
412 |
GST_DEBUG ("setting new uri to %s", uri);
|
renatofilho@787
|
413 |
|
renatofilho@787
|
414 |
play_bin_maemo->need_rebuild = TRUE;
|
renatofilho@787
|
415 |
}
|
renatofilho@787
|
416 |
break;
|
renatofilho@787
|
417 |
}
|
renatofilho@787
|
418 |
case ARG_VOLUME:
|
leo_sobral@811
|
419 |
update_volume(play_bin_maemo, g_value_get_double (value));
|
renatofilho@787
|
420 |
break;
|
renatofilho@787
|
421 |
case ARG_XID:
|
renatofilho@787
|
422 |
{
|
renatofilho@787
|
423 |
long xid;
|
renatofilho@787
|
424 |
xid = g_value_get_long (value);
|
renatofilho@792
|
425 |
if (play_bin_maemo->xid != xid)
|
renatofilho@792
|
426 |
{
|
renatofilho@787
|
427 |
play_bin_maemo->xid = xid;
|
renatofilho@787
|
428 |
update_xid (play_bin_maemo);
|
renatofilho@787
|
429 |
}
|
renatofilho@787
|
430 |
break;
|
renatofilho@787
|
431 |
}
|
renatofilho@788
|
432 |
case ARG_PARSE_METADATA:
|
renatofilho@788
|
433 |
play_bin_maemo->parse_metadata = g_value_get_boolean (value);
|
renatofilho@788
|
434 |
break;
|
renatofilho@787
|
435 |
default:
|
renatofilho@787
|
436 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
renatofilho@787
|
437 |
break;
|
renatofilho@787
|
438 |
}
|
renatofilho@787
|
439 |
}
|
renatofilho@787
|
440 |
|
renatofilho@787
|
441 |
static void
|
leo_sobral@811
|
442 |
gst_play_bin_maemo_get_property (GObject * object,
|
leo_sobral@811
|
443 |
guint prop_id,
|
leo_sobral@811
|
444 |
GValue * value,
|
leo_sobral@811
|
445 |
GParamSpec * pspec)
|
renatofilho@787
|
446 |
{
|
renatofilho@787
|
447 |
GstPlayBinMaemo *play_bin_maemo;
|
renatofilho@787
|
448 |
|
renatofilho@787
|
449 |
g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
|
renatofilho@787
|
450 |
|
renatofilho@787
|
451 |
play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
|
renatofilho@787
|
452 |
|
renatofilho@787
|
453 |
switch (prop_id) {
|
renatofilho@787
|
454 |
case ARG_URI:
|
renatofilho@787
|
455 |
g_value_set_string (value, play_bin_maemo->uri);
|
renatofilho@787
|
456 |
break;
|
renatofilho@787
|
457 |
case ARG_SOURCE:
|
renatofilho@787
|
458 |
g_value_set_object (value, play_bin_maemo->source);
|
renatofilho@787
|
459 |
break;
|
renatofilho@787
|
460 |
case ARG_VOLUME:
|
leo_sobral@811
|
461 |
g_value_set_double (value, play_bin_maemo->volume);
|
renatofilho@787
|
462 |
break;
|
renatofilho@787
|
463 |
case ARG_XID:
|
renatofilho@787
|
464 |
g_value_set_long (value, play_bin_maemo->xid);
|
renatofilho@787
|
465 |
break;
|
renatofilho@788
|
466 |
case ARG_PARSE_METADATA:
|
renatofilho@788
|
467 |
g_value_set_boolean (value, play_bin_maemo->parse_metadata);
|
renatofilho@788
|
468 |
break;
|
renatofilho@787
|
469 |
default:
|
renatofilho@787
|
470 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
renatofilho@787
|
471 |
break;
|
renatofilho@787
|
472 |
}
|
renatofilho@787
|
473 |
}
|
renatofilho@787
|
474 |
|
renatofilho@787
|
475 |
static GstStateChangeReturn
|
leo_sobral@811
|
476 |
gst_play_bin_maemo_change_state (GstElement * element,
|
leo_sobral@811
|
477 |
GstStateChange transition)
|
renatofilho@787
|
478 |
{
|
renatofilho@787
|
479 |
GstStateChangeReturn ret;
|
renatofilho@787
|
480 |
GstPlayBinMaemo *play_bin_maemo;
|
renatofilho@787
|
481 |
|
renatofilho@787
|
482 |
play_bin_maemo = GST_PLAY_BIN_MAEMO (element);
|
renatofilho@787
|
483 |
|
renatofilho@787
|
484 |
switch (transition) {
|
renatofilho@787
|
485 |
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
renatofilho@787
|
486 |
if (!setup_source (play_bin_maemo))
|
renatofilho@787
|
487 |
goto source_failed;
|
renatofilho@787
|
488 |
break;
|
renatofilho@787
|
489 |
default:
|
renatofilho@787
|
490 |
break;
|
renatofilho@787
|
491 |
}
|
renatofilho@787
|
492 |
|
renatofilho@787
|
493 |
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
renatofilho@787
|
494 |
|
renatofilho@787
|
495 |
switch (transition) {
|
renatofilho@787
|
496 |
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
renatofilho@787
|
497 |
if (ret == GST_STATE_CHANGE_FAILURE) {
|
renatofilho@787
|
498 |
play_bin_maemo->need_rebuild = TRUE;
|
renatofilho@787
|
499 |
return GST_STATE_CHANGE_FAILURE;
|
renatofilho@787
|
500 |
}
|
renatofilho@787
|
501 |
break;
|
renatofilho@787
|
502 |
/* clean-up in both cases, READY=>NULL clean-up is if there was an error */
|
renatofilho@787
|
503 |
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
renatofilho@787
|
504 |
case GST_STATE_CHANGE_READY_TO_NULL:
|
renatofilho@787
|
505 |
play_bin_maemo->need_rebuild = TRUE;
|
renatofilho@792
|
506 |
clear_elements (play_bin_maemo);
|
renatofilho@787
|
507 |
break;
|
renatofilho@787
|
508 |
default:
|
renatofilho@787
|
509 |
break;
|
renatofilho@787
|
510 |
}
|
renatofilho@787
|
511 |
return ret;
|
renatofilho@787
|
512 |
|
renatofilho@787
|
513 |
/* ERRORS */
|
renatofilho@787
|
514 |
source_failed:
|
renatofilho@787
|
515 |
{
|
renatofilho@787
|
516 |
play_bin_maemo->need_rebuild = TRUE;
|
renatofilho@787
|
517 |
|
renatofilho@787
|
518 |
return GST_STATE_CHANGE_FAILURE;
|
renatofilho@787
|
519 |
}
|
renatofilho@787
|
520 |
}
|
renatofilho@787
|
521 |
|
renatofilho@787
|
522 |
static gboolean
|
renatofilho@787
|
523 |
factory_filter_sinks (GstPluginFeature *feature,
|
renatofilho@787
|
524 |
GstPlayBinMaemo *pbm)
|
renatofilho@787
|
525 |
{
|
leo_sobral@805
|
526 |
guint rank;
|
leo_sobral@805
|
527 |
const gchar *klass;
|
renatofilho@787
|
528 |
|
leo_sobral@805
|
529 |
if (!GST_IS_ELEMENT_FACTORY (feature))
|
leo_sobral@805
|
530 |
return FALSE;
|
renatofilho@787
|
531 |
|
leo_sobral@805
|
532 |
klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
|
renatofilho@787
|
533 |
|
leo_sobral@805
|
534 |
if ((strstr (klass, "Sink/Video") == NULL) && (strstr (klass, "Sink/Audio") == NULL))
|
leo_sobral@805
|
535 |
return FALSE;
|
renatofilho@787
|
536 |
|
leo_sobral@811
|
537 |
GST_DEBUG_OBJECT (pbm, "Filtered: %s",
|
leo_sobral@811
|
538 |
gst_element_factory_get_longname ((GST_ELEMENT_FACTORY (feature))));
|
leo_sobral@805
|
539 |
rank = gst_plugin_feature_get_rank (feature);
|
leo_sobral@805
|
540 |
if (rank < GST_RANK_MARGINAL)
|
leo_sobral@805
|
541 |
return FALSE;
|
renatofilho@787
|
542 |
|
leo_sobral@805
|
543 |
return TRUE;
|
renatofilho@787
|
544 |
}
|
renatofilho@787
|
545 |
|
renatofilho@787
|
546 |
static gint
|
leo_sobral@811
|
547 |
compare_ranks (GstPluginFeature * f1,
|
leo_sobral@811
|
548 |
GstPluginFeature * f2)
|
renatofilho@787
|
549 |
{
|
renatofilho@787
|
550 |
gint diff;
|
renatofilho@787
|
551 |
const gchar *rname1, *rname2;
|
renatofilho@787
|
552 |
|
renatofilho@787
|
553 |
diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
|
renatofilho@787
|
554 |
if (diff != 0)
|
renatofilho@787
|
555 |
return diff;
|
renatofilho@787
|
556 |
|
renatofilho@787
|
557 |
rname1 = gst_plugin_feature_get_name (f1);
|
renatofilho@787
|
558 |
rname2 = gst_plugin_feature_get_name (f2);
|
renatofilho@787
|
559 |
|
renatofilho@787
|
560 |
diff = strcmp (rname2, rname1);
|
renatofilho@787
|
561 |
|
renatofilho@787
|
562 |
return diff;
|
renatofilho@787
|
563 |
}
|
renatofilho@787
|
564 |
|
renatofilho@787
|
565 |
|
renatofilho@787
|
566 |
static GList *
|
leo_sobral@811
|
567 |
find_compatibles (GstPlayBinMaemo *pbm,
|
leo_sobral@811
|
568 |
const GstCaps *caps)
|
renatofilho@787
|
569 |
{
|
renatofilho@787
|
570 |
GList *factories;
|
renatofilho@787
|
571 |
GList *to_try = NULL;
|
renatofilho@787
|
572 |
|
renatofilho@787
|
573 |
/* loop over all the factories */
|
renatofilho@787
|
574 |
for (factories = pbm->factories; factories; factories = g_list_next (factories)) {
|
renatofilho@787
|
575 |
GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data);
|
renatofilho@787
|
576 |
const GList *templates;
|
renatofilho@787
|
577 |
GList *walk;
|
renatofilho@787
|
578 |
|
renatofilho@787
|
579 |
/* get the templates from the element factory */
|
renatofilho@787
|
580 |
templates = gst_element_factory_get_static_pad_templates (factory);
|
renatofilho@787
|
581 |
for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
|
renatofilho@787
|
582 |
GstStaticPadTemplate *templ = walk->data;
|
renatofilho@787
|
583 |
|
renatofilho@787
|
584 |
/* we only care about the sink templates */
|
renatofilho@787
|
585 |
if (templ->direction == GST_PAD_SINK) {
|
renatofilho@787
|
586 |
GstCaps *intersect;
|
renatofilho@787
|
587 |
GstCaps *tmpl_caps;
|
renatofilho@787
|
588 |
|
renatofilho@787
|
589 |
/* try to intersect the caps with the caps of the template */
|
renatofilho@787
|
590 |
tmpl_caps = gst_static_caps_get (&templ->static_caps);
|
renatofilho@787
|
591 |
|
renatofilho@787
|
592 |
intersect = gst_caps_intersect (caps, tmpl_caps);
|
leo_sobral@811
|
593 |
|
renatofilho@787
|
594 |
gst_caps_unref (tmpl_caps);
|
renatofilho@787
|
595 |
|
renatofilho@787
|
596 |
/* check if the intersection is empty */
|
renatofilho@787
|
597 |
if (!gst_caps_is_empty (intersect)) {
|
renatofilho@787
|
598 |
/* non empty intersection, we can use this element */
|
renatofilho@787
|
599 |
to_try = g_list_prepend (to_try, factory);
|
renatofilho@787
|
600 |
gst_caps_unref (intersect);
|
renatofilho@787
|
601 |
break;
|
renatofilho@787
|
602 |
}
|
renatofilho@787
|
603 |
gst_caps_unref (intersect);
|
renatofilho@787
|
604 |
}
|
renatofilho@787
|
605 |
}
|
renatofilho@787
|
606 |
}
|
renatofilho@787
|
607 |
to_try = g_list_reverse (to_try);
|
renatofilho@787
|
608 |
|
renatofilho@787
|
609 |
return to_try;
|
renatofilho@787
|
610 |
}
|
renatofilho@787
|
611 |
|
renatofilho@787
|
612 |
static gboolean
|
renatofilho@787
|
613 |
autoplug_continue_cb (GstElement* object,
|
renatofilho@787
|
614 |
GstCaps* caps,
|
renatofilho@787
|
615 |
gpointer user_data)
|
renatofilho@787
|
616 |
{
|
renatofilho@787
|
617 |
GList *comp = NULL;
|
renatofilho@787
|
618 |
gboolean ret = TRUE;
|
renatofilho@788
|
619 |
GstPlayBinMaemo *pbm;
|
renatofilho@788
|
620 |
|
renatofilho@788
|
621 |
pbm = GST_PLAY_BIN_MAEMO (user_data);
|
renatofilho@788
|
622 |
|
leo_sobral@811
|
623 |
//TODO: fix this to work with all metadata elements
|
renatofilho@788
|
624 |
if (pbm->parse_metadata) {
|
renatofilho@788
|
625 |
gchar *caps_str = gst_caps_to_string (caps);
|
renatofilho@788
|
626 |
if ((strstr (caps_str, "id3") != NULL) &&
|
renatofilho@788
|
627 |
(pbm->has_metadata == FALSE)) {
|
renatofilho@788
|
628 |
|
renatofilho@788
|
629 |
g_free (caps_str);
|
renatofilho@788
|
630 |
pbm->has_metadata = TRUE;
|
renatofilho@788
|
631 |
return ret;
|
renatofilho@788
|
632 |
}
|
renatofilho@788
|
633 |
g_free (caps_str);
|
renatofilho@788
|
634 |
}
|
renatofilho@787
|
635 |
|
renatofilho@787
|
636 |
comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
|
renatofilho@787
|
637 |
if (comp != NULL) {
|
renatofilho@787
|
638 |
g_list_free (comp);
|
renatofilho@787
|
639 |
ret = FALSE;
|
renatofilho@787
|
640 |
}
|
renatofilho@787
|
641 |
|
renatofilho@787
|
642 |
return ret;
|
renatofilho@787
|
643 |
}
|
renatofilho@787
|
644 |
|
renatofilho@787
|
645 |
static void
|
renatofilho@787
|
646 |
unknown_type_cb (GstElement *object,
|
renatofilho@787
|
647 |
GstPad *pad,
|
renatofilho@787
|
648 |
GstCaps *caps,
|
renatofilho@787
|
649 |
gpointer user_data)
|
renatofilho@787
|
650 |
{
|
leo_sobral@811
|
651 |
GST_DEBUG ("unknown_type_cb: %s", gst_caps_to_string (caps));
|
renatofilho@787
|
652 |
}
|
renatofilho@787
|
653 |
|
leo_sobral@811
|
654 |
static GstPad*
|
renatofilho@787
|
655 |
find_sink_pad (GstElement * element)
|
renatofilho@787
|
656 |
{
|
renatofilho@787
|
657 |
GstIterator *it;
|
renatofilho@787
|
658 |
GstPad *pad = NULL;
|
renatofilho@787
|
659 |
gpointer point;
|
renatofilho@787
|
660 |
|
renatofilho@787
|
661 |
it = gst_element_iterate_sink_pads (element);
|
renatofilho@787
|
662 |
|
renatofilho@787
|
663 |
if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK)
|
renatofilho@787
|
664 |
pad = (GstPad *) point;
|
renatofilho@787
|
665 |
|
renatofilho@787
|
666 |
gst_iterator_free (it);
|
renatofilho@787
|
667 |
|
renatofilho@787
|
668 |
return pad;
|
renatofilho@787
|
669 |
}
|
renatofilho@787
|
670 |
|
renatofilho@788
|
671 |
static GstElement*
|
leo_sobral@811
|
672 |
create_element (GstPlayBinMaemo *pbm,
|
leo_sobral@811
|
673 |
GstElementFactory *factory)
|
renatofilho@788
|
674 |
{
|
leo_sobral@805
|
675 |
GstElement *queue;
|
leo_sobral@805
|
676 |
GstElement *bin = NULL;
|
leo_sobral@805
|
677 |
GstElement *element;
|
leo_sobral@805
|
678 |
GstPad *pad;
|
renatofilho@788
|
679 |
|
leo_sobral@805
|
680 |
element = gst_element_factory_create (factory, NULL);
|
leo_sobral@805
|
681 |
if (element == NULL)
|
leo_sobral@811
|
682 |
goto error;
|
renatofilho@792
|
683 |
|
leo_sobral@805
|
684 |
bin = gst_bin_new (NULL);
|
leo_sobral@811
|
685 |
if (bin == NULL)
|
leo_sobral@811
|
686 |
goto error;
|
renatofilho@792
|
687 |
|
leo_sobral@805
|
688 |
queue = gst_element_factory_make ("queue", NULL);
|
leo_sobral@805
|
689 |
gst_bin_add (GST_BIN (bin), queue);
|
renatofilho@792
|
690 |
|
leo_sobral@805
|
691 |
if (strstr (gst_element_factory_get_klass (factory), "Sink/Video") != NULL) {
|
leo_sobral@805
|
692 |
GstElement *colorspace;
|
renatofilho@792
|
693 |
|
leo_sobral@805
|
694 |
colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
|
leo_sobral@811
|
695 |
if (colorspace == NULL)
|
leo_sobral@811
|
696 |
goto error;
|
renatofilho@792
|
697 |
|
leo_sobral@805
|
698 |
gst_bin_add (GST_BIN (bin), colorspace);
|
leo_sobral@805
|
699 |
if (gst_element_link (queue, colorspace) == FALSE) {
|
leo_sobral@811
|
700 |
GST_WARNING_OBJECT (pbm, "Failed to link queue and colorspace");
|
leo_sobral@805
|
701 |
gst_element_set_state (colorspace, GST_STATE_NULL);
|
leo_sobral@805
|
702 |
gst_object_unref (colorspace);
|
leo_sobral@805
|
703 |
goto error;
|
renatofilho@788
|
704 |
}
|
renatofilho@788
|
705 |
|
leo_sobral@805
|
706 |
gst_bin_add (GST_BIN (bin), element);
|
leo_sobral@805
|
707 |
if (gst_element_link (colorspace, element) == FALSE) {
|
leo_sobral@811
|
708 |
GST_WARNING_OBJECT (pbm, "Failed to link colorspace and sink video: %s",
|
leo_sobral@811
|
709 |
GST_ELEMENT_NAME (element));
|
leo_sobral@805
|
710 |
gst_element_set_state (colorspace, GST_STATE_NULL);
|
leo_sobral@805
|
711 |
gst_object_unref (colorspace);
|
leo_sobral@805
|
712 |
goto error;
|
leo_sobral@805
|
713 |
}
|
renatofilho@792
|
714 |
|
leo_sobral@805
|
715 |
pbm->video_sink = element;
|
leo_sobral@805
|
716 |
update_xid (pbm);
|
leo_sobral@805
|
717 |
|
leo_sobral@805
|
718 |
} else if (strstr (gst_element_factory_get_klass (factory), "Sink/Audio") != NULL) {
|
leo_sobral@805
|
719 |
GParamSpec *vol_spec;
|
leo_sobral@805
|
720 |
GstElement *prev;
|
leo_sobral@805
|
721 |
|
leo_sobral@805
|
722 |
prev = queue;
|
leo_sobral@805
|
723 |
vol_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume");
|
leo_sobral@811
|
724 |
|
leo_sobral@805
|
725 |
if (vol_spec == NULL) {
|
leo_sobral@811
|
726 |
GstElement *conv;
|
leo_sobral@805
|
727 |
GstElement *volume;
|
leo_sobral@805
|
728 |
|
leo_sobral@811
|
729 |
conv = gst_element_factory_make ("audioconvert", "aconv");
|
leo_sobral@811
|
730 |
if (conv == NULL)
|
leo_sobral@811
|
731 |
goto error;
|
leo_sobral@811
|
732 |
|
leo_sobral@811
|
733 |
gst_bin_add (GST_BIN_CAST (bin), conv);
|
leo_sobral@811
|
734 |
|
leo_sobral@811
|
735 |
gst_element_link (queue, conv);
|
leo_sobral@811
|
736 |
|
leo_sobral@805
|
737 |
volume = gst_element_factory_make ("volume", "volume");
|
leo_sobral@811
|
738 |
if (volume == NULL)
|
leo_sobral@811
|
739 |
goto error;
|
leo_sobral@811
|
740 |
|
leo_sobral@805
|
741 |
gst_bin_add (GST_BIN (bin), volume);
|
leo_sobral@811
|
742 |
if (gst_element_link (conv, volume) == FALSE) {
|
leo_sobral@811
|
743 |
GST_WARNING_OBJECT (pbm, "Failed to link queue and volume");
|
leo_sobral@805
|
744 |
gst_element_set_state (volume, GST_STATE_NULL);
|
leo_sobral@805
|
745 |
gst_object_unref (volume);
|
leo_sobral@805
|
746 |
goto error;
|
leo_sobral@805
|
747 |
}
|
leo_sobral@805
|
748 |
|
leo_sobral@805
|
749 |
prev = volume;
|
leo_sobral@811
|
750 |
} else {
|
leo_sobral@805
|
751 |
g_param_spec_unref (vol_spec);
|
leo_sobral@805
|
752 |
}
|
leo_sobral@805
|
753 |
|
leo_sobral@805
|
754 |
gst_bin_add (GST_BIN (bin), element);
|
leo_sobral@805
|
755 |
if (gst_element_link (prev, element) == FALSE) {
|
leo_sobral@811
|
756 |
GST_WARNING_OBJECT (pbm, "Failed to link volume and sink audio: %s", GST_ELEMENT_NAME (element));
|
leo_sobral@805
|
757 |
if (prev != queue) {
|
leo_sobral@805
|
758 |
gst_element_set_state (prev, GST_STATE_NULL);
|
leo_sobral@805
|
759 |
gst_object_unref (prev);
|
leo_sobral@805
|
760 |
}
|
leo_sobral@805
|
761 |
goto error;
|
leo_sobral@805
|
762 |
}
|
leo_sobral@805
|
763 |
pbm->volume_element = (prev != queue) ? prev : element;
|
leo_sobral@811
|
764 |
update_volume (pbm, pbm->volume);
|
leo_sobral@805
|
765 |
}
|
leo_sobral@805
|
766 |
|
leo_sobral@805
|
767 |
pad = gst_element_get_pad (queue, "sink");
|
leo_sobral@805
|
768 |
gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));
|
leo_sobral@805
|
769 |
gst_object_unref (pad);
|
leo_sobral@805
|
770 |
|
leo_sobral@805
|
771 |
return bin;
|
leo_sobral@811
|
772 |
|
renatofilho@792
|
773 |
error:
|
leo_sobral@811
|
774 |
GST_WARNING_OBJECT (pbm, "Error creating pipeline");
|
renatofilho@792
|
775 |
|
leo_sobral@805
|
776 |
gst_element_set_state (bin, GST_STATE_NULL);
|
leo_sobral@805
|
777 |
gst_object_unref (bin);
|
renatofilho@792
|
778 |
|
leo_sobral@805
|
779 |
return NULL;
|
renatofilho@788
|
780 |
}
|
renatofilho@788
|
781 |
|
renatofilho@787
|
782 |
static void
|
renatofilho@787
|
783 |
new_decoded_pad_cb (GstElement *object,
|
renatofilho@787
|
784 |
GstPad* pad,
|
renatofilho@787
|
785 |
gboolean arg,
|
renatofilho@787
|
786 |
gpointer user_data)
|
renatofilho@787
|
787 |
{
|
leo_sobral@805
|
788 |
GList *comp = NULL;
|
leo_sobral@805
|
789 |
GList *walk;
|
leo_sobral@805
|
790 |
GstCaps *caps;
|
leo_sobral@805
|
791 |
gboolean linked;
|
leo_sobral@805
|
792 |
GstPlayBinMaemo *pbm;
|
renatofilho@787
|
793 |
|
leo_sobral@805
|
794 |
pbm = GST_PLAY_BIN_MAEMO (user_data);
|
leo_sobral@805
|
795 |
caps = gst_pad_get_caps (pad);
|
renatofilho@787
|
796 |
|
leo_sobral@811
|
797 |
GST_DEBUG_OBJECT (pbm, "new_decoded_pad_cb: %s", gst_caps_to_string (caps));
|
renatofilho@787
|
798 |
|
leo_sobral@805
|
799 |
comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
|
renatofilho@787
|
800 |
|
leo_sobral@805
|
801 |
if (comp == NULL) {
|
leo_sobral@811
|
802 |
GST_WARNING ("flow error: dont find comaptible");
|
leo_sobral@805
|
803 |
return;
|
leo_sobral@805
|
804 |
}
|
leo_sobral@805
|
805 |
|
leo_sobral@805
|
806 |
GST_PAD_STREAM_LOCK (pad);
|
leo_sobral@805
|
807 |
|
leo_sobral@805
|
808 |
linked = FALSE;
|
leo_sobral@805
|
809 |
for (walk=comp; walk != NULL; walk = walk->next) {
|
leo_sobral@805
|
810 |
GstElementFactory *factory = (GstElementFactory *) walk->data;
|
leo_sobral@805
|
811 |
GstElement *element;
|
leo_sobral@805
|
812 |
GstPad *sinkpad = NULL;
|
leo_sobral@811
|
813 |
gint result;
|
leo_sobral@805
|
814 |
|
leo_sobral@805
|
815 |
if ((element = create_element (pbm, factory)) == NULL) {
|
leo_sobral@805
|
816 |
GST_WARNING_OBJECT (pbm, "Could not create an element from %s",
|
leo_sobral@805
|
817 |
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
|
leo_sobral@811
|
818 |
continue;
|
leo_sobral@811
|
819 |
}
|
leo_sobral@805
|
820 |
|
leo_sobral@811
|
821 |
if (!(sinkpad = find_sink_pad (element))) {
|
leo_sobral@811
|
822 |
GST_WARNING_OBJECT (pbm, "Element %s doesn't have a sink pad", GST_ELEMENT_NAME (element));
|
leo_sobral@811
|
823 |
gst_object_unref (element);
|
leo_sobral@805
|
824 |
continue;
|
renatofilho@787
|
825 |
}
|
renatofilho@787
|
826 |
|
leo_sobral@805
|
827 |
if (!(add_element (GST_PLAY_BIN_MAEMO (user_data), element))) {
|
leo_sobral@811
|
828 |
GST_WARNING_OBJECT (pbm, "Couldn't add element %s to bin", GST_ELEMENT_NAME (element));
|
leo_sobral@811
|
829 |
gst_object_unref (sinkpad);
|
leo_sobral@805
|
830 |
gst_object_unref (element);
|
leo_sobral@805
|
831 |
continue;
|
renatofilho@787
|
832 |
}
|
renatofilho@787
|
833 |
|
leo_sobral@805
|
834 |
if ((gst_element_set_state (element, GST_STATE_READY))
|
leo_sobral@805
|
835 |
== GST_STATE_CHANGE_FAILURE) {
|
leo_sobral@811
|
836 |
GST_WARNING_OBJECT (pbm, "Couldn't set %s to READY", GST_ELEMENT_NAME (element));
|
leo_sobral@811
|
837 |
gst_object_unref (sinkpad);
|
leo_sobral@811
|
838 |
gst_bin_remove (GST_BIN (user_data), element);
|
leo_sobral@811
|
839 |
continue;
|
leo_sobral@811
|
840 |
}
|
leo_sobral@811
|
841 |
|
leo_sobral@811
|
842 |
if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK) {
|
leo_sobral@811
|
843 |
GST_WARNING_OBJECT (pbm, "Link failed on pad %s:%s", GST_DEBUG_PAD_NAME (sinkpad));
|
leo_sobral@805
|
844 |
gst_element_set_state (element, GST_STATE_NULL);
|
leo_sobral@805
|
845 |
gst_object_unref (sinkpad);
|
leo_sobral@805
|
846 |
gst_bin_remove (GST_BIN (user_data), element);
|
leo_sobral@805
|
847 |
continue;
|
renatofilho@787
|
848 |
}
|
leo_sobral@805
|
849 |
|
leo_sobral@805
|
850 |
gst_object_unref (sinkpad);
|
leo_sobral@805
|
851 |
|
leo_sobral@805
|
852 |
if ((gst_element_set_state (element, GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
|
leo_sobral@811
|
853 |
gst_element_set_state (element, GST_STATE_NULL);
|
leo_sobral@811
|
854 |
gst_bin_remove (GST_BIN (user_data), element);
|
leo_sobral@805
|
855 |
continue;
|
leo_sobral@805
|
856 |
}
|
leo_sobral@805
|
857 |
|
leo_sobral@805
|
858 |
linked = TRUE;
|
leo_sobral@805
|
859 |
break;
|
leo_sobral@805
|
860 |
}
|
leo_sobral@805
|
861 |
|
leo_sobral@805
|
862 |
g_list_free (comp);
|
leo_sobral@805
|
863 |
if (linked == FALSE) {
|
leo_sobral@811
|
864 |
g_debug ("GstFlow Error");
|
leo_sobral@811
|
865 |
GST_WARNING ("GstFlow ERROR");
|
leo_sobral@805
|
866 |
}
|
leo_sobral@805
|
867 |
GST_PAD_STREAM_UNLOCK (pad);
|
renatofilho@787
|
868 |
}
|
renatofilho@787
|
869 |
|
renatofilho@787
|
870 |
static void
|
leo_sobral@811
|
871 |
removed_decoded_pad_cb (GstElement *object,
|
leo_sobral@811
|
872 |
GstPad* pad,
|
leo_sobral@811
|
873 |
gpointer user_data)
|
renatofilho@787
|
874 |
{
|
leo_sobral@811
|
875 |
GstElement *sink;
|
leo_sobral@811
|
876 |
|
leo_sobral@811
|
877 |
GST_DEBUG("removed_decoded_pad_cb");
|
leo_sobral@811
|
878 |
|
leo_sobral@811
|
879 |
sink = gst_pad_get_parent_element (pad);
|
leo_sobral@811
|
880 |
|
leo_sobral@811
|
881 |
if (sink)
|
leo_sobral@811
|
882 |
gst_bin_remove (GST_BIN (user_data), sink);
|
leo_sobral@811
|
883 |
}
|
leo_sobral@811
|
884 |
|
leo_sobral@811
|
885 |
static GValue*
|
leo_sobral@811
|
886 |
convert_volume_base (GstPlayBinMaemo *pbm, gfloat volume)
|
leo_sobral@811
|
887 |
{
|
leo_sobral@811
|
888 |
GValue value = { 0, };
|
leo_sobral@811
|
889 |
GValue *converted_vol = g_new0(GValue, 1);
|
leo_sobral@811
|
890 |
|
leo_sobral@811
|
891 |
GParamSpec* vol_spec = g_object_class_find_property (
|
leo_sobral@811
|
892 |
G_OBJECT_GET_CLASS (pbm->volume_element), "volume");
|
leo_sobral@811
|
893 |
|
leo_sobral@811
|
894 |
g_value_init (&value, vol_spec->value_type);
|
leo_sobral@811
|
895 |
g_value_init (converted_vol, vol_spec->value_type);
|
leo_sobral@811
|
896 |
|
leo_sobral@811
|
897 |
g_object_get_property (G_OBJECT (pbm->volume_element), "volume", &value);
|
leo_sobral@811
|
898 |
|
leo_sobral@811
|
899 |
/* convert volume from double to int range if needed */
|
leo_sobral@811
|
900 |
switch (G_VALUE_TYPE (&value)) {
|
leo_sobral@811
|
901 |
case G_TYPE_UINT:
|
leo_sobral@811
|
902 |
{
|
leo_sobral@811
|
903 |
GParamSpecUInt *puint = G_PARAM_SPEC_UINT (vol_spec);
|
leo_sobral@811
|
904 |
guint scale = puint->maximum - puint->minimum;
|
leo_sobral@811
|
905 |
guint vol_guint = (guint) ((scale * volume) + puint->minimum);
|
leo_sobral@811
|
906 |
|
leo_sobral@811
|
907 |
GST_WARNING ("Range: %u - %u, Converted: %u",
|
leo_sobral@811
|
908 |
puint->minimum, puint->maximum, vol_guint);
|
leo_sobral@811
|
909 |
g_value_set_uint (converted_vol, vol_guint);
|
leo_sobral@811
|
910 |
break;
|
renatofilho@787
|
911 |
}
|
leo_sobral@811
|
912 |
case G_TYPE_INT:
|
leo_sobral@811
|
913 |
{
|
leo_sobral@811
|
914 |
GParamSpecInt *pint = G_PARAM_SPEC_INT (vol_spec);
|
leo_sobral@811
|
915 |
gint scale = pint->maximum - pint->minimum;
|
leo_sobral@811
|
916 |
gint vol_gint = (gint) ((scale * volume) + pint->minimum);
|
leo_sobral@811
|
917 |
|
leo_sobral@811
|
918 |
GST_WARNING ("Range: %d - %d, Converted: %d",
|
leo_sobral@811
|
919 |
pint->minimum, pint->maximum, vol_gint);
|
leo_sobral@811
|
920 |
g_value_set_int (converted_vol, vol_gint);
|
leo_sobral@811
|
921 |
break;
|
leo_sobral@811
|
922 |
}
|
leo_sobral@811
|
923 |
case G_TYPE_DOUBLE:
|
leo_sobral@811
|
924 |
case G_TYPE_FLOAT:
|
leo_sobral@811
|
925 |
{
|
leo_sobral@811
|
926 |
GST_WARNING ("Default converted to float: %f", volume);
|
leo_sobral@811
|
927 |
g_value_set_double (converted_vol, volume);
|
leo_sobral@811
|
928 |
break;
|
leo_sobral@811
|
929 |
}
|
leo_sobral@811
|
930 |
default:
|
leo_sobral@811
|
931 |
GST_WARNING ("Dont know how to convert volume");
|
leo_sobral@811
|
932 |
}
|
leo_sobral@811
|
933 |
|
leo_sobral@811
|
934 |
return converted_vol;
|
leo_sobral@811
|
935 |
}
|
leo_sobral@811
|
936 |
|
leo_sobral@811
|
937 |
static void
|
leo_sobral@811
|
938 |
update_volume (GstPlayBinMaemo *pbm, gfloat volume)
|
leo_sobral@811
|
939 |
{
|
leo_sobral@811
|
940 |
pbm->volume = volume;
|
leo_sobral@811
|
941 |
if (pbm->volume_element) {
|
leo_sobral@811
|
942 |
GValue *converted_vol = convert_volume_base (pbm, volume);
|
leo_sobral@811
|
943 |
g_object_set_property (G_OBJECT (pbm->volume_element), "volume",
|
leo_sobral@811
|
944 |
converted_vol);
|
leo_sobral@811
|
945 |
g_value_unset (converted_vol);
|
leo_sobral@805
|
946 |
}
|
renatofilho@787
|
947 |
}
|
renatofilho@787
|
948 |
|
renatofilho@787
|
949 |
static void
|
renatofilho@787
|
950 |
update_xid (GstPlayBinMaemo *pbm)
|
renatofilho@787
|
951 |
{
|
leo_sobral@811
|
952 |
if ((pbm->video_sink != NULL) && (pbm->xid != -1) &&
|
leo_sobral@811
|
953 |
(GST_IS_X_OVERLAY (pbm->video_sink))) {
|
leo_sobral@805
|
954 |
Display *display;
|
leo_sobral@805
|
955 |
g_object_set (G_OBJECT (pbm->video_sink),
|
leo_sobral@805
|
956 |
"force-aspect-ratio", TRUE, NULL);
|
leo_sobral@811
|
957 |
|
leo_sobral@805
|
958 |
display = XOpenDisplay(NULL);
|
leo_sobral@811
|
959 |
|
leo_sobral@805
|
960 |
XMapRaised(display, pbm->xid);
|
leo_sobral@811
|
961 |
XSync (display, FALSE);
|
leo_sobral@811
|
962 |
|
leo_sobral@808
|
963 |
XSetErrorHandler(x_error_handler);
|
renatofilho@792
|
964 |
|
leo_sobral@805
|
965 |
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (pbm->video_sink),
|
leo_sobral@805
|
966 |
pbm->xid);
|
leo_sobral@805
|
967 |
}
|
renatofilho@787
|
968 |
}
|
renatofilho@787
|
969 |
|
leo_sobral@808
|
970 |
static int
|
leo_sobral@811
|
971 |
x_error_handler(Display *display,
|
leo_sobral@811
|
972 |
XErrorEvent *event)
|
leo_sobral@808
|
973 |
{
|
leo_sobral@811
|
974 |
GST_DEBUG ("In x error handler:");
|
leo_sobral@808
|
975 |
|
leo_sobral@808
|
976 |
switch (event->error_code) {
|
leo_sobral@808
|
977 |
case BadWindow:
|
leo_sobral@811
|
978 |
GST_DEBUG ("got bad window");
|
leo_sobral@808
|
979 |
break;
|
leo_sobral@808
|
980 |
case BadDrawable:
|
leo_sobral@811
|
981 |
GST_DEBUG ("got bad drawable");
|
leo_sobral@808
|
982 |
break;
|
leo_sobral@808
|
983 |
case BadGC:
|
leo_sobral@811
|
984 |
GST_DEBUG ("got bad gc");
|
leo_sobral@808
|
985 |
break;
|
leo_sobral@808
|
986 |
default:
|
leo_sobral@811
|
987 |
GST_DEBUG ("unhandled x error = %d", event->error_code);
|
leo_sobral@808
|
988 |
}
|
leo_sobral@808
|
989 |
|
leo_sobral@808
|
990 |
return 0;
|
leo_sobral@808
|
991 |
}
|
leo_sobral@808
|
992 |
|
renatofilho@787
|
993 |
static gboolean
|
renatofilho@792
|
994 |
add_element (GstPlayBinMaemo *pbm,
|
renatofilho@792
|
995 |
GstElement *child)
|
renatofilho@792
|
996 |
{
|
leo_sobral@805
|
997 |
if (gst_bin_add (GST_BIN (pbm), child)) {
|
leo_sobral@805
|
998 |
pbm->elements = g_list_append (pbm->elements, child);
|
leo_sobral@805
|
999 |
return TRUE;
|
leo_sobral@805
|
1000 |
}
|
leo_sobral@805
|
1001 |
return FALSE;
|
renatofilho@792
|
1002 |
}
|
renatofilho@792
|
1003 |
|
renatofilho@792
|
1004 |
static void
|
renatofilho@792
|
1005 |
clear_elements (GstPlayBinMaemo *pbm)
|
renatofilho@792
|
1006 |
{
|
leo_sobral@805
|
1007 |
GList *walk;
|
renatofilho@792
|
1008 |
|
leo_sobral@805
|
1009 |
walk = pbm->elements;
|
renatofilho@792
|
1010 |
|
leo_sobral@805
|
1011 |
for (; walk != NULL; walk = walk->next) {
|
leo_sobral@805
|
1012 |
GstElement *e = GST_ELEMENT (walk->data);
|
renatofilho@792
|
1013 |
|
leo_sobral@805
|
1014 |
gst_element_set_state (e, GST_STATE_NULL);
|
leo_sobral@805
|
1015 |
gst_bin_remove (GST_BIN (pbm), e);
|
leo_sobral@805
|
1016 |
}
|
renatofilho@792
|
1017 |
|
leo_sobral@805
|
1018 |
g_list_free (pbm->elements);
|
leo_sobral@805
|
1019 |
pbm->elements = NULL;
|
leo_sobral@805
|
1020 |
pbm->source = NULL;
|
leo_sobral@805
|
1021 |
pbm->volume_element = NULL;
|
leo_sobral@805
|
1022 |
pbm->video_sink = NULL;
|
renatofilho@792
|
1023 |
}
|
renatofilho@792
|
1024 |
|
renatofilho@792
|
1025 |
static gboolean
|
renatofilho@787
|
1026 |
plugin_init(GstPlugin * plugin)
|
renatofilho@787
|
1027 |
{
|
renatofilho@787
|
1028 |
#ifdef ENABLE_NLS
|
leo_sobral@805
|
1029 |
setlocale(LC_ALL, "");
|
leo_sobral@805
|
1030 |
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
|
renatofilho@787
|
1031 |
#endif /* ENABLE_NLS */
|
renatofilho@787
|
1032 |
|
leo_sobral@805
|
1033 |
if (!gst_element_register(plugin, "playbinmaemo", GST_RANK_SECONDARY,
|
leo_sobral@805
|
1034 |
GST_TYPE_PLAY_BIN_MAEMO)) {
|
leo_sobral@805
|
1035 |
return FALSE;
|
leo_sobral@805
|
1036 |
}
|
renatofilho@787
|
1037 |
|
leo_sobral@805
|
1038 |
return TRUE;
|
renatofilho@787
|
1039 |
}
|
renatofilho@787
|
1040 |
|
renatofilho@787
|
1041 |
GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
|
renatofilho@787
|
1042 |
GST_VERSION_MINOR,
|
renatofilho@787
|
1043 |
"playbinmaemo",
|
leo_sobral@796
|
1044 |
"A playbin element that uses decodebin2 for automatic playback of audio and video",
|
renatofilho@787
|
1045 |
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME,
|
renatofilho@787
|
1046 |
GST_PACKAGE_ORIGIN)
|