93 * @value: the value to set |
101 * @value: the value to set |
94 * @value_str: the string to get the value from |
102 * @value_str: the string to get the value from |
95 * |
103 * |
96 * Converts the string to the type of the value and |
104 * Converts the string to the type of the value and |
97 * sets the value with it. |
105 * sets the value with it. |
|
106 * |
|
107 * Note that this function is dangerous as it does not return any indication |
|
108 * if the conversion worked or not. |
98 */ |
109 */ |
99 #ifdef __SYMBIAN32__ |
110 #ifdef __SYMBIAN32__ |
100 EXPORT_C |
111 EXPORT_C |
101 #endif |
112 #endif |
102 |
113 |
103 void |
114 void |
104 gst_util_set_value_from_string (GValue * value, const gchar * value_str) |
115 gst_util_set_value_from_string (GValue * value, const gchar * value_str) |
105 { |
116 { |
106 gint sscanf_ret; |
117 gboolean res; |
107 |
118 |
108 g_return_if_fail (value != NULL); |
119 g_return_if_fail (value != NULL); |
109 g_return_if_fail (value_str != NULL); |
120 g_return_if_fail (value_str != NULL); |
110 |
121 |
111 GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str, |
122 GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str, |
112 g_type_name (G_VALUE_TYPE (value))); |
123 g_type_name (G_VALUE_TYPE (value))); |
113 |
124 |
114 switch (G_VALUE_TYPE (value)) { |
125 res = gst_value_deserialize (value, value_str); |
115 case G_TYPE_STRING: |
126 if (!res && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) { |
116 g_value_set_string (value, value_str); |
127 /* backwards compat, all booleans that fail to parse are false */ |
117 break; |
128 g_value_set_boolean (value, FALSE); |
118 case G_TYPE_ENUM: |
129 res = TRUE; |
119 case G_TYPE_INT:{ |
130 } |
120 gint i; |
131 g_return_if_fail (res); |
121 |
|
122 sscanf_ret = sscanf (value_str, "%d", &i); |
|
123 g_return_if_fail (sscanf_ret == 1); |
|
124 g_value_set_int (value, i); |
|
125 break; |
|
126 } |
|
127 case G_TYPE_UINT:{ |
|
128 guint i; |
|
129 |
|
130 sscanf_ret = sscanf (value_str, "%u", &i); |
|
131 g_return_if_fail (sscanf_ret == 1); |
|
132 g_value_set_uint (value, i); |
|
133 break; |
|
134 } |
|
135 case G_TYPE_LONG:{ |
|
136 glong i; |
|
137 |
|
138 sscanf_ret = sscanf (value_str, "%ld", &i); |
|
139 g_return_if_fail (sscanf_ret == 1); |
|
140 g_value_set_long (value, i); |
|
141 break; |
|
142 } |
|
143 case G_TYPE_ULONG:{ |
|
144 gulong i; |
|
145 |
|
146 sscanf_ret = sscanf (value_str, "%lu", &i); |
|
147 g_return_if_fail (sscanf_ret == 1); |
|
148 g_value_set_ulong (value, i); |
|
149 break; |
|
150 } |
|
151 case G_TYPE_BOOLEAN:{ |
|
152 gboolean i = FALSE; |
|
153 |
|
154 if (!g_ascii_strncasecmp ("true", value_str, 4)) |
|
155 i = TRUE; |
|
156 g_value_set_boolean (value, i); |
|
157 break; |
|
158 } |
|
159 case G_TYPE_CHAR:{ |
|
160 gchar i; |
|
161 |
|
162 sscanf_ret = sscanf (value_str, "%c", &i); |
|
163 g_return_if_fail (sscanf_ret == 1); |
|
164 g_value_set_char (value, i); |
|
165 break; |
|
166 } |
|
167 case G_TYPE_UCHAR:{ |
|
168 guchar i; |
|
169 |
|
170 sscanf_ret = sscanf (value_str, "%c", &i); |
|
171 g_return_if_fail (sscanf_ret == 1); |
|
172 g_value_set_uchar (value, i); |
|
173 break; |
|
174 } |
|
175 case G_TYPE_FLOAT:{ |
|
176 gfloat i; |
|
177 |
|
178 sscanf_ret = sscanf (value_str, "%f", &i); |
|
179 g_return_if_fail (sscanf_ret == 1); |
|
180 g_value_set_float (value, i); |
|
181 break; |
|
182 } |
|
183 case G_TYPE_DOUBLE:{ |
|
184 gfloat i; |
|
185 |
|
186 sscanf_ret = sscanf (value_str, "%g", &i); |
|
187 g_return_if_fail (sscanf_ret == 1); |
|
188 g_value_set_double (value, (gdouble) i); |
|
189 break; |
|
190 } |
|
191 default: |
|
192 break; |
|
193 } |
|
194 } |
132 } |
195 |
133 |
196 /** |
134 /** |
197 * gst_util_set_object_arg: |
135 * gst_util_set_object_arg: |
198 * @object: the object to set the argument of |
136 * @object: the object to set the argument of |
199 * @name: the name of the argument to set |
137 * @name: the name of the argument to set |
200 * @value: the string value to set |
138 * @value: the string value to set |
201 * |
139 * |
202 * Convertes the string value to the type of the objects argument and |
140 * Convertes the string value to the type of the objects argument and |
203 * sets the argument with it. |
141 * sets the argument with it. |
|
142 * |
|
143 * Note that this function silently returns if @object has no property named |
|
144 * @name or when @value cannot be converted to the type of the property. |
204 */ |
145 */ |
205 #ifdef __SYMBIAN32__ |
146 #ifdef __SYMBIAN32__ |
206 EXPORT_C |
147 EXPORT_C |
207 #endif |
148 #endif |
208 |
149 |
209 void |
150 void |
210 gst_util_set_object_arg (GObject * object, const gchar * name, |
151 gst_util_set_object_arg (GObject * object, const gchar * name, |
211 const gchar * value) |
152 const gchar * value) |
212 { |
153 { |
213 gboolean sscanf_ret; |
154 GParamSpec *pspec; |
214 |
155 GType value_type; |
215 if (name && value) { |
156 GValue v = { 0, }; |
216 GParamSpec *paramspec; |
157 |
217 |
158 g_return_if_fail (G_IS_OBJECT (object)); |
218 paramspec = |
159 g_return_if_fail (name != NULL); |
219 g_object_class_find_property (G_OBJECT_GET_CLASS (object), name); |
160 g_return_if_fail (value != NULL); |
220 |
161 |
221 if (!paramspec) { |
162 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name); |
222 return; |
163 if (!pspec) |
223 } |
164 return; |
224 |
165 |
225 GST_DEBUG ("paramspec->flags is %d, paramspec->value_type is %d", |
166 value_type = G_PARAM_SPEC_VALUE_TYPE (pspec); |
226 paramspec->flags, (gint) paramspec->value_type); |
167 |
227 |
168 GST_DEBUG ("pspec->flags is %d, pspec->value_type is %s", |
228 if (paramspec->flags & G_PARAM_WRITABLE) { |
169 pspec->flags, g_type_name (value_type)); |
229 switch (paramspec->value_type) { |
170 |
230 case G_TYPE_STRING: |
171 if (!(pspec->flags & G_PARAM_WRITABLE)) |
231 g_object_set (G_OBJECT (object), name, value, NULL); |
172 return; |
232 break; |
173 |
233 case G_TYPE_ENUM: |
174 g_value_init (&v, value_type); |
234 case G_TYPE_INT:{ |
175 |
235 gint i; |
176 /* special case for element <-> xml (de)serialisation */ |
236 |
177 if (GST_VALUE_HOLDS_STRUCTURE (&v) && strcmp (value, "NULL") == 0) { |
237 sscanf_ret = sscanf (value, "%d", &i); |
178 g_value_set_boxed (&v, NULL); |
238 g_return_if_fail (sscanf_ret == 1); |
179 goto done; |
239 g_object_set (G_OBJECT (object), name, i, NULL); |
180 } |
240 break; |
181 |
241 } |
182 if (!gst_value_deserialize (&v, value)) |
242 case G_TYPE_UINT:{ |
183 return; |
243 guint i; |
184 |
244 |
185 done: |
245 sscanf_ret = sscanf (value, "%u", &i); |
186 |
246 g_return_if_fail (sscanf_ret == 1); |
187 g_object_set_property (object, pspec->name, &v); |
247 g_object_set (G_OBJECT (object), name, i, NULL); |
188 g_value_unset (&v); |
248 break; |
|
249 } |
|
250 case G_TYPE_LONG:{ |
|
251 glong i; |
|
252 |
|
253 sscanf_ret = sscanf (value, "%ld", &i); |
|
254 g_return_if_fail (sscanf_ret == 1); |
|
255 g_object_set (G_OBJECT (object), name, i, NULL); |
|
256 break; |
|
257 } |
|
258 case G_TYPE_ULONG:{ |
|
259 gulong i; |
|
260 |
|
261 sscanf_ret = sscanf (value, "%lu", &i); |
|
262 g_return_if_fail (sscanf_ret == 1); |
|
263 g_object_set (G_OBJECT (object), name, i, NULL); |
|
264 break; |
|
265 } |
|
266 case G_TYPE_BOOLEAN:{ |
|
267 gboolean i = FALSE; |
|
268 |
|
269 if (!g_ascii_strncasecmp ("true", value, 4)) |
|
270 i = TRUE; |
|
271 g_object_set (G_OBJECT (object), name, i, NULL); |
|
272 break; |
|
273 } |
|
274 case G_TYPE_CHAR:{ |
|
275 gchar i; |
|
276 |
|
277 sscanf_ret = sscanf (value, "%c", &i); |
|
278 g_return_if_fail (sscanf_ret == 1); |
|
279 g_object_set (G_OBJECT (object), name, i, NULL); |
|
280 break; |
|
281 } |
|
282 case G_TYPE_UCHAR:{ |
|
283 guchar i; |
|
284 |
|
285 sscanf_ret = sscanf (value, "%c", &i); |
|
286 g_return_if_fail (sscanf_ret == 1); |
|
287 g_object_set (G_OBJECT (object), name, i, NULL); |
|
288 break; |
|
289 } |
|
290 case G_TYPE_FLOAT:{ |
|
291 gfloat i; |
|
292 |
|
293 sscanf_ret = sscanf (value, "%f", &i); |
|
294 g_return_if_fail (sscanf_ret == 1); |
|
295 g_object_set (G_OBJECT (object), name, i, NULL); |
|
296 break; |
|
297 } |
|
298 case G_TYPE_DOUBLE:{ |
|
299 gfloat i; |
|
300 |
|
301 sscanf_ret = sscanf (value, "%g", &i); |
|
302 g_return_if_fail (sscanf_ret == 1); |
|
303 g_object_set (G_OBJECT (object), name, (gdouble) i, NULL); |
|
304 break; |
|
305 } |
|
306 default: |
|
307 if (G_IS_PARAM_SPEC_ENUM (paramspec)) { |
|
308 gint i; |
|
309 |
|
310 sscanf_ret = sscanf (value, "%d", &i); |
|
311 g_return_if_fail (sscanf_ret == 1); |
|
312 g_object_set (G_OBJECT (object), name, i, NULL); |
|
313 } |
|
314 break; |
|
315 } |
|
316 } |
|
317 } |
|
318 } |
189 } |
319 |
190 |
320 /* work around error C2520: conversion from unsigned __int64 to double |
191 /* work around error C2520: conversion from unsigned __int64 to double |
321 * not implemented, use signed __int64 |
192 * not implemented, use signed __int64 |
322 * |
193 * |
517 guint64 |
418 guint64 |
518 gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom) |
419 gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom) |
519 { |
420 { |
520 g_return_val_if_fail (denom != 0, G_MAXUINT64); |
421 g_return_val_if_fail (denom != 0, G_MAXUINT64); |
521 |
422 |
522 if (num == 0) |
423 if (G_UNLIKELY (num == 0)) |
523 return 0; |
424 return 0; |
524 |
425 |
525 if (num == 1 && denom == 1) |
426 if (G_UNLIKELY (num == denom)) |
526 return val; |
427 return val; |
527 |
428 |
528 /* if the denom is high, we need to do a 64 muldiv */ |
429 /* if the denom is high, we need to do a 64 muldiv */ |
529 if (denom > G_MAXINT32) |
430 if (G_UNLIKELY (denom > G_MAXINT32)) |
530 goto do_int64; |
431 goto do_int64; |
531 |
432 |
532 /* if num and denom are low we can do a 32 bit muldiv */ |
433 /* if num and denom are low we can do a 32 bit muldiv */ |
533 if (num <= G_MAXINT32) |
434 if (G_LIKELY (num <= G_MAXINT32)) |
534 goto do_int32; |
435 goto do_int32; |
535 |
436 |
536 /* val and num are high, we need 64 muldiv */ |
437 /* val and num are high, we need 64 muldiv */ |
537 if (val > G_MAXINT32) |
438 if (G_UNLIKELY (val > G_MAXINT32)) |
538 goto do_int64; |
439 goto do_int64; |
539 |
440 |
540 /* val is low and num is high, we can swap them and do 32 muldiv */ |
441 /* val is low and num is high, we can swap them and do 32 muldiv */ |
541 return gst_util_uint64_scale_int (num, (gint) val, (gint) denom); |
442 return gst_util_uint64_scale_int_unchecked (num, (gint) val, (gint) denom); |
542 |
443 |
543 do_int32: |
444 do_int32: |
544 return gst_util_uint64_scale_int (val, (gint) num, (gint) denom); |
445 return gst_util_uint64_scale_int_unchecked (val, (gint) num, (gint) denom); |
545 |
446 |
546 do_int64: |
447 do_int64: |
547 /* to the more heavy implementations... */ |
448 /* to the more heavy implementations... */ |
548 return gst_util_uint64_scale_int64 (val, num, denom); |
449 return gst_util_uint64_scale_int64_unchecked (val, num, denom); |
549 } |
450 } |
550 |
451 |
551 /** |
452 /** |
552 * gst_util_uint64_scale_int: |
453 * gst_util_uint64_scale_int: |
553 * @val: guint64 (such as a #GstClockTime) to scale. |
454 * @val: guint64 (such as a #GstClockTime) to scale. |
567 #endif |
468 #endif |
568 |
469 |
569 guint64 |
470 guint64 |
570 gst_util_uint64_scale_int (guint64 val, gint num, gint denom) |
471 gst_util_uint64_scale_int (guint64 val, gint num, gint denom) |
571 { |
472 { |
572 GstUInt64 result; |
|
573 GstUInt64 low, high; |
|
574 |
|
575 g_return_val_if_fail (denom > 0, G_MAXUINT64); |
473 g_return_val_if_fail (denom > 0, G_MAXUINT64); |
576 g_return_val_if_fail (num >= 0, G_MAXUINT64); |
474 g_return_val_if_fail (num >= 0, G_MAXUINT64); |
577 |
475 |
578 if (num == 0) |
476 if (G_UNLIKELY (num == 0)) |
579 return 0; |
477 return 0; |
580 |
478 |
581 if (num == 1 && denom == 1) |
479 if (G_UNLIKELY (num == denom)) |
582 return val; |
480 return val; |
583 |
481 |
584 if (val <= G_MAXUINT32) |
482 if (val <= G_MAXUINT32) |
585 /* simple case */ |
483 /* simple case */ |
586 return val * num / denom; |
484 return val * num / denom; |
587 |
485 |
588 /* do 96 bits mult/div */ |
486 return gst_util_uint64_scale_int_unchecked (val, num, denom); |
589 low.ll = val; |
487 } |
590 result.ll = ((guint64) low.l.low) * num; |
488 |
591 high.ll = ((guint64) low.l.high) * num + (result.l.high); |
489 /** |
592 |
490 * gst_util_seqnum_next: |
593 low.ll = high.ll / denom; |
491 * |
594 result.l.high = high.ll % denom; |
492 * Return a constantly incrementing sequence number. |
595 result.ll /= denom; |
493 * |
596 |
494 * This function is used internally to GStreamer to be able to determine which |
597 /* avoid overflow */ |
495 * events and messages are "the same". For example, elements may set the seqnum |
598 if (low.ll + result.l.high > G_MAXUINT32) |
496 * on a segment-done message to be the same as that of the last seek event, to |
599 goto overflow; |
497 * indicate that event and the message correspond to the same segment. |
600 |
498 * |
601 result.l.high += low.l.low; |
499 * Returns: A constantly incrementing 32-bit unsigned integer, which might |
602 |
500 * overflow back to 0 at some point. Use gst_util_seqnum_compare() to make sure |
603 return result.ll; |
501 * you handle wraparound correctly. |
604 |
502 * |
605 overflow: |
503 * Since: 0.10.22 |
606 { |
504 */ |
607 return G_MAXUINT64; |
505 #ifdef __SYMBIAN32__ |
608 } |
506 EXPORT_C |
|
507 #endif |
|
508 |
|
509 guint32 |
|
510 gst_util_seqnum_next (void) |
|
511 { |
|
512 static gint counter = 0; |
|
513 return g_atomic_int_exchange_and_add (&counter, 1); |
|
514 } |
|
515 |
|
516 /** |
|
517 * gst_util_seqnum_compare: |
|
518 * @s1: A sequence number. |
|
519 * @s2: Another sequence number. |
|
520 * |
|
521 * Compare two sequence numbers, handling wraparound. |
|
522 * |
|
523 * The current implementation just returns (gint32)(@s1 - @s2). |
|
524 * |
|
525 * Returns: A negative number if @s1 is before @s2, 0 if they are equal, or a |
|
526 * positive number if @s1 is after @s2. |
|
527 * |
|
528 * Since: 0.10.22 |
|
529 */ |
|
530 #ifdef __SYMBIAN32__ |
|
531 EXPORT_C |
|
532 #endif |
|
533 |
|
534 gint32 |
|
535 gst_util_seqnum_compare (guint32 s1, guint32 s2) |
|
536 { |
|
537 return (gint32) (s1 - s2); |
609 } |
538 } |
610 |
539 |
611 /* ----------------------------------------------------- |
540 /* ----------------------------------------------------- |
612 * |
541 * |
613 * The following code will be moved out of the main |
542 * The following code will be moved out of the main |
926 pad = NULL; |
855 pad = NULL; |
927 |
856 |
928 return pad; |
857 return pad; |
929 } |
858 } |
930 |
859 |
|
860 /* |
|
861 * Checks if the source pad and the sink pad can be linked. |
|
862 * Both @srcpad and @sinkpad must be unlinked and have a parent. |
|
863 */ |
|
864 static gboolean |
|
865 gst_pad_check_link (GstPad * srcpad, GstPad * sinkpad) |
|
866 { |
|
867 /* FIXME This function is gross. It's almost a direct copy of |
|
868 * gst_pad_link_filtered(). Any decent programmer would attempt |
|
869 * to merge the two functions, which I will do some day. --ds |
|
870 */ |
|
871 |
|
872 /* generic checks */ |
|
873 g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE); |
|
874 g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE); |
|
875 |
|
876 GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s", |
|
877 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); |
|
878 |
|
879 /* FIXME: shouldn't we convert this to g_return_val_if_fail? */ |
|
880 if (GST_PAD_PEER (srcpad) != NULL) { |
|
881 GST_CAT_INFO (GST_CAT_PADS, "Source pad %s:%s has a peer, failed", |
|
882 GST_DEBUG_PAD_NAME (srcpad)); |
|
883 return FALSE; |
|
884 } |
|
885 if (GST_PAD_PEER (sinkpad) != NULL) { |
|
886 GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has a peer, failed", |
|
887 GST_DEBUG_PAD_NAME (sinkpad)); |
|
888 return FALSE; |
|
889 } |
|
890 if (!GST_PAD_IS_SRC (srcpad)) { |
|
891 GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s is not source pad, failed", |
|
892 GST_DEBUG_PAD_NAME (srcpad)); |
|
893 return FALSE; |
|
894 } |
|
895 if (!GST_PAD_IS_SINK (sinkpad)) { |
|
896 GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s is not sink pad, failed", |
|
897 GST_DEBUG_PAD_NAME (sinkpad)); |
|
898 return FALSE; |
|
899 } |
|
900 if (GST_PAD_PARENT (srcpad) == NULL) { |
|
901 GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s has no parent, failed", |
|
902 GST_DEBUG_PAD_NAME (srcpad)); |
|
903 return FALSE; |
|
904 } |
|
905 if (GST_PAD_PARENT (sinkpad) == NULL) { |
|
906 GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has no parent, failed", |
|
907 GST_DEBUG_PAD_NAME (srcpad)); |
|
908 return FALSE; |
|
909 } |
|
910 |
|
911 return TRUE; |
|
912 } |
|
913 |
931 /** |
914 /** |
932 * gst_element_get_compatible_pad: |
915 * gst_element_get_compatible_pad: |
933 * @element: a #GstElement in which the pad should be found. |
916 * @element: a #GstElement in which the pad should be found. |
934 * @pad: the #GstPad to find a compatible one for. |
917 * @pad: the #GstPad to find a compatible one for. |
935 * @caps: the #GstCaps to use as a filter. |
918 * @caps: the #GstCaps to use as a filter. |
983 GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s", |
964 GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s", |
984 GST_DEBUG_PAD_NAME (current)); |
965 GST_DEBUG_PAD_NAME (current)); |
985 |
966 |
986 peer = gst_pad_get_peer (current); |
967 peer = gst_pad_get_peer (current); |
987 |
968 |
988 if (peer == NULL && gst_pad_can_link (pad, current)) { |
969 if (peer == NULL && gst_pad_check_link (pad, current)) { |
989 |
970 GstCaps *temp, *temp2, *intersection; |
|
971 |
|
972 /* Now check if the two pads' caps are compatible */ |
|
973 temp = gst_pad_get_caps (pad); |
|
974 if (caps) { |
|
975 intersection = gst_caps_intersect (temp, caps); |
|
976 gst_caps_unref (temp); |
|
977 } else { |
|
978 intersection = temp; |
|
979 } |
|
980 |
|
981 temp = gst_pad_get_caps (current); |
|
982 temp2 = gst_caps_intersect (temp, intersection); |
|
983 gst_caps_unref (temp); |
|
984 gst_caps_unref (intersection); |
|
985 |
|
986 intersection = temp2; |
|
987 |
|
988 if (!gst_caps_is_empty (intersection)) { |
|
989 gst_caps_unref (intersection); |
|
990 |
|
991 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, |
|
992 "found existing unlinked compatible pad %s:%s", |
|
993 GST_DEBUG_PAD_NAME (current)); |
|
994 gst_iterator_free (pads); |
|
995 |
|
996 return current; |
|
997 } else { |
|
998 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "incompatible pads"); |
|
999 } |
|
1000 gst_caps_unref (intersection); |
|
1001 } else { |
990 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, |
1002 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, |
991 "found existing unlinked pad %s:%s", |
1003 "already linked or cannot be linked (peer = %p)", peer); |
992 GST_DEBUG_PAD_NAME (current)); |
|
993 |
|
994 gst_iterator_free (pads); |
|
995 |
|
996 return current; |
|
997 } else { |
|
998 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads"); |
|
999 |
|
1000 gst_object_unref (current); |
|
1001 if (peer) |
|
1002 gst_object_unref (peer); |
|
1003 } |
1004 } |
|
1005 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads"); |
|
1006 |
|
1007 gst_object_unref (current); |
|
1008 if (peer) |
|
1009 gst_object_unref (peer); |
1004 break; |
1010 break; |
1005 } |
1011 } |
1006 case GST_ITERATOR_DONE: |
1012 case GST_ITERATOR_DONE: |
1007 done = TRUE; |
1013 done = TRUE; |
1008 break; |
1014 break; |
1839 void |
1856 void |
1840 gst_element_unlink_pads (GstElement * src, const gchar * srcpadname, |
1857 gst_element_unlink_pads (GstElement * src, const gchar * srcpadname, |
1841 GstElement * dest, const gchar * destpadname) |
1858 GstElement * dest, const gchar * destpadname) |
1842 { |
1859 { |
1843 GstPad *srcpad, *destpad; |
1860 GstPad *srcpad, *destpad; |
|
1861 gboolean srcrequest, destrequest; |
|
1862 |
|
1863 srcrequest = destrequest = FALSE; |
1844 |
1864 |
1845 g_return_if_fail (src != NULL); |
1865 g_return_if_fail (src != NULL); |
1846 g_return_if_fail (GST_IS_ELEMENT (src)); |
1866 g_return_if_fail (GST_IS_ELEMENT (src)); |
1847 g_return_if_fail (srcpadname != NULL); |
1867 g_return_if_fail (srcpadname != NULL); |
1848 g_return_if_fail (dest != NULL); |
1868 g_return_if_fail (dest != NULL); |
1849 g_return_if_fail (GST_IS_ELEMENT (dest)); |
1869 g_return_if_fail (GST_IS_ELEMENT (dest)); |
1850 g_return_if_fail (destpadname != NULL); |
1870 g_return_if_fail (destpadname != NULL); |
1851 |
1871 |
1852 /* obtain the pads requested */ |
1872 /* obtain the pads requested */ |
1853 srcpad = gst_element_get_pad (src, srcpadname); |
1873 if (!(srcpad = gst_element_get_static_pad (src, srcpadname))) |
|
1874 if ((srcpad = gst_element_get_request_pad (src, srcpadname))) |
|
1875 srcrequest = TRUE; |
1854 if (srcpad == NULL) { |
1876 if (srcpad == NULL) { |
1855 GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname); |
1877 GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname); |
1856 return; |
1878 return; |
1857 } |
1879 } |
1858 destpad = gst_element_get_pad (dest, destpadname); |
1880 if (!(destpad = gst_element_get_static_pad (dest, destpadname))) |
|
1881 if ((destpad = gst_element_get_request_pad (dest, destpadname))) |
|
1882 destrequest = TRUE; |
1859 if (destpad == NULL) { |
1883 if (destpad == NULL) { |
1860 GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"", |
1884 GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"", |
1861 destpadname); |
1885 destpadname); |
1862 gst_object_unref (srcpad); |
1886 goto free_src; |
1863 return; |
|
1864 } |
1887 } |
1865 |
1888 |
1866 /* we're satisified they can be unlinked, let's do it */ |
1889 /* we're satisified they can be unlinked, let's do it */ |
1867 gst_pad_unlink (srcpad, destpad); |
1890 gst_pad_unlink (srcpad, destpad); |
|
1891 |
|
1892 if (destrequest) |
|
1893 gst_element_release_request_pad (dest, destpad); |
|
1894 gst_object_unref (destpad); |
|
1895 |
|
1896 free_src: |
|
1897 if (srcrequest) |
|
1898 gst_element_release_request_pad (src, srcpad); |
1868 gst_object_unref (srcpad); |
1899 gst_object_unref (srcpad); |
1869 gst_object_unref (destpad); |
|
1870 } |
1900 } |
1871 |
1901 |
1872 /** |
1902 /** |
1873 * gst_element_unlink_many: |
1903 * gst_element_unlink_many: |
1874 * @element_1: the first #GstElement in the link chain. |
1904 * @element_1: the first #GstElement in the link chain. |
2133 return gst_element_seek (element, 1.0, format, seek_flags, |
2162 return gst_element_seek (element, 1.0, format, seek_flags, |
2134 GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_NONE, 0); |
2163 GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_NONE, 0); |
2135 } |
2164 } |
2136 |
2165 |
2137 /** |
2166 /** |
2138 * gst_pad_can_link: |
|
2139 * @srcpad: the source #GstPad to link. |
|
2140 * @sinkpad: the sink #GstPad to link. |
|
2141 * |
|
2142 * Checks if the source pad and the sink pad can be linked. |
|
2143 * Both @srcpad and @sinkpad must be unlinked. |
|
2144 * |
|
2145 * Returns: TRUE if the pads can be linked, FALSE otherwise. |
|
2146 */ |
|
2147 #ifdef __SYMBIAN32__ |
|
2148 EXPORT_C |
|
2149 #endif |
|
2150 |
|
2151 gboolean |
|
2152 gst_pad_can_link (GstPad * srcpad, GstPad * sinkpad) |
|
2153 { |
|
2154 /* FIXME This function is gross. It's almost a direct copy of |
|
2155 * gst_pad_link_filtered(). Any decent programmer would attempt |
|
2156 * to merge the two functions, which I will do some day. --ds |
|
2157 */ |
|
2158 |
|
2159 /* generic checks */ |
|
2160 g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE); |
|
2161 g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE); |
|
2162 |
|
2163 GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s", |
|
2164 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); |
|
2165 |
|
2166 /* FIXME: shouldn't we convert this to g_return_val_if_fail? */ |
|
2167 if (GST_PAD_PEER (srcpad) != NULL) { |
|
2168 GST_CAT_INFO (GST_CAT_PADS, "Source pad %s:%s has a peer, failed", |
|
2169 GST_DEBUG_PAD_NAME (srcpad)); |
|
2170 return FALSE; |
|
2171 } |
|
2172 if (GST_PAD_PEER (sinkpad) != NULL) { |
|
2173 GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has a peer, failed", |
|
2174 GST_DEBUG_PAD_NAME (sinkpad)); |
|
2175 return FALSE; |
|
2176 } |
|
2177 if (!GST_PAD_IS_SRC (srcpad)) { |
|
2178 GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s is not source pad, failed", |
|
2179 GST_DEBUG_PAD_NAME (srcpad)); |
|
2180 return FALSE; |
|
2181 } |
|
2182 if (!GST_PAD_IS_SINK (sinkpad)) { |
|
2183 GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s is not sink pad, failed", |
|
2184 GST_DEBUG_PAD_NAME (sinkpad)); |
|
2185 return FALSE; |
|
2186 } |
|
2187 if (GST_PAD_PARENT (srcpad) == NULL) { |
|
2188 GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s has no parent, failed", |
|
2189 GST_DEBUG_PAD_NAME (srcpad)); |
|
2190 return FALSE; |
|
2191 } |
|
2192 if (GST_PAD_PARENT (sinkpad) == NULL) { |
|
2193 GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has no parent, failed", |
|
2194 GST_DEBUG_PAD_NAME (srcpad)); |
|
2195 return FALSE; |
|
2196 } |
|
2197 |
|
2198 return TRUE; |
|
2199 } |
|
2200 |
|
2201 /** |
|
2202 * gst_pad_use_fixed_caps: |
2167 * gst_pad_use_fixed_caps: |
2203 * @pad: the pad to use |
2168 * @pad: the pad to use |
2204 * |
2169 * |
2205 * A helper function you can use that sets the |
2170 * A helper function you can use that sets the |
2206 * @gst_pad_get_fixed_caps_func as the getcaps function for the |
2171 * @gst_pad_get_fixed_caps_func as the getcaps function for the |
3074 #endif |
3043 #endif |
3075 |
3044 |
3076 gulong |
3045 gulong |
3077 gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data) |
3046 gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data) |
3078 { |
3047 { |
|
3048 return gst_pad_add_data_probe_full (pad, handler, data, NULL); |
|
3049 } |
|
3050 |
|
3051 /** |
|
3052 * gst_pad_add_data_probe_full: |
|
3053 * @pad: pad to add the data probe handler to |
|
3054 * @handler: function to call when data is passed over pad |
|
3055 * @data: data to pass along with the handler |
|
3056 * @notify: function to call when the probe is disconnected, or NULL |
|
3057 * |
|
3058 * Adds a "data probe" to a pad. This function will be called whenever data |
|
3059 * passes through a pad. In this case data means both events and buffers. The |
|
3060 * probe will be called with the data as an argument, meaning @handler should |
|
3061 * have the same callback signature as the #GstPad::have-data signal. |
|
3062 * Note that the data will have a reference count greater than 1, so it will |
|
3063 * be immutable -- you must not change it. |
|
3064 * |
|
3065 * For source pads, the probe will be called after the blocking function, if any |
|
3066 * (see gst_pad_set_blocked_async()), but before looking up the peer to chain |
|
3067 * to. For sink pads, the probe function will be called before configuring the |
|
3068 * sink with new caps, if any, and before calling the pad's chain function. |
|
3069 * |
|
3070 * Your data probe should return TRUE to let the data continue to flow, or FALSE |
|
3071 * to drop it. Dropping data is rarely useful, but occasionally comes in handy |
|
3072 * with events. |
|
3073 * |
|
3074 * Although probes are implemented internally by connecting @handler to the |
|
3075 * have-data signal on the pad, if you want to remove a probe it is insufficient |
|
3076 * to only call g_signal_handler_disconnect on the returned handler id. To |
|
3077 * remove a probe, use the appropriate function, such as |
|
3078 * gst_pad_remove_data_probe(). |
|
3079 * |
|
3080 * The @notify function is called when the probe is disconnected and usually |
|
3081 * used to free @data. |
|
3082 * |
|
3083 * Returns: The handler id. |
|
3084 * |
|
3085 * Since: 0.10.20 |
|
3086 */ |
|
3087 #ifdef __SYMBIAN32__ |
|
3088 EXPORT_C |
|
3089 #endif |
|
3090 |
|
3091 gulong |
|
3092 gst_pad_add_data_probe_full (GstPad * pad, GCallback handler, |
|
3093 gpointer data, GDestroyNotify notify) |
|
3094 { |
3079 gulong sigid; |
3095 gulong sigid; |
3080 |
3096 |
3081 g_return_val_if_fail (GST_IS_PAD (pad), 0); |
3097 g_return_val_if_fail (GST_IS_PAD (pad), 0); |
3082 g_return_val_if_fail (handler != NULL, 0); |
3098 g_return_val_if_fail (handler != NULL, 0); |
3083 |
3099 |
3084 GST_OBJECT_LOCK (pad); |
3100 GST_OBJECT_LOCK (pad); |
3085 sigid = g_signal_connect (pad, "have-data", handler, data); |
3101 |
|
3102 /* we only expose a GDestroyNotify in our API because that's less confusing */ |
|
3103 sigid = g_signal_connect_data (pad, "have-data", handler, data, |
|
3104 (GClosureNotify) notify, 0); |
|
3105 |
3086 GST_PAD_DO_EVENT_SIGNALS (pad)++; |
3106 GST_PAD_DO_EVENT_SIGNALS (pad)++; |
3087 GST_PAD_DO_BUFFER_SIGNALS (pad)++; |
3107 GST_PAD_DO_BUFFER_SIGNALS (pad)++; |
3088 GST_DEBUG ("adding data probe to pad %s:%s, now %d data, %d event probes", |
3108 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, |
3089 GST_DEBUG_PAD_NAME (pad), |
3109 "adding data probe, now %d data, %d event probes", |
3090 GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad)); |
3110 GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad)); |
3091 GST_OBJECT_UNLOCK (pad); |
3111 GST_OBJECT_UNLOCK (pad); |
3092 |
3112 |
3093 return sigid; |
3113 return sigid; |
3094 } |
3114 } |
3109 #endif |
3129 #endif |
3110 |
3130 |
3111 gulong |
3131 gulong |
3112 gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data) |
3132 gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data) |
3113 { |
3133 { |
|
3134 return gst_pad_add_event_probe_full (pad, handler, data, NULL); |
|
3135 } |
|
3136 |
|
3137 /** |
|
3138 * gst_pad_add_event_probe_full: |
|
3139 * @pad: pad to add the event probe handler to |
|
3140 * @handler: function to call when events are passed over pad |
|
3141 * @data: data to pass along with the handler, or NULL |
|
3142 * @notify: function to call when probe is disconnected, or NULL |
|
3143 * |
|
3144 * Adds a probe that will be called for all events passing through a pad. See |
|
3145 * gst_pad_add_data_probe() for more information. |
|
3146 * |
|
3147 * The @notify function is called when the probe is disconnected and usually |
|
3148 * used to free @data. |
|
3149 * |
|
3150 * Returns: The handler id |
|
3151 * |
|
3152 * Since: 0.10.20 |
|
3153 */ |
|
3154 #ifdef __SYMBIAN32__ |
|
3155 EXPORT_C |
|
3156 #endif |
|
3157 |
|
3158 gulong |
|
3159 gst_pad_add_event_probe_full (GstPad * pad, GCallback handler, |
|
3160 gpointer data, GDestroyNotify notify) |
|
3161 { |
3114 gulong sigid; |
3162 gulong sigid; |
3115 |
3163 |
3116 g_return_val_if_fail (GST_IS_PAD (pad), 0); |
3164 g_return_val_if_fail (GST_IS_PAD (pad), 0); |
3117 g_return_val_if_fail (handler != NULL, 0); |
3165 g_return_val_if_fail (handler != NULL, 0); |
3118 |
3166 |
3119 GST_OBJECT_LOCK (pad); |
3167 GST_OBJECT_LOCK (pad); |
3120 sigid = g_signal_connect (pad, "have-data::event", handler, data); |
3168 |
|
3169 /* we only expose a GDestroyNotify in our API because that's less confusing */ |
|
3170 sigid = g_signal_connect_data (pad, "have-data::event", handler, data, |
|
3171 (GClosureNotify) notify, 0); |
|
3172 |
3121 GST_PAD_DO_EVENT_SIGNALS (pad)++; |
3173 GST_PAD_DO_EVENT_SIGNALS (pad)++; |
3122 GST_DEBUG ("adding event probe to pad %s:%s, now %d probes", |
3174 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding event probe, now %d probes", |
3123 GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad)); |
3175 GST_PAD_DO_EVENT_SIGNALS (pad)); |
3124 GST_OBJECT_UNLOCK (pad); |
3176 GST_OBJECT_UNLOCK (pad); |
3125 |
3177 |
3126 return sigid; |
3178 return sigid; |
3127 } |
3179 } |
3128 |
3180 |
3142 #endif |
3194 #endif |
3143 |
3195 |
3144 gulong |
3196 gulong |
3145 gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data) |
3197 gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data) |
3146 { |
3198 { |
|
3199 return gst_pad_add_buffer_probe_full (pad, handler, data, NULL); |
|
3200 } |
|
3201 |
|
3202 /** |
|
3203 * gst_pad_add_buffer_probe_full: |
|
3204 * @pad: pad to add the buffer probe handler to |
|
3205 * @handler: function to call when buffer are passed over pad |
|
3206 * @data: data to pass along with the handler |
|
3207 * @notify: function to call when the probe is disconnected, or NULL |
|
3208 * |
|
3209 * Adds a probe that will be called for all buffers passing through a pad. See |
|
3210 * gst_pad_add_data_probe() for more information. |
|
3211 * |
|
3212 * The @notify function is called when the probe is disconnected and usually |
|
3213 * used to free @data. |
|
3214 * |
|
3215 * Returns: The handler id |
|
3216 * |
|
3217 * Since: 0.10.20 |
|
3218 */ |
|
3219 #ifdef __SYMBIAN32__ |
|
3220 EXPORT_C |
|
3221 #endif |
|
3222 |
|
3223 gulong |
|
3224 gst_pad_add_buffer_probe_full (GstPad * pad, GCallback handler, |
|
3225 gpointer data, GDestroyNotify notify) |
|
3226 { |
3147 gulong sigid; |
3227 gulong sigid; |
3148 |
3228 |
3149 g_return_val_if_fail (GST_IS_PAD (pad), 0); |
3229 g_return_val_if_fail (GST_IS_PAD (pad), 0); |
3150 g_return_val_if_fail (handler != NULL, 0); |
3230 g_return_val_if_fail (handler != NULL, 0); |
3151 |
3231 |
3152 GST_OBJECT_LOCK (pad); |
3232 GST_OBJECT_LOCK (pad); |
3153 sigid = g_signal_connect (pad, "have-data::buffer", handler, data); |
3233 |
|
3234 /* we only expose a GDestroyNotify in our API because that's less confusing */ |
|
3235 sigid = g_signal_connect_data (pad, "have-data::buffer", handler, data, |
|
3236 (GClosureNotify) notify, 0); |
|
3237 |
3154 GST_PAD_DO_BUFFER_SIGNALS (pad)++; |
3238 GST_PAD_DO_BUFFER_SIGNALS (pad)++; |
3155 GST_DEBUG ("adding buffer probe to pad %s:%s, now %d probes", |
3239 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding buffer probe, now %d probes", |
3156 GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad)); |
3240 GST_PAD_DO_BUFFER_SIGNALS (pad)); |
3157 GST_OBJECT_UNLOCK (pad); |
3241 GST_OBJECT_UNLOCK (pad); |
3158 |
3242 |
3159 return sigid; |
3243 return sigid; |
3160 } |
3244 } |
3161 |
3245 |
3426 |
3512 |
3427 return pad; |
3513 return pad; |
3428 } |
3514 } |
3429 |
3515 |
3430 /** |
3516 /** |
|
3517 * gst_bin_find_unconnected_pad: |
|
3518 * @bin: bin in which to look for elements with unlinked pads |
|
3519 * @direction: whether to look for an unlinked source or sink pad |
|
3520 * |
|
3521 * Recursively looks for elements with an unlinked pad of the given |
|
3522 * direction within the specified bin and returns an unlinked pad |
|
3523 * if one is found, or NULL otherwise. If a pad is found, the caller |
|
3524 * owns a reference to it and should use gst_object_unref() on the |
|
3525 * pad when it is not needed any longer. |
|
3526 * |
|
3527 * Returns: unlinked pad of the given direction, or NULL. |
|
3528 * |
|
3529 * Since: 0.10.3 |
|
3530 * |
|
3531 * Deprecated: use gst_bin_find_unlinked_pad() instead. |
|
3532 */ |
|
3533 #ifndef GST_REMOVE_DEPRECATED |
|
3534 |
|
3535 #ifdef __SYMBIAN32__ |
|
3536 EXPORT_C |
|
3537 #endif |
|
3538 GstPad * |
|
3539 gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction) |
|
3540 { |
|
3541 return gst_bin_find_unlinked_pad (bin, direction); |
|
3542 } |
|
3543 #endif |
|
3544 |
|
3545 /** |
3431 * gst_parse_bin_from_description: |
3546 * gst_parse_bin_from_description: |
3432 * @bin_description: command line describing the bin |
3547 * @bin_description: command line describing the bin |
3433 * @ghost_unconnected_pads: whether to automatically create ghost pads |
3548 * @ghost_unlinked_pads: whether to automatically create ghost pads |
3434 * for unconnected source or sink pads within |
3549 * for unlinked source or sink pads within the bin |
3435 * the bin |
|
3436 * @err: where to store the error message in case of an error, or NULL |
3550 * @err: where to store the error message in case of an error, or NULL |
3437 * |
3551 * |
3438 * This is a convenience wrapper around gst_parse_launch() to create a |
3552 * This is a convenience wrapper around gst_parse_launch() to create a |
3439 * #GstBin from a gst-launch-style pipeline description. See |
3553 * #GstBin from a gst-launch-style pipeline description. See |
3440 * gst_parse_launch() and the gst-launch man page for details about the |
3554 * gst_parse_launch() and the gst-launch man page for details about the |
3441 * syntax. Ghost pads on the bin for unconnected source or sink pads |
3555 * syntax. Ghost pads on the bin for unlinked source or sink pads |
3442 * within the bin can automatically be created (but only a maximum of |
3556 * within the bin can automatically be created (but only a maximum of |
3443 * one ghost pad for each direction will be created; if you expect |
3557 * one ghost pad for each direction will be created; if you expect |
3444 * multiple unconnected source pads or multiple unconnected sink pads |
3558 * multiple unlinked source pads or multiple unlinked sink pads |
3445 * and want them all ghosted, you will have to create the ghost pads |
3559 * and want them all ghosted, you will have to create the ghost pads |
3446 * yourself). |
3560 * yourself). |
3447 * |
3561 * |
3448 * Returns: a newly-created bin, or NULL if an error occurred. |
3562 * Returns: a newly-created bin, or NULL if an error occurred. |
3449 * |
3563 * |
3453 EXPORT_C |
3567 EXPORT_C |
3454 #endif |
3568 #endif |
3455 |
3569 |
3456 GstElement * |
3570 GstElement * |
3457 gst_parse_bin_from_description (const gchar * bin_description, |
3571 gst_parse_bin_from_description (const gchar * bin_description, |
3458 gboolean ghost_unconnected_pads, GError ** err) |
3572 gboolean ghost_unlinked_pads, GError ** err) |
|
3573 { |
|
3574 return gst_parse_bin_from_description_full (bin_description, |
|
3575 ghost_unlinked_pads, NULL, 0, err); |
|
3576 } |
|
3577 |
|
3578 /** |
|
3579 * gst_parse_bin_from_description_full: |
|
3580 * @bin_description: command line describing the bin |
|
3581 * @ghost_unlinked_pads: whether to automatically create ghost pads |
|
3582 * for unlinked source or sink pads within the bin |
|
3583 * @context: a parse context allocated with gst_parse_context_new(), or %NULL |
|
3584 * @flags: parsing options, or #GST_PARSE_FLAG_NONE |
|
3585 * @err: where to store the error message in case of an error, or NULL |
|
3586 * |
|
3587 * This is a convenience wrapper around gst_parse_launch() to create a |
|
3588 * #GstBin from a gst-launch-style pipeline description. See |
|
3589 * gst_parse_launch() and the gst-launch man page for details about the |
|
3590 * syntax. Ghost pads on the bin for unlinked source or sink pads |
|
3591 * within the bin can automatically be created (but only a maximum of |
|
3592 * one ghost pad for each direction will be created; if you expect |
|
3593 * multiple unlinked source pads or multiple unlinked sink pads |
|
3594 * and want them all ghosted, you will have to create the ghost pads |
|
3595 * yourself). |
|
3596 * |
|
3597 * Returns: a newly-created bin, or NULL if an error occurred. |
|
3598 * |
|
3599 * Since: 0.10.20 |
|
3600 */ |
|
3601 #ifdef __SYMBIAN32__ |
|
3602 EXPORT_C |
|
3603 #endif |
|
3604 |
|
3605 GstElement * |
|
3606 gst_parse_bin_from_description_full (const gchar * bin_description, |
|
3607 gboolean ghost_unlinked_pads, GstParseContext * context, |
|
3608 GstParseFlags flags, GError ** err) |
3459 { |
3609 { |
3460 #ifndef GST_DISABLE_PARSE |
3610 #ifndef GST_DISABLE_PARSE |
3461 GstPad *pad = NULL; |
3611 GstPad *pad = NULL; |
3462 GstBin *bin; |
3612 GstBin *bin; |
3463 gchar *desc; |
3613 gchar *desc; |
3467 |
3617 |
3468 GST_DEBUG ("Making bin from description '%s'", bin_description); |
3618 GST_DEBUG ("Making bin from description '%s'", bin_description); |
3469 |
3619 |
3470 /* parse the pipeline to a bin */ |
3620 /* parse the pipeline to a bin */ |
3471 desc = g_strdup_printf ("bin.( %s )", bin_description); |
3621 desc = g_strdup_printf ("bin.( %s )", bin_description); |
3472 bin = (GstBin *) gst_parse_launch (desc, err); |
3622 bin = (GstBin *) gst_parse_launch_full (desc, context, flags, err); |
3473 g_free (desc); |
3623 g_free (desc); |
3474 |
3624 |
3475 if (bin == NULL || (err && *err != NULL)) { |
3625 if (bin == NULL || (err && *err != NULL)) { |
3476 if (bin) |
3626 if (bin) |
3477 gst_object_unref (bin); |
3627 gst_object_unref (bin); |
3478 return NULL; |
3628 return NULL; |
3479 } |
3629 } |
3480 |
3630 |
3481 /* find pads and ghost them if necessary */ |
3631 /* find pads and ghost them if necessary */ |
3482 if (ghost_unconnected_pads) { |
3632 if (ghost_unlinked_pads) { |
3483 if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SRC))) { |
3633 if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC))) { |
3484 gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad)); |
3634 gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad)); |
3485 gst_object_unref (pad); |
3635 gst_object_unref (pad); |
3486 } |
3636 } |
3487 if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SINK))) { |
3637 if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SINK))) { |
3488 gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad)); |
3638 gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad)); |
3489 gst_object_unref (pad); |
3639 gst_object_unref (pad); |
3490 } |
3640 } |
3491 } |
3641 } |
3492 |
3642 |
3493 return GST_ELEMENT (bin); |
3643 return GST_ELEMENT (bin); |
3494 #else |
3644 #else |
3495 gchar *msg; |
3645 gchar *msg; |
3496 |
3646 |
3497 GST_WARNING ("Disabled API called: gst_parse_bin_from_description()"); |
3647 GST_WARNING ("Disabled API called"); |
3498 |
3648 |
3499 msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED); |
3649 msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED); |
3500 g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg); |
3650 g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg); |
3501 g_free (msg); |
3651 g_free (msg); |
3502 |
3652 |
3605 |
3755 |
3606 g_get_current_time (&now); |
3756 g_get_current_time (&now); |
3607 return GST_TIMEVAL_TO_TIME (now); |
3757 return GST_TIMEVAL_TO_TIME (now); |
3608 #endif |
3758 #endif |
3609 } |
3759 } |
|
3760 |
|
3761 /** |
|
3762 * gst_util_array_binary_search: |
|
3763 * @array: the sorted input array |
|
3764 * @num_elements: number of elements in the array |
|
3765 * @element_size: size of every element in bytes |
|
3766 * @search_func: function to compare two elements, @search_data will always be passed as second argument |
|
3767 * @mode: search mode that should be used |
|
3768 * @search_data: element that should be found |
|
3769 * @user_data: data to pass to @search_func |
|
3770 * |
|
3771 * Searches inside @array for @search_data by using the comparison function |
|
3772 * @search_func. @array must be sorted ascending. |
|
3773 * |
|
3774 * As @search_data is always passed as second argument to @search_func it's |
|
3775 * not required that @search_data has the same type as the array elements. |
|
3776 * |
|
3777 * The complexity of this search function is O(log (num_elements)). |
|
3778 * |
|
3779 * Returns: The address of the found element or %NULL if nothing was found |
|
3780 * |
|
3781 * Since: 0.10.23 |
|
3782 */ |
|
3783 #ifdef __SYMBIAN32__ |
|
3784 EXPORT_C |
|
3785 #endif |
|
3786 |
|
3787 gpointer |
|
3788 gst_util_array_binary_search (gpointer array, guint num_elements, |
|
3789 gsize element_size, GCompareDataFunc search_func, GstSearchMode mode, |
|
3790 gconstpointer search_data, gpointer user_data) |
|
3791 { |
|
3792 glong left = 0, right = num_elements - 1, m; |
|
3793 gint ret; |
|
3794 guint8 *data = (guint8 *) array; |
|
3795 |
|
3796 g_return_val_if_fail (array != NULL, NULL); |
|
3797 g_return_val_if_fail (element_size > 0, NULL); |
|
3798 g_return_val_if_fail (search_func != NULL, NULL); |
|
3799 |
|
3800 /* 0. No elements => return NULL */ |
|
3801 if (num_elements == 0) |
|
3802 return NULL; |
|
3803 |
|
3804 /* 1. If search_data is before the 0th element return the 0th element */ |
|
3805 ret = search_func (data, search_data, user_data); |
|
3806 if ((ret >= 0 && mode == GST_SEARCH_MODE_AFTER) || ret == 0) |
|
3807 return data; |
|
3808 else if (ret > 0) |
|
3809 return NULL; |
|
3810 |
|
3811 /* 2. If search_data is after the last element return the last element */ |
|
3812 ret = |
|
3813 search_func (data + (num_elements - 1) * element_size, search_data, |
|
3814 user_data); |
|
3815 if ((ret <= 0 && mode == GST_SEARCH_MODE_BEFORE) || ret == 0) |
|
3816 return data + (num_elements - 1) * element_size; |
|
3817 else if (ret < 0) |
|
3818 return NULL; |
|
3819 |
|
3820 /* 3. else binary search */ |
|
3821 while (TRUE) { |
|
3822 m = left + (right - left) / 2; |
|
3823 |
|
3824 ret = search_func (data + m * element_size, search_data, user_data); |
|
3825 |
|
3826 if (ret == 0) { |
|
3827 return data + m * element_size; |
|
3828 } else if (ret < 0) { |
|
3829 left = m + 1; |
|
3830 } else { |
|
3831 right = m - 1; |
|
3832 } |
|
3833 |
|
3834 /* No exact match found */ |
|
3835 if (right < left) { |
|
3836 if (mode == GST_SEARCH_MODE_EXACT) { |
|
3837 return NULL; |
|
3838 } else if (mode == GST_SEARCH_MODE_AFTER) { |
|
3839 if (ret < 0) |
|
3840 return (m < num_elements) ? data + (m + 1) * element_size : NULL; |
|
3841 else |
|
3842 return data + m * element_size; |
|
3843 } else { |
|
3844 if (ret < 0) |
|
3845 return data + m * element_size; |
|
3846 else |
|
3847 return (m > 0) ? data + (m - 1) * element_size : NULL; |
|
3848 } |
|
3849 } |
|
3850 } |
|
3851 } |