tizen2.0 init
[framework/multimedia/gst-plugins-ext0.10.git] / avsystem / src / gstavsysaudiosink.c
1 /*
2  * avsystem
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>
7  *
8  * This library is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Lesser General Public License as published by the
10  * Free Software Foundation; either version 2.1 of the License, or (at your option)
11  * any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
14  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this library; if not, write to the Free Software Foundation, Inc., 51
20  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23
24
25
26 #include <gst/gst.h>
27 #include <gst/gstutils.h>
28
29 #include <string.h>
30
31 #include "gstavsysaudiosink.h"
32
33 #define _ALSA_DAPM_
34 #define __REPLACE_RESET_WITH_CLOSE_AND_REOPEN__
35
36 #define CONVERT_MUTE_VALUE(_mute) ((_mute) ? AVSYS_AUDIO_MUTE : AVSYS_AUDIO_UNMUTE)
37
38 GST_DEBUG_CATEGORY_EXTERN (avsystem_sink_debug);
39 #define GST_CAT_DEFAULT avsystem_sink_debug
40
41 #define DEFAULT_USER_ROUTE      AVSYSAUDIOSINK_USERROUTE_AUTO
42 #define DEFAULT_AUDIO_ROUTE     AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING
43 #define DEFAULT_VOLUME_TYPE             AVSYS_AUDIO_VOLUME_TYPE_MEDIA
44 #define DEFAULT_MEDIACALL_MODE  AVSYS_AUDIO_ECHO_MODE_NONE
45 #define DEFAULT_FADEUP_VOLUME   FALSE
46 #define DEFAULT_AUDIO_MUTE      AVSYSAUDIOSINK_AUDIO_UNMUTE
47 #define DEFAULT_AUDIO_LATENCY   AVSYSAUDIOSINK_LATENCY_MID
48
49
50 //GST_DEBUG_CATEGORY_STATIC (gst_avsystemsink_debug);
51
52 /* element factory information */
53 static const GstElementDetails gst_avsysaudiosink_details =
54     GST_ELEMENT_DETAILS ("AV-system Audio OUT",
55                          "Sink/Audio",
56                          "Output to AV System",
57                          "Samsung Electronics co., ltd");
58
59 enum
60 {
61     PROP_0,
62     PROP_AUDIO_MUTE,
63     PROP_AUDIO_VOLUME_TYPE,
64     PROP_AUDIO_PRIORITY,
65     PROP_AUDIO_FADEUPVOLUME,
66     PROP_AUDIO_ROUTE_POLICY,
67     PROP_AUDIO_USER_ROUTE,
68     PROP_AUDIO_LATENCY,
69     PROP_AUDIO_HANDLE,
70     PROP_AUDIO_CALLBACK
71 };
72
73 GType
74 gst_avsysaudiosink_audio_mute_get_type (void)
75 {
76   static GType avaudio_mute_type = 0;
77   static const GEnumValue avaudio_mute[] = {
78     {AVSYSAUDIOSINK_AUDIO_UNMUTE, "Unmute", "unmute"},
79     {AVSYSAUDIOSINK_AUDIO_MUTE, "Mute immediately", "mute"},
80     {AVSYSAUDIOSINK_AUDIO_MUTE_WITH_FADEDOWN_EFFECT, "Mute with fadedown effect", "fadedown"},
81     {0, NULL, NULL},
82   };
83
84   if (!avaudio_mute_type) {
85           avaudio_mute_type =
86         g_enum_register_static ("GstAvsysAudioSinkAudioMute", avaudio_mute);
87   }
88   return avaudio_mute_type;
89 }
90
91 GType
92 gst_avsysaudiosink_user_route_get_type (void)
93 {
94         static GType user_route_type = 0;
95         static const GEnumValue user_route[] = {
96                 {AVSYSAUDIOSINK_USERROUTE_AUTO, "Route automatically", "auto"},
97                 {AVSYSAUDIOSINK_USERROUTE_PHONE, "Route to phone only", "phone"},
98                   {0, NULL, NULL},
99         };
100
101         if (!user_route_type) {
102                 user_route_type =
103                                 g_enum_register_static ("GstAvsysAudioSinkUserRoutePolicy",user_route);
104         }
105         return user_route_type;
106 }
107
108 GType
109 gst_avsysaudiosink_audio_route_get_type (void)
110 {
111   static GType playback_audio_route_type = 0;
112   static const GEnumValue playback_audio_route[] = {
113     {AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING, "Use external sound path", "external"},
114     {AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_NORMAL, "Auto change between speaker & earphone", "normal"},
115     {AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_ALERT, "Play via both speaker & earphone", "alert"},
116     {AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_HEADSET_ONLY, "Play via earphone only", "headset"},
117     {0, NULL, NULL},
118   };
119
120   if (!playback_audio_route_type) {
121           playback_audio_route_type =
122         g_enum_register_static ("GstAvsysAudioSinkAudioRoutePolicy", playback_audio_route);
123   }
124   return playback_audio_route_type;
125 }
126
127
128 GType
129 gst_avsysaudiosink_volume_table_get_type (void)
130 {
131   static GType avsysaudio_volume_table_type = 0;
132   static const GEnumValue avsysaudio_volume_table[] = {
133     {AVSYS_AUDIO_VOLUME_TYPE_SYSTEM, "System Volume", "system"},
134     {AVSYS_AUDIO_VOLUME_TYPE_NOTIFICATION, "Notification Volume", "notification"},
135     {AVSYS_AUDIO_VOLUME_TYPE_ALARM, "Alarm Volume", "alarm"},
136     {AVSYS_AUDIO_VOLUME_TYPE_RINGTONE, "Ringtone Volume", "ringtone"},
137     {AVSYS_AUDIO_VOLUME_TYPE_MEDIA, "Media Volume", "media"},
138     {AVSYS_AUDIO_VOLUME_TYPE_CALL, "Call Volume", "call"},
139     {AVSYS_AUDIO_VOLUME_TYPE_FIXED, "Fixed Volume", "fixed"},
140     {AVSYS_AUDIO_VOLUME_TYPE_EXT_SYSTEM_JAVA, "Java Volume", "java"},
141     {0, NULL, NULL},
142   };
143
144   if (!avsysaudio_volume_table_type) {
145           avsysaudio_volume_table_type =
146         g_enum_register_static ("GstAvsysAudioSinkVolumeTable", avsysaudio_volume_table);
147   }
148   return avsysaudio_volume_table_type;
149 }
150
151 GType
152 gst_avsysaudiosink_latency_get_type (void)
153 {
154   static GType avsysaudio_latency_type = 0;
155   static const GEnumValue avsysaudio_latency[] = {
156     {AVSYSAUDIOSINK_LATENCY_LOW, "Low latency", "low"},
157     {AVSYSAUDIOSINK_LATENCY_MID, "Mid latency", "mid"},
158     {AVSYSAUDIOSINK_LATENCY_HIGH, "High latency", "high"},
159     {0, NULL, NULL},
160   };
161
162   if (!avsysaudio_latency_type) {
163           avsysaudio_latency_type =
164         g_enum_register_static ("GstAvsysAudioSinkLatency", avsysaudio_latency);
165   }
166   return avsysaudio_latency_type;
167 }
168
169 static void gst_avsysaudiosink_init_interfaces (GType type);
170
171 //#define GST_BOILERPLATE_FULL(type, type_as_function, parent_type, parent_type_macro, additional_initializations)
172
173 GST_BOILERPLATE_FULL (GstAvsysAudioSink, gst_avsysaudiosink, GstAudioSink,
174                                           GST_TYPE_AUDIO_SINK, gst_avsysaudiosink_init_interfaces);
175
176
177 static void gst_avsysaudiosink_finalise (GObject * object);
178 static void gst_avsysaudiosink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
179 static void gst_avsysaudiosink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
180 #if 0   /*not use*/
181 static GstCaps *gst_avsysaudiosink_getcaps (GstBaseSink * bsink);
182 #endif
183
184 static gboolean gst_avsysaudiosink_avsys_close(GstAvsysAudioSink *avsys_audio);
185 static gboolean gst_avsysaudiosink_avsys_open(GstAvsysAudioSink *avsys_audio);
186
187 static gboolean gst_avsysaudiosink_open (GstAudioSink * asink);
188 static gboolean gst_avsysaudiosink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec);
189 static gboolean gst_avsysaudiosink_unprepare (GstAudioSink * asink);
190 static gboolean gst_avsysaudiosink_close (GstAudioSink * asink);
191 static guint gst_avsysaudiosink_write (GstAudioSink * asink, gpointer data, guint length);
192 static guint gst_avsysaudiosink_delay (GstAudioSink * asink);
193 static void gst_avsysaudiosink_reset (GstAudioSink * asink);
194 static gboolean avsysaudiosink_post_message(GstAvsysAudioSink* self,int errorcode);
195
196
197 #define AVSYS_AUDIO_FACTORY_ENDIANNESS  "LITTLE_ENDIAN"
198
199
200 static GstStaticPadTemplate avsysaudiosink_sink_factory =
201         GST_STATIC_PAD_TEMPLATE ("sink",
202                                                          GST_PAD_SINK,
203                                                          GST_PAD_ALWAYS,
204                                                          GST_STATIC_CAPS ("audio/x-raw-int, "
205                                                                          "endianness = (int) { " AVSYS_AUDIO_FACTORY_ENDIANNESS " }, "
206                                                                          "signed = (boolean) { TRUE }, "
207                                                                          "width = (int) 16, "
208                                                                          "depth = (int) 16, "
209                                                                          "rate = (int) [ 1, MAX ], "
210                                                                          "channels = (int) [ 1, 2 ]; "
211                                                                          "audio/x-raw-int, "
212                                                                          "signed = (boolean) { FALSE }, "
213                                                                          "width = (int) 8, "
214                                                                          "depth = (int) 8, "
215                                                                          "rate = (int) [ 1, MAX ], "
216                                                                          "channels = (int) [ 1, 2 ] "
217                                                                  )
218                                                          );
219 /*
220 static inline guint _time_to_sample(GstAvsysAudioSink * asink,  GstClockTime diff)
221 {
222         guint result = 0;
223         result =(GST_TIME_AS_USECONDS(diff) * asink->audio_param.samplerate)/1000000;
224         return result;
225 }
226 */
227
228 static void
229 gst_avsysaudiosink_finalise (GObject * object)
230 {
231     GstAvsysAudioSink *sink = NULL;
232
233     sink = GST_AVSYS_AUDIO_SINK (object);
234     gst_avsysaudiosink_avsys_close(sink);
235     g_mutex_free (sink->avsys_audio_lock);
236     g_mutex_free (sink->avsys_audio_reset_lock);
237
238     G_OBJECT_CLASS (parent_class)->finalize (object);
239 }
240
241 static void
242 gst_avsysaudiosink_init_interfaces (GType type)
243 {
244         /* None */
245 }
246
247 static void
248 gst_avsysaudiosink_base_init (gpointer g_class)
249 {
250     GstElementClass *element_class = NULL;
251
252     element_class = GST_ELEMENT_CLASS (g_class);
253     gst_element_class_set_details (element_class, &gst_avsysaudiosink_details);
254     gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&avsysaudiosink_sink_factory));
255 }
256
257 static GstStateChangeReturn
258 gst_avsyssudiosink_change_state (GstElement *element, GstStateChange transition);
259
260
261 static void
262 gst_avsysaudiosink_class_init (GstAvsysAudioSinkClass * klass)
263 {
264     GObjectClass *gobject_class;
265     GstElementClass *gstelement_class;
266     GstBaseSinkClass *gstbasesink_class;
267     GstBaseAudioSinkClass *gstbaseaudiosink_class;
268     GstAudioSinkClass *gstaudiosink_class;
269
270     gobject_class = (GObjectClass *) klass;
271     gstelement_class = (GstElementClass *) klass;
272     gstbasesink_class = (GstBaseSinkClass *) klass;
273     gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
274     gstaudiosink_class = (GstAudioSinkClass *) klass;
275
276     parent_class = g_type_class_peek_parent (klass);
277     gstelement_class->change_state  = GST_DEBUG_FUNCPTR(gst_avsyssudiosink_change_state);
278
279     gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_finalise);
280     gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_get_property);
281     gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_set_property);
282
283 //      gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_getcaps);
284
285     gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_open);
286     gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_prepare);
287     gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_unprepare);
288     gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_close);
289     gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_write);
290     gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_delay);
291     gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_reset);
292
293         g_object_class_install_property (  gobject_class, PROP_AUDIO_VOLUME_TYPE,
294                         g_param_spec_enum ("volumetype", "Avsystem Volume Type",
295                                         "Select avsystem audio software volume type",
296                                         GST_AVSYS_AUDIO_SINK_VOLUME_TYPE, DEFAULT_VOLUME_TYPE,
297                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
298
299         g_object_class_install_property (  gobject_class, PROP_AUDIO_PRIORITY,
300                         g_param_spec_int ("priority", "Avsystem Sound Priority", "Avsystem sound priority",
301                                         AVSYS_AUDIO_PRIORITY_NORMAL, AVSYS_AUDIO_PRIORITY_SOLO_WITH_TRANSITION_EFFECT,
302                                         AVSYS_AUDIO_PRIORITY_NORMAL, G_PARAM_READWRITE));
303
304         g_object_class_install_property (  gobject_class, PROP_AUDIO_HANDLE,
305                         g_param_spec_pointer("audio-handle", "Avsystem handle",
306                                         "Avsystem audio handle", 
307                                         G_PARAM_READWRITE));
308
309         g_object_class_install_property (  gobject_class, PROP_AUDIO_CALLBACK,
310                         g_param_spec_pointer("audio-callback", "Avsystem callback",
311                                         "Avsystem audio callback", 
312                                         G_PARAM_READWRITE));
313
314         g_object_class_install_property (gobject_class, PROP_AUDIO_FADEUPVOLUME,
315                         g_param_spec_boolean ("fadeup", "Avsystem fadeup volume",
316                                         "Enable avsystem audio fadeup volume when pause to play",
317                                         DEFAULT_FADEUP_VOLUME, G_PARAM_READWRITE));
318
319         g_object_class_install_property (gobject_class ,PROP_AUDIO_MUTE,
320                         g_param_spec_enum("mute", "Avsystem mute",
321                                         "Avsystem audio mute",
322                                         GST_AVSYS_AUDIO_SINK_MUTE, DEFAULT_AUDIO_MUTE,
323                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
324
325         g_object_class_install_property (gobject_class ,PROP_AUDIO_ROUTE_POLICY,
326                         g_param_spec_enum("audio-route", "Audio Route Policy",
327                                         "Audio route policy of system",
328                                         GST_AVSYS_AUDIO_SINK_AUDIO_ROUTE, DEFAULT_AUDIO_ROUTE,
329                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
330         
331         g_object_class_install_property (gobject_class ,PROP_AUDIO_USER_ROUTE,
332                         g_param_spec_enum("user-route", "User Route Policy",
333                                         "User route policy",
334                                         GST_AVSYS_AUDIO_SINK_USER_ROUTE, DEFAULT_USER_ROUTE,
335                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
336
337         g_object_class_install_property (gobject_class ,PROP_AUDIO_LATENCY,
338                         g_param_spec_enum("latency", "Audio Backend Latency",
339                                         "Audio backend latency",
340                                         GST_AVSYS_AUDIO_SINK_LATENCY_TYPE, DEFAULT_AUDIO_LATENCY,
341                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
342 }
343
344 static void
345 gst_avsysaudiosink_set_property (GObject * object, guint prop_id,
346                                                          const GValue * value, GParamSpec * pspec)
347 {
348     GstAvsysAudioSink *sink = NULL;
349     int nvalue = 0;
350     gboolean nbool = FALSE;
351
352     sink = GST_AVSYS_AUDIO_SINK (object);
353
354     switch (prop_id)
355     {
356     case PROP_AUDIO_HANDLE:
357                 sink->cbHandle = g_value_get_pointer(value);
358                 break;
359     case PROP_AUDIO_CALLBACK:
360                 sink->audio_stream_cb = g_value_get_pointer(value);
361                 break;
362         
363         case PROP_AUDIO_VOLUME_TYPE:
364             nvalue = g_value_get_enum(value);
365             sink->volume_type = nvalue;
366         break;
367
368     case PROP_AUDIO_PRIORITY:
369                 nvalue = g_value_get_int(value);
370         sink->sound_priority = nvalue;
371         break;
372
373     case PROP_AUDIO_MUTE:
374         nvalue = g_value_get_enum(value);
375         if(sink->audio_handle != (avsys_handle_t)-1)
376         {
377             if(AVSYS_SUCCESS(avsys_audio_set_mute_fadedown(sink->audio_handle)))
378                 sink->mute = nvalue;
379         }
380         else
381         {
382             sink->mute = nvalue;
383         }
384         break;
385     case PROP_AUDIO_FADEUPVOLUME:
386         nbool = g_value_get_boolean(value);
387         sink->use_fadeup_volume = nbool;
388         break;
389
390     case PROP_AUDIO_ROUTE_POLICY:
391         nvalue = g_value_get_enum(value);
392         sink->audio_route_policy = nvalue;
393                 switch(sink->audio_route_policy)
394                 {
395                 case AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING:
396                         GST_INFO_OBJECT(sink, "use external audio route setting");
397                         break;
398                 default:
399                         g_print("AVSYSAUDIOSINK :: Unknown audio route option %d\n", sink->audio_route_policy);
400                         GST_ERROR_OBJECT(sink, "Unknown audio route option %d", sink->audio_route_policy);
401                         break;
402                 }
403         break;
404         case PROP_AUDIO_USER_ROUTE:
405                 nvalue = g_value_get_enum(value);
406                 sink->user_route_policy = nvalue;                       
407                 break;
408         case PROP_AUDIO_LATENCY:
409                 nvalue = g_value_get_enum(value);
410                 sink->latency = nvalue;
411                 break;
412         default:
413                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
414                 break;
415         }
416 }
417
418 static void
419 gst_avsysaudiosink_get_property (GObject * object, guint prop_id,
420                                                          GValue * value, GParamSpec * pspec)
421 {
422     GstAvsysAudioSink *sink = NULL;
423
424     sink = GST_AVSYS_AUDIO_SINK (object);
425
426     switch (prop_id) {
427         case PROP_AUDIO_VOLUME_TYPE:
428         g_value_set_enum(value, sink->volume_type);
429         break;
430     case PROP_AUDIO_PRIORITY:
431         g_value_set_int(value, sink->sound_priority);
432         break;
433     case PROP_AUDIO_MUTE:
434         g_value_set_enum(value, sink->mute);
435         break;
436     case PROP_AUDIO_FADEUPVOLUME:
437         g_value_set_boolean(value, sink->use_fadeup_volume);
438         break;
439
440     case PROP_AUDIO_ROUTE_POLICY:
441         g_value_set_enum(value, sink->audio_route_policy);
442         break;
443         case PROP_AUDIO_USER_ROUTE:
444                 g_value_set_enum(value, sink->user_route_policy);
445                 break;
446         case PROP_AUDIO_LATENCY:
447                 g_value_set_enum(value, sink->latency);
448                 break;
449
450     default:
451         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
452         break;
453     }
454 }
455
456 static void
457 gst_avsysaudiosink_init (GstAvsysAudioSink * avsysaudiosink, GstAvsysAudioSinkClass * g_class)
458 {
459         GST_DEBUG_OBJECT (avsysaudiosink, "initializing avsysaudiosink");
460
461         avsysaudiosink->audio_handle = (avsys_handle_t)-1;
462         avsysaudiosink->cached_caps = NULL;
463         avsysaudiosink->avsys_audio_lock = g_mutex_new ();
464         avsysaudiosink->avsys_audio_reset_lock = g_mutex_new ();
465         avsysaudiosink->volume_type = DEFAULT_VOLUME_TYPE;
466         avsysaudiosink->sound_priority = AVSYS_AUDIO_PRIORITY_NORMAL;
467         avsysaudiosink->mute = DEFAULT_AUDIO_MUTE;
468         avsysaudiosink->use_fadeup_volume = DEFAULT_FADEUP_VOLUME;
469         avsysaudiosink->latency = DEFAULT_AUDIO_LATENCY;
470         avsysaudiosink->audio_route_policy = DEFAULT_AUDIO_ROUTE;
471         avsysaudiosink->bytes_per_sample = 1;
472 #if defined (LPCM_DUMP_SUPPORT)
473         avsysaudiosink->dumpFp = NULL;
474 #endif
475
476 }
477 #if 0
478 static GstCaps *
479 gst_avsysaudiosink_getcaps (GstBaseSink * bsink)
480 {
481     GstElementClass *element_class = NULL;
482     GstPadTemplate *pad_template = NULL;
483     GstAvsysAudioSink *sink = GST_AVSYS_AUDIO_SINK (bsink);
484     GstCaps *caps;
485
486 //    debug_fenter();
487
488     sink = GST_AVSYS_AUDIO_SINK (bsink);
489     if (sink->audio_handle == -1)
490     {
491         GST_DEBUG_OBJECT (sink, "avsystem audio not open, using template caps");
492         return NULL;              /* base class will get template caps for us */
493     }
494
495     if (sink->cached_caps)
496     {
497         GST_LOG_OBJECT (sink, "Returning cached caps");
498         return gst_caps_ref (sink->cached_caps);
499     }
500
501     element_class = GST_ELEMENT_GET_CLASS (sink);
502     pad_template = gst_element_class_get_pad_template (element_class, "sink");
503     g_return_val_if_fail (pad_template != NULL, NULL);
504
505         // todo : get supported format.
506         //caps = gst_avsysaudio_probe_supported_formats (GST_OBJECT (sink), sink->,
507         //gst_pad_template_get_caps (pad_template));
508
509         //if (caps) {
510         //sink->cached_caps = gst_caps_ref (caps);
511         //}
512
513     GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
514
515     return caps;
516 }
517 #endif
518
519 static gboolean
520 avsysaudiosink_parse_spec (GstAvsysAudioSink * avsys_audio, GstRingBufferSpec * spec)
521 {
522     /* Check param */
523     if (spec->type != GST_BUFTYPE_LINEAR ||
524         spec->channels > 2 || spec->channels < 1 ||
525         !(spec->format == GST_S8 || spec->format == GST_S16_LE) )
526         return FALSE;
527
528     switch(spec->format)
529     {
530     case GST_S8:
531         avsys_audio->audio_param.format = AVSYS_AUDIO_FORMAT_8BIT;
532         avsys_audio->bytes_per_sample = 1;
533         break;
534     case GST_S16_LE:
535         avsys_audio->audio_param.format = AVSYS_AUDIO_FORMAT_16BIT;
536         avsys_audio->bytes_per_sample = 2;
537         break;
538     default:
539         return FALSE;
540     }
541
542     /// set audio parameter for avsys audio open
543         switch(avsys_audio->latency)
544         {
545         case AVSYSAUDIOSINK_LATENCY_LOW:
546                 avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT_VIDEO;
547                 break;
548         case AVSYSAUDIOSINK_LATENCY_MID:
549                 avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT;
550                 break;
551         case AVSYSAUDIOSINK_LATENCY_HIGH:
552                 avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT_CLOCK;
553                 break;
554         }
555
556
557
558     avsys_audio->audio_param.priority = 0;
559     avsys_audio->audio_param.samplerate = spec->rate;
560     avsys_audio->audio_param.channels = spec->channels;
561
562     if(spec->channels == 2)
563         avsys_audio->bytes_per_sample *= 2;
564     else if(spec->channels > 2)
565     {
566         GST_ERROR_OBJECT(avsys_audio,"Unsupported channel number %d", spec->channels);
567         return FALSE;
568     }
569
570     /* set software volume table type */
571     avsys_audio->audio_param.vol_type = avsys_audio->volume_type;
572     avsys_audio->audio_param.priority = avsys_audio->sound_priority;
573     avsys_audio->audio_param.handle_route = avsys_audio->user_route_policy;
574
575     return TRUE;
576 }
577
578 static gboolean
579 gst_avsysaudiosink_open (GstAudioSink * asink)
580 {
581         return TRUE;
582 }
583
584 static gboolean
585 gst_avsysaudiosink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
586 {
587     GstAvsysAudioSink *avsys_audio = NULL;
588     guint       p_time = 0, b_time = 0;
589
590     avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
591
592     // set avsys audio param
593     if (!avsysaudiosink_parse_spec (avsys_audio, spec))
594         goto spec_parse;
595
596     if (gst_avsysaudiosink_avsys_open(avsys_audio) == FALSE)
597     {
598         GST_ERROR_OBJECT(avsys_audio, "gst_avsysaudiosink_avsys_open() failed");
599         return FALSE;
600     }
601
602
603     /* Ring buffer size */
604     if (AVSYS_STATE_SUCCESS ==
605         avsys_audio_get_period_buffer_time(avsys_audio->audio_handle, &p_time, &b_time))
606     {
607         if(p_time == 0 || b_time == 0)
608                 return FALSE;
609
610         spec->latency_time = (guint64)p_time;
611         spec->buffer_time = (guint64)b_time;
612     }
613     else
614     {
615         return FALSE;
616     }
617     spec->segsize = avsys_audio->avsys_size; /* '/16' see avsys_audio_open */
618     spec->segtotal = (b_time / p_time) + (((b_time % p_time)/p_time > 0.5) ? 1: 0);
619         //spec->segtotal+2;
620
621         GST_WARNING_OBJECT (avsys_audio, "latency time %u, buffer time %u, seg total %u\n",
622                         (unsigned int)(spec->latency_time/1000), (unsigned int)(spec->buffer_time/1000), spec->segtotal);
623     return TRUE;
624
625 spec_parse:
626         {
627                 GST_ELEMENT_ERROR (avsys_audio, RESOURCE, SETTINGS, (NULL),
628                                                    ("Setting of swparams failed: " ));
629                 return FALSE;
630         }
631 }
632
633 static gboolean
634 gst_avsysaudiosink_unprepare (GstAudioSink * asink)
635 {
636     GstAvsysAudioSink   *avsys_audio = NULL;
637     gboolean                    result = TRUE;
638     avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
639
640     if(!gst_avsysaudiosink_avsys_close(avsys_audio))
641     {
642         GST_ERROR_OBJECT(avsys_audio, "gst_avsysaudiosink_avsys_close() failed");
643         result = FALSE;
644     }
645
646     return result;
647 }
648
649 static gboolean
650 gst_avsysaudiosink_close (GstAudioSink * asink)
651 {
652     GstAvsysAudioSink *avsys_audio = NULL;
653
654     avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
655     gst_caps_replace (&avsys_audio->cached_caps, NULL);
656
657     return TRUE;
658 }
659
660
661 /*
662  *   Underrun and suspend recovery
663  */
664
665 static guint
666 gst_avsysaudiosink_write (GstAudioSink * asink, gpointer data, guint length)
667 {
668     GstAvsysAudioSink *avsys_audio = NULL;
669     gint        write_len = 0;
670
671     avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
672     GST_AVSYS_AUDIO_SINK_LOCK (asink);
673
674     if(avsys_audio->audio_stream_cb == NULL)
675     {
676         write_len = avsys_audio_write(avsys_audio->audio_handle, data, length);
677     
678 #if defined (LPCM_DUMP_SUPPORT)
679         fwrite(data, 1, write_len, avsys_audio->dumpFp); //This is for original data (no volume convert)
680 #endif
681         if(write_len != length)
682         {
683             goto write_error;
684         }
685     
686         GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
687     
688         return write_len;
689 write_error:
690         {
691             GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
692
693             if(AVSYS_FAIL(write_len))
694                 {
695                         GST_ERROR_OBJECT(avsys_audio, "avsys_audio_write() failed with %d\n", write_len);
696                 }
697             return length;              /* skip one period */
698
699         }
700     }
701     else
702     {
703         gboolean result;
704         result = avsys_audio->audio_stream_cb(data, length, avsys_audio->cbHandle);
705         if(!result)
706         {
707                 GST_ERROR_OBJECT(avsys_audio,"auido stream callback failed\n");
708         }
709         GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
710         return length;
711     }
712 }
713
714 static guint
715 gst_avsysaudiosink_delay (GstAudioSink * asink)
716 {
717         GstAvsysAudioSink       *avsys_audio = NULL;
718         int                                     delay = 0;
719         guint                           retValue = 0;
720
721         avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
722         GST_AVSYS_AUDIO_SINK_RESET_LOCK (asink);
723         if((int)avsys_audio->audio_handle != -1) {
724                 if(AVSYS_STATE_SUCCESS == avsys_audio_delay(avsys_audio->audio_handle, &delay)) {
725                         retValue = delay;
726                 }
727         }
728         GST_AVSYS_AUDIO_SINK_RESET_UNLOCK (asink);
729         return retValue;
730 }
731
732 static void
733 gst_avsysaudiosink_reset (GstAudioSink * asink)
734 {
735     GstAvsysAudioSink *avsys_audio = NULL;
736     int avsys_result = AVSYS_STATE_SUCCESS;
737
738     GST_AVSYS_AUDIO_SINK_LOCK (asink);
739     avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
740
741 #if defined(__REPLACE_RESET_WITH_CLOSE_AND_REOPEN__)
742     GST_AVSYS_AUDIO_SINK_RESET_LOCK (asink);
743         avsys_result = avsys_audio_close (avsys_audio->audio_handle);
744         if(AVSYS_FAIL(avsys_result))
745         {
746                 GST_ERROR_OBJECT (avsys_audio, "avsys_audio_close: internal error: ");
747         }
748         else
749         {
750                 avsys_audio->audio_handle =(avsys_handle_t) -1;
751         }
752         GST_AVSYS_AUDIO_SINK_RESET_UNLOCK (asink);
753 #else
754     if(AVSYS_STATE_SUCCESS != avsys_audio_reset(avsys_audio->audio_handle))
755     {
756         GST_ERROR_OBJECT (avsys_audio, "avsys-reset: internal error: ");
757     }
758 #endif
759
760     GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
761
762     return;
763 }
764
765
766 static gboolean
767 gst_avsysaudiosink_avsys_open(GstAvsysAudioSink *avsys_audio)
768 {
769     int avsys_result;
770
771         GST_AVSYS_AUDIO_SINK_LOCK(avsys_audio);
772     if(avsys_audio->audio_handle == (avsys_handle_t)-1) {
773
774                 GST_LOG_OBJECT (avsys_audio, "avsys_audio_open() with user policy [%d] ",  avsys_audio->user_route_policy);
775
776                 avsys_result = avsys_audio_open(&avsys_audio->audio_param, &avsys_audio->audio_handle, &avsys_audio->avsys_size);
777         if(avsys_result != AVSYS_STATE_SUCCESS)
778         {
779                 GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
780                 avsysaudiosink_post_message(avsys_audio, avsys_result);
781             return FALSE;
782         }
783
784         GST_LOG_OBJECT (avsys_audio, "Opened av system ");
785
786         GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
787
788     }
789     else {
790         GST_WARNING_OBJECT(avsys_audio, "audio handle has already opened");
791         GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
792         return FALSE;
793     }
794 #if defined (LPCM_DUMP_SUPPORT)
795     if(avsys_audio->dumpFp == NULL)
796     {
797         avsys_audio->dumpFp = fopen("/root/dump.lpcm","w");
798     }
799 #endif
800     return TRUE;
801 }
802
803 static gboolean
804 gst_avsysaudiosink_avsys_close(GstAvsysAudioSink *avsys_audio)
805 {
806     int avsys_result = AVSYS_STATE_SUCCESS;
807
808     GST_AVSYS_AUDIO_SINK_LOCK (avsys_audio);
809
810     if(avsys_audio->audio_handle !=  (avsys_handle_t)-1 )
811     {
812         avsys_result = avsys_audio_close(avsys_audio->audio_handle);
813
814         if (AVSYS_FAIL(avsys_result))
815                 {
816                         GST_ERROR_OBJECT(avsys_audio,
817                                         "avsys_audio_close() failed with 0x%x", avsys_result);
818                         GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
819                         return FALSE;
820                 }
821                 else
822                 {
823                         avsys_audio->audio_handle = (avsys_handle_t) -1;
824                         GST_INFO_OBJECT(avsys_audio, "avsys_audio_close() success");
825                 }
826
827         GST_LOG_OBJECT (avsys_audio, "Closed av system ");
828     }
829     else
830     {
831         GST_WARNING_OBJECT(avsys_audio, "audio handle has already closed");
832     }
833
834         GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
835 #if defined (LPCM_DUMP_SUPPORT)
836         if(avsys_audio->dumpFp != NULL)
837         {
838                 fclose(avsys_audio->dumpFp);
839                 avsys_audio->dumpFp = NULL;
840         }
841 #endif
842         return TRUE;
843 }
844
845 static GstStateChangeReturn
846 gst_avsyssudiosink_change_state (GstElement *element, GstStateChange transition)
847 {
848     GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
849     GstAvsysAudioSink *avsys_audio = GST_AVSYS_AUDIO_SINK (element);
850
851     int avsys_result = AVSYS_STATE_SUCCESS;
852
853     switch (transition)
854     {
855         case GST_STATE_CHANGE_NULL_TO_READY:
856             break;
857         case GST_STATE_CHANGE_READY_TO_PAUSED:
858             break;
859         case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
860 #if defined(_ALSA_DAPM_)
861                 switch(avsys_audio->audio_route_policy)
862                 {
863                 case AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING:
864                         GST_INFO_OBJECT(avsys_audio, "audio route uses external setting");
865                         break;
866                 default:
867                         GST_ERROR_OBJECT(avsys_audio, "Unknown audio route option %d\n", avsys_audio->audio_route_policy);
868                         break;
869                 }
870 #endif
871 #if defined(__REPLACE_RESET_WITH_CLOSE_AND_REOPEN__)
872                 if(avsys_audio->audio_handle == (avsys_handle_t)-1)
873                 {
874                         avsys_result = avsys_audio_open(&avsys_audio->audio_param, &avsys_audio->audio_handle, &avsys_audio->avsys_size);
875                         if(AVSYS_FAIL(avsys_result))
876                         {
877                                 GST_ERROR_OBJECT (avsys_audio, "avsys_audio_open: internal error: ");
878                                 return GST_STATE_CHANGE_FAILURE;
879                         }
880                 }
881 #endif
882
883                     if(avsys_audio->use_fadeup_volume) {
884                         GST_INFO_OBJECT(avsys_audio, "Set fadeup volume");
885                         avsys_audio_set_volume_fadeup(avsys_audio->audio_handle);
886                     }
887
888                     if(AVSYS_STATE_SUCCESS != avsys_audio_set_mute(avsys_audio->audio_handle, CONVERT_MUTE_VALUE(avsys_audio->mute)))
889                     {
890                         GST_ERROR_OBJECT(avsys_audio, "Set mute failed %d", CONVERT_MUTE_VALUE(avsys_audio->mute));
891                     }
892             break;
893         default:
894             break;
895     }
896     ret = GST_ELEMENT_CLASS(parent_class)->change_state (element, transition);
897     if (ret == GST_STATE_CHANGE_FAILURE)
898     {
899         return ret;
900     }
901     switch (transition)
902     {
903         case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
904             break;
905         case GST_STATE_CHANGE_PAUSED_TO_READY:
906             break;
907         case GST_STATE_CHANGE_READY_TO_NULL:
908             break;
909         default:
910             break;
911     }
912     return ret;
913 }
914
915
916 static gboolean
917 avsysaudiosink_post_message(GstAvsysAudioSink* self,int errorcode)
918 {
919                 GST_DEBUG("avsysaudiosink_post_message\n");
920                 gboolean ret = TRUE;
921                 GstMessage *Msg = NULL;
922                 GQuark domain;
923                 gboolean status = FALSE;
924                 GError *error = NULL;
925                 gint error_code;
926                 /*
927                 if(errorcode>0)
928                                 error_code = errorcode;
929                 else
930                                 error_code = GST_STREAM_ERROR_TYPE_NOT_FOUND; */
931                 error_code = GST_RESOURCE_ERROR_FAILED;
932                 domain = gst_resource_error_quark();
933                 error = g_error_new (domain, error_code, "AVSYSAUDIOSINK_RESOURCE_ERROR");
934                 Msg = gst_message_new_error(GST_ELEMENT(self), error, "AVSYSAUDIOSINK_ERROR");
935                 status = gst_element_post_message (GST_ELEMENT(self), Msg);
936                 if (status == FALSE)
937                 {
938                                 GST_ERROR("Error in posting message on the bus ...\n");
939                                 ret = FALSE;
940                 }
941
942                 return ret;
943 }