gstreamer_core/libs/gst/controller/gstlfocontrolsource.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  *
       
     3  * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
       
     4  *
       
     5  * gstlfocontrolsource.c: Control source that provides some periodic waveforms
       
     6  *                        as control values.
       
     7  *
       
     8  * This library is free software; you can redistribute it and/or
       
     9  * modify it under the terms of the GNU Library General Public
       
    10  * License as published by the Free Software Foundation; either
       
    11  * version 2 of the License, or (at your option) any later version.
       
    12  *
       
    13  * This library is distributed in the hope that it will be useful,
       
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16  * Library General Public License for more details.
       
    17  *
       
    18  * You should have received a copy of the GNU Library General Public
       
    19  * License along with this library; if not, write to the
       
    20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    21  * Boston, MA 02111-1307, USA.
       
    22  */
       
    23 
       
    24 /**
       
    25  * SECTION:gstlfocontrolsource
       
    26  * @short_description: LFO control source
       
    27  *
       
    28  * #GstLFOControlSource is a #GstControlSource, that provides several periodic waveforms
       
    29  * as control values. It supports all fundamental, numeric GValue types as property.
       
    30  *
       
    31  * To use #GstLFOControlSource get a new instance by calling gst_lfo_control_source_new(),
       
    32  * bind it to a #GParamSpec and set the relevant properties or use
       
    33  * gst_lfo_control_source_set_waveform.
       
    34  *
       
    35  * All functions are MT-safe.
       
    36  *
       
    37  */
       
    38 
       
    39 #include <glib-object.h>
       
    40 #include <gst/gst.h>
       
    41 
       
    42 #include "gstcontrolsource.h"
       
    43 #include "gstlfocontrolsource.h"
       
    44 #include "gstlfocontrolsourceprivate.h"
       
    45 
       
    46 #include "math.h"
       
    47 
       
    48 #ifdef __SYMBIAN32__
       
    49 #include <glib_global.h>
       
    50 #include <gobject_global.h>
       
    51 #endif
       
    52 #define EMPTY(x) (x)
       
    53 
       
    54 /* FIXME: as % in C is not the modulo operator we need here for
       
    55  * negative numbers implement our own. Are there better ways? */
       
    56 static inline GstClockTime
       
    57 _calculate_pos (GstClockTime timestamp, GstClockTime timeshift,
       
    58     GstClockTime period)
       
    59 {
       
    60   while (timestamp < timeshift)
       
    61     timestamp += period;
       
    62 
       
    63   timestamp -= timeshift;
       
    64 
       
    65   return timestamp % period;
       
    66 }
       
    67 
       
    68 #define DEFINE_SINE(type,round,convert) \
       
    69 \
       
    70 static inline g##type \
       
    71 _sine_get_##type (GstLFOControlSource *self, GstClockTime timestamp) \
       
    72 { \
       
    73   gdouble ret; \
       
    74   g##type max = g_value_get_##type (&self->priv->maximum_value); \
       
    75   g##type min = g_value_get_##type (&self->priv->minimum_value); \
       
    76   gdouble amp = convert (g_value_get_##type (&self->priv->amplitude)); \
       
    77   gdouble off = convert (g_value_get_##type (&self->priv->offset)); \
       
    78   GstClockTime pos = _calculate_pos (timestamp, self->priv->timeshift, self->priv->period); \
       
    79   \
       
    80   ret = sin (2.0 * M_PI * (self->priv->frequency / GST_SECOND) * gst_util_guint64_to_gdouble (pos)); \
       
    81   ret *= amp; \
       
    82   ret += off; \
       
    83   \
       
    84   if (round) \
       
    85     ret += 0.5; \
       
    86   \
       
    87   return (g##type) CLAMP (ret, convert (min), convert (max)); \
       
    88 } \
       
    89 \
       
    90 static gboolean \
       
    91 waveform_sine_get_##type (GstLFOControlSource *self, GstClockTime timestamp, \
       
    92     GValue *value) \
       
    93 { \
       
    94   g##type ret; \
       
    95   g_mutex_lock (self->lock); \
       
    96   ret = _sine_get_##type (self, timestamp); \
       
    97   g_value_set_##type (value, ret); \
       
    98   g_mutex_unlock (self->lock); \
       
    99   return TRUE; \
       
   100 } \
       
   101 \
       
   102 static gboolean \
       
   103 waveform_sine_get_##type##_value_array (GstLFOControlSource *self, \
       
   104    GstClockTime timestamp, GstValueArray * value_array) \
       
   105 { \
       
   106   gint i; \
       
   107   GstClockTime ts = timestamp; \
       
   108   g##type *values = (g##type *) value_array->values; \
       
   109   \
       
   110   g_mutex_lock (self->lock); \
       
   111   for(i = 0; i < value_array->nbsamples; i++) { \
       
   112     *values = _sine_get_##type (self, ts); \
       
   113     ts += value_array->sample_interval; \
       
   114     values++; \
       
   115   } \
       
   116   g_mutex_unlock (self->lock); \
       
   117   return TRUE; \
       
   118 }
       
   119 
       
   120 DEFINE_SINE (int, TRUE, EMPTY);
       
   121 DEFINE_SINE (uint, TRUE, EMPTY);
       
   122 DEFINE_SINE (long, TRUE, EMPTY);
       
   123 
       
   124 DEFINE_SINE (ulong, TRUE, EMPTY);
       
   125 DEFINE_SINE (int64, TRUE, EMPTY);
       
   126 DEFINE_SINE (uint64, TRUE, gst_util_guint64_to_gdouble);
       
   127 DEFINE_SINE (float, FALSE, EMPTY);
       
   128 DEFINE_SINE (double, FALSE, EMPTY);
       
   129 
       
   130 static GstWaveformImplementation waveform_sine = {
       
   131   (GstControlSourceGetValue) waveform_sine_get_int,
       
   132   (GstControlSourceGetValueArray) waveform_sine_get_int_value_array,
       
   133   (GstControlSourceGetValue) waveform_sine_get_uint,
       
   134   (GstControlSourceGetValueArray) waveform_sine_get_uint_value_array,
       
   135   (GstControlSourceGetValue) waveform_sine_get_long,
       
   136   (GstControlSourceGetValueArray) waveform_sine_get_long_value_array,
       
   137   (GstControlSourceGetValue) waveform_sine_get_ulong,
       
   138   (GstControlSourceGetValueArray) waveform_sine_get_ulong_value_array,
       
   139   (GstControlSourceGetValue) waveform_sine_get_int64,
       
   140   (GstControlSourceGetValueArray) waveform_sine_get_int64_value_array,
       
   141   (GstControlSourceGetValue) waveform_sine_get_uint64,
       
   142   (GstControlSourceGetValueArray) waveform_sine_get_uint64_value_array,
       
   143   (GstControlSourceGetValue) waveform_sine_get_float,
       
   144   (GstControlSourceGetValueArray) waveform_sine_get_float_value_array,
       
   145   (GstControlSourceGetValue) waveform_sine_get_double,
       
   146   (GstControlSourceGetValueArray) waveform_sine_get_double_value_array
       
   147 };
       
   148 
       
   149 #define DEFINE_SQUARE(type,round, convert) \
       
   150 \
       
   151 static inline g##type \
       
   152 _square_get_##type (GstLFOControlSource *self, GstClockTime timestamp) \
       
   153 { \
       
   154   g##type max = g_value_get_##type (&self->priv->maximum_value); \
       
   155   g##type min = g_value_get_##type (&self->priv->minimum_value); \
       
   156   gdouble amp = convert (g_value_get_##type (&self->priv->amplitude)); \
       
   157   gdouble off = convert (g_value_get_##type (&self->priv->offset)); \
       
   158   GstClockTime period = self->priv->period; \
       
   159   GstClockTime pos = _calculate_pos (timestamp, self->priv->timeshift, period); \
       
   160   gdouble ret; \
       
   161   \
       
   162   if (pos >= period / 2) \
       
   163     ret = amp; \
       
   164   else \
       
   165     ret = - amp; \
       
   166   \
       
   167   ret += off; \
       
   168   \
       
   169   if (round) \
       
   170     ret += 0.5; \
       
   171   \
       
   172   return (g##type) CLAMP (ret, convert (min), convert (max)); \
       
   173 } \
       
   174 \
       
   175 static gboolean \
       
   176 waveform_square_get_##type (GstLFOControlSource *self, GstClockTime timestamp, \
       
   177     GValue *value) \
       
   178 { \
       
   179   g##type ret; \
       
   180   g_mutex_lock (self->lock); \
       
   181   ret = _square_get_##type (self, timestamp); \
       
   182   g_value_set_##type (value, ret); \
       
   183   g_mutex_unlock (self->lock); \
       
   184   return TRUE; \
       
   185 } \
       
   186 \
       
   187 static gboolean \
       
   188 waveform_square_get_##type##_value_array (GstLFOControlSource *self, \
       
   189    GstClockTime timestamp, GstValueArray * value_array) \
       
   190 { \
       
   191   gint i; \
       
   192   GstClockTime ts = timestamp; \
       
   193   g##type *values = (g##type *) value_array->values; \
       
   194   \
       
   195   g_mutex_lock (self->lock); \
       
   196   for(i = 0; i < value_array->nbsamples; i++) { \
       
   197     *values = _square_get_##type (self, ts); \
       
   198     ts += value_array->sample_interval; \
       
   199     values++; \
       
   200   } \
       
   201   g_mutex_unlock (self->lock); \
       
   202   return TRUE; \
       
   203 }
       
   204 
       
   205 DEFINE_SQUARE (int, TRUE, EMPTY);
       
   206 
       
   207 DEFINE_SQUARE (uint, TRUE, EMPTY);
       
   208 DEFINE_SQUARE (long, TRUE, EMPTY);
       
   209 
       
   210 DEFINE_SQUARE (ulong, TRUE, EMPTY);
       
   211 DEFINE_SQUARE (int64, TRUE, EMPTY);
       
   212 DEFINE_SQUARE (uint64, TRUE, gst_util_guint64_to_gdouble);
       
   213 DEFINE_SQUARE (float, FALSE, EMPTY);
       
   214 DEFINE_SQUARE (double, FALSE, EMPTY);
       
   215 
       
   216 static GstWaveformImplementation waveform_square = {
       
   217   (GstControlSourceGetValue) waveform_square_get_int,
       
   218   (GstControlSourceGetValueArray) waveform_square_get_int_value_array,
       
   219   (GstControlSourceGetValue) waveform_square_get_uint,
       
   220   (GstControlSourceGetValueArray) waveform_square_get_uint_value_array,
       
   221   (GstControlSourceGetValue) waveform_square_get_long,
       
   222   (GstControlSourceGetValueArray) waveform_square_get_long_value_array,
       
   223   (GstControlSourceGetValue) waveform_square_get_ulong,
       
   224   (GstControlSourceGetValueArray) waveform_square_get_ulong_value_array,
       
   225   (GstControlSourceGetValue) waveform_square_get_int64,
       
   226   (GstControlSourceGetValueArray) waveform_square_get_int64_value_array,
       
   227   (GstControlSourceGetValue) waveform_square_get_uint64,
       
   228   (GstControlSourceGetValueArray) waveform_square_get_uint64_value_array,
       
   229   (GstControlSourceGetValue) waveform_square_get_float,
       
   230   (GstControlSourceGetValueArray) waveform_square_get_float_value_array,
       
   231   (GstControlSourceGetValue) waveform_square_get_double,
       
   232   (GstControlSourceGetValueArray) waveform_square_get_double_value_array
       
   233 };
       
   234 
       
   235 #define DEFINE_SAW(type,round,convert) \
       
   236 \
       
   237 static inline g##type \
       
   238 _saw_get_##type (GstLFOControlSource *self, GstClockTime timestamp) \
       
   239 { \
       
   240   g##type max = g_value_get_##type (&self->priv->maximum_value); \
       
   241   g##type min = g_value_get_##type (&self->priv->minimum_value); \
       
   242   gdouble amp = convert (g_value_get_##type (&self->priv->amplitude)); \
       
   243   gdouble off = convert (g_value_get_##type (&self->priv->offset)); \
       
   244   GstClockTime period = self->priv->period; \
       
   245   GstClockTime pos = _calculate_pos (timestamp, self->priv->timeshift, period); \
       
   246   gdouble ret; \
       
   247   \
       
   248   ret = - ((gst_util_guint64_to_gdouble (pos) - gst_util_guint64_to_gdouble (period) / 2.0) * ((2.0 * amp) / gst_util_guint64_to_gdouble (period)));\
       
   249   \
       
   250   ret += off; \
       
   251   \
       
   252   if (round) \
       
   253     ret += 0.5; \
       
   254   \
       
   255   return (g##type) CLAMP (ret, convert (min), convert (max)); \
       
   256 } \
       
   257 \
       
   258 static gboolean \
       
   259 waveform_saw_get_##type (GstLFOControlSource *self, GstClockTime timestamp, \
       
   260     GValue *value) \
       
   261 { \
       
   262   g##type ret; \
       
   263   g_mutex_lock (self->lock); \
       
   264   ret = _saw_get_##type (self, timestamp); \
       
   265   g_value_set_##type (value, ret); \
       
   266   g_mutex_unlock (self->lock); \
       
   267   return TRUE; \
       
   268 } \
       
   269 \
       
   270 static gboolean \
       
   271 waveform_saw_get_##type##_value_array (GstLFOControlSource *self, \
       
   272    GstClockTime timestamp, GstValueArray * value_array) \
       
   273 { \
       
   274   gint i; \
       
   275   GstClockTime ts = timestamp; \
       
   276   g##type *values = (g##type *) value_array->values; \
       
   277   \
       
   278   g_mutex_lock (self->lock); \
       
   279   for(i = 0; i < value_array->nbsamples; i++) { \
       
   280     *values = _saw_get_##type (self, ts); \
       
   281     ts += value_array->sample_interval; \
       
   282     values++; \
       
   283   } \
       
   284   g_mutex_unlock (self->lock); \
       
   285   return TRUE; \
       
   286 }
       
   287 
       
   288 DEFINE_SAW (int, TRUE, EMPTY);
       
   289 
       
   290 DEFINE_SAW (uint, TRUE, EMPTY);
       
   291 DEFINE_SAW (long, TRUE, EMPTY);
       
   292 
       
   293 DEFINE_SAW (ulong, TRUE, EMPTY);
       
   294 DEFINE_SAW (int64, TRUE, EMPTY);
       
   295 DEFINE_SAW (uint64, TRUE, gst_util_guint64_to_gdouble);
       
   296 DEFINE_SAW (float, FALSE, EMPTY);
       
   297 DEFINE_SAW (double, FALSE, EMPTY);
       
   298 
       
   299 static GstWaveformImplementation waveform_saw = {
       
   300   (GstControlSourceGetValue) waveform_saw_get_int,
       
   301   (GstControlSourceGetValueArray) waveform_saw_get_int_value_array,
       
   302   (GstControlSourceGetValue) waveform_saw_get_uint,
       
   303   (GstControlSourceGetValueArray) waveform_saw_get_uint_value_array,
       
   304   (GstControlSourceGetValue) waveform_saw_get_long,
       
   305   (GstControlSourceGetValueArray) waveform_saw_get_long_value_array,
       
   306   (GstControlSourceGetValue) waveform_saw_get_ulong,
       
   307   (GstControlSourceGetValueArray) waveform_saw_get_ulong_value_array,
       
   308   (GstControlSourceGetValue) waveform_saw_get_int64,
       
   309   (GstControlSourceGetValueArray) waveform_saw_get_int64_value_array,
       
   310   (GstControlSourceGetValue) waveform_saw_get_uint64,
       
   311   (GstControlSourceGetValueArray) waveform_saw_get_uint64_value_array,
       
   312   (GstControlSourceGetValue) waveform_saw_get_float,
       
   313   (GstControlSourceGetValueArray) waveform_saw_get_float_value_array,
       
   314   (GstControlSourceGetValue) waveform_saw_get_double,
       
   315   (GstControlSourceGetValueArray) waveform_saw_get_double_value_array
       
   316 };
       
   317 
       
   318 #define DEFINE_RSAW(type,round,convert) \
       
   319 \
       
   320 static inline g##type \
       
   321 _rsaw_get_##type (GstLFOControlSource *self, GstClockTime timestamp) \
       
   322 { \
       
   323   g##type max = g_value_get_##type (&self->priv->maximum_value); \
       
   324   g##type min = g_value_get_##type (&self->priv->minimum_value); \
       
   325   gdouble amp = convert (g_value_get_##type (&self->priv->amplitude)); \
       
   326   gdouble off = convert (g_value_get_##type (&self->priv->offset)); \
       
   327   GstClockTime period = self->priv->period; \
       
   328   GstClockTime pos = _calculate_pos (timestamp, self->priv->timeshift, period); \
       
   329   gdouble ret; \
       
   330   \
       
   331   ret = ((gst_util_guint64_to_gdouble (pos) - gst_util_guint64_to_gdouble (period) / 2.0) * ((2.0 * amp) / gst_util_guint64_to_gdouble (period)));\
       
   332   \
       
   333   ret += off; \
       
   334   \
       
   335   if (round) \
       
   336     ret += 0.5; \
       
   337   \
       
   338   return (g##type) CLAMP (ret, convert (min), convert (max)); \
       
   339 } \
       
   340 \
       
   341 static gboolean \
       
   342 waveform_rsaw_get_##type (GstLFOControlSource *self, GstClockTime timestamp, \
       
   343     GValue *value) \
       
   344 { \
       
   345   g##type ret; \
       
   346   g_mutex_lock (self->lock); \
       
   347   ret = _rsaw_get_##type (self, timestamp); \
       
   348   g_value_set_##type (value, ret); \
       
   349   g_mutex_unlock (self->lock); \
       
   350   return TRUE; \
       
   351 } \
       
   352 \
       
   353 static gboolean \
       
   354 waveform_rsaw_get_##type##_value_array (GstLFOControlSource *self, \
       
   355    GstClockTime timestamp, GstValueArray * value_array) \
       
   356 { \
       
   357   gint i; \
       
   358   GstClockTime ts = timestamp; \
       
   359   g##type *values = (g##type *) value_array->values; \
       
   360   \
       
   361   g_mutex_lock (self->lock); \
       
   362   for(i = 0; i < value_array->nbsamples; i++) { \
       
   363     *values = _rsaw_get_##type (self, ts); \
       
   364     ts += value_array->sample_interval; \
       
   365     values++; \
       
   366   } \
       
   367   g_mutex_unlock (self->lock); \
       
   368   return TRUE; \
       
   369 }
       
   370 
       
   371 DEFINE_RSAW (int, TRUE, EMPTY);
       
   372 
       
   373 DEFINE_RSAW (uint, TRUE, EMPTY);
       
   374 DEFINE_RSAW (long, TRUE, EMPTY);
       
   375 
       
   376 DEFINE_RSAW (ulong, TRUE, EMPTY);
       
   377 DEFINE_RSAW (int64, TRUE, EMPTY);
       
   378 DEFINE_RSAW (uint64, TRUE, gst_util_guint64_to_gdouble);
       
   379 DEFINE_RSAW (float, FALSE, EMPTY);
       
   380 DEFINE_RSAW (double, FALSE, EMPTY);
       
   381 
       
   382 static GstWaveformImplementation waveform_rsaw = {
       
   383   (GstControlSourceGetValue) waveform_rsaw_get_int,
       
   384   (GstControlSourceGetValueArray) waveform_rsaw_get_int_value_array,
       
   385   (GstControlSourceGetValue) waveform_rsaw_get_uint,
       
   386   (GstControlSourceGetValueArray) waveform_rsaw_get_uint_value_array,
       
   387   (GstControlSourceGetValue) waveform_rsaw_get_long,
       
   388   (GstControlSourceGetValueArray) waveform_rsaw_get_long_value_array,
       
   389   (GstControlSourceGetValue) waveform_rsaw_get_ulong,
       
   390   (GstControlSourceGetValueArray) waveform_rsaw_get_ulong_value_array,
       
   391   (GstControlSourceGetValue) waveform_rsaw_get_int64,
       
   392   (GstControlSourceGetValueArray) waveform_rsaw_get_int64_value_array,
       
   393   (GstControlSourceGetValue) waveform_rsaw_get_uint64,
       
   394   (GstControlSourceGetValueArray) waveform_rsaw_get_uint64_value_array,
       
   395   (GstControlSourceGetValue) waveform_rsaw_get_float,
       
   396   (GstControlSourceGetValueArray) waveform_rsaw_get_float_value_array,
       
   397   (GstControlSourceGetValue) waveform_rsaw_get_double,
       
   398   (GstControlSourceGetValueArray) waveform_rsaw_get_double_value_array
       
   399 };
       
   400 
       
   401 #define DEFINE_TRIANGLE(type,round,convert) \
       
   402 \
       
   403 static inline g##type \
       
   404 _triangle_get_##type (GstLFOControlSource *self, GstClockTime timestamp) \
       
   405 { \
       
   406   g##type max = g_value_get_##type (&self->priv->maximum_value); \
       
   407   g##type min = g_value_get_##type (&self->priv->minimum_value); \
       
   408   gdouble amp = convert (g_value_get_##type (&self->priv->amplitude)); \
       
   409   gdouble off = convert (g_value_get_##type (&self->priv->offset)); \
       
   410   GstClockTime period = self->priv->period; \
       
   411   GstClockTime pos = _calculate_pos (timestamp, self->priv->timeshift, period); \
       
   412   gdouble ret; \
       
   413   \
       
   414   if (gst_util_guint64_to_gdouble (pos) <= gst_util_guint64_to_gdouble (period) / 4.0) \
       
   415     ret = gst_util_guint64_to_gdouble (pos) * ((4.0 * amp) / gst_util_guint64_to_gdouble (period)); \
       
   416   else if (gst_util_guint64_to_gdouble (pos) <= (3.0 * gst_util_guint64_to_gdouble (period)) / 4.0) \
       
   417     ret = -(gst_util_guint64_to_gdouble (pos) - gst_util_guint64_to_gdouble (period) / 2.0) * ((4.0 * amp) / gst_util_guint64_to_gdouble (period)); \
       
   418   else \
       
   419     ret = gst_util_guint64_to_gdouble (period) - gst_util_guint64_to_gdouble (pos) * ((4.0 * amp) / gst_util_guint64_to_gdouble (period)); \
       
   420   \
       
   421   ret += off; \
       
   422   \
       
   423   if (round) \
       
   424     ret += 0.5; \
       
   425   \
       
   426   return (g##type) CLAMP (ret, convert (min), convert (max)); \
       
   427 } \
       
   428 \
       
   429 static gboolean \
       
   430 waveform_triangle_get_##type (GstLFOControlSource *self, GstClockTime timestamp, \
       
   431     GValue *value) \
       
   432 { \
       
   433   g##type ret; \
       
   434   g_mutex_lock (self->lock); \
       
   435   ret = _triangle_get_##type (self, timestamp); \
       
   436   g_value_set_##type (value, ret); \
       
   437   g_mutex_unlock (self->lock); \
       
   438   return TRUE; \
       
   439 } \
       
   440 \
       
   441 static gboolean \
       
   442 waveform_triangle_get_##type##_value_array (GstLFOControlSource *self, \
       
   443    GstClockTime timestamp, GstValueArray * value_array) \
       
   444 { \
       
   445   gint i; \
       
   446   GstClockTime ts = timestamp; \
       
   447   g##type *values = (g##type *) value_array->values; \
       
   448   \
       
   449   g_mutex_lock (self->lock); \
       
   450   for(i = 0; i < value_array->nbsamples; i++) { \
       
   451     *values = _triangle_get_##type (self, ts); \
       
   452     ts += value_array->sample_interval; \
       
   453     values++; \
       
   454   } \
       
   455   g_mutex_unlock (self->lock); \
       
   456   return TRUE; \
       
   457 }
       
   458 
       
   459 DEFINE_TRIANGLE (int, TRUE, EMPTY);
       
   460 
       
   461 DEFINE_TRIANGLE (uint, TRUE, EMPTY);
       
   462 DEFINE_TRIANGLE (long, TRUE, EMPTY);
       
   463 
       
   464 DEFINE_TRIANGLE (ulong, TRUE, EMPTY);
       
   465 DEFINE_TRIANGLE (int64, TRUE, EMPTY);
       
   466 DEFINE_TRIANGLE (uint64, TRUE, gst_util_guint64_to_gdouble);
       
   467 DEFINE_TRIANGLE (float, FALSE, EMPTY);
       
   468 DEFINE_TRIANGLE (double, FALSE, EMPTY);
       
   469 
       
   470 static GstWaveformImplementation waveform_triangle = {
       
   471   (GstControlSourceGetValue) waveform_triangle_get_int,
       
   472   (GstControlSourceGetValueArray) waveform_triangle_get_int_value_array,
       
   473   (GstControlSourceGetValue) waveform_triangle_get_uint,
       
   474   (GstControlSourceGetValueArray) waveform_triangle_get_uint_value_array,
       
   475   (GstControlSourceGetValue) waveform_triangle_get_long,
       
   476   (GstControlSourceGetValueArray) waveform_triangle_get_long_value_array,
       
   477   (GstControlSourceGetValue) waveform_triangle_get_ulong,
       
   478   (GstControlSourceGetValueArray) waveform_triangle_get_ulong_value_array,
       
   479   (GstControlSourceGetValue) waveform_triangle_get_int64,
       
   480   (GstControlSourceGetValueArray) waveform_triangle_get_int64_value_array,
       
   481   (GstControlSourceGetValue) waveform_triangle_get_uint64,
       
   482   (GstControlSourceGetValueArray) waveform_triangle_get_uint64_value_array,
       
   483   (GstControlSourceGetValue) waveform_triangle_get_float,
       
   484   (GstControlSourceGetValueArray) waveform_triangle_get_float_value_array,
       
   485   (GstControlSourceGetValue) waveform_triangle_get_double,
       
   486   (GstControlSourceGetValueArray) waveform_triangle_get_double_value_array
       
   487 };
       
   488 
       
   489 static GstWaveformImplementation *waveforms[] = {
       
   490   &waveform_sine,
       
   491   &waveform_square,
       
   492   &waveform_saw,
       
   493   &waveform_rsaw,
       
   494   &waveform_triangle
       
   495 };
       
   496 
       
   497 static guint num_waveforms = G_N_ELEMENTS (waveforms);
       
   498 
       
   499 enum
       
   500 {
       
   501   PROP_WAVEFORM = 1,
       
   502   PROP_FREQUENCY,
       
   503   PROP_TIMESHIFT,
       
   504   PROP_AMPLITUDE,
       
   505   PROP_OFFSET
       
   506 };
       
   507 #ifdef __SYMBIAN32__
       
   508 EXPORT_C
       
   509 #endif
       
   510 
       
   511 
       
   512 GType
       
   513 gst_lfo_waveform_get_type (void)
       
   514 {
       
   515   static GType gtype = 0;
       
   516 
       
   517   if (gtype == 0) {
       
   518     static const GEnumValue values[] = {
       
   519       {GST_LFO_WAVEFORM_SINE, "Sine waveform (default)",
       
   520           "sine"},
       
   521       {GST_LFO_WAVEFORM_SQUARE, "Square waveform",
       
   522           "square"},
       
   523       {GST_LFO_WAVEFORM_SAW, "Saw waveform",
       
   524           "saw"},
       
   525       {GST_LFO_WAVEFORM_REVERSE_SAW, "Reverse saw waveform",
       
   526           "reverse-saw"},
       
   527       {GST_LFO_WAVEFORM_TRIANGLE, "Triangle waveform",
       
   528           "triangle"},
       
   529       {0, NULL, NULL}
       
   530     };
       
   531 
       
   532     gtype = g_enum_register_static ("GstLFOWaveform", values);
       
   533   }
       
   534   return gtype;
       
   535 }
       
   536 
       
   537 static void gst_lfo_control_source_init (GstLFOControlSource * self);
       
   538 static void
       
   539 gst_lfo_control_source_class_init (GstLFOControlSourceClass * klass);
       
   540 
       
   541 G_DEFINE_TYPE (GstLFOControlSource, gst_lfo_control_source,
       
   542     GST_TYPE_CONTROL_SOURCE);
       
   543 
       
   544 static GObjectClass *parent_class = NULL;
       
   545 
       
   546 static void
       
   547 gst_lfo_control_source_reset (GstLFOControlSource * self)
       
   548 {
       
   549   GstControlSource *csource = GST_CONTROL_SOURCE (self);
       
   550 
       
   551   csource->get_value = NULL;
       
   552   csource->get_value_array = NULL;
       
   553 
       
   554   self->priv->type = self->priv->base = G_TYPE_INVALID;
       
   555 
       
   556   if (G_IS_VALUE (&self->priv->minimum_value))
       
   557     g_value_unset (&self->priv->minimum_value);
       
   558   if (G_IS_VALUE (&self->priv->maximum_value))
       
   559     g_value_unset (&self->priv->maximum_value);
       
   560 
       
   561   if (G_IS_VALUE (&self->priv->amplitude))
       
   562     g_value_unset (&self->priv->amplitude);
       
   563   if (G_IS_VALUE (&self->priv->offset))
       
   564     g_value_unset (&self->priv->offset);
       
   565 }
       
   566 
       
   567 /**
       
   568  * gst_lfo_control_source_new:
       
   569  *
       
   570  * This returns a new, unbound #GstLFOControlSource.
       
   571  *
       
   572  * Returns: a new, unbound #GstLFOControlSource.
       
   573  */
       
   574 #ifdef __SYMBIAN32__
       
   575 EXPORT_C
       
   576 #endif
       
   577 
       
   578 GstLFOControlSource *
       
   579 gst_lfo_control_source_new (void)
       
   580 {
       
   581   return g_object_new (GST_TYPE_LFO_CONTROL_SOURCE, NULL);
       
   582 }
       
   583 
       
   584 static gboolean
       
   585 gst_lfo_control_source_set_waveform (GstLFOControlSource * self,
       
   586     GstLFOWaveform waveform)
       
   587 {
       
   588   GstControlSource *csource = GST_CONTROL_SOURCE (self);
       
   589   gboolean ret = TRUE;
       
   590 
       
   591   if (waveform >= num_waveforms || waveform < 0) {
       
   592     GST_WARNING ("waveform %d invalid or not implemented yet", waveform);
       
   593     return FALSE;
       
   594   }
       
   595 
       
   596   if (self->priv->base == G_TYPE_INVALID) {
       
   597     GST_WARNING ("not bound to a property yet");
       
   598     return FALSE;
       
   599   }
       
   600 
       
   601   switch (self->priv->base) {
       
   602     case G_TYPE_INT:
       
   603       csource->get_value = waveforms[waveform]->get_int;
       
   604       csource->get_value_array = waveforms[waveform]->get_int_value_array;
       
   605       break;
       
   606     case G_TYPE_UINT:{
       
   607       csource->get_value = waveforms[waveform]->get_uint;
       
   608       csource->get_value_array = waveforms[waveform]->get_uint_value_array;
       
   609       break;
       
   610     }
       
   611     case G_TYPE_LONG:{
       
   612       csource->get_value = waveforms[waveform]->get_long;
       
   613       csource->get_value_array = waveforms[waveform]->get_long_value_array;
       
   614       break;
       
   615     }
       
   616     case G_TYPE_ULONG:{
       
   617       csource->get_value = waveforms[waveform]->get_ulong;
       
   618       csource->get_value_array = waveforms[waveform]->get_ulong_value_array;
       
   619       break;
       
   620     }
       
   621     case G_TYPE_INT64:{
       
   622       csource->get_value = waveforms[waveform]->get_int64;
       
   623       csource->get_value_array = waveforms[waveform]->get_int64_value_array;
       
   624       break;
       
   625     }
       
   626     case G_TYPE_UINT64:{
       
   627       csource->get_value = waveforms[waveform]->get_uint64;
       
   628       csource->get_value_array = waveforms[waveform]->get_uint64_value_array;
       
   629       break;
       
   630     }
       
   631     case G_TYPE_FLOAT:{
       
   632       csource->get_value = waveforms[waveform]->get_float;
       
   633       csource->get_value_array = waveforms[waveform]->get_float_value_array;
       
   634       break;
       
   635     }
       
   636     case G_TYPE_DOUBLE:{
       
   637       csource->get_value = waveforms[waveform]->get_double;
       
   638       csource->get_value_array = waveforms[waveform]->get_double_value_array;
       
   639       break;
       
   640     }
       
   641     default:
       
   642       ret = FALSE;
       
   643       break;
       
   644   }
       
   645 
       
   646   if (ret)
       
   647     self->priv->waveform = waveform;
       
   648   else
       
   649     GST_WARNING ("incomplete implementation for type '%s'",
       
   650         GST_STR_NULL (g_type_name (self->priv->type)));
       
   651 
       
   652   return ret;
       
   653 }
       
   654 
       
   655 static gboolean
       
   656 gst_lfo_control_source_bind (GstControlSource * source, GParamSpec * pspec)
       
   657 {
       
   658   GType type, base;
       
   659   GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (source);
       
   660   gboolean ret = TRUE;
       
   661 
       
   662   /* get the fundamental base type */
       
   663   self->priv->type = base = type = G_PARAM_SPEC_VALUE_TYPE (pspec);
       
   664   while ((type = g_type_parent (type)))
       
   665     base = type;
       
   666 
       
   667   self->priv->base = base;
       
   668   /* restore type */
       
   669   type = self->priv->type;
       
   670 
       
   671   switch (base) {
       
   672     case G_TYPE_INT:{
       
   673       GParamSpecInt *tpspec = G_PARAM_SPEC_INT (pspec);
       
   674 
       
   675       g_value_init (&self->priv->minimum_value, type);
       
   676       g_value_set_int (&self->priv->minimum_value, tpspec->minimum);
       
   677       g_value_init (&self->priv->maximum_value, type);
       
   678       g_value_set_int (&self->priv->maximum_value, tpspec->maximum);
       
   679 
       
   680       if (!G_IS_VALUE (&self->priv->amplitude)) {
       
   681         g_value_init (&self->priv->amplitude, type);
       
   682         g_value_set_int (&self->priv->amplitude, 0);
       
   683       }
       
   684 
       
   685       if (!G_IS_VALUE (&self->priv->offset)) {
       
   686         g_value_init (&self->priv->offset, type);
       
   687         g_value_set_int (&self->priv->offset, tpspec->default_value);
       
   688       }
       
   689       break;
       
   690     }
       
   691     case G_TYPE_UINT:{
       
   692       GParamSpecUInt *tpspec = G_PARAM_SPEC_UINT (pspec);
       
   693 
       
   694       g_value_init (&self->priv->minimum_value, type);
       
   695       g_value_set_uint (&self->priv->minimum_value, tpspec->minimum);
       
   696       g_value_init (&self->priv->maximum_value, type);
       
   697       g_value_set_uint (&self->priv->maximum_value, tpspec->maximum);
       
   698 
       
   699       if (!G_IS_VALUE (&self->priv->amplitude)) {
       
   700         g_value_init (&self->priv->amplitude, type);
       
   701         g_value_set_uint (&self->priv->amplitude, 0);
       
   702       }
       
   703 
       
   704       if (!G_IS_VALUE (&self->priv->offset)) {
       
   705         g_value_init (&self->priv->offset, type);
       
   706         g_value_set_uint (&self->priv->offset, tpspec->default_value);
       
   707       }
       
   708       break;
       
   709     }
       
   710     case G_TYPE_LONG:{
       
   711       GParamSpecLong *tpspec = G_PARAM_SPEC_LONG (pspec);
       
   712 
       
   713       g_value_init (&self->priv->minimum_value, type);
       
   714       g_value_set_long (&self->priv->minimum_value, tpspec->minimum);
       
   715       g_value_init (&self->priv->maximum_value, type);
       
   716       g_value_set_long (&self->priv->maximum_value, tpspec->maximum);
       
   717       if (!G_IS_VALUE (&self->priv->amplitude)) {
       
   718         g_value_init (&self->priv->amplitude, type);
       
   719         g_value_set_long (&self->priv->amplitude, 0);
       
   720       }
       
   721 
       
   722       if (!G_IS_VALUE (&self->priv->offset)) {
       
   723         g_value_init (&self->priv->offset, type);
       
   724         g_value_set_long (&self->priv->offset, tpspec->default_value);
       
   725       }
       
   726       break;
       
   727     }
       
   728     case G_TYPE_ULONG:{
       
   729       GParamSpecULong *tpspec = G_PARAM_SPEC_ULONG (pspec);
       
   730 
       
   731       g_value_init (&self->priv->minimum_value, type);
       
   732       g_value_set_ulong (&self->priv->minimum_value, tpspec->minimum);
       
   733       g_value_init (&self->priv->maximum_value, type);
       
   734       g_value_set_ulong (&self->priv->maximum_value, tpspec->maximum);
       
   735       if (!G_IS_VALUE (&self->priv->amplitude)) {
       
   736         g_value_init (&self->priv->amplitude, type);
       
   737         g_value_set_ulong (&self->priv->amplitude, 0);
       
   738       }
       
   739 
       
   740       if (!G_IS_VALUE (&self->priv->offset)) {
       
   741         g_value_init (&self->priv->offset, type);
       
   742         g_value_set_ulong (&self->priv->offset, tpspec->default_value);
       
   743       }
       
   744       break;
       
   745     }
       
   746     case G_TYPE_INT64:{
       
   747       GParamSpecInt64 *tpspec = G_PARAM_SPEC_INT64 (pspec);
       
   748 
       
   749       g_value_init (&self->priv->minimum_value, type);
       
   750       g_value_set_int64 (&self->priv->minimum_value, tpspec->minimum);
       
   751       g_value_init (&self->priv->maximum_value, type);
       
   752       g_value_set_int64 (&self->priv->maximum_value, tpspec->maximum);
       
   753       if (!G_IS_VALUE (&self->priv->amplitude)) {
       
   754         g_value_init (&self->priv->amplitude, type);
       
   755         g_value_set_int64 (&self->priv->amplitude, 0);
       
   756       }
       
   757 
       
   758       if (!G_IS_VALUE (&self->priv->offset)) {
       
   759         g_value_init (&self->priv->offset, type);
       
   760         g_value_set_int64 (&self->priv->offset, tpspec->default_value);
       
   761       }
       
   762       break;
       
   763     }
       
   764     case G_TYPE_UINT64:{
       
   765       GParamSpecUInt64 *tpspec = G_PARAM_SPEC_UINT64 (pspec);
       
   766 
       
   767       g_value_init (&self->priv->minimum_value, type);
       
   768       g_value_set_uint64 (&self->priv->minimum_value, tpspec->minimum);
       
   769       g_value_init (&self->priv->maximum_value, type);
       
   770       g_value_set_uint64 (&self->priv->maximum_value, tpspec->maximum);
       
   771       if (!G_IS_VALUE (&self->priv->amplitude)) {
       
   772         g_value_init (&self->priv->amplitude, type);
       
   773         g_value_set_uint64 (&self->priv->amplitude, 0);
       
   774       }
       
   775 
       
   776       if (!G_IS_VALUE (&self->priv->offset)) {
       
   777         g_value_init (&self->priv->offset, type);
       
   778         g_value_set_uint64 (&self->priv->offset, tpspec->default_value);
       
   779       }
       
   780       break;
       
   781     }
       
   782     case G_TYPE_FLOAT:{
       
   783       GParamSpecFloat *tpspec = G_PARAM_SPEC_FLOAT (pspec);
       
   784 
       
   785       g_value_init (&self->priv->minimum_value, type);
       
   786       g_value_set_float (&self->priv->minimum_value, tpspec->minimum);
       
   787       g_value_init (&self->priv->maximum_value, type);
       
   788       g_value_set_float (&self->priv->maximum_value, tpspec->maximum);
       
   789       if (!G_IS_VALUE (&self->priv->amplitude)) {
       
   790         g_value_init (&self->priv->amplitude, type);
       
   791         g_value_set_float (&self->priv->amplitude, 0.0);
       
   792       }
       
   793 
       
   794       if (!G_IS_VALUE (&self->priv->offset)) {
       
   795         g_value_init (&self->priv->offset, type);
       
   796         g_value_set_float (&self->priv->offset, tpspec->default_value);
       
   797       }
       
   798       break;
       
   799     }
       
   800     case G_TYPE_DOUBLE:{
       
   801       GParamSpecDouble *tpspec = G_PARAM_SPEC_DOUBLE (pspec);
       
   802 
       
   803       g_value_init (&self->priv->minimum_value, type);
       
   804       g_value_set_double (&self->priv->minimum_value, tpspec->minimum);
       
   805       g_value_init (&self->priv->maximum_value, type);
       
   806       g_value_set_double (&self->priv->maximum_value, tpspec->maximum);
       
   807       if (!G_IS_VALUE (&self->priv->amplitude)) {
       
   808         g_value_init (&self->priv->amplitude, type);
       
   809         g_value_set_float (&self->priv->amplitude, 0.0);
       
   810       }
       
   811 
       
   812       if (!G_IS_VALUE (&self->priv->offset)) {
       
   813         g_value_init (&self->priv->offset, type);
       
   814         g_value_set_float (&self->priv->offset, tpspec->default_value);
       
   815       }
       
   816       break;
       
   817     }
       
   818     default:
       
   819       GST_WARNING ("incomplete implementation for paramspec type '%s'",
       
   820           G_PARAM_SPEC_TYPE_NAME (pspec));
       
   821       ret = FALSE;
       
   822       break;
       
   823   }
       
   824 
       
   825   if (ret) {
       
   826     GValue amp = { 0, }
       
   827     , off = {
       
   828     0,};
       
   829 
       
   830     /* This should never fail unless the user already set amplitude or offset
       
   831      * with an incompatible type before _bind () */
       
   832     if (!g_value_type_transformable (G_VALUE_TYPE (&self->priv->amplitude),
       
   833             base)
       
   834         || !g_value_type_transformable (G_VALUE_TYPE (&self->priv->offset),
       
   835             base)) {
       
   836       GST_WARNING ("incompatible types for amplitude or offset");
       
   837       gst_lfo_control_source_reset (self);
       
   838       return FALSE;
       
   839     }
       
   840 
       
   841     /* Generate copies and transform to the correct type */
       
   842     g_value_init (&amp, base);
       
   843     g_value_transform (&self->priv->amplitude, &amp);
       
   844     g_value_init (&off, base);
       
   845     g_value_transform (&self->priv->offset, &off);
       
   846 
       
   847     ret = gst_lfo_control_source_set_waveform (self, self->priv->waveform);
       
   848 
       
   849     g_value_unset (&self->priv->amplitude);
       
   850     g_value_init (&self->priv->amplitude, self->priv->base);
       
   851     g_value_transform (&amp, &self->priv->amplitude);
       
   852 
       
   853     g_value_unset (&self->priv->offset);
       
   854     g_value_init (&self->priv->offset, self->priv->base);
       
   855     g_value_transform (&off, &self->priv->offset);
       
   856 
       
   857     g_value_unset (&amp);
       
   858     g_value_unset (&off);
       
   859   }
       
   860 
       
   861   if (!ret)
       
   862     gst_lfo_control_source_reset (self);
       
   863 
       
   864   return ret;
       
   865 }
       
   866 
       
   867 static void
       
   868 gst_lfo_control_source_init (GstLFOControlSource * self)
       
   869 {
       
   870   self->priv =
       
   871       G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_LFO_CONTROL_SOURCE,
       
   872       GstLFOControlSourcePrivate);
       
   873   self->priv->waveform = GST_LFO_WAVEFORM_SINE;
       
   874   self->priv->frequency = 1.0;
       
   875   self->priv->period = GST_SECOND / self->priv->frequency;
       
   876   self->priv->timeshift = 0;
       
   877 
       
   878   self->lock = g_mutex_new ();
       
   879 }
       
   880 
       
   881 static void
       
   882 gst_lfo_control_source_finalize (GObject * obj)
       
   883 {
       
   884   GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (obj);
       
   885 
       
   886   gst_lfo_control_source_reset (self);
       
   887 
       
   888   if (self->lock) {
       
   889     g_mutex_free (self->lock);
       
   890     self->lock = NULL;
       
   891   }
       
   892 
       
   893   G_OBJECT_CLASS (parent_class)->finalize (obj);
       
   894 }
       
   895 
       
   896 static void
       
   897 gst_lfo_control_source_dispose (GObject * obj)
       
   898 {
       
   899   G_OBJECT_CLASS (parent_class)->dispose (obj);
       
   900 }
       
   901 
       
   902 static void
       
   903 gst_lfo_control_source_set_property (GObject * object, guint prop_id,
       
   904     const GValue * value, GParamSpec * pspec)
       
   905 {
       
   906   GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (object);
       
   907 
       
   908   switch (prop_id) {
       
   909     case PROP_WAVEFORM:
       
   910       g_mutex_lock (self->lock);
       
   911       gst_lfo_control_source_set_waveform (self, g_value_get_enum (value));
       
   912       g_mutex_unlock (self->lock);
       
   913       break;
       
   914     case PROP_FREQUENCY:{
       
   915       gdouble frequency = g_value_get_double (value);
       
   916 
       
   917       g_return_if_fail (frequency > 0
       
   918           || ((GstClockTime) (GST_SECOND / frequency)) != 0);
       
   919 
       
   920       g_mutex_lock (self->lock);
       
   921       self->priv->frequency = frequency;
       
   922       self->priv->period = GST_SECOND / frequency;
       
   923       g_mutex_unlock (self->lock);
       
   924       break;
       
   925     }
       
   926     case PROP_TIMESHIFT:
       
   927       g_mutex_lock (self->lock);
       
   928       self->priv->timeshift = g_value_get_uint64 (value);
       
   929       g_mutex_unlock (self->lock);
       
   930       break;
       
   931     case PROP_AMPLITUDE:{
       
   932       GValue *val = g_value_get_boxed (value);
       
   933 
       
   934       if (self->priv->type != G_TYPE_INVALID) {
       
   935         g_return_if_fail (g_value_type_transformable (self->priv->type,
       
   936                 G_VALUE_TYPE (val)));
       
   937 
       
   938         g_mutex_lock (self->lock);
       
   939         if (G_IS_VALUE (&self->priv->amplitude))
       
   940           g_value_unset (&self->priv->amplitude);
       
   941 
       
   942         g_value_init (&self->priv->amplitude, self->priv->type);
       
   943         g_value_transform (val, &self->priv->amplitude);
       
   944         g_mutex_unlock (self->lock);
       
   945       } else {
       
   946         g_mutex_lock (self->lock);
       
   947         if (G_IS_VALUE (&self->priv->amplitude))
       
   948           g_value_unset (&self->priv->amplitude);
       
   949 
       
   950         g_value_init (&self->priv->amplitude, G_VALUE_TYPE (val));
       
   951         g_value_copy (val, &self->priv->amplitude);
       
   952         g_mutex_unlock (self->lock);
       
   953       }
       
   954 
       
   955       break;
       
   956     }
       
   957     case PROP_OFFSET:{
       
   958       GValue *val = g_value_get_boxed (value);
       
   959 
       
   960       if (self->priv->type != G_TYPE_INVALID) {
       
   961         g_return_if_fail (g_value_type_transformable (self->priv->type,
       
   962                 G_VALUE_TYPE (val)));
       
   963 
       
   964         g_mutex_lock (self->lock);
       
   965         if (G_IS_VALUE (&self->priv->offset))
       
   966           g_value_unset (&self->priv->offset);
       
   967 
       
   968         g_value_init (&self->priv->offset, self->priv->type);
       
   969         g_value_transform (val, &self->priv->offset);
       
   970         g_mutex_unlock (self->lock);
       
   971       } else {
       
   972         g_mutex_lock (self->lock);
       
   973         if (G_IS_VALUE (&self->priv->offset))
       
   974           g_value_unset (&self->priv->offset);
       
   975 
       
   976         g_value_init (&self->priv->offset, G_VALUE_TYPE (val));
       
   977         g_value_copy (val, &self->priv->offset);
       
   978         g_mutex_unlock (self->lock);
       
   979       }
       
   980 
       
   981       break;
       
   982     }
       
   983     default:
       
   984       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   985       break;
       
   986   }
       
   987 }
       
   988 
       
   989 static void
       
   990 gst_lfo_control_source_get_property (GObject * object, guint prop_id,
       
   991     GValue * value, GParamSpec * pspec)
       
   992 {
       
   993   GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (object);
       
   994 
       
   995   switch (prop_id) {
       
   996     case PROP_WAVEFORM:
       
   997       g_value_set_enum (value, self->priv->waveform);
       
   998       break;
       
   999     case PROP_FREQUENCY:
       
  1000       g_value_set_double (value, self->priv->frequency);
       
  1001       break;
       
  1002     case PROP_TIMESHIFT:
       
  1003       g_value_set_uint64 (value, self->priv->timeshift);
       
  1004       break;
       
  1005     case PROP_AMPLITUDE:
       
  1006       g_value_set_boxed (value, &self->priv->amplitude);
       
  1007       break;
       
  1008     case PROP_OFFSET:
       
  1009       g_value_set_boxed (value, &self->priv->offset);
       
  1010       break;
       
  1011     default:
       
  1012       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
  1013       break;
       
  1014   }
       
  1015 }
       
  1016 
       
  1017 static void
       
  1018 gst_lfo_control_source_class_init (GstLFOControlSourceClass * klass)
       
  1019 {
       
  1020   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
       
  1021   GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
       
  1022 
       
  1023   parent_class = g_type_class_peek_parent (klass);
       
  1024   g_type_class_add_private (klass, sizeof (GstLFOControlSourcePrivate));
       
  1025 
       
  1026   gobject_class->finalize = gst_lfo_control_source_finalize;
       
  1027   gobject_class->dispose = gst_lfo_control_source_dispose;
       
  1028   gobject_class->set_property = gst_lfo_control_source_set_property;
       
  1029   gobject_class->get_property = gst_lfo_control_source_get_property;
       
  1030 
       
  1031   csource_class->bind = gst_lfo_control_source_bind;
       
  1032 
       
  1033   /**
       
  1034    * GstLFOControlSource:waveform
       
  1035    *
       
  1036    * Specifies the waveform that should be used for this #GstLFOControlSource.
       
  1037    * 
       
  1038    **/
       
  1039   g_object_class_install_property (gobject_class, PROP_WAVEFORM,
       
  1040       g_param_spec_enum ("waveform", "Waveform", "Waveform",
       
  1041           GST_TYPE_LFO_WAVEFORM, GST_LFO_WAVEFORM_SINE, G_PARAM_READWRITE));
       
  1042 
       
  1043   /**
       
  1044    * GstLFOControlSource:frequency
       
  1045    *
       
  1046    * Specifies the frequency that should be used for the waveform
       
  1047    * of this #GstLFOControlSource. It should be large enough
       
  1048    * so that the period is longer than one nanosecond.
       
  1049    * 
       
  1050    **/
       
  1051   g_object_class_install_property (gobject_class, PROP_FREQUENCY,
       
  1052       g_param_spec_double ("frequency", "Frequency",
       
  1053           "Frequency of the waveform", 0.0, G_MAXDOUBLE, 1.0,
       
  1054           G_PARAM_READWRITE));
       
  1055 
       
  1056   /**
       
  1057    * GstLFOControlSource:timeshift
       
  1058    *
       
  1059    * Specifies the timeshift to the right that should be used for the waveform
       
  1060    * of this #GstLFOControlSource in nanoseconds.
       
  1061    *
       
  1062    * To get a n nanosecond shift to the left use
       
  1063    * "(GST_SECOND / frequency) - n".
       
  1064    *
       
  1065    **/
       
  1066   g_object_class_install_property (gobject_class, PROP_TIMESHIFT,
       
  1067       g_param_spec_uint64 ("timeshift", "Timeshift",
       
  1068           "Timeshift of the waveform to the right", 0, G_MAXUINT64, 0,
       
  1069           G_PARAM_READWRITE));
       
  1070 
       
  1071   /**
       
  1072    * GstLFOControlSource:amplitude
       
  1073    *
       
  1074    * Specifies the amplitude for the waveform of this #GstLFOControlSource.
       
  1075    *
       
  1076    * It should be given as a #GValue with a type that can be transformed
       
  1077    * to the type of the bound property.
       
  1078    **/
       
  1079   g_object_class_install_property (gobject_class, PROP_AMPLITUDE,
       
  1080       g_param_spec_boxed ("amplitude", "Amplitude", "Amplitude of the waveform",
       
  1081           G_TYPE_VALUE, G_PARAM_READWRITE));
       
  1082 
       
  1083   /**
       
  1084    * GstLFOControlSource:offset
       
  1085    *
       
  1086    * Specifies the offset for the waveform of this #GstLFOControlSource.
       
  1087    *
       
  1088    * It should be given as a #GValue with a type that can be transformed
       
  1089    * to the type of the bound property.
       
  1090    **/
       
  1091   g_object_class_install_property (gobject_class, PROP_OFFSET,
       
  1092       g_param_spec_boxed ("offset", "Offset", "Offset of the waveform",
       
  1093           G_TYPE_VALUE, G_PARAM_READWRITE));
       
  1094 }