]> git.sesse.net Git - vlc/blob - lib/audio.c
lib: reset the audio output when selecting amem or custom plugin
[vlc] / 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 );
90             goto error;
91         }
92         item->p_next = list;
93         list = item;
94     }
95     module_list_free( module_list );
96
97     VLC_UNUSED( p_instance );
98     return list;
99 }
100
101 /********************************************
102  * Free the list of available audio outputs
103  ***********************************************/
104 void libvlc_audio_output_list_release( libvlc_audio_output_t *list )
105 {
106     while( list != NULL )
107     {
108         libvlc_audio_output_t *next = list->p_next;
109
110         free( list->psz_name );
111         free( list->psz_description );
112         free( list );
113         list = next;
114     }
115 }
116
117
118 /***********************
119  * Set the audio output.
120  ***********************/
121 int libvlc_audio_output_set( libvlc_media_player_t *mp, const char *psz_name )
122 {
123     char *value;
124
125     if( !module_exists( psz_name )
126      || asprintf( &value, "%s,none", psz_name ) == -1 )
127         return -1;
128     var_SetString( mp, "aout", value );
129     free( value );
130
131     /* Forget the existing audio output */
132     input_resource_ResetAout(mp->input.p_resource);
133
134     /* Create a new audio output */
135     audio_output_t *aout = input_resource_GetAout(mp->input.p_resource);
136     if( aout != NULL )
137         input_resource_PutAout(mp->input.p_resource, aout);
138
139     return 0;
140 }
141
142 libvlc_audio_output_device_t *
143 libvlc_audio_output_device_list_get( libvlc_instance_t *p_instance,
144                                      const char *aout )
145 {
146     char varname[32];
147     if( (size_t)snprintf( varname, sizeof(varname), "%s-audio-device", aout )
148                                                            >= sizeof(varname) )
149         return NULL;
150
151     libvlc_audio_output_device_t *list = NULL, **pp = &list;
152     char **values, **texts;
153     ssize_t count = config_GetPszChoices( VLC_OBJECT(p_instance->p_libvlc_int),
154                                           varname, &values, &texts );
155     for( ssize_t i = 0; i < count; i++ )
156     {
157         libvlc_audio_output_device_t *item = malloc( sizeof(*item) );
158         if( unlikely(item == NULL) )
159             break;
160
161         *pp = item;
162         pp = &item->p_next;
163         item->psz_device = values[i];
164         item->psz_description = texts[i];
165     }
166
167     *pp = NULL;
168     free( texts );
169     free( values );
170     (void) p_instance;
171     return list;
172 }
173
174 void libvlc_audio_output_device_list_release( libvlc_audio_output_device_t *l )
175 {
176     while( l != NULL )
177     {
178         libvlc_audio_output_device_t *next = l->p_next;
179
180         free( l->psz_description );
181         free( l->psz_device );
182         free( l );
183         l = next;
184     }
185 }
186
187 int libvlc_audio_output_device_count( libvlc_instance_t *p_instance,
188                                       const char *psz_audio_output )
189 {
190     (void) p_instance; (void) psz_audio_output;
191     return 0;
192 }
193
194 char *libvlc_audio_output_device_longname( libvlc_instance_t *p_instance,
195                                            const char *psz_audio_output,
196                                            int i_device )
197 {
198     (void) p_instance; (void) psz_audio_output; (void) i_device;
199     return NULL;
200 }
201
202 char *libvlc_audio_output_device_id( libvlc_instance_t *p_instance,
203                                      const char *psz_audio_output,
204                                      int i_device )
205 {
206     (void) p_instance; (void) psz_audio_output; (void) i_device;
207     return NULL;
208 }
209
210 /*****************************
211  * Set device for using
212  *****************************/
213 void libvlc_audio_output_device_set( libvlc_media_player_t *mp,
214                                      const char *psz_audio_output,
215                                      const char *psz_device_id )
216 {
217     char *psz_config_name;
218     if( !psz_audio_output || !psz_device_id )
219         return;
220     if( asprintf( &psz_config_name, "%s-audio-device", psz_audio_output ) == -1 )
221         return;
222     if( !var_Type( mp, psz_config_name ) )
223         /* Don't recreate the same variable over and over and over... */
224         var_Create( mp, psz_config_name, VLC_VAR_STRING );
225     var_SetString( mp, psz_config_name, psz_device_id );
226     free( psz_config_name );
227 }
228
229 int libvlc_audio_output_get_device_type( libvlc_media_player_t *mp )
230 {
231     (void) mp;
232     return libvlc_AudioOutputDevice_Error;
233 }
234
235 void libvlc_audio_output_set_device_type( libvlc_media_player_t *mp,
236                                           int device_type )
237 {
238     (void) mp; (void) device_type;
239 }
240
241 void libvlc_audio_toggle_mute( libvlc_media_player_t *mp )
242 {
243     int mute = libvlc_audio_get_mute( mp );
244     if( mute != -1 )
245         libvlc_audio_set_mute( mp, !mute );
246 }
247
248 int libvlc_audio_get_mute( libvlc_media_player_t *mp )
249 {
250     int mute = -1;
251
252     audio_output_t *aout = GetAOut( mp );
253     if( aout != NULL )
254     {
255         mute = aout_MuteGet( aout );
256         vlc_object_release( aout );
257     }
258     return mute;
259 }
260
261 void libvlc_audio_set_mute( libvlc_media_player_t *mp, int mute )
262 {
263     audio_output_t *aout = GetAOut( mp );
264     if( aout != NULL )
265     {
266         mute = aout_MuteSet( aout, mute );
267         vlc_object_release( aout );
268     }
269 }
270
271 int libvlc_audio_get_volume( libvlc_media_player_t *mp )
272 {
273     int volume = -1;
274
275     audio_output_t *aout = GetAOut( mp );
276     if( aout != NULL )
277     {
278         float vol = aout_VolumeGet( aout );
279         vlc_object_release( aout );
280         volume = lroundf( vol * 100.f );
281     }
282     return volume;
283 }
284
285 int libvlc_audio_set_volume( libvlc_media_player_t *mp, int volume )
286 {
287     float vol = volume / 100.f;
288     if (vol < 0.f)
289     {
290         libvlc_printerr( "Volume out of range" );
291         return -1;
292     }
293
294     int ret = -1;
295     audio_output_t *aout = GetAOut( mp );
296     if( aout != NULL )
297     {
298         ret = aout_VolumeSet( aout, vol );
299         vlc_object_release( aout );
300     }
301     return ret;
302 }
303
304 /*****************************************************************************
305  * libvlc_audio_get_track_count : Get the number of available audio tracks
306  *****************************************************************************/
307 int libvlc_audio_get_track_count( libvlc_media_player_t *p_mi )
308 {
309     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
310     int i_track_count;
311
312     if( !p_input_thread )
313         return -1;
314
315     i_track_count = var_CountChoices( p_input_thread, "audio-es" );
316
317     vlc_object_release( p_input_thread );
318     return i_track_count;
319 }
320
321 /*****************************************************************************
322  * libvlc_audio_get_track_description : Get the description of available audio tracks
323  *****************************************************************************/
324 libvlc_track_description_t *
325         libvlc_audio_get_track_description( libvlc_media_player_t *p_mi )
326 {
327     return libvlc_get_track_description( p_mi, "audio-es" );
328 }
329
330 /*****************************************************************************
331  * libvlc_audio_get_track : Get the current audio track
332  *****************************************************************************/
333 int libvlc_audio_get_track( libvlc_media_player_t *p_mi )
334 {
335     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
336     if( !p_input_thread )
337         return -1;
338
339     int id = var_GetInteger( p_input_thread, "audio-es" );
340     vlc_object_release( p_input_thread );
341     return id;
342 }
343
344 /*****************************************************************************
345  * libvlc_audio_set_track : Set the current audio track
346  *****************************************************************************/
347 int libvlc_audio_set_track( libvlc_media_player_t *p_mi, int i_track )
348 {
349     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
350     vlc_value_t val_list;
351     int i_ret = -1;
352
353     if( !p_input_thread )
354         return -1;
355
356     var_Change( p_input_thread, "audio-es", VLC_VAR_GETCHOICES, &val_list, NULL );
357     for( int i = 0; i < val_list.p_list->i_count; i++ )
358     {
359         if( i_track == val_list.p_list->p_values[i].i_int )
360         {
361             if( var_SetInteger( p_input_thread, "audio-es", i_track ) < 0 )
362                 break;
363             i_ret = 0;
364             goto end;
365         }
366     }
367     libvlc_printerr( "Track identifier not found" );
368 end:
369     var_FreeList( &val_list, NULL );
370     vlc_object_release( p_input_thread );
371     return i_ret;
372 }
373
374 /*****************************************************************************
375  * libvlc_audio_get_channel : Get the current audio channel
376  *****************************************************************************/
377 int libvlc_audio_get_channel( libvlc_media_player_t *mp )
378 {
379     audio_output_t *p_aout = GetAOut( mp );
380     if( !p_aout )
381         return 0;
382
383     int val = var_GetInteger( p_aout, "stereo-mode" );
384     vlc_object_release( p_aout );
385     return val;
386 }
387
388 /*****************************************************************************
389  * libvlc_audio_set_channel : Set the current audio channel
390  *****************************************************************************/
391 int libvlc_audio_set_channel( libvlc_media_player_t *mp, int channel )
392 {
393     audio_output_t *p_aout = GetAOut( mp );
394     int ret = 0;
395
396     if( !p_aout )
397         return -1;
398
399     if( var_SetInteger( p_aout, "stereo-mode", channel ) < 0 )
400     {
401         libvlc_printerr( "Audio channel out of range" );
402         ret = -1;
403     }
404     vlc_object_release( p_aout );
405     return ret;
406 }
407
408 /*****************************************************************************
409  * libvlc_audio_get_delay : Get the current audio delay
410  *****************************************************************************/
411 int64_t libvlc_audio_get_delay( libvlc_media_player_t *p_mi )
412 {
413     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
414     int64_t val = 0;
415     if( p_input_thread != NULL )
416     {
417       val = var_GetTime( p_input_thread, "audio-delay" );
418       vlc_object_release( p_input_thread );
419     }
420     return val;
421 }
422
423 /*****************************************************************************
424  * libvlc_audio_set_delay : Set the current audio delay
425  *****************************************************************************/
426 int libvlc_audio_set_delay( libvlc_media_player_t *p_mi, int64_t i_delay )
427 {
428     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
429     int ret = 0;
430     if( p_input_thread != NULL )
431     {
432       var_SetTime( p_input_thread, "audio-delay", i_delay );
433       vlc_object_release( p_input_thread );
434     }
435     else
436     {
437       ret = -1;
438     }
439     return ret;
440 }
441
442 /*****************************************************************************
443  * libvlc_audio_equalizer_get_preset_count : Get the number of equalizer presets
444  *****************************************************************************/
445 unsigned libvlc_audio_equalizer_get_preset_count( void )
446 {
447     return NB_PRESETS;
448 }
449
450 /*****************************************************************************
451  * libvlc_audio_equalizer_get_preset_name : Get the name for a preset
452  *****************************************************************************/
453 const char *libvlc_audio_equalizer_get_preset_name( unsigned u_index )
454 {
455     if ( u_index >= NB_PRESETS )
456         return NULL;
457
458     return preset_list_text[ u_index ];
459 }
460
461 /*****************************************************************************
462  * libvlc_audio_equalizer_get_band_count : Get the number of equalizer frequency bands
463  *****************************************************************************/
464 unsigned libvlc_audio_equalizer_get_band_count( void )
465 {
466     return EQZ_BANDS_MAX;
467 }
468
469 /*****************************************************************************
470  * libvlc_audio_equalizer_get_band_frequency : Get the frequency for a band
471  *****************************************************************************/
472 float libvlc_audio_equalizer_get_band_frequency( unsigned u_index )
473 {
474     if ( u_index >= EQZ_BANDS_MAX )
475         return -1.f;
476
477     return f_iso_frequency_table_10b[ u_index ];
478 }
479
480 /*****************************************************************************
481  * libvlc_audio_equalizer_new : Create a new audio equalizer with zeroed values
482  *****************************************************************************/
483 libvlc_equalizer_t *libvlc_audio_equalizer_new( void )
484 {
485     libvlc_equalizer_t *p_equalizer;
486     p_equalizer = malloc( sizeof( *p_equalizer ) );
487     if ( unlikely( p_equalizer == NULL ) )
488         return NULL;
489
490     p_equalizer->f_preamp = 0.f;
491     for ( unsigned i = 0; i < EQZ_BANDS_MAX; i++ )
492         p_equalizer->f_amp[ i ] = 0.f;
493
494     return p_equalizer;
495 }
496
497 /*****************************************************************************
498  * libvlc_audio_equalizer_new_from_preset : Create a new audio equalizer based on a preset
499  *****************************************************************************/
500 libvlc_equalizer_t *libvlc_audio_equalizer_new_from_preset( unsigned u_index )
501 {
502     libvlc_equalizer_t *p_equalizer;
503
504     if ( u_index >= NB_PRESETS )
505         return NULL;
506
507     p_equalizer = malloc( sizeof( *p_equalizer ) );
508     if ( unlikely( p_equalizer == NULL ) )
509         return NULL;
510
511     p_equalizer->f_preamp = eqz_preset_10b[ u_index ].f_preamp;
512
513     for ( unsigned i = 0; i < EQZ_BANDS_MAX; i++ )
514         p_equalizer->f_amp[ i ] = eqz_preset_10b[ u_index ].f_amp[ i ];
515
516     return p_equalizer;
517 }
518
519 /*****************************************************************************
520  * libvlc_audio_equalizer_release : Release a previously created equalizer
521  *****************************************************************************/
522 void libvlc_audio_equalizer_release( libvlc_equalizer_t *p_equalizer )
523 {
524     free( p_equalizer );
525 }
526
527 /*****************************************************************************
528  * libvlc_audio_equalizer_set_preamp : Set the preamp value for an equalizer
529  *****************************************************************************/
530 int libvlc_audio_equalizer_set_preamp( libvlc_equalizer_t *p_equalizer, float f_preamp )
531 {
532     if ( f_preamp < -20.0f )
533         f_preamp = -20.0f;
534     else if ( f_preamp > 20.0f )
535         f_preamp = 20.0f;
536
537     p_equalizer->f_preamp = f_preamp;
538     return 0;
539 }
540
541 /*****************************************************************************
542  * libvlc_audio_equalizer_get_preamp : Get the preamp value for an equalizer
543  *****************************************************************************/
544 float libvlc_audio_equalizer_get_preamp( libvlc_equalizer_t *p_equalizer )
545 {
546     return p_equalizer->f_preamp;
547 }
548
549 /*****************************************************************************
550  * libvlc_audio_equalizer_set_amp_at_index : Set the amplification value for an equalizer band
551  *****************************************************************************/
552 int libvlc_audio_equalizer_set_amp_at_index( libvlc_equalizer_t *p_equalizer, float f_amp, unsigned u_band )
553 {
554     if ( u_band >= EQZ_BANDS_MAX )
555         return -1;
556
557     if ( f_amp < -20.0f )
558         f_amp = -20.0f;
559     else if ( f_amp > 20.0f )
560         f_amp = 20.0f;
561
562     p_equalizer->f_amp[ u_band ] = f_amp;
563     return 0;
564 }
565
566 /*****************************************************************************
567  * libvlc_audio_equalizer_get_amp_at_index : Get the amplification value for an equalizer band
568  *****************************************************************************/
569 float libvlc_audio_equalizer_get_amp_at_index( libvlc_equalizer_t *p_equalizer, unsigned u_band )
570 {
571     if ( u_band >= EQZ_BANDS_MAX )
572         return 0.f;
573
574     return p_equalizer->f_amp[ u_band ];
575 }