101 * @value: the value to set |
93 * @value: the value to set |
102 * @value_str: the string to get the value from |
94 * @value_str: the string to get the value from |
103 * |
95 * |
104 * Converts the string to the type of the value and |
96 * Converts the string to the type of the value and |
105 * sets the value with it. |
97 * 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. |
|
109 */ |
98 */ |
110 #ifdef __SYMBIAN32__ |
99 #ifdef __SYMBIAN32__ |
111 EXPORT_C |
100 EXPORT_C |
112 #endif |
101 #endif |
113 |
102 |
114 void |
103 void |
115 gst_util_set_value_from_string (GValue * value, const gchar * value_str) |
104 gst_util_set_value_from_string (GValue * value, const gchar * value_str) |
116 { |
105 { |
117 gboolean res; |
106 gint sscanf_ret; |
118 |
107 |
119 g_return_if_fail (value != NULL); |
108 g_return_if_fail (value != NULL); |
120 g_return_if_fail (value_str != NULL); |
109 g_return_if_fail (value_str != NULL); |
121 |
110 |
122 GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str, |
111 GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str, |
123 g_type_name (G_VALUE_TYPE (value))); |
112 g_type_name (G_VALUE_TYPE (value))); |
124 |
113 |
125 res = gst_value_deserialize (value, value_str); |
114 switch (G_VALUE_TYPE (value)) { |
126 if (!res && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) { |
115 case G_TYPE_STRING: |
127 /* backwards compat, all booleans that fail to parse are false */ |
116 g_value_set_string (value, value_str); |
128 g_value_set_boolean (value, FALSE); |
117 break; |
129 res = TRUE; |
118 case G_TYPE_ENUM: |
130 } |
119 case G_TYPE_INT:{ |
131 g_return_if_fail (res); |
120 gint i; |
|
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 } |
132 } |
194 } |
133 |
195 |
134 /** |
196 /** |
135 * gst_util_set_object_arg: |
197 * gst_util_set_object_arg: |
136 * @object: the object to set the argument of |
198 * @object: the object to set the argument of |
137 * @name: the name of the argument to set |
199 * @name: the name of the argument to set |
138 * @value: the string value to set |
200 * @value: the string value to set |
139 * |
201 * |
140 * Convertes the string value to the type of the objects argument and |
202 * Convertes the string value to the type of the objects argument and |
141 * sets the argument with it. |
203 * 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. |
|
145 */ |
204 */ |
146 #ifdef __SYMBIAN32__ |
205 #ifdef __SYMBIAN32__ |
147 EXPORT_C |
206 EXPORT_C |
148 #endif |
207 #endif |
149 |
208 |
150 void |
209 void |
151 gst_util_set_object_arg (GObject * object, const gchar * name, |
210 gst_util_set_object_arg (GObject * object, const gchar * name, |
152 const gchar * value) |
211 const gchar * value) |
153 { |
212 { |
154 GParamSpec *pspec; |
213 gboolean sscanf_ret; |
155 GType value_type; |
214 |
156 GValue v = { 0, }; |
215 if (name && value) { |
157 |
216 GParamSpec *paramspec; |
158 g_return_if_fail (G_IS_OBJECT (object)); |
217 |
159 g_return_if_fail (name != NULL); |
218 paramspec = |
160 g_return_if_fail (value != NULL); |
219 g_object_class_find_property (G_OBJECT_GET_CLASS (object), name); |
161 |
220 |
162 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name); |
221 if (!paramspec) { |
163 if (!pspec) |
222 return; |
164 return; |
223 } |
165 |
224 |
166 value_type = G_PARAM_SPEC_VALUE_TYPE (pspec); |
225 GST_DEBUG ("paramspec->flags is %d, paramspec->value_type is %d", |
167 |
226 paramspec->flags, (gint) paramspec->value_type); |
168 GST_DEBUG ("pspec->flags is %d, pspec->value_type is %s", |
227 |
169 pspec->flags, g_type_name (value_type)); |
228 if (paramspec->flags & G_PARAM_WRITABLE) { |
170 |
229 switch (paramspec->value_type) { |
171 if (!(pspec->flags & G_PARAM_WRITABLE)) |
230 case G_TYPE_STRING: |
172 return; |
231 g_object_set (G_OBJECT (object), name, value, NULL); |
173 |
232 break; |
174 g_value_init (&v, value_type); |
233 case G_TYPE_ENUM: |
175 |
234 case G_TYPE_INT:{ |
176 /* special case for element <-> xml (de)serialisation */ |
235 gint i; |
177 if (GST_VALUE_HOLDS_STRUCTURE (&v) && strcmp (value, "NULL") == 0) { |
236 |
178 g_value_set_boxed (&v, NULL); |
237 sscanf_ret = sscanf (value, "%d", &i); |
179 goto done; |
238 g_return_if_fail (sscanf_ret == 1); |
180 } |
239 g_object_set (G_OBJECT (object), name, i, NULL); |
181 |
240 break; |
182 if (!gst_value_deserialize (&v, value)) |
241 } |
183 return; |
242 case G_TYPE_UINT:{ |
184 |
243 guint i; |
185 done: |
244 |
186 |
245 sscanf_ret = sscanf (value, "%u", &i); |
187 g_object_set_property (object, pspec->name, &v); |
246 g_return_if_fail (sscanf_ret == 1); |
188 g_value_unset (&v); |
247 g_object_set (G_OBJECT (object), name, i, NULL); |
|
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 } |
189 } |
318 } |
190 |
319 |
191 /* work around error C2520: conversion from unsigned __int64 to double |
320 /* work around error C2520: conversion from unsigned __int64 to double |
192 * not implemented, use signed __int64 |
321 * not implemented, use signed __int64 |
193 * |
322 * |
366 { |
495 { |
367 return G_MAXUINT64; |
496 return G_MAXUINT64; |
368 } |
497 } |
369 } |
498 } |
370 |
499 |
371 static inline guint64 |
500 /** |
372 gst_util_uint64_scale_int_unchecked (guint64 val, gint num, gint denom) |
501 * gst_util_uint64_scale: |
|
502 * @val: the number to scale |
|
503 * @num: the numerator of the scale ratio |
|
504 * @denom: the denominator of the scale ratio |
|
505 * |
|
506 * Scale @val by @num / @denom, trying to avoid overflows. |
|
507 * |
|
508 * This function can potentially be very slow if denom > G_MAXUINT32. |
|
509 * |
|
510 * Returns: @val * @num / @denom, trying to avoid overflows. |
|
511 * In the case of an overflow, this function returns G_MAXUINT64. |
|
512 */ |
|
513 #ifdef __SYMBIAN32__ |
|
514 EXPORT_C |
|
515 #endif |
|
516 |
|
517 guint64 |
|
518 gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom) |
|
519 { |
|
520 g_return_val_if_fail (denom != 0, G_MAXUINT64); |
|
521 |
|
522 if (num == 0) |
|
523 return 0; |
|
524 |
|
525 if (num == 1 && denom == 1) |
|
526 return val; |
|
527 |
|
528 /* if the denom is high, we need to do a 64 muldiv */ |
|
529 if (denom > G_MAXINT32) |
|
530 goto do_int64; |
|
531 |
|
532 /* if num and denom are low we can do a 32 bit muldiv */ |
|
533 if (num <= G_MAXINT32) |
|
534 goto do_int32; |
|
535 |
|
536 /* val and num are high, we need 64 muldiv */ |
|
537 if (val > G_MAXINT32) |
|
538 goto do_int64; |
|
539 |
|
540 /* 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); |
|
542 |
|
543 do_int32: |
|
544 return gst_util_uint64_scale_int (val, (gint) num, (gint) denom); |
|
545 |
|
546 do_int64: |
|
547 /* to the more heavy implementations... */ |
|
548 return gst_util_uint64_scale_int64 (val, num, denom); |
|
549 } |
|
550 |
|
551 /** |
|
552 * gst_util_uint64_scale_int: |
|
553 * @val: guint64 (such as a #GstClockTime) to scale. |
|
554 * @num: numerator of the scale factor. |
|
555 * @denom: denominator of the scale factor. |
|
556 * |
|
557 * Scale a guint64 by a factor expressed as a fraction (num/denom), avoiding |
|
558 * overflows and loss of precision. |
|
559 * |
|
560 * @num and @denom must be positive integers. @denom cannot be 0. |
|
561 * |
|
562 * Returns: @val * @num / @denom, avoiding overflow and loss of precision. |
|
563 * In the case of an overflow, this function returns G_MAXUINT64. |
|
564 */ |
|
565 #ifdef __SYMBIAN32__ |
|
566 EXPORT_C |
|
567 #endif |
|
568 |
|
569 guint64 |
|
570 gst_util_uint64_scale_int (guint64 val, gint num, gint denom) |
373 { |
571 { |
374 GstUInt64 result; |
572 GstUInt64 result; |
375 GstUInt64 low, high; |
573 GstUInt64 low, high; |
|
574 |
|
575 g_return_val_if_fail (denom > 0, G_MAXUINT64); |
|
576 g_return_val_if_fail (num >= 0, G_MAXUINT64); |
|
577 |
|
578 if (num == 0) |
|
579 return 0; |
|
580 |
|
581 if (num == 1 && denom == 1) |
|
582 return val; |
|
583 |
|
584 if (val <= G_MAXUINT32) |
|
585 /* simple case */ |
|
586 return val * num / denom; |
376 |
587 |
377 /* do 96 bits mult/div */ |
588 /* do 96 bits mult/div */ |
378 low.ll = val; |
589 low.ll = val; |
379 result.ll = ((guint64) low.l.low) * num; |
590 result.ll = ((guint64) low.l.low) * num; |
380 high.ll = ((guint64) low.l.high) * num + (result.l.high); |
591 high.ll = ((guint64) low.l.high) * num + (result.l.high); |
382 low.ll = high.ll / denom; |
593 low.ll = high.ll / denom; |
383 result.l.high = high.ll % denom; |
594 result.l.high = high.ll % denom; |
384 result.ll /= denom; |
595 result.ll /= denom; |
385 |
596 |
386 /* avoid overflow */ |
597 /* avoid overflow */ |
387 if (G_UNLIKELY (low.ll + result.l.high > G_MAXUINT32)) |
598 if (low.ll + result.l.high > G_MAXUINT32) |
388 goto overflow; |
599 goto overflow; |
389 |
600 |
390 result.l.high += low.l.low; |
601 result.l.high += low.l.low; |
391 |
602 |
392 return result.ll; |
603 return result.ll; |
393 |
604 |
394 overflow: |
605 overflow: |
395 { |
606 { |
396 return G_MAXUINT64; |
607 return G_MAXUINT64; |
397 } |
608 } |
398 } |
|
399 |
|
400 |
|
401 /** |
|
402 * gst_util_uint64_scale: |
|
403 * @val: the number to scale |
|
404 * @num: the numerator of the scale ratio |
|
405 * @denom: the denominator of the scale ratio |
|
406 * |
|
407 * Scale @val by @num / @denom, trying to avoid overflows. |
|
408 * |
|
409 * This function can potentially be very slow if denom > G_MAXUINT32. |
|
410 * |
|
411 * Returns: @val * @num / @denom, trying to avoid overflows. |
|
412 * In the case of an overflow, this function returns G_MAXUINT64. |
|
413 */ |
|
414 #ifdef __SYMBIAN32__ |
|
415 EXPORT_C |
|
416 #endif |
|
417 |
|
418 guint64 |
|
419 gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom) |
|
420 { |
|
421 g_return_val_if_fail (denom != 0, G_MAXUINT64); |
|
422 |
|
423 if (G_UNLIKELY (num == 0)) |
|
424 return 0; |
|
425 |
|
426 if (G_UNLIKELY (num == denom)) |
|
427 return val; |
|
428 |
|
429 /* if the denom is high, we need to do a 64 muldiv */ |
|
430 if (G_UNLIKELY (denom > G_MAXINT32)) |
|
431 goto do_int64; |
|
432 |
|
433 /* if num and denom are low we can do a 32 bit muldiv */ |
|
434 if (G_LIKELY (num <= G_MAXINT32)) |
|
435 goto do_int32; |
|
436 |
|
437 /* val and num are high, we need 64 muldiv */ |
|
438 if (G_UNLIKELY (val > G_MAXINT32)) |
|
439 goto do_int64; |
|
440 |
|
441 /* val is low and num is high, we can swap them and do 32 muldiv */ |
|
442 return gst_util_uint64_scale_int_unchecked (num, (gint) val, (gint) denom); |
|
443 |
|
444 do_int32: |
|
445 return gst_util_uint64_scale_int_unchecked (val, (gint) num, (gint) denom); |
|
446 |
|
447 do_int64: |
|
448 /* to the more heavy implementations... */ |
|
449 return gst_util_uint64_scale_int64_unchecked (val, num, denom); |
|
450 } |
|
451 |
|
452 /** |
|
453 * gst_util_uint64_scale_int: |
|
454 * @val: guint64 (such as a #GstClockTime) to scale. |
|
455 * @num: numerator of the scale factor. |
|
456 * @denom: denominator of the scale factor. |
|
457 * |
|
458 * Scale a guint64 by a factor expressed as a fraction (num/denom), avoiding |
|
459 * overflows and loss of precision. |
|
460 * |
|
461 * @num and @denom must be positive integers. @denom cannot be 0. |
|
462 * |
|
463 * Returns: @val * @num / @denom, avoiding overflow and loss of precision. |
|
464 * In the case of an overflow, this function returns G_MAXUINT64. |
|
465 */ |
|
466 #ifdef __SYMBIAN32__ |
|
467 EXPORT_C |
|
468 #endif |
|
469 |
|
470 guint64 |
|
471 gst_util_uint64_scale_int (guint64 val, gint num, gint denom) |
|
472 { |
|
473 g_return_val_if_fail (denom > 0, G_MAXUINT64); |
|
474 g_return_val_if_fail (num >= 0, G_MAXUINT64); |
|
475 |
|
476 if (G_UNLIKELY (num == 0)) |
|
477 return 0; |
|
478 |
|
479 if (G_UNLIKELY (num == denom)) |
|
480 return val; |
|
481 |
|
482 if (val <= G_MAXUINT32) |
|
483 /* simple case */ |
|
484 return val * num / denom; |
|
485 |
|
486 return gst_util_uint64_scale_int_unchecked (val, num, denom); |
|
487 } |
|
488 |
|
489 /** |
|
490 * gst_util_seqnum_next: |
|
491 * |
|
492 * Return a constantly incrementing sequence number. |
|
493 * |
|
494 * This function is used internally to GStreamer to be able to determine which |
|
495 * events and messages are "the same". For example, elements may set the seqnum |
|
496 * on a segment-done message to be the same as that of the last seek event, to |
|
497 * indicate that event and the message correspond to the same segment. |
|
498 * |
|
499 * Returns: A constantly incrementing 32-bit unsigned integer, which might |
|
500 * overflow back to 0 at some point. Use gst_util_seqnum_compare() to make sure |
|
501 * you handle wraparound correctly. |
|
502 * |
|
503 * Since: 0.10.22 |
|
504 */ |
|
505 #ifdef __SYMBIAN32__ |
|
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); |
|
538 } |
609 } |
539 |
610 |
540 /* ----------------------------------------------------- |
611 /* ----------------------------------------------------- |
541 * |
612 * |
542 * The following code will be moved out of the main |
613 * The following code will be moved out of the main |
855 pad = NULL; |
926 pad = NULL; |
856 |
927 |
857 return pad; |
928 return pad; |
858 } |
929 } |
859 |
930 |
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 |
|
914 /** |
931 /** |
915 * gst_element_get_compatible_pad: |
932 * gst_element_get_compatible_pad: |
916 * @element: a #GstElement in which the pad should be found. |
933 * @element: a #GstElement in which the pad should be found. |
917 * @pad: the #GstPad to find a compatible one for. |
934 * @pad: the #GstPad to find a compatible one for. |
918 * @caps: the #GstCaps to use as a filter. |
935 * @caps: the #GstCaps to use as a filter. |
964 GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s", |
983 GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s", |
965 GST_DEBUG_PAD_NAME (current)); |
984 GST_DEBUG_PAD_NAME (current)); |
966 |
985 |
967 peer = gst_pad_get_peer (current); |
986 peer = gst_pad_get_peer (current); |
968 |
987 |
969 if (peer == NULL && gst_pad_check_link (pad, current)) { |
988 if (peer == NULL && gst_pad_can_link (pad, current)) { |
970 GstCaps *temp, *temp2, *intersection; |
989 |
971 |
990 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, |
972 /* Now check if the two pads' caps are compatible */ |
991 "found existing unlinked pad %s:%s", |
973 temp = gst_pad_get_caps (pad); |
992 GST_DEBUG_PAD_NAME (current)); |
974 if (caps) { |
993 |
975 intersection = gst_caps_intersect (temp, caps); |
994 gst_iterator_free (pads); |
976 gst_caps_unref (temp); |
995 |
977 } else { |
996 return current; |
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 { |
997 } else { |
1002 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, |
998 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads"); |
1003 "already linked or cannot be linked (peer = %p)", peer); |
999 |
|
1000 gst_object_unref (current); |
|
1001 if (peer) |
|
1002 gst_object_unref (peer); |
1004 } |
1003 } |
1005 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads"); |
|
1006 |
|
1007 gst_object_unref (current); |
|
1008 if (peer) |
|
1009 gst_object_unref (peer); |
|
1010 break; |
1004 break; |
1011 } |
1005 } |
1012 case GST_ITERATOR_DONE: |
1006 case GST_ITERATOR_DONE: |
1013 done = TRUE; |
1007 done = TRUE; |
1014 break; |
1008 break; |
1856 void |
1839 void |
1857 gst_element_unlink_pads (GstElement * src, const gchar * srcpadname, |
1840 gst_element_unlink_pads (GstElement * src, const gchar * srcpadname, |
1858 GstElement * dest, const gchar * destpadname) |
1841 GstElement * dest, const gchar * destpadname) |
1859 { |
1842 { |
1860 GstPad *srcpad, *destpad; |
1843 GstPad *srcpad, *destpad; |
1861 gboolean srcrequest, destrequest; |
|
1862 |
|
1863 srcrequest = destrequest = FALSE; |
|
1864 |
1844 |
1865 g_return_if_fail (src != NULL); |
1845 g_return_if_fail (src != NULL); |
1866 g_return_if_fail (GST_IS_ELEMENT (src)); |
1846 g_return_if_fail (GST_IS_ELEMENT (src)); |
1867 g_return_if_fail (srcpadname != NULL); |
1847 g_return_if_fail (srcpadname != NULL); |
1868 g_return_if_fail (dest != NULL); |
1848 g_return_if_fail (dest != NULL); |
1869 g_return_if_fail (GST_IS_ELEMENT (dest)); |
1849 g_return_if_fail (GST_IS_ELEMENT (dest)); |
1870 g_return_if_fail (destpadname != NULL); |
1850 g_return_if_fail (destpadname != NULL); |
1871 |
1851 |
1872 /* obtain the pads requested */ |
1852 /* obtain the pads requested */ |
1873 if (!(srcpad = gst_element_get_static_pad (src, srcpadname))) |
1853 srcpad = gst_element_get_pad (src, srcpadname); |
1874 if ((srcpad = gst_element_get_request_pad (src, srcpadname))) |
|
1875 srcrequest = TRUE; |
|
1876 if (srcpad == NULL) { |
1854 if (srcpad == NULL) { |
1877 GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname); |
1855 GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname); |
1878 return; |
1856 return; |
1879 } |
1857 } |
1880 if (!(destpad = gst_element_get_static_pad (dest, destpadname))) |
1858 destpad = gst_element_get_pad (dest, destpadname); |
1881 if ((destpad = gst_element_get_request_pad (dest, destpadname))) |
|
1882 destrequest = TRUE; |
|
1883 if (destpad == NULL) { |
1859 if (destpad == NULL) { |
1884 GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"", |
1860 GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"", |
1885 destpadname); |
1861 destpadname); |
1886 goto free_src; |
1862 gst_object_unref (srcpad); |
|
1863 return; |
1887 } |
1864 } |
1888 |
1865 |
1889 /* we're satisified they can be unlinked, let's do it */ |
1866 /* we're satisified they can be unlinked, let's do it */ |
1890 gst_pad_unlink (srcpad, destpad); |
1867 gst_pad_unlink (srcpad, destpad); |
1891 |
1868 gst_object_unref (srcpad); |
1892 if (destrequest) |
|
1893 gst_element_release_request_pad (dest, destpad); |
|
1894 gst_object_unref (destpad); |
1869 gst_object_unref (destpad); |
1895 |
|
1896 free_src: |
|
1897 if (srcrequest) |
|
1898 gst_element_release_request_pad (src, srcpad); |
|
1899 gst_object_unref (srcpad); |
|
1900 } |
1870 } |
1901 |
1871 |
1902 /** |
1872 /** |
1903 * gst_element_unlink_many: |
1873 * gst_element_unlink_many: |
1904 * @element_1: the first #GstElement in the link chain. |
1874 * @element_1: the first #GstElement in the link chain. |
2162 return gst_element_seek (element, 1.0, format, seek_flags, |
2133 return gst_element_seek (element, 1.0, format, seek_flags, |
2163 GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_NONE, 0); |
2134 GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_NONE, 0); |
2164 } |
2135 } |
2165 |
2136 |
2166 /** |
2137 /** |
|
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 /** |
2167 * gst_pad_use_fixed_caps: |
2202 * gst_pad_use_fixed_caps: |
2168 * @pad: the pad to use |
2203 * @pad: the pad to use |
2169 * |
2204 * |
2170 * A helper function you can use that sets the |
2205 * A helper function you can use that sets the |
2171 * @gst_pad_get_fixed_caps_func as the getcaps function for the |
2206 * @gst_pad_get_fixed_caps_func as the getcaps function for the |
3043 #endif |
3074 #endif |
3044 |
3075 |
3045 gulong |
3076 gulong |
3046 gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data) |
3077 gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data) |
3047 { |
3078 { |
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 { |
|
3095 gulong sigid; |
3079 gulong sigid; |
3096 |
3080 |
3097 g_return_val_if_fail (GST_IS_PAD (pad), 0); |
3081 g_return_val_if_fail (GST_IS_PAD (pad), 0); |
3098 g_return_val_if_fail (handler != NULL, 0); |
3082 g_return_val_if_fail (handler != NULL, 0); |
3099 |
3083 |
3100 GST_OBJECT_LOCK (pad); |
3084 GST_OBJECT_LOCK (pad); |
3101 |
3085 sigid = g_signal_connect (pad, "have-data", handler, data); |
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 |
|
3106 GST_PAD_DO_EVENT_SIGNALS (pad)++; |
3086 GST_PAD_DO_EVENT_SIGNALS (pad)++; |
3107 GST_PAD_DO_BUFFER_SIGNALS (pad)++; |
3087 GST_PAD_DO_BUFFER_SIGNALS (pad)++; |
3108 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, |
3088 GST_DEBUG ("adding data probe to pad %s:%s, now %d data, %d event probes", |
3109 "adding data probe, now %d data, %d event probes", |
3089 GST_DEBUG_PAD_NAME (pad), |
3110 GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad)); |
3090 GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad)); |
3111 GST_OBJECT_UNLOCK (pad); |
3091 GST_OBJECT_UNLOCK (pad); |
3112 |
3092 |
3113 return sigid; |
3093 return sigid; |
3114 } |
3094 } |
3129 #endif |
3109 #endif |
3130 |
3110 |
3131 gulong |
3111 gulong |
3132 gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data) |
3112 gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data) |
3133 { |
3113 { |
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 { |
|
3162 gulong sigid; |
3114 gulong sigid; |
3163 |
3115 |
3164 g_return_val_if_fail (GST_IS_PAD (pad), 0); |
3116 g_return_val_if_fail (GST_IS_PAD (pad), 0); |
3165 g_return_val_if_fail (handler != NULL, 0); |
3117 g_return_val_if_fail (handler != NULL, 0); |
3166 |
3118 |
3167 GST_OBJECT_LOCK (pad); |
3119 GST_OBJECT_LOCK (pad); |
3168 |
3120 sigid = g_signal_connect (pad, "have-data::event", handler, data); |
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 |
|
3173 GST_PAD_DO_EVENT_SIGNALS (pad)++; |
3121 GST_PAD_DO_EVENT_SIGNALS (pad)++; |
3174 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding event probe, now %d probes", |
3122 GST_DEBUG ("adding event probe to pad %s:%s, now %d probes", |
3175 GST_PAD_DO_EVENT_SIGNALS (pad)); |
3123 GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad)); |
3176 GST_OBJECT_UNLOCK (pad); |
3124 GST_OBJECT_UNLOCK (pad); |
3177 |
3125 |
3178 return sigid; |
3126 return sigid; |
3179 } |
3127 } |
3180 |
3128 |
3194 #endif |
3142 #endif |
3195 |
3143 |
3196 gulong |
3144 gulong |
3197 gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data) |
3145 gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data) |
3198 { |
3146 { |
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 { |
|
3227 gulong sigid; |
3147 gulong sigid; |
3228 |
3148 |
3229 g_return_val_if_fail (GST_IS_PAD (pad), 0); |
3149 g_return_val_if_fail (GST_IS_PAD (pad), 0); |
3230 g_return_val_if_fail (handler != NULL, 0); |
3150 g_return_val_if_fail (handler != NULL, 0); |
3231 |
3151 |
3232 GST_OBJECT_LOCK (pad); |
3152 GST_OBJECT_LOCK (pad); |
3233 |
3153 sigid = g_signal_connect (pad, "have-data::buffer", handler, data); |
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 |
|
3238 GST_PAD_DO_BUFFER_SIGNALS (pad)++; |
3154 GST_PAD_DO_BUFFER_SIGNALS (pad)++; |
3239 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding buffer probe, now %d probes", |
3155 GST_DEBUG ("adding buffer probe to pad %s:%s, now %d probes", |
3240 GST_PAD_DO_BUFFER_SIGNALS (pad)); |
3156 GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad)); |
3241 GST_OBJECT_UNLOCK (pad); |
3157 GST_OBJECT_UNLOCK (pad); |
3242 |
3158 |
3243 return sigid; |
3159 return sigid; |
3244 } |
3160 } |
3245 |
3161 |
3512 |
3426 |
3513 return pad; |
3427 return pad; |
3514 } |
3428 } |
3515 |
3429 |
3516 /** |
3430 /** |
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 /** |
|
3546 * gst_parse_bin_from_description: |
3431 * gst_parse_bin_from_description: |
3547 * @bin_description: command line describing the bin |
3432 * @bin_description: command line describing the bin |
3548 * @ghost_unlinked_pads: whether to automatically create ghost pads |
3433 * @ghost_unconnected_pads: whether to automatically create ghost pads |
3549 * for unlinked source or sink pads within the bin |
3434 * for unconnected source or sink pads within |
|
3435 * the bin |
3550 * @err: where to store the error message in case of an error, or NULL |
3436 * @err: where to store the error message in case of an error, or NULL |
3551 * |
3437 * |
3552 * This is a convenience wrapper around gst_parse_launch() to create a |
3438 * This is a convenience wrapper around gst_parse_launch() to create a |
3553 * #GstBin from a gst-launch-style pipeline description. See |
3439 * #GstBin from a gst-launch-style pipeline description. See |
3554 * gst_parse_launch() and the gst-launch man page for details about the |
3440 * gst_parse_launch() and the gst-launch man page for details about the |
3555 * syntax. Ghost pads on the bin for unlinked source or sink pads |
3441 * syntax. Ghost pads on the bin for unconnected source or sink pads |
3556 * within the bin can automatically be created (but only a maximum of |
3442 * within the bin can automatically be created (but only a maximum of |
3557 * one ghost pad for each direction will be created; if you expect |
3443 * one ghost pad for each direction will be created; if you expect |
3558 * multiple unlinked source pads or multiple unlinked sink pads |
3444 * multiple unconnected source pads or multiple unconnected sink pads |
3559 * and want them all ghosted, you will have to create the ghost pads |
3445 * and want them all ghosted, you will have to create the ghost pads |
3560 * yourself). |
3446 * yourself). |
3561 * |
3447 * |
3562 * Returns: a newly-created bin, or NULL if an error occurred. |
3448 * Returns: a newly-created bin, or NULL if an error occurred. |
3563 * |
3449 * |
3567 EXPORT_C |
3453 EXPORT_C |
3568 #endif |
3454 #endif |
3569 |
3455 |
3570 GstElement * |
3456 GstElement * |
3571 gst_parse_bin_from_description (const gchar * bin_description, |
3457 gst_parse_bin_from_description (const gchar * bin_description, |
3572 gboolean ghost_unlinked_pads, GError ** err) |
3458 gboolean ghost_unconnected_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) |
|
3609 { |
3459 { |
3610 #ifndef GST_DISABLE_PARSE |
3460 #ifndef GST_DISABLE_PARSE |
3611 GstPad *pad = NULL; |
3461 GstPad *pad = NULL; |
3612 GstBin *bin; |
3462 GstBin *bin; |
3613 gchar *desc; |
3463 gchar *desc; |
3617 |
3467 |
3618 GST_DEBUG ("Making bin from description '%s'", bin_description); |
3468 GST_DEBUG ("Making bin from description '%s'", bin_description); |
3619 |
3469 |
3620 /* parse the pipeline to a bin */ |
3470 /* parse the pipeline to a bin */ |
3621 desc = g_strdup_printf ("bin.( %s )", bin_description); |
3471 desc = g_strdup_printf ("bin.( %s )", bin_description); |
3622 bin = (GstBin *) gst_parse_launch_full (desc, context, flags, err); |
3472 bin = (GstBin *) gst_parse_launch (desc, err); |
3623 g_free (desc); |
3473 g_free (desc); |
3624 |
3474 |
3625 if (bin == NULL || (err && *err != NULL)) { |
3475 if (bin == NULL || (err && *err != NULL)) { |
3626 if (bin) |
3476 if (bin) |
3627 gst_object_unref (bin); |
3477 gst_object_unref (bin); |
3628 return NULL; |
3478 return NULL; |
3629 } |
3479 } |
3630 |
3480 |
3631 /* find pads and ghost them if necessary */ |
3481 /* find pads and ghost them if necessary */ |
3632 if (ghost_unlinked_pads) { |
3482 if (ghost_unconnected_pads) { |
3633 if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC))) { |
3483 if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SRC))) { |
3634 gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad)); |
3484 gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad)); |
3635 gst_object_unref (pad); |
3485 gst_object_unref (pad); |
3636 } |
3486 } |
3637 if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SINK))) { |
3487 if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SINK))) { |
3638 gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad)); |
3488 gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad)); |
3639 gst_object_unref (pad); |
3489 gst_object_unref (pad); |
3640 } |
3490 } |
3641 } |
3491 } |
3642 |
3492 |
3643 return GST_ELEMENT (bin); |
3493 return GST_ELEMENT (bin); |
3644 #else |
3494 #else |
3645 gchar *msg; |
3495 gchar *msg; |
3646 |
3496 |
3647 GST_WARNING ("Disabled API called"); |
3497 GST_WARNING ("Disabled API called: gst_parse_bin_from_description()"); |
3648 |
3498 |
3649 msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED); |
3499 msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED); |
3650 g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg); |
3500 g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg); |
3651 g_free (msg); |
3501 g_free (msg); |
3652 |
3502 |
3755 |
3605 |
3756 g_get_current_time (&now); |
3606 g_get_current_time (&now); |
3757 return GST_TIMEVAL_TO_TIME (now); |
3607 return GST_TIMEVAL_TO_TIME (now); |
3758 #endif |
3608 #endif |
3759 } |
3609 } |
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 } |
|