Initialize Tizen 2.3
[framework/multimedia/gst-plugins-ext0.10.git] / wearable / 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 #define DEFAULT_AUDIO_OPEN_FORCEDLY     FALSE
50
51 //GST_DEBUG_CATEGORY_STATIC (gst_avsystemsink_debug);
52
53 /* element factory information */
54 static const GstElementDetails gst_avsysaudiosink_details =
55         GST_ELEMENT_DETAILS ("AV-system Audio OUT",
56                                                 "Sink/Audio",
57                                                 "Output to AV System",
58                                                 "Samsung Electronics co., ltd");
59
60 static const avsys_audio_channel_pos_t gst_pos_to_avsys[GST_AUDIO_CHANNEL_POSITION_NUM] = {
61         [GST_AUDIO_CHANNEL_POSITION_FRONT_MONO] = AVSYS_AUDIO_CHANNEL_POSITION_MONO,
62         [GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT] = AVSYS_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
63         [GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT] = AVSYS_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
64         [GST_AUDIO_CHANNEL_POSITION_REAR_CENTER] = AVSYS_AUDIO_CHANNEL_POSITION_REAR_CENTER,
65         [GST_AUDIO_CHANNEL_POSITION_REAR_LEFT] = AVSYS_AUDIO_CHANNEL_POSITION_REAR_LEFT,
66         [GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT] = AVSYS_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
67         [GST_AUDIO_CHANNEL_POSITION_LFE] = AVSYS_AUDIO_CHANNEL_POSITION_LFE,
68         [GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER] = AVSYS_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
69         [GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = AVSYS_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
70         [GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = AVSYS_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
71         [GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT] = AVSYS_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
72         [GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT] = AVSYS_AUDIO_CHANNEL_POSITION_SIDE_RIGHT,
73         [GST_AUDIO_CHANNEL_POSITION_NONE] = AVSYS_AUDIO_CHANNEL_POSITION_INVALID
74 };
75
76 enum
77 {
78         PROP_0,
79         PROP_AUDIO_MUTE,
80         PROP_AUDIO_VOLUME_TYPE,
81         PROP_AUDIO_PRIORITY,
82         PROP_AUDIO_FADEUPVOLUME,
83         PROP_AUDIO_ROUTE_POLICY,
84         PROP_AUDIO_USER_ROUTE,
85         PROP_AUDIO_LATENCY,
86         PROP_AUDIO_HANDLE,
87         PROP_AUDIO_CALLBACK,
88         PROP_AUDIO_CLOSE_HANDLE_ON_PREPARE,
89         PROP_AUDIO_OPEN_FORCEDLY,
90 #ifdef USE_PA_AUDIO_FILTER
91         PROP_SPEED,
92         PROP_FILTER_ACTION,
93         PROP_FILTER_OUTPUT_MODE,
94         PROP_PRESET_MODE,
95         PROP_CUSTOM_EQ,
96         PROP_CUSTOM_EXT,
97 #endif
98 };
99
100 #ifdef USE_PA_AUDIO_FILTER
101 #define AUDIOVSP_DEFAULT_PLAYBACK_RATE  1.0
102 #define AUDIOVSP_MIN_PLAYBACK_RATE      0.5
103 #define AUDIOVSP_MAX_PLAYBACK_RATE      2.0
104
105 #define DEFAULT_FILTER_ACTION                   FILTER_NONE
106 #define DEFAULT_FILTER_OUTPUT_MODE              OUTPUT_SPK
107 #define DEFAULT_PRESET_MODE                             PRESET_NORMAL
108
109 enum FilterActionType
110 {
111         FILTER_NONE,
112         FILTER_PRESET,
113         FILTER_ADVANCED_SETTING
114 };
115
116 enum OutputMode
117 {
118         OUTPUT_SPK,
119         OUTPUT_EAR,
120         OUTPUT_OTHERS,
121         OUTPUT_NUM
122 };
123
124 enum PresetMode
125 {
126         PRESET_NORMAL,
127         PRESET_POP,
128         PRESET_ROCK,
129         PRESET_DANCE,
130         PRESET_JAZZ,
131         PRESET_CLASSIC,
132         PRESET_VOCAL,
133         PRESET_BASS_BOOST,
134         PRESET_TREBLE_BOOST,
135         PRESET_MTHEATER,
136         PRESET_EXTERNALIZATION,
137         PRESET_CAFE,
138         PRESET_CONCERT_HALL,
139         PRESET_VOICE,
140         PRESET_MOVIE,
141         PRESET_VIRT51,
142         PRESET_HIPHOP,
143         PRESET_RNB,
144         PRESET_FLAT,
145         PRESET_TUBE,
146
147         PRESET_NUM
148 };
149 #endif
150
151 GType
152 gst_avsysaudiosink_audio_mute_get_type (void)
153 {
154         static GType avaudio_mute_type = 0;
155         static const GEnumValue avaudio_mute[] = {
156                 {AVSYSAUDIOSINK_AUDIO_UNMUTE, "Unmute", "unmute"},
157                 {AVSYSAUDIOSINK_AUDIO_MUTE, "Mute immediately", "mute"},
158                 {AVSYSAUDIOSINK_AUDIO_MUTE_WITH_FADEDOWN_EFFECT, "Mute with fadedown effect", "fadedown"},
159                 {0, NULL, NULL},
160         };
161
162         if (!avaudio_mute_type) {
163                 avaudio_mute_type =
164                         g_enum_register_static ("GstAvsysAudioSinkAudioMute", avaudio_mute);
165         }
166         return avaudio_mute_type;
167 }
168
169 GType
170 gst_avsysaudiosink_user_route_get_type (void)
171 {
172         static GType user_route_type = 0;
173         static const GEnumValue user_route[] = {
174                 {AVSYSAUDIOSINK_USERROUTE_AUTO, "Route automatically", "auto"},
175                 {AVSYSAUDIOSINK_USERROUTE_PHONE, "Route to phone only", "phone"},
176                 {AVSYSAUDIOSINK_USERROUTE_ALL, "Route to all", "all"},
177                 {0, NULL, NULL},
178         };
179
180         if (!user_route_type) {
181                 user_route_type =
182                         g_enum_register_static ("GstAvsysAudioSinkUserRoutePolicy",user_route);
183         }
184         return user_route_type;
185 }
186
187 GType
188 gst_avsysaudiosink_audio_route_get_type (void)
189 {
190         static GType playback_audio_route_type = 0;
191         static const GEnumValue playback_audio_route[] = {
192                 {AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING, "Use external sound path", "external"},
193                 {AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_NORMAL, "Auto change between speaker & earphone", "normal"},
194                 {AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_ALERT, "Play via both speaker & earphone", "alert"},
195                 {AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_HEADSET_ONLY, "Play via earphone only", "headset"},
196                 {0, NULL, NULL},
197         };
198
199         if (!playback_audio_route_type) {
200                 playback_audio_route_type =
201                         g_enum_register_static ("GstAvsysAudioSinkAudioRoutePolicy", playback_audio_route);
202         }
203         return playback_audio_route_type;
204 }
205
206 GType
207 gst_avsysaudiosink_latency_get_type (void)
208 {
209         static GType avsysaudio_latency_type = 0;
210         static const GEnumValue avsysaudio_latency[] = {
211                 {AVSYSAUDIOSINK_LATENCY_LOW, "Low latency", "low"},
212                 {AVSYSAUDIOSINK_LATENCY_MID, "Mid latency", "mid"},
213                 {AVSYSAUDIOSINK_LATENCY_HIGH, "High latency", "high"},
214                 {0, NULL, NULL},
215         };
216
217         if (!avsysaudio_latency_type) {
218                 avsysaudio_latency_type =
219                         g_enum_register_static ("GstAvsysAudioSinkLatency", avsysaudio_latency);
220         }
221         return avsysaudio_latency_type;
222 }
223
224 static void gst_avsysaudiosink_init_interfaces (GType type);
225
226 //#define GST_BOILERPLATE_FULL(type, type_as_function, parent_type, parent_type_macro, additional_initializations)
227
228 GST_BOILERPLATE_FULL (GstAvsysAudioSink, gst_avsysaudiosink, GstAudioSink,
229                                           GST_TYPE_AUDIO_SINK, gst_avsysaudiosink_init_interfaces);
230
231
232 static void gst_avsysaudiosink_finalise (GObject * object);
233 static void gst_avsysaudiosink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
234 static void gst_avsysaudiosink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
235 #if 0   /*not use*/
236 static GstCaps *gst_avsysaudiosink_getcaps (GstBaseSink * bsink);
237 #endif
238
239 static gboolean gst_avsysaudiosink_avsys_close(GstAvsysAudioSink *avsys_audio);
240 static gboolean gst_avsysaudiosink_avsys_open(GstAvsysAudioSink *avsys_audio);
241
242 static gboolean gst_avsysaudiosink_open (GstAudioSink * asink);
243 static gboolean gst_avsysaudiosink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec);
244 static gboolean gst_avsysaudiosink_unprepare (GstAudioSink * asink);
245 static gboolean gst_avsysaudiosink_close (GstAudioSink * asink);
246 static guint gst_avsysaudiosink_write (GstAudioSink * asink, gpointer data, guint length);
247 static guint gst_avsysaudiosink_delay (GstAudioSink * asink);
248 static void gst_avsysaudiosink_reset (GstAudioSink * asink);
249 static gboolean avsysaudiosink_post_message(GstAvsysAudioSink* self,int errorcode);
250
251
252 #define AVSYS_AUDIO_FACTORY_ENDIANNESS  "LITTLE_ENDIAN"
253
254
255 static GstStaticPadTemplate avsysaudiosink_sink_factory =
256         GST_STATIC_PAD_TEMPLATE ("sink",
257                                                          GST_PAD_SINK,
258                                                          GST_PAD_ALWAYS,
259                                                          GST_STATIC_CAPS ("audio/x-raw-int, "
260                                                                          "endianness = (int) { " AVSYS_AUDIO_FACTORY_ENDIANNESS " }, "
261                                                                          "signed = (boolean) { TRUE }, "
262                                                                          "width = (int) 16, "
263                                                                          "depth = (int) 16, "
264                                                                          "rate = (int) 44100, "
265                                                                          "channels = (int) [ 1, 6 ]; "
266                                                                          "audio/x-raw-int, "
267                                                                          "signed = (boolean) { FALSE }, "
268                                                                          "width = (int) 8, "
269                                                                          "depth = (int) 8, "
270                                                                          "rate = (int) 44100, "
271                                                                          "channels = (int) [ 1, 6 ] "
272                                                                  )
273                                                          );
274 /*
275 static inline guint _time_to_sample(GstAvsysAudioSink * asink,  GstClockTime diff)
276 {
277         guint result = 0;
278         result =(GST_TIME_AS_USECONDS(diff) * asink->audio_param.samplerate)/1000000;
279         return result;
280 }
281 */
282
283 static void
284 gst_avsysaudiosink_finalise (GObject * object)
285 {
286         GstAvsysAudioSink *sink = NULL;
287         sink = GST_AVSYS_AUDIO_SINK (object);
288
289         GST_WARNING(">> Start(%d)", sink->audio_handle);
290
291         GST_AVSYS_AUDIO_SINK_LOCK(sink);
292         gst_avsysaudiosink_avsys_close(sink);
293         GST_AVSYS_AUDIO_SINK_UNLOCK(sink);
294         g_mutex_free (sink->avsys_audio_lock);
295         g_mutex_free (sink->avsys_audio_delay_lock);
296         g_mutex_free (sink->avsys_audio_reset_lock);
297
298         GST_WARNING("<< End(%d)", sink->audio_handle);
299
300         G_OBJECT_CLASS (parent_class)->finalize (object);
301 }
302
303 static void
304 gst_avsysaudiosink_init_interfaces (GType type)
305 {
306         /* None */
307 }
308
309 static void
310 gst_avsysaudiosink_base_init (gpointer g_class)
311 {
312         GstElementClass *element_class = NULL;
313
314         element_class = GST_ELEMENT_CLASS (g_class);
315         gst_element_class_set_details (element_class, &gst_avsysaudiosink_details);
316         gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&avsysaudiosink_sink_factory));
317 }
318
319 static GstStateChangeReturn
320 gst_avsyssudiosink_change_state (GstElement *element, GstStateChange transition);
321
322
323 static void
324 gst_avsysaudiosink_class_init (GstAvsysAudioSinkClass * klass)
325 {
326         GObjectClass *gobject_class;
327         GstElementClass *gstelement_class;
328         GstBaseSinkClass *gstbasesink_class;
329         GstBaseAudioSinkClass *gstbaseaudiosink_class;
330         GstAudioSinkClass *gstaudiosink_class;
331
332         gobject_class = (GObjectClass *) klass;
333         gstelement_class = (GstElementClass *) klass;
334         gstbasesink_class = (GstBaseSinkClass *) klass;
335         gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
336         gstaudiosink_class = (GstAudioSinkClass *) klass;
337
338         parent_class = g_type_class_peek_parent (klass);
339         gstelement_class->change_state  = GST_DEBUG_FUNCPTR(gst_avsyssudiosink_change_state);
340
341         gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_finalise);
342         gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_get_property);
343         gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_set_property);
344
345         //      gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_getcaps);
346
347         gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_open);
348         gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_prepare);
349         gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_unprepare);
350         gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_close);
351         gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_write);
352         gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_delay);
353         gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_reset);
354
355         g_object_class_install_property (  gobject_class, PROP_AUDIO_VOLUME_TYPE,
356                         g_param_spec_int ("volumetype", "Avsystem Volume Type",
357                                         "Select avsystem audio software volume type", 0, G_MAXINT,
358                                         DEFAULT_VOLUME_TYPE, G_PARAM_READWRITE));
359
360         g_object_class_install_property (  gobject_class, PROP_AUDIO_PRIORITY,
361                         g_param_spec_int ("priority", "Avsystem Sound Priority", "Avsystem sound priority",
362                                         AVSYS_AUDIO_PRIORITY_NORMAL, AVSYS_AUDIO_PRIORITY_MAX - 1,
363                                         AVSYS_AUDIO_PRIORITY_NORMAL, G_PARAM_READWRITE));
364
365         g_object_class_install_property (  gobject_class, PROP_AUDIO_HANDLE,
366                         g_param_spec_pointer("audio-handle", "Avsystem handle",
367                                         "Avsystem audio handle",
368                                         G_PARAM_READWRITE));
369
370         g_object_class_install_property (  gobject_class, PROP_AUDIO_CALLBACK,
371                         g_param_spec_pointer("audio-callback", "Avsystem callback",
372                                         "Avsystem audio callback",
373                                         G_PARAM_READWRITE));
374
375         g_object_class_install_property (gobject_class, PROP_AUDIO_FADEUPVOLUME,
376                         g_param_spec_boolean ("fadeup", "Avsystem fadeup volume",
377                                         "Enable avsystem audio fadeup volume when pause to play",
378                                         DEFAULT_FADEUP_VOLUME, G_PARAM_READWRITE));
379
380         g_object_class_install_property (gobject_class ,PROP_AUDIO_MUTE,
381                         g_param_spec_enum("mute", "Avsystem mute",
382                                         "Avsystem audio mute",
383                                         GST_AVSYS_AUDIO_SINK_MUTE, DEFAULT_AUDIO_MUTE,
384                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
385
386         g_object_class_install_property (gobject_class ,PROP_AUDIO_ROUTE_POLICY,
387                         g_param_spec_enum("audio-route", "Audio Route Policy",
388                                         "Audio route policy of system",
389                                         GST_AVSYS_AUDIO_SINK_AUDIO_ROUTE, DEFAULT_AUDIO_ROUTE,
390                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
391
392         g_object_class_install_property (gobject_class ,PROP_AUDIO_USER_ROUTE,
393                         g_param_spec_enum("user-route", "User Route Policy",
394                                         "User route policy",
395                                         GST_AVSYS_AUDIO_SINK_USER_ROUTE, DEFAULT_USER_ROUTE,
396                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
397
398         g_object_class_install_property (gobject_class ,PROP_AUDIO_LATENCY,
399                         g_param_spec_enum("latency", "Audio Backend Latency",
400                                         "Audio backend latency",
401                                         GST_AVSYS_AUDIO_SINK_LATENCY_TYPE, DEFAULT_AUDIO_LATENCY,
402                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
403
404         g_object_class_install_property (gobject_class, PROP_AUDIO_CLOSE_HANDLE_ON_PREPARE,
405                         g_param_spec_boolean ("close-handle-on-prepare", "Close Handle on Prepare",
406                                         "Close Handle on Prepare",
407                                         DEFAULT_AUDIO_CLOSE_HANDLE_ON_PREPARE, G_PARAM_READWRITE));
408
409         g_object_class_install_property (gobject_class, PROP_AUDIO_OPEN_FORCEDLY,
410                                 g_param_spec_boolean ("open-audio", "Open Audio",
411                                                 "Open Audio dev",
412                                                 DEFAULT_AUDIO_OPEN_FORCEDLY, G_PARAM_READWRITE));
413
414 #ifdef USE_PA_AUDIO_FILTER
415         g_object_class_install_property(gobject_class, PROP_SPEED,
416                 g_param_spec_float("speed", "speed", "speed",
417                 AUDIOVSP_MIN_PLAYBACK_RATE,
418                 AUDIOVSP_MAX_PLAYBACK_RATE,
419                 AUDIOVSP_DEFAULT_PLAYBACK_RATE,
420                 G_PARAM_READWRITE));
421
422         g_object_class_install_property(gobject_class, PROP_FILTER_ACTION,
423                 g_param_spec_uint("filter-action", "filter action", "(0)none (1)preset (2)advanced setting",
424                 0, 2, DEFAULT_FILTER_ACTION, G_PARAM_READWRITE));
425
426         g_object_class_install_property(gobject_class, PROP_FILTER_OUTPUT_MODE,
427                 g_param_spec_uint("filter-output-mode", "filter output mode", "(0)Speaker (1)Ear (2)Others",
428                 0, 2, DEFAULT_FILTER_OUTPUT_MODE, G_PARAM_READWRITE));
429
430         g_object_class_install_property(gobject_class, PROP_PRESET_MODE,
431                 g_param_spec_uint("preset-mode", "preset mode", "(0)normal (1)pop (2)rock (3)dance (4)jazz (5)classic (6)vocal (7)bass boost (8)treble boost (9)mtheater (10)externalization (11)cafe (12)concert hall (13)voice (14)movie (15)virt 5.1 (16)hip-hop (17)R&B (18)flat (19)tube",
432                 0, 19, DEFAULT_PRESET_MODE, G_PARAM_READWRITE));
433
434         g_object_class_install_property (gobject_class, PROP_CUSTOM_EQ,
435                 g_param_spec_pointer("custom-eq", "custom eq level array",
436                 "pointer for array of EQ bands level", G_PARAM_READWRITE));
437
438         g_object_class_install_property (gobject_class, PROP_CUSTOM_EXT,
439                 g_param_spec_pointer("custom-ext", "custom ext level array",
440                 "pointer for array of custom effect level", G_PARAM_READWRITE));
441 #endif
442 }
443
444 static void
445 gst_avsysaudiosink_set_property (GObject * object, guint prop_id,
446                                                          const GValue * value, GParamSpec * pspec)
447 {
448         GstAvsysAudioSink *sink = NULL;
449         int nvalue = 0;
450         gboolean nbool = FALSE;
451 #ifdef USE_PA_AUDIO_FILTER
452         gshort *pointer;
453 #endif
454
455         sink = GST_AVSYS_AUDIO_SINK (object);
456
457         switch (prop_id) {
458         case PROP_AUDIO_VOLUME_TYPE:
459                 nvalue = g_value_get_int(value);
460                 sink->volume_type = nvalue;
461                 if (sink->audio_handle != (avsys_handle_t)-1) {
462                         avsys_audio_update_volume_config(sink->audio_handle, sink->volume_type);
463                 }
464                 break;
465         case PROP_AUDIO_PRIORITY:
466                 nvalue = g_value_get_int(value);
467                 sink->sound_priority = nvalue;
468                 GST_INFO_OBJECT(sink, "Set audio priority(%d)", nvalue);
469                 if (sink->audio_handle != (avsys_handle_t)-1) {
470                         int error = AVSYS_STATE_ERR_UNKNOWN;
471                         int handle_route = 0;
472                         sink->audio_param.priority = sink->sound_priority;
473                         error = avsys_audio_handle_update_priority(sink->audio_handle, nvalue, handle_route, AVSYS_AUDIO_SET_PRIORITY);
474                         if (AVSYS_FAIL(error)) {
475                                 GST_ERROR_OBJECT(sink, "Failed to set audio priority(%d) to audio handle(%d)", nvalue, sink->audio_handle);
476                                 break;
477                         }
478                 }
479                 break;
480         case PROP_AUDIO_MUTE:
481                 nvalue = g_value_get_enum(value);
482                 if (sink->audio_handle != (avsys_handle_t)-1) {
483                         if (nvalue == AVSYSAUDIOSINK_AUDIO_MUTE_WITH_FADEDOWN_EFFECT) {
484                                 if(AVSYS_SUCCESS(avsys_audio_set_mute_fadedown(sink->audio_handle)))
485                                         sink->mute = nvalue;
486                         } else {
487                                 if(AVSYS_SUCCESS(avsys_audio_set_mute(sink->audio_handle, nvalue)))
488                                         sink->mute = nvalue;
489                         }
490                 } else {
491                         sink->mute = nvalue;
492                 }
493                 break;
494         case PROP_AUDIO_FADEUPVOLUME:
495                 nbool = g_value_get_boolean(value);
496                 sink->use_fadeup_volume = nbool;
497                 break;
498         case PROP_AUDIO_ROUTE_POLICY:
499                 nvalue = g_value_get_enum(value);
500                 sink->audio_route_policy = nvalue;
501                 switch (sink->audio_route_policy) {
502                 case AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING:
503                         GST_INFO_OBJECT(sink, "use external audio route setting");
504                         break;
505                 default:
506                         g_print("AVSYSAUDIOSINK :: Unknown audio route option %d\n", sink->audio_route_policy);
507                         GST_ERROR_OBJECT(sink, "Unknown audio route option %d", sink->audio_route_policy);
508                         break;
509                 }
510                 break;
511         case PROP_AUDIO_USER_ROUTE:
512                 nvalue = g_value_get_enum(value);
513                 sink->user_route_policy = nvalue;
514                 break;
515         case PROP_AUDIO_LATENCY:
516                 nvalue = g_value_get_enum(value);
517                 sink->latency = nvalue;
518                 break;
519         case PROP_AUDIO_HANDLE:
520                 sink->cbHandle = g_value_get_pointer(value);
521                 break;
522         case PROP_AUDIO_CALLBACK:
523                 sink->audio_stream_cb = g_value_get_pointer(value);
524                 break;
525         case PROP_AUDIO_CLOSE_HANDLE_ON_PREPARE:
526                 nbool = g_value_get_boolean(value);
527                 sink->close_handle_on_prepare = nbool;
528                 break;
529         case PROP_AUDIO_OPEN_FORCEDLY:
530                 nbool = g_value_get_boolean(value);
531                 if (nbool) {
532                         GST_AVSYS_AUDIO_SINK_LOCK(sink);
533                         if (gst_avsysaudiosink_avsys_open(sink) == FALSE) {
534                                 GST_ERROR_OBJECT(sink, "gst_avsysaudiosink_avsys_open() failed");
535                         }
536                         GST_AVSYS_AUDIO_SINK_UNLOCK (sink);
537                 }
538                 break;
539 #ifdef USE_PA_AUDIO_FILTER
540         case PROP_SPEED:
541                 GST_INFO_OBJECT(sink, "request setting filter speed:%f (current:%f)",
542                         g_value_get_float(value), sink->playback_rate);
543                 sink->playback_rate = g_value_get_float(value);
544                 if (sink->audio_handle != -1) {
545                         avsys_audio_set_vsp_speed(sink->audio_handle, (guint)(sink->playback_rate * 1000));
546                 }
547                 break;
548         case PROP_FILTER_ACTION:
549                 sink->filter_action = g_value_get_uint(value);
550                 if (sink->audio_handle != -1) {
551                         avsys_audio_set_soundalive_filter_action(sink->audio_handle, sink->filter_action);
552                         if (sink->filter_action == FILTER_ADVANCED_SETTING) {
553                                 avsys_audio_set_soundalive_eq(sink->audio_handle, sink->custom_eq);
554                                 avsys_audio_set_soundalive_ext(sink->audio_handle, sink->custom_ext);
555                         }
556                 }
557                 break;
558         case PROP_FILTER_OUTPUT_MODE:
559                 GST_INFO_OBJECT(sink, "request setting filter_output_mode:%d (current:%d)",
560                         g_value_get_uint(value), sink->filter_output_mode);
561                 sink->filter_output_mode = g_value_get_uint(value);
562                 if (sink->audio_handle != -1)
563                         avsys_audio_set_soundalive_device(sink->audio_handle, sink->filter_output_mode);
564                 break;
565         case PROP_PRESET_MODE:
566                 sink->preset_mode = g_value_get_uint(value);
567                 if (sink->audio_handle != -1)
568                         avsys_audio_set_soundalive_preset_mode(sink->audio_handle, sink->preset_mode);
569                 break;
570         case PROP_CUSTOM_EQ:
571                 pointer = g_value_get_pointer(value);
572                 if (pointer) {
573                         gint *custom_eq = (gint *)pointer;
574                         GST_INFO_OBJECT(sink, "request setting custom_eq:%d,%d,%d,%d,%d,%d,%d (current:%d,%d,%d,%d,%d,%d,%d)",
575                                 custom_eq[0], custom_eq[1], custom_eq[2], custom_eq[3], custom_eq[4], custom_eq[5], custom_eq[6],
576                                 sink->custom_eq[0], sink->custom_eq[1], sink->custom_eq[2], sink->custom_eq[3],
577                                 sink->custom_eq[4], sink->custom_eq[5], sink->custom_eq[6]);
578                         memcpy(sink->custom_eq, pointer, sizeof(gint) * CUSTOM_EQ_BAND_MAX);
579                         if ((sink->audio_handle != -1) && (sink->filter_action == FILTER_ADVANCED_SETTING)) {
580                                 avsys_audio_set_soundalive_eq(sink->audio_handle, sink->custom_eq);
581                         }
582                 }
583                 break;
584         case PROP_CUSTOM_EXT:
585                 pointer = g_value_get_pointer(value);
586                 if (pointer) {
587                         gint *custom_ext = (gint *)pointer;
588                         GST_INFO_OBJECT(sink, "request setting custom_ext:%d,%d,%d,%d,%d (current:%d,%d,%d,%d,%d)",
589                                 custom_ext[CUSTOM_EXT_3D_LEVEL], custom_ext[CUSTOM_EXT_BASS_LEVEL],
590                                 custom_ext[CUSTOM_EXT_CONCERT_HALL_LEVEL], custom_ext[CUSTOM_EXT_CONCERT_HALL_VOLUME],
591                                 custom_ext[CUSTOM_EXT_CLARITY_LEVEL],
592                                 sink->custom_ext[CUSTOM_EXT_3D_LEVEL], sink->custom_ext[CUSTOM_EXT_BASS_LEVEL],
593                                 sink->custom_ext[CUSTOM_EXT_CONCERT_HALL_LEVEL], sink->custom_ext[CUSTOM_EXT_CONCERT_HALL_VOLUME],
594                                 sink->custom_ext[CUSTOM_EXT_CLARITY_LEVEL]);
595                         memcpy(sink->custom_ext, pointer, sizeof(gint) * CUSTOM_EXT_PARAM_MAX);
596                         if ((sink->audio_handle != -1) && (sink->filter_action == FILTER_ADVANCED_SETTING)) {
597                                 avsys_audio_set_soundalive_ext(sink->audio_handle, sink->custom_ext);
598                         }
599                 }
600                 break;
601 #endif
602         default:
603                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
604                 break;
605         }
606 }
607
608 static void
609 gst_avsysaudiosink_get_property (GObject * object, guint prop_id,
610                                                          GValue * value, GParamSpec * pspec)
611 {
612         GstAvsysAudioSink *sink = NULL;
613
614         sink = GST_AVSYS_AUDIO_SINK (object);
615
616         switch (prop_id) {
617         case PROP_AUDIO_VOLUME_TYPE:
618                 g_value_set_int(value, sink->volume_type);
619                 break;
620         case PROP_AUDIO_PRIORITY:
621                 g_value_set_int(value, sink->sound_priority);
622                 break;
623         case PROP_AUDIO_MUTE:
624                 g_value_set_enum(value, sink->mute);
625                 break;
626         case PROP_AUDIO_FADEUPVOLUME:
627                 g_value_set_boolean(value, sink->use_fadeup_volume);
628                 break;
629         case PROP_AUDIO_ROUTE_POLICY:
630                 g_value_set_enum(value, sink->audio_route_policy);
631                 break;
632         case PROP_AUDIO_USER_ROUTE:
633                 g_value_set_enum(value, sink->user_route_policy);
634                 break;
635         case PROP_AUDIO_LATENCY:
636                 g_value_set_enum(value, sink->latency);
637                 break;
638         case PROP_AUDIO_HANDLE:
639                 g_value_set_pointer(value, sink->cbHandle);
640                 break;
641         case PROP_AUDIO_CALLBACK:
642                 g_value_set_pointer(value, sink->audio_stream_cb);
643                 break;
644         case PROP_AUDIO_CLOSE_HANDLE_ON_PREPARE:
645                 g_value_set_boolean(value, sink->close_handle_on_prepare);
646                 break;
647         case PROP_AUDIO_OPEN_FORCEDLY:
648                 break;
649 #ifdef USE_PA_AUDIO_FILTER
650         case PROP_SPEED:
651                 g_value_set_float(value, sink->playback_rate);
652                 break;
653         case PROP_FILTER_ACTION:
654                 g_value_set_uint(value, sink->filter_action);
655                 break;
656         case PROP_FILTER_OUTPUT_MODE:
657                 g_value_set_uint(value, sink->filter_output_mode);
658                 break;
659         case PROP_PRESET_MODE:
660                 g_value_set_uint(value, sink->preset_mode);
661                 break;
662         case PROP_CUSTOM_EQ:
663                 g_value_set_pointer(value, sink->custom_eq);
664                 break;
665         case PROP_CUSTOM_EXT:
666                 g_value_set_pointer(value, sink->custom_ext);
667                 break;
668 #endif
669         default:
670                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
671                 break;
672         }
673 }
674
675 static void
676 gst_avsysaudiosink_init (GstAvsysAudioSink * avsysaudiosink, GstAvsysAudioSinkClass * g_class)
677 {
678         GST_DEBUG_OBJECT (avsysaudiosink, "initializing avsysaudiosink");
679
680         avsysaudiosink->audio_handle = (avsys_handle_t)-1;
681         avsysaudiosink->cached_caps = NULL;
682         avsysaudiosink->avsys_audio_lock = g_mutex_new ();
683         avsysaudiosink->avsys_audio_delay_lock = g_mutex_new ();
684         avsysaudiosink->avsys_audio_reset_lock = g_mutex_new ();
685         avsysaudiosink->volume_type = DEFAULT_VOLUME_TYPE;
686         avsysaudiosink->sound_priority = AVSYS_AUDIO_PRIORITY_NORMAL;
687         avsysaudiosink->mute = DEFAULT_AUDIO_MUTE;
688         avsysaudiosink->use_fadeup_volume = DEFAULT_FADEUP_VOLUME;
689         avsysaudiosink->latency = DEFAULT_AUDIO_LATENCY;
690         avsysaudiosink->audio_route_policy = DEFAULT_AUDIO_ROUTE;
691         avsysaudiosink->bytes_per_sample = 1;
692         avsysaudiosink->close_handle_on_prepare = DEFAULT_AUDIO_CLOSE_HANDLE_ON_PREPARE;
693         avsysaudiosink->first_write = FALSE;
694 #if defined (LPCM_DUMP_SUPPORT)
695         avsysaudiosink->dumpFp = NULL;
696 #endif
697         avsysaudiosink->audio_param.format = AVSYS_AUDIO_FORMAT_UNKNOWN;
698 #ifdef USE_PA_AUDIO_FILTER
699         avsysaudiosink->filter_action = DEFAULT_FILTER_ACTION;
700         avsysaudiosink->filter_output_mode = DEFAULT_FILTER_OUTPUT_MODE;
701         avsysaudiosink->preset_mode = DEFAULT_PRESET_MODE;
702         memset(avsysaudiosink->custom_eq, 0x00, sizeof(gint) * CUSTOM_EQ_BAND_MAX);
703         memset(avsysaudiosink->custom_ext, 0x00, sizeof(gint) * CUSTOM_EXT_PARAM_MAX);
704         avsysaudiosink->playback_rate = AUDIOVSP_DEFAULT_PLAYBACK_RATE;
705 #endif
706 }
707 #if 0
708 static GstCaps *
709 gst_avsysaudiosink_getcaps (GstBaseSink * bsink)
710 {
711     GstElementClass *element_class = NULL;
712     GstPadTemplate *pad_template = NULL;
713     GstAvsysAudioSink *sink = GST_AVSYS_AUDIO_SINK (bsink);
714     GstCaps *caps;
715
716 //    debug_fenter();
717
718     sink = GST_AVSYS_AUDIO_SINK (bsink);
719     if (sink->audio_handle == -1)
720     {
721         GST_DEBUG_OBJECT (sink, "avsystem audio not open, using template caps");
722         return NULL;              /* base class will get template caps for us */
723     }
724
725     if (sink->cached_caps)
726     {
727         GST_LOG_OBJECT (sink, "Returning cached caps");
728         return gst_caps_ref (sink->cached_caps);
729     }
730
731     element_class = GST_ELEMENT_GET_CLASS (sink);
732     pad_template = gst_element_class_get_pad_template (element_class, "sink");
733     g_return_val_if_fail (pad_template != NULL, NULL);
734
735         // todo : get supported format.
736         //caps = gst_avsysaudio_probe_supported_formats (GST_OBJECT (sink), sink->,
737         //gst_pad_template_get_caps (pad_template));
738
739         //if (caps) {
740         //sink->cached_caps = gst_caps_ref (caps);
741         //}
742
743     GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
744
745     return caps;
746 }
747 #endif
748
749 static avsys_audio_channel_pos_t *
750 gst_avsysaudiosink_gst_to_channel_map (avsys_audio_channel_pos_t * map,
751         const GstRingBufferSpec * spec)
752 {
753         int i;
754         GstAudioChannelPosition *pos;
755
756         for (i = 0; i < AVSYS_CHANNEL_MAX; i++) {
757                 map[i] = AVSYS_AUDIO_CHANNEL_POSITION_INVALID;
758         }
759
760         if (!(pos = gst_audio_get_channel_positions (gst_caps_get_structure (spec->caps, 0)))) {
761                 return NULL;
762         }
763
764         for (i = 0; i < spec->channels; i++) {
765                 if (pos[i] == GST_AUDIO_CHANNEL_POSITION_NONE) {
766                         g_free (pos);
767                         return NULL;
768                 } else if (pos[i] < GST_AUDIO_CHANNEL_POSITION_NUM) {
769                         map[i] = gst_pos_to_avsys[pos[i]];
770                 } else {
771                         map[i] = AVSYS_AUDIO_CHANNEL_POSITION_INVALID;
772                 }
773         }
774
775         g_free (pos);
776
777         return map;
778 }
779
780 static gboolean
781 avsysaudiosink_parse_spec (GstAvsysAudioSink * avsys_audio, GstRingBufferSpec * spec)
782 {
783         /* Check param */
784         if (spec->type != GST_BUFTYPE_LINEAR ||
785                 spec->channels > 6 || spec->channels < 1 ||
786                 !(spec->format == GST_S8 || spec->format == GST_S16_LE) )
787                 return FALSE;
788
789         switch (spec->format) {
790         case GST_S8:
791                 avsys_audio->audio_param.format = AVSYS_AUDIO_FORMAT_8BIT;
792                 avsys_audio->bytes_per_sample = 1;
793                 break;
794         case GST_S16_LE:
795                 avsys_audio->audio_param.format = AVSYS_AUDIO_FORMAT_16BIT;
796                 avsys_audio->bytes_per_sample = 2;
797                 break;
798         default:
799                 return FALSE;
800         }
801
802         /// set audio parameter for avsys audio open
803         switch (avsys_audio->latency) {
804         case AVSYSAUDIOSINK_LATENCY_LOW:
805                 avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT_VIDEO;
806                 break;
807         case AVSYSAUDIOSINK_LATENCY_MID:
808                 avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT;
809                 break;
810         case AVSYSAUDIOSINK_LATENCY_HIGH:
811                 avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT_CLOCK;
812                 break;
813         }
814
815         avsys_audio->audio_param.priority = 0;
816         avsys_audio->audio_param.samplerate = spec->rate;
817         avsys_audio->audio_param.channels = spec->channels;
818         avsys_audio->bytes_per_sample *= spec->channels;
819         gst_avsysaudiosink_gst_to_channel_map (avsys_audio->audio_param.map, spec);
820
821         /* set software volume table type */
822         avsys_audio->audio_param.vol_type = avsys_audio->volume_type;
823         avsys_audio->audio_param.priority = avsys_audio->sound_priority;
824         avsys_audio->audio_param.handle_route = avsys_audio->user_route_policy;
825
826         return TRUE;
827 }
828
829 static gboolean
830 gst_avsysaudiosink_open (GstAudioSink * asink)
831 {
832         return TRUE;
833 }
834
835 static gboolean
836 gst_avsysaudiosink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
837 {
838         guint   p_time = 0, b_time = 0;
839         gboolean ret = FALSE;
840         gboolean close_on_exit = FALSE;
841         GstAvsysAudioSink *avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
842
843         GST_WARNING(">> Start(%d)", avsys_audio->audio_handle);
844
845         GST_AVSYS_AUDIO_SINK_LOCK(avsys_audio);
846
847         // set avsys audio param
848         if (!avsysaudiosink_parse_spec (avsys_audio, spec)) {
849                 GST_ELEMENT_ERROR (avsys_audio, RESOURCE, SETTINGS, (NULL),
850                                                                    ("Setting of swparams failed: " ));
851                 goto exit;
852         }
853
854         /* Open Handle */
855         if (gst_avsysaudiosink_avsys_open(avsys_audio) == FALSE) {
856                 GST_ERROR_OBJECT(avsys_audio, "gst_avsysaudiosink_avsys_open() failed");
857                 goto OPEN_FAILED;
858         }
859
860         /* Ring buffer size */
861         if (AVSYS_STATE_SUCCESS ==
862                 avsys_audio_get_period_buffer_time(avsys_audio->audio_handle, &p_time, &b_time)) {
863                 if(p_time == 0 || b_time == 0) {
864                         GST_WARNING_OBJECT(avsys_audio, "");
865                         close_on_exit = TRUE;
866                         goto exit;
867                 }
868                 spec->latency_time = (guint64)p_time;
869                 spec->buffer_time = (guint64)b_time;
870         } else {
871                 GST_WARNING_OBJECT(avsys_audio, "");
872                 close_on_exit = TRUE;
873                 goto exit;
874         }
875         spec->segsize = avsys_audio->avsys_size; /* '/16' see avsys_audio_open */
876         spec->segtotal = (b_time / p_time) + (((b_time % p_time)/p_time > 0.5) ? 1: 0);
877         //spec->segtotal+2;
878         GST_WARNING ("latency time %u, buffer time %u, seg total %u\n",
879                                 (unsigned int)(spec->latency_time/1000), (unsigned int)(spec->buffer_time/1000), spec->segtotal);
880
881         /* Close if needed */
882         close_on_exit = avsys_audio->close_handle_on_prepare;
883
884         ret = TRUE;
885
886 exit:
887         if (close_on_exit) {
888                 if (gst_avsysaudiosink_avsys_close(avsys_audio) == FALSE) {
889                         GST_ERROR_OBJECT(avsys_audio, "gst_avsysaudiosink_avsys_close() failed");
890                 }
891         }
892
893         GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
894         GST_WARNING("<< End(%d), ret=%d", avsys_audio->audio_handle, ret);
895         return ret;
896
897 OPEN_FAILED:
898         avsysaudiosink_post_message(avsys_audio, GST_RESOURCE_ERROR_OPEN_READ);
899         GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
900         GST_WARNING("<< End(%d), ret=%d", avsys_audio->audio_handle, ret);
901         return ret;
902 }
903
904 static gboolean
905 gst_avsysaudiosink_unprepare (GstAudioSink * asink)
906 {
907         gboolean ret = TRUE;
908         GstAvsysAudioSink       *avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
909
910         GST_WARNING(">> Start(%d)", avsys_audio->audio_handle);
911         GST_AVSYS_AUDIO_SINK_LOCK(avsys_audio);
912         if(!gst_avsysaudiosink_avsys_close(avsys_audio)) {
913                 GST_ERROR_OBJECT(avsys_audio, "gst_avsysaudiosink_avsys_close() failed");
914                 ret = FALSE;
915         }
916         GST_AVSYS_AUDIO_SINK_UNLOCK(avsys_audio);
917         GST_WARNING("<< End(%d), ret=%d", avsys_audio->audio_handle, ret);
918
919         return ret;
920 }
921
922 static gboolean
923 gst_avsysaudiosink_close (GstAudioSink * asink)
924 {
925         GstAvsysAudioSink *avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
926         gst_caps_replace (&avsys_audio->cached_caps, NULL);
927
928         return TRUE;
929 }
930
931
932 /*
933  *   Underrun and suspend recovery
934  */
935
936 static guint
937 gst_avsysaudiosink_write (GstAudioSink * asink, gpointer data, guint length)
938 {
939         GstAvsysAudioSink *avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
940         gint    write_len = 0;
941         guint ret = 0;
942
943         GST_AVSYS_AUDIO_SINK_LOCK (asink);
944
945         if (avsys_audio->audio_stream_cb == NULL) {
946 #if defined (LPCM_DUMP_SUPPORT)
947                 fwrite(data, 1, write_len, avsys_audio->dumpFp); //This is for original data (no volume convert)
948 #endif
949                 write_len = avsys_audio_write(avsys_audio->audio_handle, data, length);
950                 if(write_len == length) {
951                         ret = write_len;
952                 } else {
953                         if(AVSYS_FAIL(write_len)) {
954                                 GST_ERROR_OBJECT(avsys_audio, "avsys_audio_write() failed with %d\n", write_len);
955                         }
956                         ret = length; /* skip one period */
957                 }
958         } else {
959                 if(!avsys_audio->audio_stream_cb(data, length, avsys_audio->cbHandle)) {
960                         GST_ERROR_OBJECT(avsys_audio,"auido stream callback failed\n");
961                 }
962                 ret = length;
963         }
964
965         if (avsys_audio->first_write) {
966                 GST_WARNING("First write (%d/%d)", ret, length);
967                 avsys_audio->first_write = FALSE;
968         }
969
970         GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
971         return ret;
972
973 }
974
975 static guint
976 gst_avsysaudiosink_delay (GstAudioSink * asink)
977 {
978         GstAvsysAudioSink *avsys_audio = NULL;
979         int delay = 0;
980         guint retValue = 0;
981
982         avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
983         GST_AVSYS_AUDIO_SINK_DELAY_LOCK (asink);
984         if ((int)avsys_audio->audio_handle != -1) {
985                 if (AVSYS_STATE_SUCCESS == avsys_audio_delay(avsys_audio->audio_handle, &delay)) {
986                         retValue = delay;
987                 }
988         }
989         GST_AVSYS_AUDIO_SINK_DELAY_UNLOCK (asink);
990         return retValue;
991 }
992
993 static void
994 gst_avsysaudiosink_reset (GstAudioSink * asink)
995 {
996         int avsys_result = AVSYS_STATE_SUCCESS;
997         GstAvsysAudioSink *avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
998
999         GST_WARNING(">> Start(%d)", avsys_audio->audio_handle);
1000         GST_AVSYS_AUDIO_SINK_LOCK (asink);
1001
1002 #if defined(__REPLACE_RESET_WITH_CLOSE_AND_REOPEN__)
1003         if(!gst_avsysaudiosink_avsys_close(avsys_audio)) {
1004                 GST_ERROR_OBJECT(avsys_audio, "gst_avsysaudiosink_avsys_close() failed");
1005         }
1006 #else
1007         if(AVSYS_STATE_SUCCESS != avsys_audio_reset(avsys_audio->audio_handle)) {
1008                 GST_ERROR_OBJECT (avsys_audio, "avsys-reset: internal error: ");
1009         }
1010 #endif
1011
1012         GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
1013         GST_WARNING("<<  End(%d)", avsys_audio->audio_handle);
1014
1015         return;
1016 }
1017
1018
1019 static gboolean
1020 gst_avsysaudiosink_avsys_open(GstAvsysAudioSink *avsys_audio)
1021 {
1022         gboolean ret = TRUE;
1023         int avsys_result;
1024         int available = FALSE;
1025
1026         if (avsys_audio->audio_handle == (avsys_handle_t)-1) {
1027                 GST_LOG_OBJECT (avsys_audio, "avsys_audio_open() with user policy [%d] ",  avsys_audio->user_route_policy);
1028
1029                 /* workaround for PA audio filter */
1030                 if (avsys_audio->latency == AVSYSAUDIOSINK_LATENCY_HIGH) {
1031                         avsys_audio_is_available_high_latency(&available);
1032                         if (available == FALSE) {
1033                                 avsys_audio->latency = AVSYSAUDIOSINK_LATENCY_MID;
1034                                 avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT;
1035                         }
1036                 }
1037
1038                 avsys_result = avsys_audio_open(&avsys_audio->audio_param, &avsys_audio->audio_handle, &avsys_audio->avsys_size);
1039                 if (avsys_result != AVSYS_STATE_SUCCESS) {
1040                         GST_ERROR_OBJECT(avsys_audio, "avsys_audio_open() failed with 0x%x", avsys_result);
1041                         avsysaudiosink_post_message(avsys_audio, GST_RESOURCE_ERROR_OPEN_READ);
1042                         ret = FALSE;
1043                 } else {
1044                         GST_WARNING("avsys_audio_open() success [%d]", avsys_audio->audio_handle);
1045                         avsys_audio->first_write = TRUE;
1046
1047 #ifdef USE_PA_AUDIO_FILTER
1048                         avsys_audio_set_vsp_speed(avsys_audio->audio_handle, (guint)(avsys_audio->playback_rate * 1000));
1049 #endif
1050
1051                         // check audio handle was already muted.
1052                         if(avsys_audio->mute == TRUE) {
1053                             if(AVSYS_SUCCESS(avsys_audio_set_mute(avsys_audio->audio_handle, AVSYS_AUDIO_MUTE)))
1054                                 GST_DEBUG("avsys_audio_set_mute() success. mute handle open success.\n");
1055                             else
1056                                 GST_DEBUG("avsys_audio_set mute() fail.\n");
1057                         }
1058                 }
1059         } else {
1060                 GST_WARNING("audio handle has already opened");
1061                 ret = FALSE;
1062         }
1063 #if defined (LPCM_DUMP_SUPPORT)
1064         if (avsys_audio->dumpFp == NULL) {
1065                 avsys_audio->dumpFp = fopen("/root/dump.lpcm","w");
1066         }
1067 #endif
1068         return ret;
1069 }
1070
1071 static gboolean
1072 gst_avsysaudiosink_avsys_close(GstAvsysAudioSink *avsys_audio)
1073 {
1074         gboolean ret = TRUE;
1075         int avsys_result = AVSYS_STATE_SUCCESS;
1076
1077         if (avsys_audio->audio_handle !=  (avsys_handle_t)-1 ) {
1078                 avsys_result = avsys_audio_close(avsys_audio->audio_handle);
1079                 if (AVSYS_FAIL(avsys_result)) {
1080                         GST_ERROR_OBJECT(avsys_audio, "avsys_audio_close() failed with 0x%x", avsys_result);
1081                         ret = FALSE;
1082                 } else {
1083                         GST_WARNING("avsys_audio_close(%d) success", avsys_audio->audio_handle);
1084                         avsys_audio->audio_handle = (avsys_handle_t) -1;
1085                 }
1086         } else {
1087                 GST_INFO("audio handle has already closed");
1088         }
1089
1090 #if defined (LPCM_DUMP_SUPPORT)
1091         if(avsys_audio->dumpFp != NULL)
1092         {
1093                 fclose(avsys_audio->dumpFp);
1094                 avsys_audio->dumpFp = NULL;
1095         }
1096 #endif
1097         return ret;
1098 }
1099
1100 static GstStateChangeReturn
1101 gst_avsyssudiosink_change_state (GstElement *element, GstStateChange transition)
1102 {
1103         GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1104         GstAvsysAudioSink *avsys_audio = GST_AVSYS_AUDIO_SINK (element);
1105
1106         int avsys_result = AVSYS_STATE_SUCCESS;
1107
1108         switch (transition) {
1109                 case GST_STATE_CHANGE_NULL_TO_READY:
1110                         break;
1111                 case GST_STATE_CHANGE_READY_TO_PAUSED:
1112                         break;
1113                 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1114 #if defined(_ALSA_DAPM_)
1115                         switch(avsys_audio->audio_route_policy) {
1116                         case AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING:
1117                                 GST_INFO_OBJECT(avsys_audio, "audio route uses external setting");
1118                                 break;
1119                         default:
1120                                 GST_ERROR_OBJECT(avsys_audio, "Unknown audio route option %d\n", avsys_audio->audio_route_policy);
1121                                 break;
1122                         }
1123 #endif
1124                         GST_AVSYS_AUDIO_SINK_LOCK (avsys_audio);
1125 #if defined(__REPLACE_RESET_WITH_CLOSE_AND_REOPEN__)
1126                         if (avsys_audio->audio_handle == (avsys_handle_t)-1 &&
1127                                 avsys_audio->audio_param.format != AVSYS_AUDIO_FORMAT_UNKNOWN) {
1128                                 if (gst_avsysaudiosink_avsys_open(avsys_audio) == FALSE) {
1129                                         GST_ERROR_OBJECT(avsys_audio, "gst_avsysaudiosink_avsys_open() failed");
1130                                         GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
1131                                         return GST_STATE_CHANGE_FAILURE;
1132                                 }
1133                         }
1134 #endif
1135                         if (avsys_audio->use_fadeup_volume) {
1136                                 GST_INFO_OBJECT(avsys_audio, "Set fadeup volume");
1137                                 avsys_audio_set_volume_fadeup(avsys_audio->audio_handle);
1138                         }
1139                         GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
1140
1141 #if 0
1142                         if(AVSYS_STATE_SUCCESS != avsys_audio_set_mute(avsys_audio->audio_handle, CONVERT_MUTE_VALUE(avsys_audio->mute)))
1143                         {
1144                                 GST_ERROR_OBJECT(avsys_audio, "Set mute failed %d", CONVERT_MUTE_VALUE(avsys_audio->mute));
1145                         }
1146 #endif
1147                         break;
1148                 default:
1149                         break;
1150         }
1151         ret = GST_ELEMENT_CLASS(parent_class)->change_state (element, transition);
1152         if (ret == GST_STATE_CHANGE_FAILURE) {
1153                 return ret;
1154         }
1155         switch (transition) {
1156         case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1157                 break;
1158         case GST_STATE_CHANGE_PAUSED_TO_READY:
1159                 break;
1160         case GST_STATE_CHANGE_READY_TO_NULL:
1161                 break;
1162         default:
1163                 break;
1164         }
1165         return ret;
1166 }
1167
1168
1169 static gboolean
1170 avsysaudiosink_post_message(GstAvsysAudioSink* self,int errorcode)
1171 {
1172                 GST_DEBUG("avsysaudiosink_post_message\n");
1173                 gboolean ret = TRUE;
1174                 GstMessage *Msg = NULL;
1175                 GQuark domain;
1176                 gboolean status = FALSE;
1177                 GError *error = NULL;
1178                 gint error_code;
1179                 /*
1180                 if(errorcode>0)
1181                                 error_code = errorcode;
1182                 else
1183                                 error_code = GST_STREAM_ERROR_TYPE_NOT_FOUND; */
1184                 error_code = errorcode;
1185                 domain = gst_resource_error_quark();
1186                 error = g_error_new (domain, error_code, "AVSYSAUDIOSINK_RESOURCE_ERROR");
1187                 Msg = gst_message_new_error(GST_ELEMENT(self), error, "AVSYSAUDIOSINK_ERROR");
1188                 status = gst_element_post_message (GST_ELEMENT(self), Msg);
1189                 if (status == FALSE)
1190                 {
1191                                 GST_ERROR("Error in posting message on the bus ...\n");
1192                                 ret = FALSE;
1193                 }
1194
1195                 return ret;
1196 }