libvlc: add renderer_discoverer external API
[vlc.git] / lib / audio.c
1 /*****************************************************************************
2  * libvlc_audio.c: New libvlc audio control API
3  *****************************************************************************
4  * Copyright (C) 2006 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Filippo Carone <filippo@carone.org>
8  *          Jean-Paul Saman <jpsaman _at_ m2x _dot_ nl>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <assert.h>
30 #include <math.h>
31
32 #include <vlc/libvlc.h>
33 #include <vlc/libvlc_media.h>
34 #include <vlc/libvlc_media_player.h>
35
36 #include <vlc_common.h>
37 #include <vlc_input.h>
38 #include <vlc_aout.h>
39 #include <vlc_modules.h>
40
41 #include "libvlc_internal.h"
42 #include "media_player_internal.h"
43
44 /*
45  * Remember to release the returned audio_output_t since it is locked at
46  * the end of this function.
47  */
48 static audio_output_t *GetAOut( libvlc_media_player_t *mp )
49 {
50     assert( mp != NULL );
51
52     audio_output_t *p_aout = input_resource_HoldAout( mp->input.p_resource );
53     if( p_aout == NULL )
54         libvlc_printerr( "No active audio output" );
55     return p_aout;
56 }
57
58 /*****************************************
59  * Get the list of available audio outputs
60  *****************************************/
61 libvlc_audio_output_t *
62         libvlc_audio_output_list_get( libvlc_instance_t *p_instance )
63 {
64     size_t count;
65     module_t **module_list = module_list_get( &count );
66     libvlc_audio_output_t *list = NULL;
67
68     for (size_t i = 0; i < count; i++)
69     {
70         module_t *module = module_list[i];
71
72         if( !module_provides( module, "audio output" ) )
73             continue;
74
75         libvlc_audio_output_t *item = malloc( sizeof( *item ) );
76         if( unlikely(item == NULL) )
77         {
78     error:
79             libvlc_printerr( "Not enough memory" );
80             libvlc_audio_output_list_release( list );
81             list = NULL;
82             break;
83         }
84
85         item->psz_name = strdup( module_get_object( module ) );
86         item->psz_description = strdup( module_get_name( module, true ) );
87         if( unlikely(item->psz_name == NULL || item->psz_description == NULL) )
88         {
89             free( item->psz_name );
90             free( item->psz_description );
91             free( item );
92             goto error;
93         }
94         item->p_next = list;
95         list = item;
96     }
97     module_list_free( module_list );
98
99     VLC_UNUSED( p_instance );
100     return list;
101 }
102
103 /********************************************
104  * Free the list of available audio outputs
105  ***********************************************/
106 void libvlc_audio_output_list_release( libvlc_audio_output_t *list )
107 {
108     while( list != NULL )
109     {
110         libvlc_audio_output_t *next = list->p_next;
111
112         free( list->psz_name );
113         free( list->psz_description );
114         free( list );
115         list = next;
116     }
117 }
118
119
120 /***********************
121  * Set the audio output.
122  ***********************/
123 int libvlc_audio_output_set( libvlc_media_player_t *mp, const char *psz_name )
124 {
125     char *value;
126
127     if( !module_exists( psz_name )
128      || asprintf( &value, "%s,none", psz_name ) == -1 )
129         return -1;
130     var_SetString( mp, "aout", value );
131     free( value );
132
133     /* Forget the existing audio output */
134     input_resource_ResetAout(mp->input.p_resource);
135
136     /* Create a new audio output */
137     audio_output_t *aout = input_resource_GetAout(mp->input.p_resource);
138     if( aout != NULL )
139         input_resource_PutAout(mp->input.p_resource, aout);
140
141     return 0;
142 }
143
144 libvlc_audio_output_device_t *
145 libvlc_audio_output_device_enum( libvlc_media_player_t *mp )
146 {
147     audio_output_t *aout = GetAOut( mp );
148     if( aout == NULL )
149         return NULL;
150
151     libvlc_audio_output_device_t *list, **pp = &list;
152     char **values, **texts;
153
154     int n = aout_DevicesList( aout, &values, &texts );
155     vlc_object_release( aout );
156     if( n < 0 )
157         goto err;
158
159     for (int i = 0; i < n; i++)
160     {
161         libvlc_audio_output_device_t *item = malloc( sizeof(*item) );
162         if( unlikely(item == NULL) )
163         {
164             free( texts[i] );
165             free( values[i] );
166             continue;
167         }
168
169         *pp = item;
170         pp = &item->p_next;
171         item->psz_device = values[i];
172         item->psz_description = texts[i];
173     }
174
175     free( texts );
176     free( values );
177 err:
178     *pp = NULL;
179     return list;
180 }
181
182 libvlc_audio_output_device_t *
183 libvlc_audio_output_device_list_get( libvlc_instance_t *p_instance,
184                                      const char *aout )
185 {
186     char varname[32];
187     if( (size_t)snprintf( varname, sizeof(varname), "%s-audio-device", aout )
188                                                            >= sizeof(varname) )
189         return NULL;
190
191     libvlc_audio_output_device_t *list = NULL, **pp = &list;
192     char **values, **texts;
193     ssize_t count = config_GetPszChoices( VLC_OBJECT(p_instance->p_libvlc_int),
194                                           varname, &values, &texts );
195     for( ssize_t i = 0; i < count; i++ )
196     {
197         libvlc_audio_output_device_t *item = malloc( sizeof(*item) );
198         if( unlikely(item == NULL) )
199             break;
200
201         *pp = item;
202         pp = &item->p_next;
203         item->psz_device = values[i];
204         item->psz_description = texts[i];
205     }
206
207     *pp = NULL;
208     free( texts );
209     free( values );
210     (void) p_instance;
211     return list;
212 }
213
214 void libvlc_audio_output_device_list_release( libvlc_audio_output_device_t *l )
215 {
216     while( l != NULL )
217     {
218         libvlc_audio_output_device_t *next = l->p_next;
219
220         free( l->psz_description );
221         free( l->psz_device );
222         free( l );
223         l = next;
224     }
225 }
226
227 int libvlc_audio_output_device_count( libvlc_instance_t *p_instance,
228                                       const char *psz_audio_output )
229 {
230     (void) p_instance; (void) psz_audio_output;
231     return 0;
232 }
233
234 char *libvlc_audio_output_device_longname( libvlc_instance_t *p_instance,
235                                            const char *psz_audio_output,
236                                            int i_device )
237 {
238     (void) p_instance; (void) psz_audio_output; (void) i_device;
239     return NULL;
240 }
241
242 char *libvlc_audio_output_device_id( libvlc_instance_t *p_instance,
243                                      const char *psz_audio_output,
244                                      int i_device )
245 {
246     (void) p_instance; (void) psz_audio_output; (void) i_device;
247     return NULL;
248 }
249
250 /*****************************
251  * Set device for using
252  *****************************/
253 void libvlc_audio_output_device_set( libvlc_media_player_t *mp,
254                                      const char *module, const char *devid )
255 {
256     if( devid == NULL )
257         return;
258
259     if( module != NULL )
260     {
261         char *cfg_name;
262
263         if( asprintf( &cfg_name, "%s-audio-device", module ) == -1 )
264             return;
265
266         if( !var_Type( mp, cfg_name ) )
267             /* Don't recreate the same variable over and over and over... */
268             var_Create( mp, cfg_name, VLC_VAR_STRING );
269         var_SetString( mp, cfg_name, devid );
270         free( cfg_name );
271         return;
272     }
273
274     audio_output_t *aout = GetAOut( mp );
275     if( aout == NULL )
276         return;
277
278     aout_DeviceSet( aout, devid );
279     vlc_object_release( aout );
280 }
281
282 char *libvlc_audio_output_device_get( libvlc_media_player_t *mp )
283 {
284     audio_output_t *aout = GetAOut( mp );
285     if( aout == NULL )
286         return NULL;
287
288     char *devid = aout_DeviceGet( aout );
289
290     vlc_object_release( aout );
291
292     return devid;
293 }
294
295 int libvlc_audio_output_get_device_type( libvlc_media_player_t *mp )
296 {
297     (void) mp;
298     return libvlc_AudioOutputDevice_Error;
299 }
300
301 void libvlc_audio_output_set_device_type( libvlc_media_player_t *mp,
302                                           int device_type )
303 {
304     (void) mp; (void) device_type;
305 }
306
307 void libvlc_audio_toggle_mute( libvlc_media_player_t *mp )
308 {
309     int mute = libvlc_audio_get_mute( mp );
310     if( mute != -1 )
311         libvlc_audio_set_mute( mp, !mute );
312 }
313
314 int libvlc_audio_get_mute( libvlc_media_player_t *mp )
315 {
316     int mute = -1;
317
318     audio_output_t *aout = GetAOut( mp );
319     if( aout != NULL )
320     {
321         mute = aout_MuteGet( aout );
322         vlc_object_release( aout );
323     }
324     return mute;
325 }
326
327 void libvlc_audio_set_mute( libvlc_media_player_t *mp, int mute )
328 {
329     audio_output_t *aout = GetAOut( mp );
330     if( aout != NULL )
331     {
332         mute = aout_MuteSet( aout, mute );
333         vlc_object_release( aout );
334     }
335 }
336
337 int libvlc_audio_get_volume( libvlc_media_player_t *mp )
338 {
339     int volume = -1;
340
341     audio_output_t *aout = GetAOut( mp );
342     if( aout != NULL )
343     {
344         float vol = aout_VolumeGet( aout );
345         vlc_object_release( aout );
346         volume = lroundf( vol * 100.f );
347     }
348     return volume;
349 }
350
351 int libvlc_audio_set_volume( libvlc_media_player_t *mp, int volume )
352 {
353     float vol = volume / 100.f;
354     if (!isgreaterequal(vol, 0.f))
355     {
356         libvlc_printerr( "Volume out of range" );
357         return -1;
358     }
359
360     int ret = -1;
361     audio_output_t *aout = GetAOut( mp );
362     if( aout != NULL )
363     {
364         ret = aout_VolumeSet( aout, vol );
365         vlc_object_release( aout );
366     }
367     return ret;
368 }
369
370 /*****************************************************************************
371  * libvlc_audio_get_track_count : Get the number of available audio tracks
372  *****************************************************************************/
373 int libvlc_audio_get_track_count( libvlc_media_player_t *p_mi )
374 {
375     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
376     int i_track_count;
377
378     if( !p_input_thread )
379         return -1;
380
381     i_track_count = var_CountChoices( p_input_thread, "audio-es" );
382
383     vlc_object_release( p_input_thread );
384     return i_track_count;
385 }
386
387 /*****************************************************************************
388  * libvlc_audio_get_track_description : Get the description of available audio tracks
389  *****************************************************************************/
390 libvlc_track_description_t *
391         libvlc_audio_get_track_description( libvlc_media_player_t *p_mi )
392 {
393     return libvlc_get_track_description( p_mi, "audio-es" );
394 }
395
396 /*****************************************************************************
397  * libvlc_audio_get_track : Get the current audio track
398  *****************************************************************************/
399 int libvlc_audio_get_track( libvlc_media_player_t *p_mi )
400 {
401     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
402     if( !p_input_thread )
403         return -1;
404
405     int id = var_GetInteger( p_input_thread, "audio-es" );
406     vlc_object_release( p_input_thread );
407     return id;
408 }
409
410 /*****************************************************************************
411  * libvlc_audio_set_track : Set the current audio track
412  *****************************************************************************/
413 int libvlc_audio_set_track( libvlc_media_player_t *p_mi, int i_track )
414 {
415     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
416     vlc_value_t val_list;
417     int i_ret = -1;
418
419     if( !p_input_thread )
420         return -1;
421
422     var_Change( p_input_thread, "audio-es", VLC_VAR_GETCHOICES, &val_list, NULL );
423     for( int i = 0; i < val_list.p_list->i_count; i++ )
424     {
425         if( i_track == val_list.p_list->p_values[i].i_int )
426         {
427             if( var_SetInteger( p_input_thread, "audio-es", i_track ) < 0 )
428                 break;
429             i_ret = 0;
430             goto end;
431         }
432     }
433     libvlc_printerr( "Track identifier not found" );
434 end:
435     var_FreeList( &val_list, NULL );
436     vlc_object_release( p_input_thread );
437     return i_ret;
438 }
439
440 /*****************************************************************************
441  * libvlc_audio_get_channel : Get the current audio channel
442  *****************************************************************************/
443 int libvlc_audio_get_channel( libvlc_media_player_t *mp )
444 {
445     audio_output_t *p_aout = GetAOut( mp );
446     if( !p_aout )
447         return 0;
448
449     int val = var_GetInteger( p_aout, "stereo-mode" );
450     vlc_object_release( p_aout );
451     return val;
452 }
453
454 /*****************************************************************************
455  * libvlc_audio_set_channel : Set the current audio channel
456  *****************************************************************************/
457 int libvlc_audio_set_channel( libvlc_media_player_t *mp, int channel )
458 {
459     audio_output_t *p_aout = GetAOut( mp );
460     int ret = 0;
461
462     if( !p_aout )
463         return -1;
464
465     if( var_SetInteger( p_aout, "stereo-mode", channel ) < 0 )
466     {
467         libvlc_printerr( "Audio channel out of range" );
468         ret = -1;
469     }
470     vlc_object_release( p_aout );
471     return ret;
472 }
473
474 /*****************************************************************************
475  * libvlc_audio_get_delay : Get the current audio delay
476  *****************************************************************************/
477 int64_t libvlc_audio_get_delay( libvlc_media_player_t *p_mi )
478 {
479     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
480     int64_t val = 0;
481     if( p_input_thread != NULL )
482     {
483       val = var_GetInteger( p_input_thread, "audio-delay" );
484       vlc_object_release( p_input_thread );
485     }
486     return val;
487 }
488
489 /*****************************************************************************
490  * libvlc_audio_set_delay : Set the current audio delay
491  *****************************************************************************/
492 int libvlc_audio_set_delay( libvlc_media_player_t *p_mi, int64_t i_delay )
493 {
494     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
495     int ret = 0;
496     if( p_input_thread != NULL )
497     {
498       var_SetInteger( p_input_thread, "audio-delay", i_delay );
499       vlc_object_release( p_input_thread );
500     }
501     else
502     {
503       ret = -1;
504     }
505     return ret;
506 }
507
508 /*****************************************************************************
509  * libvlc_audio_equalizer_get_preset_count : Get the number of equalizer presets
510  *****************************************************************************/
511 unsigned libvlc_audio_equalizer_get_preset_count( void )
512 {
513     return NB_PRESETS;
514 }
515
516 /*****************************************************************************
517  * libvlc_audio_equalizer_get_preset_name : Get the name for a preset
518  *****************************************************************************/
519 const char *libvlc_audio_equalizer_get_preset_name( unsigned u_index )
520 {
521     if ( u_index >= NB_PRESETS )
522         return NULL;
523
524     return preset_list_text[ u_index ];
525 }
526
527 /*****************************************************************************
528  * libvlc_audio_equalizer_get_band_count : Get the number of equalizer frequency bands
529  *****************************************************************************/
530 unsigned libvlc_audio_equalizer_get_band_count( void )
531 {
532     return EQZ_BANDS_MAX;
533 }
534
535 /*****************************************************************************
536  * libvlc_audio_equalizer_get_band_frequency : Get the frequency for a band
537  *****************************************************************************/
538 float libvlc_audio_equalizer_get_band_frequency( unsigned u_index )
539 {
540     if ( u_index >= EQZ_BANDS_MAX )
541         return -1.f;
542
543     return f_iso_frequency_table_10b[ u_index ];
544 }
545
546 /*****************************************************************************
547  * libvlc_audio_equalizer_new : Create a new audio equalizer with zeroed values
548  *****************************************************************************/
549 libvlc_equalizer_t *libvlc_audio_equalizer_new( void )
550 {
551     libvlc_equalizer_t *p_equalizer;
552     p_equalizer = malloc( sizeof( *p_equalizer ) );
553     if ( unlikely( p_equalizer == NULL ) )
554         return NULL;
555
556     p_equalizer->f_preamp = 0.f;
557     for ( unsigned i = 0; i < EQZ_BANDS_MAX; i++ )
558         p_equalizer->f_amp[ i ] = 0.f;
559
560     return p_equalizer;
561 }
562
563 /*****************************************************************************
564  * libvlc_audio_equalizer_new_from_preset : Create a new audio equalizer based on a preset
565  *****************************************************************************/
566 libvlc_equalizer_t *libvlc_audio_equalizer_new_from_preset( unsigned u_index )
567 {
568     libvlc_equalizer_t *p_equalizer;
569
570     if ( u_index >= NB_PRESETS )
571         return NULL;
572
573     p_equalizer = malloc( sizeof( *p_equalizer ) );
574     if ( unlikely( p_equalizer == NULL ) )
575         return NULL;
576
577     p_equalizer->f_preamp = eqz_preset_10b[ u_index ].f_preamp;
578
579     for ( unsigned i = 0; i < EQZ_BANDS_MAX; i++ )
580         p_equalizer->f_amp[ i ] = eqz_preset_10b[ u_index ].f_amp[ i ];
581
582     return p_equalizer;
583 }
584
585 /*****************************************************************************
586  * libvlc_audio_equalizer_release : Release a previously created equalizer
587  *****************************************************************************/
588 void libvlc_audio_equalizer_release( libvlc_equalizer_t *p_equalizer )
589 {
590     free( p_equalizer );
591 }
592
593 /*****************************************************************************
594  * libvlc_audio_equalizer_set_preamp : Set the preamp value for an equalizer
595  *****************************************************************************/
596 int libvlc_audio_equalizer_set_preamp( libvlc_equalizer_t *p_equalizer, float f_preamp )
597 {
598     if( isnan(f_preamp) )
599         return -1;
600     if( f_preamp < -20.f )
601         f_preamp = -20.f;
602     else if( f_preamp > 20.f )
603         f_preamp = 20.f;
604
605     p_equalizer->f_preamp = f_preamp;
606     return 0;
607 }
608
609 /*****************************************************************************
610  * libvlc_audio_equalizer_get_preamp : Get the preamp value for an equalizer
611  *****************************************************************************/
612 float libvlc_audio_equalizer_get_preamp( libvlc_equalizer_t *p_equalizer )
613 {
614     return p_equalizer->f_preamp;
615 }
616
617 /*****************************************************************************
618  * libvlc_audio_equalizer_set_amp_at_index : Set the amplification value for an equalizer band
619  *****************************************************************************/
620 int libvlc_audio_equalizer_set_amp_at_index( libvlc_equalizer_t *p_equalizer, float f_amp, unsigned u_band )
621 {
622     if( u_band >= EQZ_BANDS_MAX || isnan(f_amp) )
623         return -1;
624
625
626     if( f_amp < -20.f )
627         f_amp = -20.f;
628     else if( f_amp > 20.f )
629         f_amp = 20.f;
630
631     p_equalizer->f_amp[ u_band ] = f_amp;
632     return 0;
633 }
634
635 /*****************************************************************************
636  * libvlc_audio_equalizer_get_amp_at_index : Get the amplification value for an equalizer band
637  *****************************************************************************/
638 float libvlc_audio_equalizer_get_amp_at_index( libvlc_equalizer_t *p_equalizer, unsigned u_band )
639 {
640     if ( u_band >= EQZ_BANDS_MAX )
641         return nanf("");
642
643     return p_equalizer->f_amp[ u_band ];
644 }