a92cf3e2c0bcb8b1f521ec1418dd856a1e1ddd5f
[vlc.git] / modules / access / alsa.c
1 /*****************************************************************************
2  * alsa.c: ALSA capture module for VLC
3  *****************************************************************************
4  * Copyright (C) 2012 RĂ©mi Denis-Courmont
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <assert.h>
26 #include <sys/types.h>
27 #include <poll.h>
28 #include <alsa/asoundlib.h>
29
30 #include <vlc_common.h>
31 #include <vlc_demux.h>
32 #include <vlc_aout.h>
33 #include <vlc_plugin.h>
34
35 #define HELP_TEXT N_( \
36     "Pass alsa:// to open the default ALSA capture device, " \
37     "or alsa://SOURCE to open a specific device named SOURCE.")
38 #define STEREO_TEXT N_("Stereo")
39 #define RATE_TEXT N_("Sample rate")
40
41 static int Open (vlc_object_t *);
42 static void Close (vlc_object_t *);
43
44 static const int rate_values[] = { 192000, 176400,
45     96000, 88200, 48000, 44100,
46     32000, 22050, 24000, 16000,
47     11025, 8000, 4000
48 };
49 static const char *const rate_names[] = { N_("192000 Hz"), N_("176400 Hz"),
50     N_("96000 Hz"), N_("88200 Hz"), N_("48000 Hz"), N_("44100 Hz"),
51     N_("32000 Hz"), N_("22050 Hz"), N_("24000 Hz"), N_("16000 Hz"),
52     N_("11025 Hz"), N_("8000 Hz"), N_("4000 Hz")
53 };
54
55 vlc_module_begin ()
56     set_shortname (N_("ALSA"))
57     set_description (N_("ALSA audio capture"))
58     set_capability ("access", 0)
59     set_category (CAT_INPUT)
60     set_subcategory (SUBCAT_INPUT_ACCESS)
61     set_help (HELP_TEXT)
62
63     add_obsolete_string ("alsa-format") /* since 2.1.0 */
64     add_bool ("alsa-stereo", true, STEREO_TEXT, STEREO_TEXT, true)
65     add_integer ("alsa-samplerate", 48000, RATE_TEXT, RATE_TEXT, true)
66         change_integer_list (rate_values, rate_names)
67
68     add_shortcut ("alsa")
69     set_callbacks (Open, Close)
70 vlc_module_end ()
71
72 /** Helper for ALSA -> VLC debugging output */
73 /** XXX: duplicated from ALSA output */
74 static void Dump (vlc_object_t *obj, const char *msg,
75                   int (*cb)(void *, snd_output_t *), void *p)
76 {
77     snd_output_t *output;
78     char *str;
79
80     if (unlikely(snd_output_buffer_open (&output)))
81         return;
82
83     int val = cb (p, output);
84     if (val)
85     {
86         msg_Warn (obj, "cannot get info: %s", snd_strerror (val));
87         return;
88     }
89
90     size_t len = snd_output_buffer_string (output, &str);
91     if (len > 0 && str[len - 1])
92         len--; /* strip trailing newline */
93     msg_Dbg (obj, "%s%.*s", msg, (int)len, str);
94     snd_output_close (output);
95 }
96 #define Dump(o, m, cb, p) \
97         Dump(VLC_OBJECT(o), m, (int (*)(void *, snd_output_t *))(cb), p)
98
99 static void DumpDevice (vlc_object_t *obj, snd_pcm_t *pcm)
100 {
101     snd_pcm_info_t *info;
102
103     Dump (obj, " ", snd_pcm_dump, pcm);
104     snd_pcm_info_alloca (&info);
105     if (snd_pcm_info (pcm, info) == 0)
106     {
107         msg_Dbg (obj, " device name   : %s", snd_pcm_info_get_name (info));
108         msg_Dbg (obj, " device ID     : %s", snd_pcm_info_get_id (info));
109         msg_Dbg (obj, " subdevice name: %s",
110                 snd_pcm_info_get_subdevice_name (info));
111     }
112 }
113
114 static void DumpDeviceStatus (vlc_object_t *obj, snd_pcm_t *pcm)
115 {
116     snd_pcm_status_t *status;
117
118     snd_pcm_status_alloca (&status);
119     snd_pcm_status (pcm, status);
120     Dump (obj, "current status:\n", snd_pcm_status_dump, status);
121 }
122 #define DumpDeviceStatus(o, p) DumpDeviceStatus(VLC_OBJECT(o), p)
123
124
125 typedef struct
126 {
127     snd_pcm_t *pcm;
128     es_out_id_t *es;
129     vlc_thread_t thread;
130
131     vlc_tick_t start;
132     vlc_tick_t caching;
133     snd_pcm_uframes_t period_size;
134     unsigned rate;
135 } demux_sys_t;
136
137 static void Poll (snd_pcm_t *pcm, int canc)
138 {
139     int n = snd_pcm_poll_descriptors_count (pcm);
140     struct pollfd ufd[n];
141     unsigned short revents;
142
143     snd_pcm_poll_descriptors (pcm, ufd, n);
144     do
145     {
146         vlc_restorecancel (canc);
147         while (poll (ufd, n, -1) == -1);
148         canc = vlc_savecancel ();
149         snd_pcm_poll_descriptors_revents (pcm, ufd, n, &revents);
150     }
151     while (!revents);
152 }
153
154 static void *Thread (void *data)
155 {
156     demux_t *demux = data;
157     demux_sys_t *sys = demux->p_sys;
158     snd_pcm_t *pcm = sys->pcm;
159     size_t bytes;
160     int canc, val;
161
162     canc = vlc_savecancel ();
163     bytes = snd_pcm_frames_to_bytes (pcm, sys->period_size);
164     val = snd_pcm_start (pcm);
165     if (val)
166     {
167         msg_Err (demux, "cannot prepare device: %s", snd_strerror (val));
168         return NULL;
169     }
170
171     for (;;)
172     {
173         block_t *block = block_Alloc (bytes);
174         if (unlikely(block == NULL))
175             break;
176
177         /* Wait for data */
178         Poll (pcm, canc);
179
180         /* Read data */
181         snd_pcm_sframes_t frames, delay;
182         vlc_tick_t pts;
183
184         frames = snd_pcm_readi (pcm, block->p_buffer, sys->period_size);
185         pts = vlc_tick_now ();
186         if (frames < 0)
187         {
188             block_Release (block);
189             if (frames == -EAGAIN)
190                 continue;
191
192             val = snd_pcm_recover (pcm, frames, 1);
193             if (val == 0)
194             {
195                 msg_Warn (demux, "cannot read samples: %s",
196                           snd_strerror (frames));
197                 snd_pcm_state_t state = snd_pcm_state (pcm);
198                 switch (state)
199                 {
200                 case SND_PCM_STATE_PREPARED:
201                     val = snd_pcm_start (pcm);
202                     if (val < 0)
203                     {
204                         msg_Err (demux, "cannot prepare device: %s",
205                                  snd_strerror (val));
206                         return NULL;
207                     }
208                     continue;
209                 case SND_PCM_STATE_RUNNING:
210                     continue;
211                 default:
212                     break;
213                 }
214             }
215             msg_Err (demux, "cannot recover record stream: %s",
216                      snd_strerror (val));
217             DumpDeviceStatus (demux, pcm);
218             break;
219         }
220
221         /* Compute time stamp */
222         if (snd_pcm_delay (pcm, &delay))
223             delay = 0;
224         delay += frames;
225         pts -= vlc_tick_from_samples(delay,  sys->rate);
226
227         block->i_buffer = snd_pcm_frames_to_bytes (pcm, frames);
228         block->i_nb_samples = frames;
229         block->i_pts = pts;
230         block->i_length = vlc_tick_from_samples(frames, sys->rate);
231
232         es_out_SetPCR(demux->out, block->i_pts);
233         es_out_Send (demux->out, sys->es, block);
234     }
235     return NULL;
236 }
237
238 static int Control (demux_t *demux, int query, va_list ap)
239 {
240     demux_sys_t *sys = demux->p_sys;
241
242     switch (query)
243     {
244         case DEMUX_GET_TIME:
245             *va_arg (ap, vlc_tick_t *) = vlc_tick_now () - sys->start;
246             break;
247
248         case DEMUX_GET_PTS_DELAY:
249             *va_arg (ap, vlc_tick_t *) = sys->caching;
250             break;
251
252         //case DEMUX_SET_NEXT_DEMUX_TIME: still needed?
253
254         case DEMUX_HAS_UNSUPPORTED_META:
255         case DEMUX_CAN_RECORD:
256         case DEMUX_CAN_PAUSE:
257         case DEMUX_CAN_CONTROL_PACE:
258         case DEMUX_CAN_CONTROL_RATE:
259         case DEMUX_CAN_SEEK:
260             *va_arg (ap, bool *) = false;
261             break;;
262
263         default:
264             return VLC_EGENERIC;
265     }
266
267     return VLC_SUCCESS;
268 }
269
270 static const vlc_fourcc_t formats[] = {
271     [SND_PCM_FORMAT_S8]                 = VLC_CODEC_S8,
272     [SND_PCM_FORMAT_U8]                 = VLC_CODEC_U8,
273     [SND_PCM_FORMAT_S16_LE]             = VLC_CODEC_S16L,
274     [SND_PCM_FORMAT_S16_BE]             = VLC_CODEC_S16B,
275     [SND_PCM_FORMAT_U16_LE]             = VLC_CODEC_U16L,
276     [SND_PCM_FORMAT_U16_BE]             = VLC_CODEC_U16B,
277     [SND_PCM_FORMAT_S24_LE]             = VLC_CODEC_S24L32,
278     [SND_PCM_FORMAT_S24_BE]             = VLC_CODEC_S24B32,
279     [SND_PCM_FORMAT_U24_LE]             = VLC_CODEC_U32L, // TODO: replay gain
280     [SND_PCM_FORMAT_U24_BE]             = VLC_CODEC_U32B, // ^
281     [SND_PCM_FORMAT_S32_LE]             = VLC_CODEC_S32L,
282     [SND_PCM_FORMAT_S32_BE]             = VLC_CODEC_S32B,
283     [SND_PCM_FORMAT_U32_LE]             = VLC_CODEC_U32L,
284     [SND_PCM_FORMAT_U32_BE]             = VLC_CODEC_U32B,
285     [SND_PCM_FORMAT_FLOAT_LE]           = VLC_CODEC_F32L,
286     [SND_PCM_FORMAT_FLOAT_BE]           = VLC_CODEC_F32B,
287     [SND_PCM_FORMAT_FLOAT64_LE]         = VLC_CODEC_F64L,
288     [SND_PCM_FORMAT_FLOAT64_BE]         = VLC_CODEC_F64B,
289   //[SND_PCM_FORMAT_IEC958_SUBFRAME_LE] = VLC_CODEC_SPDIFL,
290   //[SND_PCM_FORMAT_IEC958_SUBFRAME_BE] = VLC_CODEC_SPDIFB,
291     [SND_PCM_FORMAT_MU_LAW]             = VLC_CODEC_MULAW,
292     [SND_PCM_FORMAT_A_LAW]              = VLC_CODEC_ALAW,
293   //[SND_PCM_FORMAT_IMA_ADPCM]          = VLC_CODEC_ADPCM_?, // XXX: which one?
294     [SND_PCM_FORMAT_MPEG]               = VLC_CODEC_MPGA,
295     [SND_PCM_FORMAT_GSM]                = VLC_CODEC_GSM,
296   //[SND_PCM_FORMAT_SPECIAL]            = VLC_CODEC_?
297     [SND_PCM_FORMAT_S24_3LE]            = VLC_CODEC_S24L,
298     [SND_PCM_FORMAT_S24_3BE]            = VLC_CODEC_S24B,
299     [SND_PCM_FORMAT_U24_3LE]            = VLC_CODEC_U24L,
300     [SND_PCM_FORMAT_U24_3BE]            = VLC_CODEC_U24B,
301     [SND_PCM_FORMAT_S20_3LE]            = VLC_CODEC_S24L, // TODO: replay gain
302     [SND_PCM_FORMAT_S20_3BE]            = VLC_CODEC_S24B, // ^
303     [SND_PCM_FORMAT_U20_3LE]            = VLC_CODEC_U24L, // ^
304     [SND_PCM_FORMAT_U20_3BE]            = VLC_CODEC_U24B, // ^
305     [SND_PCM_FORMAT_S18_3LE]            = VLC_CODEC_S24L, // ^
306     [SND_PCM_FORMAT_S18_3BE]            = VLC_CODEC_S24B, // ^
307     [SND_PCM_FORMAT_U18_3LE]            = VLC_CODEC_U24L, // ^
308     [SND_PCM_FORMAT_U18_3BE]            = VLC_CODEC_U24B, // ^
309 };
310
311 #ifdef WORDS_BIGENDIAN
312 # define C(f) f##BE, f##LE
313 #else
314 # define C(f) f##LE, f##BE
315 #endif
316
317 /* Formats in order of decreasing preference */
318 static const uint8_t choices[] = {
319     C(SND_PCM_FORMAT_FLOAT_),
320     C(SND_PCM_FORMAT_S32_),
321     C(SND_PCM_FORMAT_U32_),
322     C(SND_PCM_FORMAT_S16_),
323     C(SND_PCM_FORMAT_U16_),
324     C(SND_PCM_FORMAT_FLOAT64_),
325     C(SND_PCM_FORMAT_S24_3),
326     C(SND_PCM_FORMAT_U24_3),
327     SND_PCM_FORMAT_MPEG,
328     SND_PCM_FORMAT_GSM,
329     SND_PCM_FORMAT_MU_LAW,
330     SND_PCM_FORMAT_A_LAW,
331     SND_PCM_FORMAT_S8,
332     SND_PCM_FORMAT_U8,
333 };
334
335 static uint16_t channel_maps[] = {
336     AOUT_CHAN_CENTER, AOUT_CHANS_2_0, AOUT_CHANS_3_0 /* ? */,
337     AOUT_CHANS_4_0, AOUT_CHANS_5_0 /* ? */, AOUT_CHANS_5_1,
338     /* TODO: support 7-8 channels - need channels reodering */
339 };
340
341 static int Open (vlc_object_t *obj)
342 {
343     demux_t *demux = (demux_t *)obj;
344
345     if (demux->out == NULL)
346         return VLC_EGENERIC;
347
348     demux_sys_t *sys = vlc_obj_malloc(obj, sizeof (*sys));
349     if (unlikely(sys == NULL))
350         return VLC_ENOMEM;
351
352     /* Open the device */
353     const char *device = demux->psz_location;
354     if (device == NULL || !device[0])
355         device = "default";
356
357     const int mode = SND_PCM_NONBLOCK
358                  /*| SND_PCM_NO_AUTO_RESAMPLE*/
359                    | SND_PCM_NO_AUTO_CHANNELS
360                  /*| SND_PCM_NO_AUTO_FORMAT*/;
361     snd_pcm_t *pcm;
362     int val = snd_pcm_open (&pcm, device, SND_PCM_STREAM_CAPTURE, mode);
363     if (val != 0)
364     {
365         msg_Err (demux, "cannot open ALSA device \"%s\": %s", device,
366                  snd_strerror (val));
367         return VLC_EGENERIC;
368     }
369     sys->pcm = pcm;
370     msg_Dbg (demux, "using ALSA device: %s", device);
371     DumpDevice (VLC_OBJECT(demux), pcm);
372
373     /* Negotiate capture parameters */
374     snd_pcm_hw_params_t *hw;
375     es_format_t fmt;
376     unsigned param;
377     int dir;
378
379     snd_pcm_hw_params_alloca (&hw);
380     snd_pcm_hw_params_any (pcm, hw);
381     Dump (demux, "initial hardware setup:\n", snd_pcm_hw_params_dump, hw);
382
383     val = snd_pcm_hw_params_set_rate_resample (pcm, hw, 0);
384     if (val)
385     {
386         msg_Err (demux, "cannot disable resampling: %s", snd_strerror (val));
387         goto error;
388     }
389
390     val = snd_pcm_hw_params_set_access (pcm, hw,
391                                         SND_PCM_ACCESS_RW_INTERLEAVED);
392     if (val)
393     {
394         msg_Err (demux, "cannot set access mode: %s", snd_strerror (val));
395         goto error;
396     }
397
398     snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
399     for (size_t i = 0; i < sizeof (choices) / sizeof (choices[0]); i++)
400         if (snd_pcm_hw_params_test_format (pcm, hw, choices[i]) == 0)
401         {
402             val = snd_pcm_hw_params_set_format (pcm, hw, choices[i]);
403             if (val)
404             {
405                 msg_Err (demux, "cannot set sample format: %s",
406                          snd_strerror (val));
407                 goto error;
408             }
409             format = choices[i];
410             break;
411         }
412
413     if (format == SND_PCM_FORMAT_UNKNOWN)
414     {
415         msg_Err (demux, "no supported sample format");
416         goto error;
417     }
418
419     assert ((size_t)format < (sizeof (formats) / sizeof (formats[0])));
420     es_format_Init (&fmt, AUDIO_ES, formats[format]);
421     fmt.audio.i_format = fmt.i_codec;
422
423     param = 1 + var_InheritBool (demux, "alsa-stereo");
424     val = snd_pcm_hw_params_set_channels_max (pcm, hw, &param);
425     if (val)
426     {
427         msg_Err (demux, "cannot restrict channels count: %s",
428                  snd_strerror (val));
429         goto error;
430     }
431     val = snd_pcm_hw_params_set_channels_last (pcm, hw, &param);
432     if (val)
433     {
434         msg_Err (demux, "cannot set channels count: %s", snd_strerror (val));
435         goto error;
436     }
437     assert (param > 0);
438     assert (param < (sizeof (channel_maps) / sizeof (channel_maps[0])));
439     fmt.audio.i_channels = param;
440     fmt.audio.i_physical_channels = channel_maps[param - 1];
441
442     param = var_InheritInteger (demux, "alsa-samplerate");
443     val = snd_pcm_hw_params_set_rate_max (pcm, hw, &param, NULL);
444     if (val)
445     {
446         msg_Err (demux, "cannot restrict rate to %u Hz or less: %s", 192000,
447                  snd_strerror (val));
448         goto error;
449     }
450     val = snd_pcm_hw_params_set_rate_last (pcm, hw, &param, &dir);
451     if (val)
452     {
453         msg_Err (demux, "cannot set sample rate: %s", snd_strerror (val));
454         goto error;
455     }
456     if (dir)
457         msg_Warn (demux, "sample rate is not integral");
458     fmt.audio.i_rate = param;
459     sys->rate = param;
460
461     sys->start = vlc_tick_now ();
462     sys->caching = VLC_TICK_FROM_MS(var_InheritInteger (demux, "live-caching"));
463     param = sys->caching;
464     val = snd_pcm_hw_params_set_buffer_time_near (pcm, hw, &param, NULL);
465     if (val)
466     {
467         msg_Err (demux, "cannot set buffer duration: %s", snd_strerror (val));
468         goto error;
469     }
470
471     param /= 4;
472     val = snd_pcm_hw_params_set_period_time_near (pcm, hw, &param, NULL);
473     if (val)
474     {
475         msg_Err (demux, "cannot set period: %s", snd_strerror (val));
476         goto error;
477     }
478
479     val = snd_pcm_hw_params_get_period_size (hw, &sys->period_size, &dir);
480     if (val)
481     {
482         msg_Err (demux, "cannot get period size: %s", snd_strerror (val));
483         goto error;
484     }
485     if (dir > 0)
486         sys->period_size++;
487
488     /* Commit hardware parameters */
489     val = snd_pcm_hw_params (pcm, hw);
490     if (val)
491     {
492         msg_Err (demux, "cannot commit hardware parameters: %s",
493                  snd_strerror (val));
494         goto error;
495     }
496     Dump (demux, "final HW setup:\n", snd_pcm_hw_params_dump, hw);
497
498     /* Kick recording */
499     aout_FormatPrepare (&fmt.audio);
500     sys->es = es_out_Add (demux->out, &fmt);
501     demux->p_sys = sys;
502
503     if (vlc_clone (&sys->thread, Thread, demux, VLC_THREAD_PRIORITY_INPUT))
504     {
505         es_out_Del (demux->out, sys->es);
506         goto error;
507     }
508
509     demux->pf_demux = NULL;
510     demux->pf_control = Control;
511     return VLC_SUCCESS;
512 error:
513     snd_pcm_close (pcm);
514     return VLC_EGENERIC;
515 }
516
517 static void Close (vlc_object_t *obj)
518 {
519     demux_t *demux = (demux_t *)obj;
520     demux_sys_t *sys = demux->p_sys;
521
522     vlc_cancel (sys->thread);
523     vlc_join (sys->thread, NULL);
524
525     snd_pcm_close (sys->pcm);
526 }