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