input: add an input_item_t arg to input_CreateFilename()
[vlc.git] / modules / audio_output / tizen_audio.c
blob6ed34ac3d3145beb9c5b0ded13ba5051ffa7d5a1
1 /*****************************************************************************
2 * tizen_audio.c: Tizen audio output module
3 *****************************************************************************
4 * Copyright © 2015 VLC authors, VideoLAN and VideoLabs
6 * Authors: Thomas Guillem <thomas@gllm.fr>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include <assert.h>
28 #include <dlfcn.h>
29 #include <stdbool.h>
30 #include <stdatomic.h>
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_aout.h>
36 #include "audio_io.h"
37 #include "sound_manager.h"
39 static int Open( vlc_object_t * );
40 static void Close( vlc_object_t * );
42 typedef struct
44 /* sw gain */
45 float soft_gain;
46 bool soft_mute;
48 audio_out_h out;
49 bool b_prepared;
50 bool b_error;
51 atomic_bool interrupted_completed;
53 unsigned int i_rate;
54 audio_sample_type_e i_sample_type;
55 audio_channel_e i_channel;
57 int (*pf_audio_out_drain)( audio_out_h output );
58 int (*pf_audio_out_flush)( audio_out_h output );
59 } aout_sys_t;
61 /* Soft volume helper */
62 #include "audio_output/volume.h"
64 vlc_module_begin ()
65 set_shortname( "Tizen audio" )
66 set_description( "Tizen audio output" )
67 set_capability( "audio output", 180 )
68 set_category( CAT_AUDIO )
69 set_subcategory( SUBCAT_AUDIO_AOUT )
70 add_sw_gain()
71 add_shortcut( "tizen" )
72 set_callbacks( Open, Close )
73 vlc_module_end ()
75 static const char *
76 AudioIO_Err2Str( audio_io_error_e e )
78 switch( e )
80 case AUDIO_IO_ERROR_NONE:
81 return "AUDIO_IO_ERROR_NONE";
82 case AUDIO_IO_ERROR_OUT_OF_MEMORY:
83 return "AUDIO_IO_ERROR_OUT_OF_MEMORY";
84 case AUDIO_IO_ERROR_INVALID_PARAMETER:
85 return "AUDIO_IO_ERROR_INVALID_PARAMETER";
86 case AUDIO_IO_ERROR_INVALID_OPERATION:
87 return "AUDIO_IO_ERROR_INVALID_OPERATION";
88 case AUDIO_IO_ERROR_PERMISSION_DENIED:
89 return "AUDIO_IO_ERROR_PERMISSION_DENIED";
90 case AUDIO_IO_ERROR_NOT_SUPPORTED:
91 return "AUDIO_IO_ERROR_NOT_SUPPORTED";
92 case AUDIO_IO_ERROR_DEVICE_NOT_OPENED:
93 return "AUDIO_IO_ERROR_DEVICE_NOT_OPENED";
94 case AUDIO_IO_ERROR_DEVICE_NOT_CLOSED:
95 return "AUDIO_IO_ERROR_DEVICE_NOT_CLOSED";
96 case AUDIO_IO_ERROR_INVALID_BUFFER:
97 return "AUDIO_IO_ERROR_INVALID_BUFFER";
98 case AUDIO_IO_ERROR_SOUND_POLICY:
99 return "AUDIO_IO_ERROR_SOUND_POLICY";
100 default:
101 return "UNKNOWN_ERROR";
105 static int
106 AudioIO_VlcRet( audio_output_t *p_aout, const char *p_func, int i_ret )
108 if( i_ret != AUDIO_IO_ERROR_NONE )
110 aout_sys_t *p_sys = p_aout->sys;
112 msg_Err( p_aout, "%s failed: 0x%X, %s", p_func,
113 i_ret, AudioIO_Err2Str( i_ret ) );
115 /* Error could be recoverable if audio_out was interrupted. */
116 p_sys->b_error = true;
117 return VLC_EGENERIC;
119 else
120 return VLC_SUCCESS;
122 #define VLCRET( func ) AudioIO_VlcRet( p_aout, #func, func )
124 static int
125 AudioIO_Prepare( audio_output_t *p_aout )
127 aout_sys_t *p_sys = p_aout->sys;
129 /* if no more interrupted, cancel error and try again */
130 if( atomic_exchange( &p_sys->interrupted_completed, false ) )
131 p_sys->b_error = false;
133 if( p_sys->b_error )
134 return VLC_EGENERIC;
136 if( !p_sys->b_prepared )
138 if( VLCRET( audio_out_prepare( p_sys->out ) ) )
139 return VLC_EGENERIC;
140 p_sys->b_prepared = true;
142 return VLC_SUCCESS;
145 static int
146 AudioIO_Unprepare( audio_output_t *p_aout )
148 aout_sys_t *p_sys = p_aout->sys;
150 if( p_sys->b_prepared )
152 p_sys->b_prepared = false;
154 /* Unlocked to avoid deadlock with AudioIO_StreamCb */
155 if( VLCRET( audio_out_unprepare( p_sys->out ) ) )
156 return VLC_EGENERIC;
158 return VLC_SUCCESS;
161 static void
162 AudioIO_InterruptedCb(audio_io_interrupted_code_e code, void *p_user_data)
164 audio_output_t *p_aout = p_user_data;
165 aout_sys_t *p_sys = p_aout->sys;
167 if( code == AUDIO_IO_INTERRUPTED_COMPLETED
168 || code == AUDIO_IO_INTERRUPTED_BY_EARJACK_UNPLUG )
170 msg_Warn( p_aout, "audio_out interrupted completed by %d", code);
171 atomic_store( &p_sys->interrupted_completed, true );
173 else
175 msg_Warn( p_aout, "audio_out interrupted by %d", code);
176 atomic_store( &p_sys->interrupted_completed, false );
180 static int
181 AudioIO_Start( audio_output_t *p_aout )
183 aout_sys_t *p_sys = p_aout->sys;
185 /* Out create */
186 if( VLCRET( audio_out_create( p_sys->i_rate, p_sys->i_channel,
187 p_sys->i_sample_type, SOUND_TYPE_MEDIA,
188 &p_sys->out ) ) )
189 return VLC_EGENERIC;
190 return VLCRET( audio_out_set_interrupted_cb( p_sys->out,
191 AudioIO_InterruptedCb,
192 p_aout ) );
195 static int
196 Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
198 aout_sys_t *p_sys = p_aout->sys;
200 if( aout_FormatNbChannels( p_fmt ) == 0 )
201 return VLC_EGENERIC;
203 aout_FormatPrint( p_aout, "Tizen audio is looking for:", p_fmt );
205 /* Sample rate: tizen accept rate between 8000 and 48000 Hz */
206 p_sys->i_rate = p_fmt->i_rate = VLC_CLIP( p_fmt->i_rate, 8000, 48000 );
208 /* Channel */
209 switch( p_fmt->i_physical_channels )
211 case AOUT_CHAN_LEFT:
212 p_sys->i_channel = AUDIO_CHANNEL_MONO;
213 break;
214 default:
215 case AOUT_CHANS_STEREO:
216 p_fmt->i_physical_channels = AOUT_CHANS_STEREO;
217 p_sys->i_channel = AUDIO_CHANNEL_STEREO;
218 break;
221 /* Sample type */
222 switch( p_fmt->i_format )
224 case VLC_CODEC_U8:
225 p_sys->i_sample_type = AUDIO_SAMPLE_TYPE_U8;
226 break;
227 default:
228 case VLC_CODEC_S16N:
229 p_fmt->i_format = VLC_CODEC_S16N;
230 p_sys->i_sample_type = AUDIO_SAMPLE_TYPE_S16_LE;
231 break;
234 if( AudioIO_Start( p_aout ) != VLC_SUCCESS )
235 return VLC_EGENERIC;
237 p_fmt->channel_type = AUDIO_CHANNEL_TYPE_BITMAP;
239 aout_FormatPrepare( p_fmt );
240 aout_SoftVolumeStart( p_aout );
242 aout_FormatPrint( p_aout, "Tizen audio will output:", p_fmt );
244 return VLC_SUCCESS;
247 static void
248 Stop( audio_output_t *p_aout )
250 aout_sys_t *p_sys = p_aout->sys;
252 if( p_sys->out)
254 AudioIO_Unprepare( p_aout );
255 audio_out_unset_interrupted_cb( p_sys->out );
256 audio_out_destroy( p_sys->out );
257 p_sys->out = NULL;
259 p_sys->b_error = false;
260 atomic_store( &p_sys->interrupted_completed, false );
262 p_sys->i_rate = 0;
263 p_sys->i_channel = 0;
264 p_sys->i_sample_type = 0;
267 static void
268 Play( audio_output_t *p_aout, block_t *p_block, vlc_tick_t date )
270 aout_sys_t *p_sys = p_aout->sys;
272 if( !p_sys->out || AudioIO_Prepare( p_aout ) )
274 block_Release( p_block );
275 return;
278 while( p_block )
280 int i_ret = audio_out_write( p_sys->out, p_block->p_buffer, p_block->i_buffer );
281 if( i_ret < 0 )
283 AudioIO_VlcRet( p_aout, "audio_out_write", i_ret );
284 block_Release( p_block );
285 p_block = NULL;
287 else
289 p_block->i_buffer -= i_ret;
290 p_block->p_buffer += i_ret;
291 if( !p_block->i_buffer )
293 block_Release( p_block );
294 p_block = NULL;
298 (void) date;
301 static void
302 Pause( audio_output_t *p_aout, bool b_pause, vlc_tick_t i_date )
304 aout_sys_t *p_sys = p_aout->sys;
305 (void) i_date;
307 if( !p_sys->out )
308 return;
310 if( b_pause )
311 AudioIO_Unprepare( p_aout );
314 static void
315 Flush( audio_output_t *p_aout, bool b_wait )
317 aout_sys_t *p_sys = p_aout->sys;
319 if( !p_sys->out )
320 return;
322 if( p_sys->pf_audio_out_drain || p_sys->pf_audio_out_flush )
324 if( b_wait )
325 VLCRET( p_sys->pf_audio_out_drain( p_sys->out ) );
326 else
327 VLCRET( p_sys->pf_audio_out_flush( p_sys->out ) );
329 else
331 (void) b_wait;
332 if( AudioIO_Unprepare( p_aout ) )
333 return;
334 audio_out_unset_interrupted_cb( p_sys->out );
335 audio_out_destroy( p_sys->out );
336 p_sys->out = NULL;
337 AudioIO_Start( p_aout );
341 static int
342 Open( vlc_object_t *obj )
344 audio_output_t *p_aout = (audio_output_t *) obj;
345 aout_sys_t *p_sys;
347 p_sys = calloc( 1, sizeof (aout_sys_t) );
348 if( unlikely( p_sys == NULL ) )
349 return VLC_ENOMEM;
351 p_aout->sys = p_sys;
352 p_aout->start = Start;
353 p_aout->stop = Stop;
354 p_aout->play = Play;
355 p_aout->pause = Pause;
356 p_aout->flush = Flush;
357 /* p_aout->time_get = TimeGet; FIXME */
359 /* Available only on 2.4 */
360 p_sys->pf_audio_out_drain = dlsym( RTLD_DEFAULT, "audio_out_drain" );
361 p_sys->pf_audio_out_flush = dlsym( RTLD_DEFAULT, "audio_out_flush" );
363 aout_SoftVolumeInit( p_aout );
365 atomic_init( &p_sys->interrupted_completed, false );
367 return VLC_SUCCESS;
370 static void
371 Close( vlc_object_t *obj )
373 audio_output_t *p_aout = (audio_output_t *) obj;
374 aout_sys_t *p_sys = p_aout->sys;
376 free( p_sys );