gst_plugins_symbian/gst/devsound/gstdevsoundsink.c
changeset 0 0e761a78d257
child 7 71e347f905f2
child 29 567bb019e3e3
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
       
     3  *               2000,2005 Wim Taymans <wim@fluendo.com>
       
     4  *
       
     5  * gstdevsoundsink.c:
       
     6  *
       
     7  * This library is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Library General Public
       
     9  * License as published by the Free Software Foundation; either
       
    10  * version 2 of the License, or (at your option) any later version.
       
    11  *
       
    12  * This library is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    15  * Library General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Library General Public
       
    18  * License along with this library; if not, write to the
       
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    20  * Boston, MA 02111-1307, USA.
       
    21  */
       
    22 
       
    23 #ifdef HAVE_CONFIG_H
       
    24 #include "config.h"
       
    25 #endif
       
    26 
       
    27 #include "common.h"
       
    28 #include "gstdevsoundsink.h"
       
    29 #include "gsterrorconcealmentinterface.h"
       
    30 #include "gstg711decoderinterface.h"
       
    31 #include "gstg729decoderinterface.h"
       
    32 #include "gstilbcdecoderinterface.h"
       
    33 #include "string.h"
       
    34 #include <glib_global.h>
       
    35 
       
    36 GST_DEBUG_CATEGORY_EXTERN (devsound_debug);
       
    37 #define GST_CAT_DEFAULT devsound_debug
       
    38 
       
    39 /* elementfactory information */
       
    40 static const GstElementDetails gst_devsound_sink_details=
       
    41 GST_ELEMENT_DETAILS ("Audio Sink (DEVSOUND)",
       
    42         "Sink/Audio",
       
    43         "Output to a speaker via Devsound",
       
    44         " "
       
    45 );
       
    46 
       
    47 static void gst_devsound_sink_base_init(gpointer g_class);
       
    48 static void gst_devsound_sink_class_init(GstDevsoundSinkClass * klass);
       
    49 static void gst_devsound_sink_init(GstDevsoundSink * devsoundsink);
       
    50 
       
    51 static void gst_devsound_sink_dispose(GObject * object);
       
    52 static void gst_devsound_sink_finalise(GObject * object);
       
    53 
       
    54 static void gst_devsound_sink_get_property(GObject * object, guint prop_id,
       
    55         GValue * value, GParamSpec * pspec);
       
    56 static void gst_devsound_sink_set_property(GObject * object, guint prop_id,
       
    57         const GValue * value, GParamSpec * pspec);
       
    58 
       
    59 static GstCaps *gst_devsound_sink_getcaps(GstBaseSink * bsink);
       
    60 static gboolean gst_devsound_sink_setcaps(GstBaseSink *bsink, GstCaps *caps);
       
    61 
       
    62 
       
    63 static gboolean gst_devsound_sink_event(GstBaseSink * asink, GstEvent * event);
       
    64 
       
    65 static void *StartDevSoundThread(void *threadid);
       
    66 
       
    67 
       
    68 //Error concealment interface impl
       
    69 static void gst_error_concealment_handler_init (gpointer g_iface,
       
    70     gpointer iface_data);
       
    71 static gint gst_ConcealErrorForNextBuffer();
       
    72 static gint gst_SetFrameMode(gboolean aFrameMode);
       
    73 static gint gst_FrameModeRqrdForEC(gboolean* aFrameModeRqrd);
       
    74 static void gst_Apply_ErrorConcealment_Update(GstDevsoundSink* dssink);
       
    75 
       
    76 //G711 interface impl
       
    77 static void gst_g711_decoder_handler_init (gpointer g_iface,
       
    78     gpointer iface_data);
       
    79 static gint gst_SetDecoderMode(enum TG711DecodeMode aDecodeMode);
       
    80 static gint gst_SetCng(gboolean aCng);
       
    81 static gint gst_GetCng(gboolean* aCng);
       
    82 static gint gst_SetPlc(gboolean aPlc);
       
    83 static void gst_Apply_G711_Decoder_Update(GstDevsoundSink* dssink );
       
    84 
       
    85 
       
    86 //G729 interface impl
       
    87 static void gst_g729_decoder_handler_init (gpointer g_iface,
       
    88     gpointer iface_data);
       
    89 static gint gst_BadLsfNextBuffer();
       
    90 static void gst_Apply_G729_Decoder_Update(GstDevsoundSink* dssink );
       
    91 
       
    92 //Ilbc interface impl
       
    93 static void gst_ilbc_decoder_handler_init (gpointer g_iface,
       
    94     gpointer iface_data);
       
    95 static gint gst_GetIlbcCng(gboolean* aCng);
       
    96 static gint gst_SetIlbcCng(gboolean aCng);
       
    97 static gint gst_SetIlbcDecoderMode(enum TIlbcDecodeMode aDecodeMode);
       
    98 static void  gst_Apply_Ilbc_Decoder_Update(GstDevsoundSink* dssink );
       
    99 
       
   100 
       
   101 static gboolean gst_sink_start (GstBaseSink * sink);
       
   102 static gboolean gst_sink_stop (GstBaseSink * sink);
       
   103 static GstFlowReturn gst_sink_render (GstBaseSink * sink,
       
   104     GstBuffer * buffer);
       
   105 
       
   106 pthread_t ds_thread;
       
   107 pthread_mutex_t ds_mutex;
       
   108 pthread_cond_t ds_condition;
       
   109 
       
   110 enum consumer_thread_state_enum {
       
   111    CONSUMER_THREAD_UNINITIALIZED,
       
   112    CONSUMER_THREAD_INITIALIZING,
       
   113    CONSUMER_THREAD_INITIALIZED
       
   114 };
       
   115 enum consumer_thread_state_enum consumer_thread_state;
       
   116 
       
   117 
       
   118 
       
   119 GQueue *   buffer_queue = NULL;
       
   120 
       
   121 gboolean framemode;
       
   122 gboolean framemodereq;
       
   123 gboolean concealerror = FALSE;
       
   124 
       
   125 gboolean g711decodemode;
       
   126 gboolean g711cng;
       
   127 gboolean g711plc;
       
   128 gboolean ilbccng;
       
   129 enum TIlbcDecodeMode ilbcdecodemode;
       
   130 gint output;
       
   131 
       
   132 enum
       
   133     {
       
   134     LAST_SIGNAL
       
   135     };
       
   136 
       
   137 
       
   138 typedef struct _GstCustomIfaceUpdate GstCustomIfaceUpdate;
       
   139 
       
   140 struct _GstCustomIfaceUpdate{
       
   141 gboolean  framemodeupdate;
       
   142 gboolean  framemoderequpdate;
       
   143 gboolean  concealerrorupate;
       
   144 gboolean  g711decodemodeupdate;
       
   145 gboolean  g711setcngupdate;
       
   146 gboolean  g711setplcupdate;
       
   147 gboolean  g729badlsfnextbufferupdate;
       
   148 gboolean  ilbccngupdate;
       
   149 gboolean  ilbcdecodermodeupdate;
       
   150 };
       
   151 
       
   152 GstCustomIfaceUpdate customInfaceUpdate = {0,0,0,0,0,0,0,0,0};
       
   153 
       
   154 #define DEFAULT_DEVICE  "default"
       
   155 
       
   156 enum
       
   157     {
       
   158     PROP_0,
       
   159     PROP_DEVICE,
       
   160     VOLUME,
       
   161     MAXVOLUME,
       
   162     VOLUMERAMP,
       
   163     CHANNELS,
       
   164     LEFTBALANCE,
       
   165     RIGHTBALANCE,
       
   166     RATE,
       
   167     PRIORITY,
       
   168     PREFERENCE,
       
   169     SAMPLESPLAYED,
       
   170     FOURCC, //FOURCC is not needed
       
   171     MIMETYPE,
       
   172     OUTPUTDEVICE
       
   173     };
       
   174 
       
   175 enum command_to_consumer_thread_enum
       
   176     {
       
   177     OPEN = 2,
       
   178     WRITEDATA,
       
   179     /*UPDATE,*/
       
   180     CLOSE
       
   181     };
       
   182 enum command_to_consumer_thread_enum cmd;
       
   183 
       
   184 static GstStaticPadTemplate devsoundsink_sink_factory=
       
   185     GST_STATIC_PAD_TEMPLATE ("sink",
       
   186         GST_PAD_SINK,
       
   187         GST_PAD_ALWAYS,
       
   188         GST_STATIC_CAPS ("audio/x-raw-int, "
       
   189                 "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, "
       
   190                 "signed = (boolean) TRUE, "
       
   191                 "width = (int) 16, "
       
   192                 "depth = (int) 16, "
       
   193                 "rate = (int) [ 8000, 48000 ],"
       
   194                 "channels = (int) [ 1, 2 ]; "
       
   195                 "audio/amr, "
       
   196                 //"width = (int) 8, "
       
   197                 //"depth = (int) 8, "
       
   198                 "rate = (int) 8000, "
       
   199                 "channels = (int) 1 ; "
       
   200                 "audio/x-alaw, "
       
   201                 "rate = (int) [ 8000, 48000 ], "
       
   202                 "channels = (int) [ 1, 2 ]; "
       
   203                 "audio/g729, "
       
   204                 "rate = (int) [ 8000, 48000 ], "
       
   205                 "channels = (int) [ 1, 2 ]; "
       
   206                 "audio/mp3, "
       
   207                 "rate = (int) [ 8000, 48000 ], "
       
   208                 "channels = (int) [ 1, 2 ]; "                
       
   209                 "audio/ilbc, "
       
   210                 "rate = (int) [ 8000, 48000 ], "
       
   211                 "channels = (int) [ 1, 2 ]; "
       
   212                 "audio/x-mulaw, "
       
   213                 "rate = (int) [ 8000, 48000 ], "
       
   214                 "channels = (int) [ 1, 2 ]")
       
   215                 );
       
   216 
       
   217 static GstElementClass *parent_class= NULL;
       
   218 
       
   219 GType gst_devsound_sink_get_type(void)
       
   220     {
       
   221     static GType devsoundsink_type = 0;
       
   222 
       
   223     if (!devsoundsink_type)
       
   224         {
       
   225         static const GTypeInfo devsoundsink_info =
       
   226             {
       
   227                     sizeof(GstDevsoundSinkClass),
       
   228                     gst_devsound_sink_base_init,
       
   229                     NULL,
       
   230                     (GClassInitFunc) gst_devsound_sink_class_init,
       
   231                     NULL,
       
   232                     NULL,
       
   233                     sizeof(GstDevsoundSink),
       
   234                     0,
       
   235                     (GInstanceInitFunc) gst_devsound_sink_init
       
   236 ,        };
       
   237 
       
   238 
       
   239         static const GInterfaceInfo error_concealment_info = {
       
   240             gst_error_concealment_handler_init,
       
   241            NULL,
       
   242            NULL
       
   243              };
       
   244 
       
   245         static const GInterfaceInfo g711_decoder_info = {
       
   246              gst_g711_decoder_handler_init,
       
   247             NULL,
       
   248             NULL
       
   249             };
       
   250 
       
   251         static const GInterfaceInfo g729_decoder_info = {
       
   252                 gst_g729_decoder_handler_init,
       
   253                NULL,
       
   254                NULL
       
   255                };
       
   256 
       
   257         static const GInterfaceInfo ilbc_decoder_info = {
       
   258                 gst_ilbc_decoder_handler_init,
       
   259                NULL,
       
   260                NULL
       
   261                };
       
   262 
       
   263         devsoundsink_type =
       
   264         g_type_register_static (GST_TYPE_BASE_SINK, "GstDevsoundSink",
       
   265             &devsoundsink_info, 0);
       
   266 
       
   267 
       
   268         g_type_add_interface_static (devsoundsink_type, GST_TYPE_ERROR_CONCEALMENT,
       
   269          &error_concealment_info);
       
   270 
       
   271         g_type_add_interface_static (devsoundsink_type, GST_TYPE_G711_DECODER,
       
   272              &g711_decoder_info);
       
   273 
       
   274         g_type_add_interface_static (devsoundsink_type, GST_TYPE_G729_DECODER,
       
   275                &g729_decoder_info);
       
   276 
       
   277         g_type_add_interface_static (devsoundsink_type, GST_TYPE_ILBC_DECODER,
       
   278                &ilbc_decoder_info);
       
   279 
       
   280         }
       
   281 
       
   282     return devsoundsink_type;
       
   283     }
       
   284 
       
   285 static void gst_devsound_sink_dispose(GObject * object)
       
   286     {
       
   287     GstDevsoundSink *devsoundsink= GST_DEVSOUND_SINK (object);
       
   288 
       
   289     if (devsoundsink->probed_caps)
       
   290         {
       
   291         gst_caps_unref(devsoundsink->probed_caps);
       
   292         devsoundsink->probed_caps = NULL;
       
   293         }
       
   294 
       
   295     G_OBJECT_CLASS (parent_class)->dispose (object);
       
   296     }
       
   297 
       
   298 static void gst_devsound_sink_base_init(gpointer g_class)
       
   299     {
       
   300     GstElementClass *element_class= GST_ELEMENT_CLASS (g_class);
       
   301 
       
   302     gst_element_class_set_details(element_class, &gst_devsound_sink_details);
       
   303 
       
   304     gst_element_class_add_pad_template(element_class,
       
   305             gst_static_pad_template_get(&devsoundsink_sink_factory));
       
   306 
       
   307 
       
   308     }
       
   309 static void gst_devsound_sink_class_init(GstDevsoundSinkClass * klass)
       
   310     {
       
   311     GObjectClass *gobject_class;
       
   312     GstElementClass *gstelement_class;
       
   313     GstBaseSinkClass *gstbasesink_class;
       
   314 
       
   315 
       
   316     gobject_class = (GObjectClass *) klass;
       
   317     gstelement_class = (GstElementClass *) klass;
       
   318     gstbasesink_class = (GstBaseSinkClass *) klass;
       
   319 
       
   320 
       
   321     parent_class = g_type_class_peek_parent(klass);
       
   322 
       
   323     gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_devsound_sink_dispose);
       
   324     gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_devsound_sink_finalise);
       
   325     gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_devsound_sink_get_property);
       
   326     gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_devsound_sink_set_property);
       
   327 
       
   328     g_object_class_install_property(gobject_class, PROP_DEVICE,
       
   329             g_param_spec_string("device", "Device", "Devsound device ",
       
   330             DEFAULT_DEVICE, G_PARAM_READWRITE));
       
   331 
       
   332     g_object_class_install_property(gobject_class, VOLUME,
       
   333                 g_param_spec_int("volume", "Volume", "Devsound volume",
       
   334                         -1, G_MAXINT, -1, G_PARAM_READWRITE));
       
   335 
       
   336     g_object_class_install_property(gobject_class, VOLUMERAMP,
       
   337               g_param_spec_int("volumeramp", "VolumeRamp", "Devsound volume ramp",
       
   338                       -1, G_MAXINT, -1, G_PARAM_READWRITE));
       
   339 
       
   340     g_object_class_install_property(gobject_class, MAXVOLUME,
       
   341             g_param_spec_int("maxvolume", "MaxVolume", "Devsound max volume",
       
   342                     -1, G_MAXINT, -1, G_PARAM_READABLE));
       
   343 
       
   344     g_object_class_install_property(gobject_class, LEFTBALANCE,
       
   345                   g_param_spec_int("leftbalance", "Left Balance", "Left Balance",
       
   346                           -1, G_MAXINT, -1, G_PARAM_READWRITE));
       
   347 
       
   348     g_object_class_install_property(gobject_class, RIGHTBALANCE,
       
   349                    g_param_spec_int("rightbalance", "Right Balance", "Right Balance",
       
   350                            -1, G_MAXINT, -1, G_PARAM_READWRITE));
       
   351 
       
   352     g_object_class_install_property(gobject_class, SAMPLESPLAYED,
       
   353                       g_param_spec_int("samplesplayed", "Samples Played", "Samples Played",
       
   354                               -1, G_MAXINT, -1, G_PARAM_READABLE));
       
   355 
       
   356     g_object_class_install_property(gobject_class, PRIORITY,
       
   357             g_param_spec_int("priority", "Priority", "Priority ", -1,
       
   358                     G_MAXINT, -1,
       
   359                     G_PARAM_READWRITE));
       
   360 
       
   361     g_object_class_install_property(gobject_class, PREFERENCE,
       
   362             g_param_spec_int("preference", "Preference", "Preference ", -1,
       
   363                     G_MAXINT, -1,
       
   364                     G_PARAM_READWRITE));
       
   365 
       
   366     g_object_class_install_property(gobject_class, RATE,
       
   367             g_param_spec_int("rate", "Rate", "Rate ", -1,
       
   368                     G_MAXINT, -1,
       
   369                     G_PARAM_READWRITE));
       
   370 
       
   371     g_object_class_install_property(gobject_class, CHANNELS,
       
   372             g_param_spec_int("channels", "Channels", "Channels ", -1,
       
   373                     G_MAXINT, -1,
       
   374                     G_PARAM_READWRITE));
       
   375 
       
   376     g_object_class_install_property(gobject_class, OUTPUTDEVICE,
       
   377              g_param_spec_int("outputdevice", "Output Device", "Output Device ", -1,
       
   378                      G_MAXINT, -1,
       
   379                      G_PARAM_READWRITE));
       
   380     
       
   381     gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_sink_start);
       
   382     gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_sink_stop);
       
   383     gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_sink_render);
       
   384 
       
   385     gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_devsound_sink_getcaps);
       
   386     gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_devsound_sink_setcaps);
       
   387     gstbasesink_class->event    = GST_DEBUG_FUNCPTR (gst_devsound_sink_event);
       
   388     }
       
   389 
       
   390 static void gst_devsound_sink_init(GstDevsoundSink * devsoundsink)
       
   391     {
       
   392     GST_DEBUG_OBJECT(devsoundsink, "initializing devsoundsink");
       
   393     devsoundsink->device = g_strdup(DEFAULT_DEVICE);
       
   394     devsoundsink->handle = NULL;
       
   395     devsoundsink->preference = 0; //default=>EMdaPriorityPreferenceNone;
       
   396     devsoundsink->priority = 0;   //default=>EMdaPriorityNormal;
       
   397     pthread_mutex_init(&ds_mutex, NULL);
       
   398     pthread_cond_init(&ds_condition, NULL);
       
   399     }
       
   400 
       
   401 static void *StartDevSoundThread(void *threadarg)
       
   402     {
       
   403 
       
   404     GstDevsoundSink *devsound;
       
   405 
       
   406     gint remainingDataLen = 0;
       
   407     GstBuffer *buffer = NULL;
       
   408     gboolean lastBufferSet=FALSE;
       
   409     devsound = (GstDevsoundSink*) threadarg;
       
   410 
       
   411     open_devsound(&(devsound->handle));
       
   412 
       
   413 
       
   414     //get supported (in/out)put datatypes
       
   415     //from devsound to build caps
       
   416     getsupporteddatatypes(devsound);
       
   417 
       
   418     // TODO obtain mutex to update variable here???
       
   419     consumer_thread_state = CONSUMER_THREAD_INITIALIZED;
       
   420 
       
   421     // Signal any waiting threads that consumer thread creation was successful.
       
   422     pthread_mutex_lock(&ds_mutex);
       
   423     pthread_cond_signal(&ds_condition);
       
   424     pthread_mutex_unlock(&ds_mutex);
       
   425 
       
   426     // Wait until we receive a command from the main thread
       
   427     // TODO obtain mutex to read variable here???
       
   428     while ( cmd == OPEN )
       
   429         {
       
   430         pthread_mutex_lock(&ds_mutex);
       
   431         pthread_cond_wait(&ds_condition, &ds_mutex);
       
   432         pthread_mutex_unlock(&ds_mutex);
       
   433         }
       
   434 
       
   435     // This could happen if client creates sink and deletes it
       
   436     // without putting it to play state
       
   437     if ( cmd != CLOSE )
       
   438         {
       
   439         //TODO if there is preemption we have to somehow signal
       
   440         //the pipeline in the render
       
   441         initialize_devsound(devsound);
       
   442 
       
   443         playinit(devsound->handle);
       
   444         initproperties(devsound);
       
   445         }
       
   446     while (1)
       
   447         {
       
   448         switch (cmd)
       
   449             {
       
   450             case WRITEDATA:
       
   451                 {
       
   452                 pre_init_setconf(devsound);
       
   453                 gst_Apply_ErrorConcealment_Update(devsound);
       
   454                 gst_Apply_G711_Decoder_Update(devsound);
       
   455                 gst_Apply_G729_Decoder_Update(devsound);
       
   456                 gst_Apply_Ilbc_Decoder_Update(devsound);
       
   457 
       
   458                 // TODO we could do this in BTBF callback
       
   459                 populateproperties(devsound);
       
   460 
       
   461                 framemodereq = devsound->framemodereq;
       
   462                 g711cng = devsound->g711cng;
       
   463                 ilbccng = devsound->ilbccng;
       
   464                 output = devsound->output;
       
   465 
       
   466                 if(buffer_queue->length > 0)
       
   467                     {
       
   468                     if (remainingDataLen == 0)
       
   469                         {
       
   470                         // TODO enable lock and unlock
       
   471                         GST_OBJECT_LOCK (devsound);
       
   472                         buffer = GST_BUFFER_CAST(g_queue_peek_head(buffer_queue));
       
   473                         GST_OBJECT_UNLOCK(devsound);
       
   474                         remainingDataLen = GST_BUFFER_SIZE(buffer);
       
   475                         }
       
   476 
       
   477                     lastBufferSet =  GST_BUFFER_FLAG_IS_SET(buffer,GST_BUFFER_FLAG_LAST);
       
   478                     remainingDataLen = write_data(devsound->handle,
       
   479                             GST_BUFFER_DATA(buffer) + (GST_BUFFER_SIZE(buffer) - remainingDataLen),
       
   480                             remainingDataLen,
       
   481                             lastBufferSet);
       
   482 
       
   483                     if (remainingDataLen == 0)
       
   484                         {
       
   485                         GST_OBJECT_LOCK (devsound);
       
   486                         buffer = GST_BUFFER_CAST(g_queue_pop_head(buffer_queue));
       
   487                         GST_OBJECT_UNLOCK(devsound);
       
   488                         gst_buffer_unref(buffer);
       
   489                         buffer = NULL;
       
   490                         }
       
   491 
       
   492                     if (lastBufferSet && remainingDataLen == 0)
       
   493                         {
       
   494                         // Last Buffer is already sent to DevSound
       
   495                         // and we have received PlayError so now we exit
       
   496                         // from the big loop next time
       
   497 /*
       
   498                         pthread_mutex_lock(&ds_mutex);
       
   499                         pthread_cond_signal(&ds_condition);
       
   500                         pthread_mutex_unlock(&ds_mutex);
       
   501 */
       
   502                         cmd = CLOSE;
       
   503                        }
       
   504                     }
       
   505                 else
       
   506                     {
       
   507                     pthread_mutex_lock(&ds_mutex);
       
   508                     pthread_cond_wait(&ds_condition, &ds_mutex);
       
   509                     pthread_mutex_unlock(&ds_mutex);
       
   510                     }
       
   511                 }
       
   512                 break;
       
   513             case CLOSE:
       
   514                 {
       
   515                 close_devsound(devsound);
       
   516                 devsound->handle= NULL;
       
   517                 pthread_mutex_lock(&ds_mutex);
       
   518                 pthread_cond_signal(&ds_condition);
       
   519                 pthread_mutex_unlock(&ds_mutex);
       
   520                 // TODO obtain mutex here
       
   521                 consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED;
       
   522                 pthread_exit(NULL);
       
   523                 }
       
   524                 break;
       
   525             default:
       
   526                 // TODO obtain mutex here
       
   527                 consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED;
       
   528                 pthread_exit(NULL);
       
   529                 break;
       
   530             }
       
   531         }
       
   532     // TODO obtain mutex here
       
   533     consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED;
       
   534     pthread_exit(NULL);
       
   535     }
       
   536 
       
   537 static gboolean gst_sink_start (GstBaseSink * sink)
       
   538     {
       
   539     GstBuffer *tmp_gstbuffer=NULL;
       
   540     GstDevsoundSink *devsound = GST_DEVSOUND_SINK(sink);
       
   541 
       
   542     if(buffer_queue)
       
   543         {
       
   544         while (buffer_queue->length)
       
   545             {
       
   546             tmp_gstbuffer = (GstBuffer*)g_queue_pop_tail(buffer_queue);
       
   547             gst_buffer_unref(tmp_gstbuffer);
       
   548             }
       
   549         g_queue_free(buffer_queue);
       
   550         buffer_queue = NULL;
       
   551         }
       
   552     
       
   553     if(buffer_queue == NULL)
       
   554           {
       
   555           buffer_queue = g_queue_new();
       
   556           }
       
   557 
       
   558     consumer_thread_state = CONSUMER_THREAD_INITIALIZING;
       
   559     cmd = OPEN;
       
   560     pthread_create(&ds_thread,  NULL, StartDevSoundThread, (void *)devsound);
       
   561 
       
   562     // Wait until consumer thread is created
       
   563     // TODO : obtain mutex to retreive thread state?
       
   564     if (consumer_thread_state == CONSUMER_THREAD_INITIALIZING)
       
   565         {
       
   566         pthread_mutex_lock(&ds_mutex);
       
   567         pthread_cond_wait(&ds_condition, &ds_mutex);
       
   568         pthread_mutex_unlock(&ds_mutex);
       
   569         }
       
   570 
       
   571     return TRUE;
       
   572     }
       
   573 
       
   574 static gboolean gst_sink_stop (GstBaseSink * sink)
       
   575     {
       
   576     GstBuffer *tmp_gstbuffer=NULL;
       
   577     GstDevsoundSink *devsound = GST_DEVSOUND_SINK(sink);
       
   578 
       
   579     cmd = CLOSE;
       
   580 
       
   581     pthread_mutex_lock(&ds_mutex);
       
   582     pthread_cond_signal(&ds_condition);
       
   583     pthread_mutex_unlock(&ds_mutex);
       
   584 
       
   585     GST_OBJECT_LOCK(devsound);
       
   586     while (buffer_queue->length)
       
   587         {
       
   588         tmp_gstbuffer = (GstBuffer*)g_queue_pop_tail(buffer_queue);
       
   589         gst_buffer_unref(tmp_gstbuffer);
       
   590         }
       
   591     g_queue_free(buffer_queue);
       
   592     buffer_queue = NULL;
       
   593     GST_OBJECT_UNLOCK(devsound);
       
   594 
       
   595     return TRUE;
       
   596     }
       
   597 
       
   598 static GstFlowReturn gst_sink_render (GstBaseSink * sink,
       
   599     GstBuffer * buffer)
       
   600     {
       
   601     GstDevsoundSink *devsound = GST_DEVSOUND_SINK(sink);
       
   602     GstBuffer* tmp;
       
   603 
       
   604     if (get_ds_cb_error(devsound->handle))
       
   605         {
       
   606         return GST_FLOW_CUSTOM_ERROR;
       
   607         }
       
   608         
       
   609     tmp = gst_buffer_copy(buffer);
       
   610  
       
   611     GST_OBJECT_LOCK (devsound);
       
   612     g_queue_push_tail (buffer_queue, tmp);
       
   613     GST_OBJECT_UNLOCK (devsound);
       
   614 
       
   615     cmd = WRITEDATA;
       
   616     pthread_mutex_lock(&ds_mutex);
       
   617     pthread_cond_signal(&ds_condition);
       
   618     pthread_mutex_unlock(&ds_mutex);
       
   619 
       
   620     return GST_FLOW_OK;
       
   621     }
       
   622 
       
   623 static void gst_devsound_sink_finalise(GObject * object)
       
   624     {
       
   625     GstDevsoundSink *devsoundsink= GST_DEVSOUND_SINK (object);
       
   626     g_free(devsoundsink->device);
       
   627 
       
   628     }
       
   629 
       
   630 static void gst_devsound_sink_set_property(GObject * object, guint prop_id,
       
   631         const GValue * value, GParamSpec * pspec)
       
   632     {
       
   633     GstDevsoundSink *sink;
       
   634 
       
   635     sink = GST_DEVSOUND_SINK (object);
       
   636 
       
   637     switch (prop_id)
       
   638         {
       
   639         case PROP_DEVICE:
       
   640             if (sink->device)
       
   641                 g_free(sink->device);
       
   642             sink->device = g_value_dup_string(value);
       
   643             if (sink->probed_caps)
       
   644                 {
       
   645                 gst_caps_unref(sink->probed_caps);
       
   646                 sink->probed_caps = NULL;
       
   647                 }
       
   648             break;
       
   649         case CHANNELS:
       
   650             sink->channels = g_value_get_int(value);
       
   651             sink->pending.channelsupdate = TRUE;
       
   652             break;
       
   653         case RATE:
       
   654             sink->rate = g_value_get_int(value);
       
   655             //Convert rate to something devsound understands
       
   656             sink->rate = gst_devsound_sink_get_rate(sink->rate);
       
   657             sink->pending.rateupdate = TRUE;
       
   658             break;
       
   659         case VOLUME:
       
   660             sink->volume = g_value_get_int(value);
       
   661             sink->pending.volumeupdate = TRUE;
       
   662             break;
       
   663         case LEFTBALANCE:
       
   664             sink->leftbalance = g_value_get_int(value);
       
   665             sink->pending.leftbalanceupdate = TRUE;
       
   666             break;
       
   667         case RIGHTBALANCE:
       
   668             sink->rightbalance = g_value_get_int(value);
       
   669             sink->pending.rightbalanceupdate = TRUE;
       
   670             break;
       
   671         case VOLUMERAMP:
       
   672             sink->volumeramp = g_value_get_int(value);
       
   673             sink->pending.volumerampupdate = TRUE;
       
   674             break;
       
   675         case PRIORITY:
       
   676             sink->priority = g_value_get_int(value);
       
   677             sink->pending.priorityupdate = TRUE;
       
   678             break;
       
   679         case PREFERENCE:
       
   680             sink->preference = g_value_get_int(value);
       
   681             sink->pending.preferenceupdate = TRUE;
       
   682             break;
       
   683         case FOURCC: //FOURCC is not needed
       
   684             sink->fourcc = g_value_get_int(value);
       
   685             sink->pending.fourccupdate = TRUE;
       
   686             break;
       
   687 
       
   688         case MIMETYPE:
       
   689             sink->mimetype = g_value_dup_string(value);
       
   690             break;
       
   691         case OUTPUTDEVICE:
       
   692             sink->output = g_value_get_int(value);
       
   693             sink->pending.outputupdate = TRUE;
       
   694             break;
       
   695         default:
       
   696             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   697             break;
       
   698         }
       
   699 
       
   700     }
       
   701 
       
   702 static void gst_devsound_sink_get_property(GObject * object, guint prop_id,
       
   703         GValue * value, GParamSpec * pspec)
       
   704     {
       
   705     GstDevsoundSink *sink;
       
   706     sink = GST_DEVSOUND_SINK (object);
       
   707 
       
   708     switch (prop_id)
       
   709         {
       
   710         case PROP_DEVICE:
       
   711             g_value_set_string(value, sink->device);
       
   712             break;
       
   713         case CHANNELS:
       
   714             g_value_set_int(value, sink->channels);
       
   715             break;
       
   716         case RATE:
       
   717             g_value_set_int(value, sink->rate);
       
   718             break;
       
   719         case VOLUME:
       
   720             g_value_set_int(value, sink->volume);
       
   721             break;
       
   722         case MAXVOLUME:
       
   723             g_value_set_int(value, sink->maxvolume);
       
   724             break;
       
   725         case SAMPLESPLAYED:
       
   726               g_value_set_int(value, sink->samplesplayed);
       
   727               break;
       
   728         case OUTPUTDEVICE:
       
   729               g_value_set_int(value, sink->output);
       
   730               break;
       
   731         default:
       
   732             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   733             break;
       
   734         }
       
   735     }
       
   736 
       
   737 static gboolean gst_devsound_sink_setcaps(GstBaseSink *bsink, GstCaps *caps)
       
   738     {
       
   739     GstDevsoundSink *devsoundsink;
       
   740     GstStructure *structure;
       
   741     const gchar *mimetype;
       
   742     int width,depth,endianness,sign,channels,rate;
       
   743 
       
   744     devsoundsink = GST_DEVSOUND_SINK (bsink);
       
   745 
       
   746     structure = gst_caps_get_structure (caps, 0);
       
   747     mimetype = gst_structure_get_name (structure);
       
   748 
       
   749     gst_structure_get_int (structure, "width", &width);
       
   750     gst_structure_get_int (structure, "depth", &depth);
       
   751     gst_structure_get_int (structure, "endianness", &endianness);
       
   752     gst_structure_get_int (structure, "rate", &rate);
       
   753     gst_structure_get_int (structure, "channels",&channels);
       
   754     gst_structure_get_boolean (structure, "signed", &sign);
       
   755 
       
   756 
       
   757     devsoundsink->rate = gst_devsound_sink_get_rate(rate);
       
   758     devsoundsink->channels = channels;
       
   759 
       
   760     set_channels(devsoundsink->handle,devsoundsink->channels);
       
   761 
       
   762     set_rate(devsoundsink->handle,devsoundsink->rate);
       
   763 
       
   764     if (!strncmp (mimetype, "audio/x-raw-int", 15))
       
   765         {
       
   766         devsoundsink->fourcc = 0x36315020; //KMMFFourCCCodePCM16
       
   767         }
       
   768     else if (!strncmp(mimetype,"audio/amr",9))
       
   769         {
       
   770         devsoundsink->fourcc = 0x524d4120; //KMMFFourCCCodeAMR
       
   771         }
       
   772     else if (!strncmp (mimetype, "audio/x-mulaw", 13)||
       
   773              !strncmp (mimetype, "audio/x-alaw", 12))
       
   774         {
       
   775         devsoundsink->fourcc = 0x31313747; //KMccFourCCIdG711
       
   776         }
       
   777     else if (!strncmp(mimetype, "audio/ilbc", 10))
       
   778         {
       
   779         devsoundsink->fourcc = 0x43424c49; //KMccFourCCIdILBC
       
   780         }
       
   781     else if (!strncmp(mimetype, "audio/g729", 10))
       
   782         {
       
   783         devsoundsink->fourcc = 0x39323747; //KMccFourCCIdG729   
       
   784         }
       
   785     else if (!strncmp(mimetype, "audio/mp3", 9))
       
   786         {
       
   787         devsoundsink->fourcc = 0x33504d20; //KMMFFourCCCodeMP3    
       
   788         }
       
   789     else
       
   790         {
       
   791         devsoundsink->fourcc = 0x36315020; //KMMFFourCCCodePCM16
       
   792         }
       
   793 
       
   794     set_fourcc(devsoundsink->handle,devsoundsink->fourcc);
       
   795 
       
   796     pthread_mutex_lock(&ds_mutex);
       
   797     pthread_cond_signal(&ds_condition);
       
   798     pthread_mutex_unlock(&ds_mutex);
       
   799 
       
   800     return TRUE;
       
   801     }
       
   802 static GstCaps * gst_devsound_sink_getcaps(GstBaseSink * bsink)
       
   803     {
       
   804     GstDevsoundSink *devsoundsink;
       
   805     GstCaps *caps;
       
   806     GstPadTemplate *pad_template;
       
   807 
       
   808    // GstStructure *str;
       
   809    //GstCaps *caps2;
       
   810    //GstCaps *caps3;
       
   811 
       
   812     devsoundsink = GST_DEVSOUND_SINK (bsink);
       
   813 
       
   814     GST_DEBUG_OBJECT(devsoundsink, "getcaps called");
       
   815 
       
   816     pad_template = gst_static_pad_template_get(&devsoundsink_sink_factory);
       
   817     caps = gst_caps_copy(gst_pad_template_get_caps(pad_template));
       
   818 
       
   819     return caps;
       
   820     //************
       
   821  /*   caps2 = gst_caps_new_empty();
       
   822     total = g_list_length(devsoundsink->fmt);
       
   823 
       
   824     for (;devsoundsink->fmt; devsoundsink->fmt = g_list_next(devsoundsink->fmt))
       
   825         {
       
   826         data = (guint*)devsoundsink->fmt->data;
       
   827         switch ((gint)data)
       
   828             {
       
   829             case 0x36315020: //KMMFFourCCCodePCM16
       
   830                 str = gst_structure_new("audio/x-raw-int",
       
   831                         "signed",G_TYPE_BOOLEAN, TRUE,
       
   832                         "width", G_TYPE_INT, 16,
       
   833                         "depth", G_TYPE_INT, 16,
       
   834                         "channels", GST_TYPE_INT_RANGE,1, 2,
       
   835                         "rate", GST_TYPE_INT_RANGE,8000, 48000, NULL);
       
   836                 break;
       
   837 
       
   838             case 0x524d4120: //KMMFFourCCCodeAMR
       
   839                 str = gst_structure_new("audio/amr",
       
   840                         "width", G_TYPE_INT, 8,
       
   841                         "depth", G_TYPE_INT, 8,
       
   842                         "channels", G_TYPE_INT, 1,
       
   843                         "rate", G_TYPE_INT, 8000,
       
   844                         NULL);
       
   845                 break;
       
   846             case 0x31313747: //KMccFourCCIdG711
       
   847                 str = gst_structure_new("audio/g711",
       
   848                         "width", G_TYPE_INT, 8,
       
   849                         "depth", G_TYPE_INT, 8,
       
   850                         "channels", G_TYPE_INT, 1,
       
   851                         "rate", G_TYPE_INT, 8000,
       
   852                         NULL);
       
   853                 break;
       
   854             default:
       
   855                 str = NULL;
       
   856                 break;
       
   857             }
       
   858 
       
   859         if(str!=NULL)
       
   860             gst_caps_append_structure(caps2, str);
       
   861         }
       
   862 
       
   863     caps3 = gst_caps_union(caps,caps2);
       
   864     //  gst_object_unref(pad_template);
       
   865 
       
   866     return caps3;
       
   867     */
       
   868     }
       
   869 
       
   870 
       
   871 static gint gst_devsound_sink_get_rate(gint rate)
       
   872     {
       
   873     gint result;
       
   874 
       
   875     switch (rate)
       
   876         {
       
   877         case 8000:
       
   878             result=0x00000001;//EMMFSampleRate8000Hz;
       
   879             break;
       
   880         case 11025:
       
   881             result=0x00000002;//EMMFSampleRate11025Hz;
       
   882             break;
       
   883         case 16000:
       
   884             result=0x00000004;//EMMFSampleRate16000Hz;
       
   885             break;
       
   886         case 22050:
       
   887             result=0x00000008;//EMMFSampleRate22050Hz;
       
   888             break;
       
   889         case 32000:
       
   890             result=0x00000010;//EMMFSampleRate32000Hz;
       
   891             break;
       
   892         case 44100:
       
   893             result=0x00000020;//EMMFSampleRate44100Hz;
       
   894             break;
       
   895         case 48000:
       
   896             result=0x00000040;//EMMFSampleRate48000Hz;
       
   897             break;
       
   898         case 88200:
       
   899             result=0x00000080;//EMMFSampleRate88200Hz;
       
   900             break;
       
   901         case 96000:
       
   902             result= 0x00000100;//EMMFSampleRate96000Hz;
       
   903             break;
       
   904         case 12000:
       
   905             result=0x00000200;//EMMFSampleRate12000Hz;
       
   906             break;
       
   907         case 24000:
       
   908             result=0x00000400;//EMMFSampleRate24000Hz;
       
   909             break;
       
   910         case 64000:
       
   911             result=0x00000800; //EMMFSampleRate64000Hz;
       
   912             break;
       
   913         default:
       
   914             result=0x00000001;//EMMFSampleRate8000Hz;
       
   915             break;
       
   916 
       
   917         }
       
   918     return result;
       
   919 
       
   920     }
       
   921 
       
   922 
       
   923 
       
   924 static gboolean gst_devsound_sink_event(GstBaseSink *asink, GstEvent *event)
       
   925     {
       
   926     GstDevsoundSink *sink= GST_DEVSOUND_SINK (asink);
       
   927     GstBuffer* lastBuffer = NULL;
       
   928     switch (GST_EVENT_TYPE (event))
       
   929         {
       
   930         case GST_EVENT_EOS:
       
   931             // end-of-stream, we should close down all stream leftovers here
       
   932             //reset_devsound(sink->handle);
       
   933 
       
   934             if(buffer_queue->length)
       
   935                 {
       
   936                 GST_OBJECT_LOCK(sink);
       
   937                 lastBuffer = GST_BUFFER(g_queue_peek_tail(buffer_queue));
       
   938                 GST_BUFFER_FLAG_SET(lastBuffer,GST_BUFFER_FLAG_LAST);
       
   939                 GST_OBJECT_UNLOCK(sink);
       
   940                 }
       
   941             else
       
   942                 {
       
   943                 lastBuffer = gst_buffer_new();
       
   944                 GST_BUFFER_FLAG_SET(lastBuffer,GST_BUFFER_FLAG_LAST);
       
   945                 GST_OBJECT_LOCK(sink);
       
   946                 g_queue_push_tail(buffer_queue,lastBuffer);
       
   947                 GST_OBJECT_UNLOCK(sink);
       
   948                 cmd = WRITEDATA;
       
   949                 pthread_mutex_lock(&ds_mutex);
       
   950                 pthread_cond_signal(&ds_condition);
       
   951                 pthread_mutex_unlock(&ds_mutex);
       
   952                 }
       
   953             pthread_mutex_lock(&ds_mutex);
       
   954             pthread_cond_wait(&ds_condition, &ds_mutex);
       
   955             pthread_mutex_unlock(&ds_mutex);
       
   956 
       
   957             break;
       
   958         default:
       
   959             break;
       
   960         }
       
   961 
       
   962     return TRUE;
       
   963     }
       
   964 
       
   965 
       
   966 /************************************
       
   967 * Error Concealment Interface begins
       
   968 * **********************************/
       
   969 static void gst_error_concealment_handler_init (gpointer g_iface,
       
   970     gpointer iface_data)
       
   971     {
       
   972     GstErrorConcealmentIntfc *iface = (GstErrorConcealmentIntfc *) g_iface;
       
   973 
       
   974     iface->ConcealErrorForNextBuffer = gst_ConcealErrorForNextBuffer;
       
   975     iface->SetFrameMode = gst_SetFrameMode;
       
   976     iface->FrameModeRqrdForEC = gst_FrameModeRqrdForEC;
       
   977 
       
   978     }
       
   979 
       
   980 
       
   981 static gint gst_ConcealErrorForNextBuffer()
       
   982     {
       
   983     customInfaceUpdate.concealerrorupate = TRUE;
       
   984     return 0;
       
   985     }
       
   986 
       
   987 static gint gst_SetFrameMode(gboolean aFrameMode)
       
   988     {
       
   989     customInfaceUpdate.framemodeupdate = TRUE;
       
   990     framemode = aFrameMode;
       
   991     return 0;
       
   992     }
       
   993 
       
   994 static gint gst_FrameModeRqrdForEC(gboolean* aFrameModeRqrd)
       
   995     {
       
   996     *aFrameModeRqrd = framemodereq;
       
   997     return 0;
       
   998     }
       
   999 
       
  1000 static void gst_Apply_ErrorConcealment_Update(GstDevsoundSink* dssink)
       
  1001     {
       
  1002 
       
  1003     if(customInfaceUpdate.concealerrorupate == TRUE)
       
  1004         {
       
  1005         conceal_error_for_next_buffer(dssink->handle);
       
  1006         customInfaceUpdate.concealerrorupate = FALSE;
       
  1007         }
       
  1008     if(customInfaceUpdate.framemodeupdate == TRUE)
       
  1009         {
       
  1010         set_framemode(dssink->handle,framemode);
       
  1011         customInfaceUpdate.framemodeupdate = FALSE;
       
  1012         }
       
  1013     }
       
  1014 
       
  1015 /***********************************************************
       
  1016  * G711 Decoder interface begins
       
  1017  * *********************************************************/
       
  1018 static void gst_g711_decoder_handler_init (gpointer g_iface,
       
  1019     gpointer iface_data)
       
  1020     {
       
  1021     GstG711DecoderIntfc *iface = (GstG711DecoderIntfc *) g_iface;
       
  1022 
       
  1023     iface->GetCng         = gst_GetCng;
       
  1024     iface->SetCng         = gst_SetCng;
       
  1025     iface->SetDecoderMode = gst_SetDecoderMode;
       
  1026     iface->SetPlc         = gst_SetPlc;
       
  1027 
       
  1028     }
       
  1029 
       
  1030 static gint gst_SetDecoderMode(enum TG711DecodeMode aDecodeMode)
       
  1031     {
       
  1032     customInfaceUpdate.g711decodemodeupdate = TRUE;
       
  1033     g711decodemode  = aDecodeMode;
       
  1034     return 0;
       
  1035     }
       
  1036 static gint gst_SetCng(gboolean aCng)
       
  1037     {
       
  1038     customInfaceUpdate.g711setcngupdate = TRUE;
       
  1039     g711cng = aCng;
       
  1040     return 0;
       
  1041     }
       
  1042 static gint gst_GetCng(gboolean* aCng)
       
  1043     {
       
  1044     *aCng = g711cng;
       
  1045     return 0;
       
  1046     }
       
  1047 static gint gst_SetPlc(gboolean aPlc)
       
  1048     {
       
  1049     customInfaceUpdate.g711setplcupdate = TRUE;
       
  1050     g711plc = aPlc;
       
  1051     return 0;
       
  1052     }
       
  1053 
       
  1054 static void gst_Apply_G711_Decoder_Update(GstDevsoundSink* dssink )
       
  1055     {
       
  1056 
       
  1057     if(customInfaceUpdate.g711decodemodeupdate == TRUE)
       
  1058         {
       
  1059         set_decodermode(dssink->handle,g711decodemode);
       
  1060         customInfaceUpdate.g711decodemodeupdate = FALSE;
       
  1061         }
       
  1062     if(customInfaceUpdate.g711setcngupdate == TRUE)
       
  1063         {
       
  1064         set_cng(dssink->handle,g711cng);
       
  1065         customInfaceUpdate.g711setcngupdate = FALSE;
       
  1066         }
       
  1067     if(customInfaceUpdate.g711setplcupdate == TRUE)
       
  1068         {
       
  1069         set_plc(dssink->handle,g711plc);
       
  1070         customInfaceUpdate.g711setplcupdate = FALSE;
       
  1071         }
       
  1072 
       
  1073     }
       
  1074 
       
  1075 //G729 interface impl
       
  1076 static void gst_g729_decoder_handler_init (gpointer g_iface,
       
  1077     gpointer iface_data)
       
  1078     {
       
  1079     GstG729DecoderIntfc *iface = (GstG729DecoderIntfc *) g_iface;
       
  1080 
       
  1081     iface->BadLsfNextBuffer = gst_BadLsfNextBuffer;
       
  1082 
       
  1083     }
       
  1084 
       
  1085 static gint gst_BadLsfNextBuffer()
       
  1086     {
       
  1087     customInfaceUpdate.g729badlsfnextbufferupdate = TRUE;
       
  1088     }
       
  1089 
       
  1090 static void gst_Apply_G729_Decoder_Update(GstDevsoundSink* dssink )
       
  1091     {
       
  1092     if(customInfaceUpdate.g729badlsfnextbufferupdate)
       
  1093         {
       
  1094         badlsfnextbuffer(dssink->handle);
       
  1095         customInfaceUpdate.g729badlsfnextbufferupdate = FALSE;
       
  1096         }
       
  1097 
       
  1098     }
       
  1099 
       
  1100 //Ilbc interface impl
       
  1101 static void gst_ilbc_decoder_handler_init (gpointer g_iface,
       
  1102     gpointer iface_data)
       
  1103     {
       
  1104     GstIlbcDecoderIntfc *iface = (GstIlbcDecoderIntfc *) g_iface;
       
  1105 
       
  1106     iface->GetCng = gst_GetIlbcCng;
       
  1107     iface->SetCng = gst_SetIlbcCng;
       
  1108     iface->SetDecoderMode = gst_SetIlbcDecoderMode;
       
  1109 
       
  1110     }
       
  1111 
       
  1112 static gint gst_GetIlbcCng(gboolean* aCng)
       
  1113     {
       
  1114     *aCng = ilbccng;
       
  1115     return 0;
       
  1116     }
       
  1117 
       
  1118 static gint gst_SetIlbcCng(gboolean aCng)
       
  1119     {
       
  1120     customInfaceUpdate.ilbccngupdate = TRUE;
       
  1121     ilbccng = aCng;
       
  1122     return 0;
       
  1123     }
       
  1124 static gint gst_SetIlbcDecoderMode(enum TIlbcDecodeMode aDecodeMode)
       
  1125     {
       
  1126     customInfaceUpdate.ilbcdecodermodeupdate = TRUE;
       
  1127     ilbcdecodemode = aDecodeMode;
       
  1128     return 0;
       
  1129     }
       
  1130 
       
  1131 static void gst_Apply_Ilbc_Decoder_Update(GstDevsoundSink* dssink )
       
  1132     {
       
  1133 
       
  1134     if(customInfaceUpdate.ilbccngupdate)
       
  1135         {
       
  1136         set_ilbccng(dssink->handle,ilbccng);
       
  1137         customInfaceUpdate.ilbccngupdate = FALSE;
       
  1138         }
       
  1139     if(customInfaceUpdate.ilbcdecodermodeupdate)
       
  1140         {
       
  1141         set_ilbcdecodermode(dssink->handle,ilbcdecodemode);
       
  1142         customInfaceUpdate.ilbcdecodermodeupdate = FALSE;
       
  1143         }
       
  1144     }