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