bbf8e10d79ae82cef40fc978e8387c8b5a05179e
[platform/core/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 GType
128 gst_avsysaudiosink_latency_get_type (void)
129 {
130         static GType avsysaudio_latency_type = 0;
131         static const GEnumValue avsysaudio_latency[] = {
132                 {AVSYSAUDIOSINK_LATENCY_LOW, "Low latency", "low"},
133                 {AVSYSAUDIOSINK_LATENCY_MID, "Mid latency", "mid"},
134                 {AVSYSAUDIOSINK_LATENCY_HIGH, "High latency", "high"},
135                 {0, NULL, NULL},
136         };
137
138         if (!avsysaudio_latency_type) {
139                 avsysaudio_latency_type =
140                         g_enum_register_static ("GstAvsysAudioSinkLatency", avsysaudio_latency);
141         }
142         return avsysaudio_latency_type;
143 }
144
145 static void gst_avsysaudiosink_init_interfaces (GType type);
146
147 //#define GST_BOILERPLATE_FULL(type, type_as_function, parent_type, parent_type_macro, additional_initializations)
148
149 GST_BOILERPLATE_FULL (GstAvsysAudioSink, gst_avsysaudiosink, GstAudioSink,
150                                           GST_TYPE_AUDIO_SINK, gst_avsysaudiosink_init_interfaces);
151
152
153 static void gst_avsysaudiosink_finalise (GObject * object);
154 static void gst_avsysaudiosink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
155 static void gst_avsysaudiosink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
156 #if 0   /*not use*/
157 static GstCaps *gst_avsysaudiosink_getcaps (GstBaseSink * bsink);
158 #endif
159
160 static gboolean gst_avsysaudiosink_avsys_close(GstAvsysAudioSink *avsys_audio);
161 static gboolean gst_avsysaudiosink_avsys_open(GstAvsysAudioSink *avsys_audio);
162
163 static gboolean gst_avsysaudiosink_open (GstAudioSink * asink);
164 static gboolean gst_avsysaudiosink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec);
165 static gboolean gst_avsysaudiosink_unprepare (GstAudioSink * asink);
166 static gboolean gst_avsysaudiosink_close (GstAudioSink * asink);
167 static guint gst_avsysaudiosink_write (GstAudioSink * asink, gpointer data, guint length);
168 static guint gst_avsysaudiosink_delay (GstAudioSink * asink);
169 static void gst_avsysaudiosink_reset (GstAudioSink * asink);
170 static gboolean avsysaudiosink_post_message(GstAvsysAudioSink* self,int errorcode);
171
172
173 #define AVSYS_AUDIO_FACTORY_ENDIANNESS  "LITTLE_ENDIAN"
174
175
176 static GstStaticPadTemplate avsysaudiosink_sink_factory =
177         GST_STATIC_PAD_TEMPLATE ("sink",
178                                                          GST_PAD_SINK,
179                                                          GST_PAD_ALWAYS,
180                                                          GST_STATIC_CAPS ("audio/x-raw-int, "
181                                                                          "endianness = (int) { " AVSYS_AUDIO_FACTORY_ENDIANNESS " }, "
182                                                                          "signed = (boolean) { TRUE }, "
183                                                                          "width = (int) 16, "
184                                                                          "depth = (int) 16, "
185                                                                          "rate = (int) [ 1, MAX ], "
186                                                                          "channels = (int) [ 1, 6 ]; "
187                                                                          "audio/x-raw-int, "
188                                                                          "signed = (boolean) { FALSE }, "
189                                                                          "width = (int) 8, "
190                                                                          "depth = (int) 8, "
191                                                                          "rate = (int) [ 1, MAX ], "
192                                                                          "channels = (int) [ 1, 6 ] "
193                                                                  )
194                                                          );
195 /*
196 static inline guint _time_to_sample(GstAvsysAudioSink * asink,  GstClockTime diff)
197 {
198         guint result = 0;
199         result =(GST_TIME_AS_USECONDS(diff) * asink->audio_param.samplerate)/1000000;
200         return result;
201 }
202 */
203
204 static void
205 gst_avsysaudiosink_finalise (GObject * object)
206 {
207         GstAvsysAudioSink *sink = NULL;
208
209         sink = GST_AVSYS_AUDIO_SINK (object);
210         gst_avsysaudiosink_avsys_close(sink);
211         g_mutex_free (sink->avsys_audio_lock);
212         g_mutex_free (sink->avsys_audio_reset_lock);
213
214         G_OBJECT_CLASS (parent_class)->finalize (object);
215 }
216
217 static void
218 gst_avsysaudiosink_init_interfaces (GType type)
219 {
220         /* None */
221 }
222
223 static void
224 gst_avsysaudiosink_base_init (gpointer g_class)
225 {
226         GstElementClass *element_class = NULL;
227
228         element_class = GST_ELEMENT_CLASS (g_class);
229         gst_element_class_set_details (element_class, &gst_avsysaudiosink_details);
230         gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&avsysaudiosink_sink_factory));
231 }
232
233 static GstStateChangeReturn
234 gst_avsyssudiosink_change_state (GstElement *element, GstStateChange transition);
235
236
237 static void
238 gst_avsysaudiosink_class_init (GstAvsysAudioSinkClass * klass)
239 {
240         GObjectClass *gobject_class;
241         GstElementClass *gstelement_class;
242         GstBaseSinkClass *gstbasesink_class;
243         GstBaseAudioSinkClass *gstbaseaudiosink_class;
244         GstAudioSinkClass *gstaudiosink_class;
245
246         gobject_class = (GObjectClass *) klass;
247         gstelement_class = (GstElementClass *) klass;
248         gstbasesink_class = (GstBaseSinkClass *) klass;
249         gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
250         gstaudiosink_class = (GstAudioSinkClass *) klass;
251
252         parent_class = g_type_class_peek_parent (klass);
253         gstelement_class->change_state  = GST_DEBUG_FUNCPTR(gst_avsyssudiosink_change_state);
254
255         gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_finalise);
256         gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_get_property);
257         gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_set_property);
258
259         //      gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_getcaps);
260
261         gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_open);
262         gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_prepare);
263         gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_unprepare);
264         gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_close);
265         gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_write);
266         gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_delay);
267         gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_reset);
268
269         g_object_class_install_property (  gobject_class, PROP_AUDIO_VOLUME_TYPE,
270                         g_param_spec_int ("volumetype", "Avsystem Volume Type",
271                                         "Select avsystem audio software volume type", 0, G_MAXINT,
272                                         DEFAULT_VOLUME_TYPE, G_PARAM_READWRITE));
273
274         g_object_class_install_property (  gobject_class, PROP_AUDIO_PRIORITY,
275                         g_param_spec_int ("priority", "Avsystem Sound Priority", "Avsystem sound priority",
276                                         AVSYS_AUDIO_PRIORITY_NORMAL, AVSYS_AUDIO_PRIORITY_SOLO_WITH_TRANSITION_EFFECT,
277                                         AVSYS_AUDIO_PRIORITY_NORMAL, G_PARAM_READWRITE));
278
279         g_object_class_install_property (  gobject_class, PROP_AUDIO_HANDLE,
280                         g_param_spec_pointer("audio-handle", "Avsystem handle",
281                                         "Avsystem audio handle", 
282                                         G_PARAM_READWRITE));
283
284         g_object_class_install_property (  gobject_class, PROP_AUDIO_CALLBACK,
285                         g_param_spec_pointer("audio-callback", "Avsystem callback",
286                                         "Avsystem audio callback", 
287                                         G_PARAM_READWRITE));
288
289         g_object_class_install_property (gobject_class, PROP_AUDIO_FADEUPVOLUME,
290                         g_param_spec_boolean ("fadeup", "Avsystem fadeup volume",
291                                         "Enable avsystem audio fadeup volume when pause to play",
292                                         DEFAULT_FADEUP_VOLUME, G_PARAM_READWRITE));
293
294         g_object_class_install_property (gobject_class ,PROP_AUDIO_MUTE,
295                         g_param_spec_enum("mute", "Avsystem mute",
296                                         "Avsystem audio mute",
297                                         GST_AVSYS_AUDIO_SINK_MUTE, DEFAULT_AUDIO_MUTE,
298                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
299
300         g_object_class_install_property (gobject_class ,PROP_AUDIO_ROUTE_POLICY,
301                         g_param_spec_enum("audio-route", "Audio Route Policy",
302                                         "Audio route policy of system",
303                                         GST_AVSYS_AUDIO_SINK_AUDIO_ROUTE, DEFAULT_AUDIO_ROUTE,
304                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
305         
306         g_object_class_install_property (gobject_class ,PROP_AUDIO_USER_ROUTE,
307                         g_param_spec_enum("user-route", "User Route Policy",
308                                         "User route policy",
309                                         GST_AVSYS_AUDIO_SINK_USER_ROUTE, DEFAULT_USER_ROUTE,
310                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
311
312         g_object_class_install_property (gobject_class ,PROP_AUDIO_LATENCY,
313                         g_param_spec_enum("latency", "Audio Backend Latency",
314                                         "Audio backend latency",
315                                         GST_AVSYS_AUDIO_SINK_LATENCY_TYPE, DEFAULT_AUDIO_LATENCY,
316                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
317 }
318
319 static void
320 gst_avsysaudiosink_set_property (GObject * object, guint prop_id,
321                                                          const GValue * value, GParamSpec * pspec)
322 {
323         GstAvsysAudioSink *sink = NULL;
324         int nvalue = 0;
325         gboolean nbool = FALSE;
326
327         sink = GST_AVSYS_AUDIO_SINK (object);
328
329         switch (prop_id) {
330         case PROP_AUDIO_HANDLE:
331                 sink->cbHandle = g_value_get_pointer(value);
332                 break;
333         case PROP_AUDIO_CALLBACK:
334                 sink->audio_stream_cb = g_value_get_pointer(value);
335                 break;
336         case PROP_AUDIO_VOLUME_TYPE:
337                 nvalue = g_value_get_int(value);
338                 sink->volume_type = nvalue;
339                 if (sink->audio_handle != (avsys_handle_t)-1) {
340                         avsys_audio_update_volume_config(sink->audio_handle, sink->volume_type);
341                 }
342                 break;
343         case PROP_AUDIO_PRIORITY:
344                 nvalue = g_value_get_int(value);
345                 sink->sound_priority = nvalue;
346                 break;
347         case PROP_AUDIO_MUTE:
348                 nvalue = g_value_get_enum(value);
349                 if (sink->audio_handle != (avsys_handle_t)-1) {
350                         if(AVSYS_SUCCESS(avsys_audio_set_mute_fadedown(sink->audio_handle)))
351                                 sink->mute = nvalue;
352                 } else {
353                         sink->mute = nvalue;
354                 }
355                 break;
356         case PROP_AUDIO_FADEUPVOLUME:
357                 nbool = g_value_get_boolean(value);
358                 sink->use_fadeup_volume = nbool;
359                 break;
360         case PROP_AUDIO_ROUTE_POLICY:
361                 nvalue = g_value_get_enum(value);
362                 sink->audio_route_policy = nvalue;
363                 switch (sink->audio_route_policy) {
364                 case AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING:
365                         GST_INFO_OBJECT(sink, "use external audio route setting");
366                         break;
367                 default:
368                         g_print("AVSYSAUDIOSINK :: Unknown audio route option %d\n", sink->audio_route_policy);
369                         GST_ERROR_OBJECT(sink, "Unknown audio route option %d", sink->audio_route_policy);
370                         break;
371                 }
372                 break;
373         case PROP_AUDIO_USER_ROUTE:
374                 nvalue = g_value_get_enum(value);
375                 sink->user_route_policy = nvalue;
376                 break;
377         case PROP_AUDIO_LATENCY:
378                 nvalue = g_value_get_enum(value);
379                 sink->latency = nvalue;
380                 break;
381         default:
382                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
383                 break;
384         }
385 }
386
387 static void
388 gst_avsysaudiosink_get_property (GObject * object, guint prop_id,
389                                                          GValue * value, GParamSpec * pspec)
390 {
391         GstAvsysAudioSink *sink = NULL;
392
393         sink = GST_AVSYS_AUDIO_SINK (object);
394
395         switch (prop_id) {
396         case PROP_AUDIO_VOLUME_TYPE:
397                 g_value_set_int(value, sink->volume_type);
398                 break;
399         case PROP_AUDIO_PRIORITY:
400                 g_value_set_int(value, sink->sound_priority);
401                 break;
402         case PROP_AUDIO_MUTE:
403                 g_value_set_enum(value, sink->mute);
404                 break;
405         case PROP_AUDIO_FADEUPVOLUME:
406                 g_value_set_boolean(value, sink->use_fadeup_volume);
407                 break;
408         case PROP_AUDIO_ROUTE_POLICY:
409                 g_value_set_enum(value, sink->audio_route_policy);
410                 break;
411         case PROP_AUDIO_USER_ROUTE:
412                 g_value_set_enum(value, sink->user_route_policy);
413                 break;
414         case PROP_AUDIO_LATENCY:
415                 g_value_set_enum(value, sink->latency);
416                 break;
417
418         default:
419                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
420                 break;
421         }
422 }
423
424 static void
425 gst_avsysaudiosink_init (GstAvsysAudioSink * avsysaudiosink, GstAvsysAudioSinkClass * g_class)
426 {
427         GST_DEBUG_OBJECT (avsysaudiosink, "initializing avsysaudiosink");
428
429         avsysaudiosink->audio_handle = (avsys_handle_t)-1;
430         avsysaudiosink->cached_caps = NULL;
431         avsysaudiosink->avsys_audio_lock = g_mutex_new ();
432         avsysaudiosink->avsys_audio_reset_lock = g_mutex_new ();
433         avsysaudiosink->volume_type = DEFAULT_VOLUME_TYPE;
434         avsysaudiosink->sound_priority = AVSYS_AUDIO_PRIORITY_NORMAL;
435         avsysaudiosink->mute = DEFAULT_AUDIO_MUTE;
436         avsysaudiosink->use_fadeup_volume = DEFAULT_FADEUP_VOLUME;
437         avsysaudiosink->latency = DEFAULT_AUDIO_LATENCY;
438         avsysaudiosink->audio_route_policy = DEFAULT_AUDIO_ROUTE;
439         avsysaudiosink->bytes_per_sample = 1;
440 #if defined (LPCM_DUMP_SUPPORT)
441         avsysaudiosink->dumpFp = NULL;
442 #endif
443
444 }
445 #if 0
446 static GstCaps *
447 gst_avsysaudiosink_getcaps (GstBaseSink * bsink)
448 {
449     GstElementClass *element_class = NULL;
450     GstPadTemplate *pad_template = NULL;
451     GstAvsysAudioSink *sink = GST_AVSYS_AUDIO_SINK (bsink);
452     GstCaps *caps;
453
454 //    debug_fenter();
455
456     sink = GST_AVSYS_AUDIO_SINK (bsink);
457     if (sink->audio_handle == -1)
458     {
459         GST_DEBUG_OBJECT (sink, "avsystem audio not open, using template caps");
460         return NULL;              /* base class will get template caps for us */
461     }
462
463     if (sink->cached_caps)
464     {
465         GST_LOG_OBJECT (sink, "Returning cached caps");
466         return gst_caps_ref (sink->cached_caps);
467     }
468
469     element_class = GST_ELEMENT_GET_CLASS (sink);
470     pad_template = gst_element_class_get_pad_template (element_class, "sink");
471     g_return_val_if_fail (pad_template != NULL, NULL);
472
473         // todo : get supported format.
474         //caps = gst_avsysaudio_probe_supported_formats (GST_OBJECT (sink), sink->,
475         //gst_pad_template_get_caps (pad_template));
476
477         //if (caps) {
478         //sink->cached_caps = gst_caps_ref (caps);
479         //}
480
481     GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
482
483     return caps;
484 }
485 #endif
486
487 static gboolean
488 avsysaudiosink_parse_spec (GstAvsysAudioSink * avsys_audio, GstRingBufferSpec * spec)
489 {
490         /* Check param */
491         if (spec->type != GST_BUFTYPE_LINEAR ||
492                 spec->channels > 6 || spec->channels < 1 ||
493                 !(spec->format == GST_S8 || spec->format == GST_S16_LE) )
494                 return FALSE;
495
496         switch (spec->format) {
497         case GST_S8:
498                 avsys_audio->audio_param.format = AVSYS_AUDIO_FORMAT_8BIT;
499                 avsys_audio->bytes_per_sample = 1;
500                 break;
501         case GST_S16_LE:
502                 avsys_audio->audio_param.format = AVSYS_AUDIO_FORMAT_16BIT;
503                 avsys_audio->bytes_per_sample = 2;
504                 break;
505         default:
506                 return FALSE;
507         }
508
509         /// set audio parameter for avsys audio open
510         switch (avsys_audio->latency) {
511         case AVSYSAUDIOSINK_LATENCY_LOW:
512                 avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT_VIDEO;
513                 break;
514         case AVSYSAUDIOSINK_LATENCY_MID:
515                 avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT;
516                 break;
517         case AVSYSAUDIOSINK_LATENCY_HIGH:
518                 avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT_CLOCK;
519                 break;
520         }
521
522         avsys_audio->audio_param.priority = 0;
523         avsys_audio->audio_param.samplerate = spec->rate;
524         avsys_audio->audio_param.channels = spec->channels;
525         avsys_audio->bytes_per_sample *= spec->channels;
526
527         /* set software volume table type */
528         avsys_audio->audio_param.vol_type = avsys_audio->volume_type;
529         avsys_audio->audio_param.priority = avsys_audio->sound_priority;
530         avsys_audio->audio_param.handle_route = avsys_audio->user_route_policy;
531
532         return TRUE;
533 }
534
535 static gboolean
536 gst_avsysaudiosink_open (GstAudioSink * asink)
537 {
538         return TRUE;
539 }
540
541 static gboolean
542 gst_avsysaudiosink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
543 {
544         GstAvsysAudioSink *avsys_audio = NULL;
545         guint   p_time = 0, b_time = 0;
546
547         avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
548
549         // set avsys audio param
550         if (!avsysaudiosink_parse_spec (avsys_audio, spec))
551                 goto spec_parse;
552
553         if (gst_avsysaudiosink_avsys_open(avsys_audio) == FALSE) {
554                 GST_ERROR_OBJECT(avsys_audio, "gst_avsysaudiosink_avsys_open() failed");
555                 return FALSE;
556         }
557
558         /* Ring buffer size */
559         if (AVSYS_STATE_SUCCESS ==
560                 avsys_audio_get_period_buffer_time(avsys_audio->audio_handle, &p_time, &b_time)) {
561                 if(p_time == 0 || b_time == 0)
562                         return FALSE;
563
564                 spec->latency_time = (guint64)p_time;
565                 spec->buffer_time = (guint64)b_time;
566         } else {
567                 return FALSE;
568         }
569         spec->segsize = avsys_audio->avsys_size; /* '/16' see avsys_audio_open */
570         spec->segtotal = (b_time / p_time) + (((b_time % p_time)/p_time > 0.5) ? 1: 0);
571         //spec->segtotal+2;
572
573         GST_WARNING_OBJECT (avsys_audio, "latency time %u, buffer time %u, seg total %u\n",
574                         (unsigned int)(spec->latency_time/1000), (unsigned int)(spec->buffer_time/1000), spec->segtotal);
575         return TRUE;
576
577 spec_parse:
578         {
579                 GST_ELEMENT_ERROR (avsys_audio, RESOURCE, SETTINGS, (NULL),
580                                                    ("Setting of swparams failed: " ));
581                 return FALSE;
582         }
583 }
584
585 static gboolean
586 gst_avsysaudiosink_unprepare (GstAudioSink * asink)
587 {
588         GstAvsysAudioSink       *avsys_audio = NULL;
589         gboolean                        result = TRUE;
590         avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
591
592         if(!gst_avsysaudiosink_avsys_close(avsys_audio))
593         {
594                 GST_ERROR_OBJECT(avsys_audio, "gst_avsysaudiosink_avsys_close() failed");
595                 result = FALSE;
596         }
597
598         return result;
599 }
600
601 static gboolean
602 gst_avsysaudiosink_close (GstAudioSink * asink)
603 {
604         GstAvsysAudioSink *avsys_audio = NULL;
605
606         avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
607         gst_caps_replace (&avsys_audio->cached_caps, NULL);
608
609         return TRUE;
610 }
611
612
613 /*
614  *   Underrun and suspend recovery
615  */
616
617 static guint
618 gst_avsysaudiosink_write (GstAudioSink * asink, gpointer data, guint length)
619 {
620         GstAvsysAudioSink *avsys_audio = NULL;
621         gint    write_len = 0;
622
623         avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
624         GST_AVSYS_AUDIO_SINK_LOCK (asink);
625
626         if (avsys_audio->audio_stream_cb == NULL) {
627         write_len = avsys_audio_write(avsys_audio->audio_handle, data, length);
628
629 #if defined (LPCM_DUMP_SUPPORT)
630                 fwrite(data, 1, write_len, avsys_audio->dumpFp); //This is for original data (no volume convert)
631 #endif
632                 if(write_len != length)
633                 {
634                     goto write_error;
635                 }
636
637                 GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
638
639                 return write_len;
640 write_error:
641                 {
642                         GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
643
644                         if(AVSYS_FAIL(write_len))
645                         {
646                                 GST_ERROR_OBJECT(avsys_audio, "avsys_audio_write() failed with %d\n", write_len);
647                         }
648                         return length;              /* skip one period */
649                 }
650         } else {
651                 gboolean result;
652                 result = avsys_audio->audio_stream_cb(data, length, avsys_audio->cbHandle);
653                 if(!result)
654                 {
655                         GST_ERROR_OBJECT(avsys_audio,"auido stream callback failed\n");
656                 }
657                 GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
658                 return length;
659         }
660 }
661
662 static guint
663 gst_avsysaudiosink_delay (GstAudioSink * asink)
664 {
665         GstAvsysAudioSink *avsys_audio = NULL;
666         int delay = 0;
667         guint retValue = 0;
668
669         avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
670         GST_AVSYS_AUDIO_SINK_RESET_LOCK (asink);
671         if ((int)avsys_audio->audio_handle != -1) {
672                 if (AVSYS_STATE_SUCCESS == avsys_audio_delay(avsys_audio->audio_handle, &delay)) {
673                         retValue = delay;
674                 }
675         }
676         GST_AVSYS_AUDIO_SINK_RESET_UNLOCK (asink);
677         return retValue;
678 }
679
680 static void
681 gst_avsysaudiosink_reset (GstAudioSink * asink)
682 {
683         GstAvsysAudioSink *avsys_audio = NULL;
684         int avsys_result = AVSYS_STATE_SUCCESS;
685
686         GST_AVSYS_AUDIO_SINK_LOCK (asink);
687         avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
688
689 #if defined(__REPLACE_RESET_WITH_CLOSE_AND_REOPEN__)
690         GST_AVSYS_AUDIO_SINK_RESET_LOCK (asink);
691         avsys_result = avsys_audio_close (avsys_audio->audio_handle);
692         if(AVSYS_FAIL(avsys_result)) {
693                 GST_ERROR_OBJECT (avsys_audio, "avsys_audio_close: internal error: ");
694         } else {
695                 avsys_audio->audio_handle =(avsys_handle_t) -1;
696         }
697         GST_AVSYS_AUDIO_SINK_RESET_UNLOCK (asink);
698 #else
699         if(AVSYS_STATE_SUCCESS != avsys_audio_reset(avsys_audio->audio_handle)) {
700                 GST_ERROR_OBJECT (avsys_audio, "avsys-reset: internal error: ");
701         }
702 #endif
703
704         GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
705
706         return;
707 }
708
709
710 static gboolean
711 gst_avsysaudiosink_avsys_open(GstAvsysAudioSink *avsys_audio)
712 {
713         int avsys_result;
714
715         GST_AVSYS_AUDIO_SINK_LOCK(avsys_audio);
716         if (avsys_audio->audio_handle == (avsys_handle_t)-1) {
717
718                 GST_LOG_OBJECT (avsys_audio, "avsys_audio_open() with user policy [%d] ",  avsys_audio->user_route_policy);
719
720                 avsys_result = avsys_audio_open(&avsys_audio->audio_param, &avsys_audio->audio_handle, &avsys_audio->avsys_size);
721                 if (avsys_result != AVSYS_STATE_SUCCESS) {
722                         GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
723                         avsysaudiosink_post_message(avsys_audio, avsys_result);
724                         return FALSE;
725                 }
726
727                 GST_LOG_OBJECT (avsys_audio, "Opened av system ");
728
729                 GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
730         } else {
731                 GST_WARNING_OBJECT(avsys_audio, "audio handle has already opened");
732                 GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
733                 return FALSE;
734         }
735 #if defined (LPCM_DUMP_SUPPORT)
736         if (avsys_audio->dumpFp == NULL) {
737                 avsys_audio->dumpFp = fopen("/root/dump.lpcm","w");
738         }
739 #endif
740         return TRUE;
741 }
742
743 static gboolean
744 gst_avsysaudiosink_avsys_close(GstAvsysAudioSink *avsys_audio)
745 {
746         int avsys_result = AVSYS_STATE_SUCCESS;
747
748         GST_AVSYS_AUDIO_SINK_LOCK (avsys_audio);
749
750         if (avsys_audio->audio_handle !=  (avsys_handle_t)-1 ) {
751                 avsys_result = avsys_audio_close(avsys_audio->audio_handle);
752
753                 if (AVSYS_FAIL(avsys_result))
754                 {
755                         GST_ERROR_OBJECT(avsys_audio,
756                                         "avsys_audio_close() failed with 0x%x", avsys_result);
757                         GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
758                         return FALSE;
759                 } else {
760                         avsys_audio->audio_handle = (avsys_handle_t) -1;
761                         GST_INFO_OBJECT(avsys_audio, "avsys_audio_close() success");
762                 }
763
764                 GST_LOG_OBJECT (avsys_audio, "Closed av system ");
765         } else {
766                 GST_WARNING_OBJECT(avsys_audio, "audio handle has already closed");
767         }
768
769         GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
770 #if defined (LPCM_DUMP_SUPPORT)
771         if(avsys_audio->dumpFp != NULL)
772         {
773                 fclose(avsys_audio->dumpFp);
774                 avsys_audio->dumpFp = NULL;
775         }
776 #endif
777         return TRUE;
778 }
779
780 static GstStateChangeReturn
781 gst_avsyssudiosink_change_state (GstElement *element, GstStateChange transition)
782 {
783         GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
784         GstAvsysAudioSink *avsys_audio = GST_AVSYS_AUDIO_SINK (element);
785
786         int avsys_result = AVSYS_STATE_SUCCESS;
787
788         switch (transition) {
789                 case GST_STATE_CHANGE_NULL_TO_READY:
790                         break;
791                 case GST_STATE_CHANGE_READY_TO_PAUSED:
792                         break;
793                 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
794 #if defined(_ALSA_DAPM_)
795                         switch(avsys_audio->audio_route_policy) {
796                         case AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING:
797                                 GST_INFO_OBJECT(avsys_audio, "audio route uses external setting");
798                                 break;
799                         default:
800                                 GST_ERROR_OBJECT(avsys_audio, "Unknown audio route option %d\n", avsys_audio->audio_route_policy);
801                                 break;
802                         }
803 #endif
804 #if defined(__REPLACE_RESET_WITH_CLOSE_AND_REOPEN__)
805                         if (avsys_audio->audio_handle == (avsys_handle_t)-1) {
806                                 avsys_result = avsys_audio_open(&avsys_audio->audio_param, &avsys_audio->audio_handle, &avsys_audio->avsys_size);
807                                 if (AVSYS_FAIL(avsys_result)) {
808                                         GST_ERROR_OBJECT (avsys_audio, "avsys_audio_open: internal error: ");
809                                         return GST_STATE_CHANGE_FAILURE;
810                                 }
811                         }
812 #endif
813
814                         if (avsys_audio->use_fadeup_volume) {
815                                 GST_INFO_OBJECT(avsys_audio, "Set fadeup volume");
816                                 avsys_audio_set_volume_fadeup(avsys_audio->audio_handle);
817                         }
818
819                         if(AVSYS_STATE_SUCCESS != avsys_audio_set_mute(avsys_audio->audio_handle, CONVERT_MUTE_VALUE(avsys_audio->mute)))
820                         {
821                                 GST_ERROR_OBJECT(avsys_audio, "Set mute failed %d", CONVERT_MUTE_VALUE(avsys_audio->mute));
822                         }
823                         break;
824                 default:
825                         break;
826         }
827         ret = GST_ELEMENT_CLASS(parent_class)->change_state (element, transition);
828         if (ret == GST_STATE_CHANGE_FAILURE) {
829                 return ret;
830         }
831         switch (transition) {
832         case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
833                 break;
834         case GST_STATE_CHANGE_PAUSED_TO_READY:
835                 break;
836         case GST_STATE_CHANGE_READY_TO_NULL:
837                 break;
838         default:
839                 break;
840         }
841         return ret;
842 }
843
844
845 static gboolean
846 avsysaudiosink_post_message(GstAvsysAudioSink* self,int errorcode)
847 {
848                 GST_DEBUG("avsysaudiosink_post_message\n");
849                 gboolean ret = TRUE;
850                 GstMessage *Msg = NULL;
851                 GQuark domain;
852                 gboolean status = FALSE;
853                 GError *error = NULL;
854                 gint error_code;
855                 /*
856                 if(errorcode>0)
857                                 error_code = errorcode;
858                 else
859                                 error_code = GST_STREAM_ERROR_TYPE_NOT_FOUND; */
860                 error_code = GST_RESOURCE_ERROR_FAILED;
861                 domain = gst_resource_error_quark();
862                 error = g_error_new (domain, error_code, "AVSYSAUDIOSINK_RESOURCE_ERROR");
863                 Msg = gst_message_new_error(GST_ELEMENT(self), error, "AVSYSAUDIOSINK_ERROR");
864                 status = gst_element_post_message (GST_ELEMENT(self), Msg);
865                 if (status == FALSE)
866                 {
867                                 GST_ERROR("Error in posting message on the bus ...\n");
868                                 ret = FALSE;
869                 }
870
871                 return ret;
872 }