41 #include <gst/gst.h> |
41 #include <gst/gst.h> |
42 |
42 |
43 #include "gstcontrolsource.h" |
43 #include "gstcontrolsource.h" |
44 #include "gstinterpolationcontrolsource.h" |
44 #include "gstinterpolationcontrolsource.h" |
45 #include "gstinterpolationcontrolsourceprivate.h" |
45 #include "gstinterpolationcontrolsourceprivate.h" |
|
46 |
46 #ifdef __SYMBIAN32__ |
47 #ifdef __SYMBIAN32__ |
47 #include <glib_global.h> |
48 #include <glib_global.h> |
48 #include <gobject_global.h> |
49 #include <gobject_global.h> |
49 #endif |
50 #endif |
50 #define GST_CAT_DEFAULT controller_debug |
51 extern GstInterpolateMethod *interpolation_methods[]; |
51 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT); |
52 extern guint num_interpolation_methods; |
52 |
53 |
53 static void gst_interpolation_control_source_init (GstInterpolationControlSource |
54 static void gst_interpolation_control_source_init (GstInterpolationControlSource |
54 * self); |
55 * self); |
55 static void |
56 static void |
56 gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass |
57 gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass |
93 g_value_unset (&self->priv->minimum_value); |
94 g_value_unset (&self->priv->minimum_value); |
94 if (G_IS_VALUE (&self->priv->maximum_value)) |
95 if (G_IS_VALUE (&self->priv->maximum_value)) |
95 g_value_unset (&self->priv->maximum_value); |
96 g_value_unset (&self->priv->maximum_value); |
96 |
97 |
97 if (self->priv->values) { |
98 if (self->priv->values) { |
98 g_sequence_free (self->priv->values); |
99 g_list_foreach (self->priv->values, (GFunc) gst_control_point_free, NULL); |
|
100 g_list_free (self->priv->values); |
99 self->priv->values = NULL; |
101 self->priv->values = NULL; |
100 } |
102 } |
101 |
103 |
102 self->priv->nvalues = 0; |
104 self->priv->nvalues = 0; |
|
105 self->priv->last_requested_value = NULL; |
103 self->priv->valid_cache = FALSE; |
106 self->priv->valid_cache = FALSE; |
104 } |
107 } |
105 |
108 |
106 /** |
109 /** |
107 * gst_interpolation_control_source_new: |
110 * gst_interpolation_control_source_new: |
130 * <note><para>User interpolation is not yet available and quadratic interpolation |
133 * <note><para>User interpolation is not yet available and quadratic interpolation |
131 * is deprecated and maps to cubic interpolation.</para></note> |
134 * is deprecated and maps to cubic interpolation.</para></note> |
132 * |
135 * |
133 * Returns: %TRUE if the interpolation mode could be set, %FALSE otherwise |
136 * Returns: %TRUE if the interpolation mode could be set, %FALSE otherwise |
134 */ |
137 */ |
135 /* *INDENT-OFF* */ |
|
136 #ifdef __SYMBIAN32__ |
138 #ifdef __SYMBIAN32__ |
137 EXPORT_C |
139 EXPORT_C |
138 #endif |
140 #endif |
139 |
141 |
140 gboolean |
142 gboolean |
141 gst_interpolation_control_source_set_interpolation_mode ( |
143 gst_interpolation_control_source_set_interpolation_mode |
142 GstInterpolationControlSource * self, GstInterpolateMode mode) |
144 (GstInterpolationControlSource * self, GstInterpolateMode mode) { |
143 /* *INDENT-ON* */ |
|
144 { |
|
145 gboolean ret = TRUE; |
145 gboolean ret = TRUE; |
146 GstControlSource *csource = GST_CONTROL_SOURCE (self); |
146 GstControlSource *csource = GST_CONTROL_SOURCE (self); |
147 |
147 |
148 if (mode >= priv_gst_num_interpolation_methods |
148 if (mode >= num_interpolation_methods || interpolation_methods[mode] == NULL) { |
149 || priv_gst_interpolation_methods[mode] == NULL) { |
|
150 GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode); |
149 GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode); |
151 return FALSE; |
150 return FALSE; |
152 } |
151 } |
153 |
152 |
154 if (mode == GST_INTERPOLATE_QUADRATIC) { |
153 if (mode == GST_INTERPOLATE_QUADRATIC) { |
162 } |
161 } |
163 |
162 |
164 g_mutex_lock (self->lock); |
163 g_mutex_lock (self->lock); |
165 switch (self->priv->base) { |
164 switch (self->priv->base) { |
166 case G_TYPE_INT: |
165 case G_TYPE_INT: |
167 csource->get_value = priv_gst_interpolation_methods[mode]->get_int; |
166 csource->get_value = interpolation_methods[mode]->get_int; |
168 csource->get_value_array = |
167 csource->get_value_array = |
169 priv_gst_interpolation_methods[mode]->get_int_value_array; |
168 interpolation_methods[mode]->get_int_value_array; |
170 break; |
169 break; |
171 case G_TYPE_UINT:{ |
170 case G_TYPE_UINT:{ |
172 csource->get_value = priv_gst_interpolation_methods[mode]->get_uint; |
171 csource->get_value = interpolation_methods[mode]->get_uint; |
173 csource->get_value_array = |
172 csource->get_value_array = |
174 priv_gst_interpolation_methods[mode]->get_uint_value_array; |
173 interpolation_methods[mode]->get_uint_value_array; |
175 break; |
174 break; |
176 } |
175 } |
177 case G_TYPE_LONG:{ |
176 case G_TYPE_LONG:{ |
178 csource->get_value = priv_gst_interpolation_methods[mode]->get_long; |
177 csource->get_value = interpolation_methods[mode]->get_long; |
179 csource->get_value_array = |
178 csource->get_value_array = |
180 priv_gst_interpolation_methods[mode]->get_long_value_array; |
179 interpolation_methods[mode]->get_long_value_array; |
181 break; |
180 break; |
182 } |
181 } |
183 case G_TYPE_ULONG:{ |
182 case G_TYPE_ULONG:{ |
184 csource->get_value = priv_gst_interpolation_methods[mode]->get_ulong; |
183 csource->get_value = interpolation_methods[mode]->get_ulong; |
185 csource->get_value_array = |
184 csource->get_value_array = |
186 priv_gst_interpolation_methods[mode]->get_ulong_value_array; |
185 interpolation_methods[mode]->get_ulong_value_array; |
187 break; |
186 break; |
188 } |
187 } |
189 case G_TYPE_INT64:{ |
188 case G_TYPE_INT64:{ |
190 csource->get_value = priv_gst_interpolation_methods[mode]->get_int64; |
189 csource->get_value = interpolation_methods[mode]->get_int64; |
191 csource->get_value_array = |
190 csource->get_value_array = |
192 priv_gst_interpolation_methods[mode]->get_int64_value_array; |
191 interpolation_methods[mode]->get_int64_value_array; |
193 break; |
192 break; |
194 } |
193 } |
195 case G_TYPE_UINT64:{ |
194 case G_TYPE_UINT64:{ |
196 csource->get_value = priv_gst_interpolation_methods[mode]->get_uint64; |
195 csource->get_value = interpolation_methods[mode]->get_uint64; |
197 csource->get_value_array = |
196 csource->get_value_array = |
198 priv_gst_interpolation_methods[mode]->get_uint64_value_array; |
197 interpolation_methods[mode]->get_uint64_value_array; |
199 break; |
198 break; |
200 } |
199 } |
201 case G_TYPE_FLOAT:{ |
200 case G_TYPE_FLOAT:{ |
202 csource->get_value = priv_gst_interpolation_methods[mode]->get_float; |
201 csource->get_value = interpolation_methods[mode]->get_float; |
203 csource->get_value_array = |
202 csource->get_value_array = |
204 priv_gst_interpolation_methods[mode]->get_float_value_array; |
203 interpolation_methods[mode]->get_float_value_array; |
205 break; |
204 break; |
206 } |
205 } |
207 case G_TYPE_DOUBLE:{ |
206 case G_TYPE_DOUBLE:{ |
208 csource->get_value = priv_gst_interpolation_methods[mode]->get_double; |
207 csource->get_value = interpolation_methods[mode]->get_double; |
209 csource->get_value_array = |
208 csource->get_value_array = |
210 priv_gst_interpolation_methods[mode]->get_double_value_array; |
209 interpolation_methods[mode]->get_double_value_array; |
211 break; |
210 break; |
212 } |
211 } |
213 case G_TYPE_BOOLEAN:{ |
212 case G_TYPE_BOOLEAN:{ |
214 csource->get_value = priv_gst_interpolation_methods[mode]->get_boolean; |
213 csource->get_value = interpolation_methods[mode]->get_boolean; |
215 csource->get_value_array = |
214 csource->get_value_array = |
216 priv_gst_interpolation_methods[mode]->get_boolean_value_array; |
215 interpolation_methods[mode]->get_boolean_value_array; |
217 break; |
216 break; |
218 } |
217 } |
219 case G_TYPE_ENUM:{ |
218 case G_TYPE_ENUM:{ |
220 csource->get_value = priv_gst_interpolation_methods[mode]->get_enum; |
219 csource->get_value = interpolation_methods[mode]->get_enum; |
221 csource->get_value_array = |
220 csource->get_value_array = |
222 priv_gst_interpolation_methods[mode]->get_enum_value_array; |
221 interpolation_methods[mode]->get_enum_value_array; |
223 break; |
222 break; |
224 } |
223 } |
225 case G_TYPE_STRING:{ |
224 case G_TYPE_STRING:{ |
226 csource->get_value = priv_gst_interpolation_methods[mode]->get_string; |
225 csource->get_value = interpolation_methods[mode]->get_string; |
227 csource->get_value_array = |
226 csource->get_value_array = |
228 priv_gst_interpolation_methods[mode]->get_string_value_array; |
227 interpolation_methods[mode]->get_string_value_array; |
229 break; |
228 break; |
230 } |
229 } |
231 default: |
230 default: |
232 ret = FALSE; |
231 ret = FALSE; |
233 break; |
232 break; |
428 GstClockTime ct2 = *(GstClockTime *) p2; |
427 GstClockTime ct2 = *(GstClockTime *) p2; |
429 |
428 |
430 return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1)); |
429 return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1)); |
431 } |
430 } |
432 |
431 |
433 static GstControlPoint * |
|
434 _make_new_cp (GstInterpolationControlSource * self, GstClockTime timestamp, |
|
435 GValue * value) |
|
436 { |
|
437 GstControlPoint *cp; |
|
438 |
|
439 /* create a new GstControlPoint */ |
|
440 cp = g_slice_new0 (GstControlPoint); |
|
441 cp->timestamp = timestamp; |
|
442 g_value_init (&cp->value, self->priv->type); |
|
443 g_value_copy (value, &cp->value); |
|
444 |
|
445 return cp; |
|
446 } |
|
447 |
|
448 static void |
432 static void |
449 gst_interpolation_control_source_set_internal (GstInterpolationControlSource * |
433 gst_interpolation_control_source_set_internal (GstInterpolationControlSource * |
450 self, GstClockTime timestamp, GValue * value) |
434 self, GstClockTime timestamp, GValue * value) |
451 { |
435 { |
452 GSequenceIter *iter; |
436 GstControlPoint *cp; |
|
437 GList *node; |
453 |
438 |
454 /* check if a control point for the timestamp already exists */ |
439 /* check if a control point for the timestamp already exists */ |
455 |
440 if ((node = g_list_find_custom (self->priv->values, ×tamp, |
456 /* iter contains the iter right *after* timestamp */ |
441 gst_control_point_find))) { |
457 if (G_LIKELY (self->priv->values)) { |
442 cp = node->data; |
458 iter = |
443 g_value_reset (&cp->value); |
459 g_sequence_search (self->priv->values, ×tamp, |
444 g_value_copy (value, &cp->value); |
460 (GCompareDataFunc) gst_control_point_find, NULL); |
|
461 if (iter) { |
|
462 GSequenceIter *prev = g_sequence_iter_prev (iter); |
|
463 GstControlPoint *cp = g_sequence_get (prev); |
|
464 |
|
465 /* If the timestamp is the same just update the control point value */ |
|
466 if (cp->timestamp == timestamp) { |
|
467 /* update control point */ |
|
468 g_value_reset (&cp->value); |
|
469 g_value_copy (value, &cp->value); |
|
470 goto done; |
|
471 } |
|
472 } |
|
473 } else { |
445 } else { |
|
446 /* create a new GstControlPoint */ |
|
447 cp = g_new0 (GstControlPoint, 1); |
|
448 cp->timestamp = timestamp; |
|
449 g_value_init (&cp->value, self->priv->type); |
|
450 g_value_copy (value, &cp->value); |
|
451 /* and sort it into the prop->values list */ |
474 self->priv->values = |
452 self->priv->values = |
475 g_sequence_new ((GDestroyNotify) gst_control_point_free); |
453 g_list_insert_sorted (self->priv->values, cp, |
476 } |
454 gst_control_point_compare); |
477 |
455 self->priv->nvalues++; |
478 /* sort new cp into the prop->values list */ |
456 } |
479 g_sequence_insert_sorted (self->priv->values, _make_new_cp (self, timestamp, |
|
480 value), (GCompareDataFunc) gst_control_point_compare, NULL); |
|
481 self->priv->nvalues++; |
|
482 |
|
483 done: |
|
484 self->priv->valid_cache = FALSE; |
457 self->priv->valid_cache = FALSE; |
485 } |
458 } |
486 |
|
487 |
459 |
488 /** |
460 /** |
489 * gst_interpolation_control_source_set: |
461 * gst_interpolation_control_source_set: |
490 * @self: the #GstInterpolationControlSource object |
462 * @self: the #GstInterpolationControlSource object |
491 * @timestamp: the time the control-change is scheduled for |
463 * @timestamp: the time the control-change is scheduled for |
575 |
547 |
576 gboolean |
548 gboolean |
577 gst_interpolation_control_source_unset (GstInterpolationControlSource * self, |
549 gst_interpolation_control_source_unset (GstInterpolationControlSource * self, |
578 GstClockTime timestamp) |
550 GstClockTime timestamp) |
579 { |
551 { |
580 GSequenceIter *iter; |
552 GList *node; |
581 gboolean res = FALSE; |
553 gboolean res = FALSE; |
582 |
554 |
583 g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE); |
555 g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE); |
584 g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); |
556 g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); |
585 |
557 |
586 g_mutex_lock (self->lock); |
558 g_mutex_lock (self->lock); |
587 /* check if a control point for the timestamp exists */ |
559 /* check if a control point for the timestamp exists */ |
588 if ((iter = |
560 if ((node = g_list_find_custom (self->priv->values, ×tamp, |
589 g_sequence_search (self->priv->values, ×tamp, |
561 gst_control_point_find))) { |
590 (GCompareDataFunc) gst_control_point_find, NULL))) { |
562 GstControlPoint *cp = node->data; |
591 GstControlPoint *cp; |
563 |
592 |
564 if (cp->timestamp == 0) { |
593 /* Iter contains the iter right after timestamp, i.e. |
565 /* Restore the default node */ |
594 * we need to get the previous one and check the timestamp |
566 g_value_reset (&cp->value); |
595 */ |
567 g_value_copy (&self->priv->default_value, &cp->value); |
596 iter = g_sequence_iter_prev (iter); |
568 } else { |
597 cp = g_sequence_get (iter); |
569 if (node == self->priv->last_requested_value) |
598 if (cp->timestamp == timestamp) { |
570 self->priv->last_requested_value = NULL; |
599 g_sequence_remove (iter); |
571 gst_control_point_free (node->data); /* free GstControlPoint */ |
|
572 self->priv->values = g_list_delete_link (self->priv->values, node); |
600 self->priv->nvalues--; |
573 self->priv->nvalues--; |
601 self->priv->valid_cache = FALSE; |
574 } |
602 res = TRUE; |
575 self->priv->valid_cache = FALSE; |
603 } |
576 res = TRUE; |
604 } |
577 } |
605 g_mutex_unlock (self->lock); |
578 g_mutex_unlock (self->lock); |
606 |
579 |
607 return res; |
580 return res; |
608 } |
581 } |
624 { |
597 { |
625 g_return_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self)); |
598 g_return_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self)); |
626 |
599 |
627 g_mutex_lock (self->lock); |
600 g_mutex_lock (self->lock); |
628 /* free GstControlPoint structures */ |
601 /* free GstControlPoint structures */ |
629 if (self->priv->values) { |
602 g_list_foreach (self->priv->values, (GFunc) gst_control_point_free, NULL); |
630 g_sequence_free (self->priv->values); |
603 g_list_free (self->priv->values); |
631 self->priv->values = NULL; |
604 self->priv->last_requested_value = NULL; |
632 } |
605 self->priv->values = NULL; |
633 self->priv->nvalues = 0; |
606 self->priv->nvalues = 0; |
634 self->priv->valid_cache = FALSE; |
607 self->priv->valid_cache = FALSE; |
635 |
608 |
636 g_mutex_unlock (self->lock); |
609 g_mutex_unlock (self->lock); |
637 } |
610 } |
638 |
611 |
639 static void |
|
640 _append_control_point (GstControlPoint * cp, GList ** l) |
|
641 { |
|
642 *l = g_list_prepend (*l, cp); |
|
643 } |
|
644 |
|
645 /** |
612 /** |
646 * gst_interpolation_control_source_get_all: |
613 * gst_interpolation_control_source_get_all: |
647 * @self: the #GstInterpolationControlSource to get the list from |
614 * @self: the #GstInterpolationControlSource to get the list from |
648 * |
615 * |
649 * Returns a read-only copy of the list of #GstTimedValue for the given property. |
616 * Returns a read-only copy of the list of #GstTimedValue for the given property. |
661 GList *res = NULL; |
628 GList *res = NULL; |
662 |
629 |
663 g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), NULL); |
630 g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), NULL); |
664 |
631 |
665 g_mutex_lock (self->lock); |
632 g_mutex_lock (self->lock); |
666 if (G_LIKELY (self->priv->values)) |
633 if (self->priv->values) |
667 g_sequence_foreach (self->priv->values, (GFunc) _append_control_point, |
634 res = g_list_copy (self->priv->values); |
668 &res); |
|
669 g_mutex_unlock (self->lock); |
635 g_mutex_unlock (self->lock); |
670 |
636 |
671 return g_list_reverse (res); |
637 return res; |
672 } |
638 } |
673 |
639 |
674 /** |
640 /** |
675 * gst_interpolation_control_source_get_count: |
641 * gst_interpolation_control_source_get_count: |
676 * @self: the #GstInterpolationControlSource to get the number of values from |
642 * @self: the #GstInterpolationControlSource to get the number of values from |