Merge pull request #4314 from MartijnKaijser/beta1
[vuplus_xbmc] / xbmc / cores / AudioEngine / Sinks / AESinkALSA.cpp
1 /*
2  *      Copyright (C) 2010-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20 #include "system.h"
21 #ifdef HAS_ALSA
22
23 #include <stdint.h>
24 #include <limits.h>
25 #include <set>
26 #include <sstream>
27
28 #include "AESinkALSA.h"
29 #include "cores/AudioEngine/Utils/AEUtil.h"
30 #include "cores/AudioEngine/Utils/AEELDParser.h"
31 #include "utils/StdString.h"
32 #include "utils/log.h"
33 #include "utils/MathUtils.h"
34 #include "threads/SingleLock.h"
35 #if defined(HAS_LIBAMCODEC)
36 #include "utils/AMLUtils.h"
37 #endif
38
39 #define ALSA_OPTIONS (SND_PCM_NO_AUTO_FORMAT | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_RESAMPLE)
40
41 #define ALSA_MAX_CHANNELS 16
42 static enum AEChannel ALSAChannelMap[ALSA_MAX_CHANNELS + 1] = {
43   AE_CH_FL      , AE_CH_FR      , AE_CH_BL      , AE_CH_BR      , AE_CH_FC      , AE_CH_LFE     , AE_CH_SL      , AE_CH_SR      ,
44   AE_CH_UNKNOWN1, AE_CH_UNKNOWN2, AE_CH_UNKNOWN3, AE_CH_UNKNOWN4, AE_CH_UNKNOWN5, AE_CH_UNKNOWN6, AE_CH_UNKNOWN7, AE_CH_UNKNOWN8, /* for p16v devices */
45   AE_CH_NULL
46 };
47
48 static enum AEChannel ALSAChannelMap51Wide[ALSA_MAX_CHANNELS + 1] = {
49   AE_CH_FL      , AE_CH_FR      , AE_CH_SL      , AE_CH_SR      , AE_CH_FC      , AE_CH_LFE     , AE_CH_BL      , AE_CH_BR      ,
50   AE_CH_UNKNOWN1, AE_CH_UNKNOWN2, AE_CH_UNKNOWN3, AE_CH_UNKNOWN4, AE_CH_UNKNOWN5, AE_CH_UNKNOWN6, AE_CH_UNKNOWN7, AE_CH_UNKNOWN8, /* for p16v devices */
51   AE_CH_NULL
52 };
53
54 static enum AEChannel ALSAChannelMapPassthrough[ALSA_MAX_CHANNELS + 1] = {
55   AE_CH_RAW     , AE_CH_RAW     , AE_CH_RAW     , AE_CH_RAW     , AE_CH_RAW     , AE_CH_RAW     , AE_CH_RAW      , AE_CH_RAW      ,
56   AE_CH_UNKNOWN1, AE_CH_UNKNOWN2, AE_CH_UNKNOWN3, AE_CH_UNKNOWN4, AE_CH_UNKNOWN5, AE_CH_UNKNOWN6, AE_CH_UNKNOWN7, AE_CH_UNKNOWN8, /* for p16v devices */
57   AE_CH_NULL
58 };
59
60 static unsigned int ALSASampleRateList[] =
61 {
62   5512,
63   8000,
64   11025,
65   16000,
66   22050,
67   32000,
68   44100,
69   48000,
70   64000,
71   88200,
72   96000,
73   176400,
74   192000,
75   384000,
76   0
77 };
78
79 CAESinkALSA::CAESinkALSA() :
80   m_bufferSize(0),
81   m_formatSampleRateMul(0.0),
82   m_passthrough(false),
83   m_pcm(NULL),
84   m_timeout(0)
85 {
86   /* ensure that ALSA has been initialized */
87   if (!snd_config)
88     snd_config_update();
89 }
90
91 CAESinkALSA::~CAESinkALSA()
92 {
93   Deinitialize();
94 }
95
96 inline CAEChannelInfo CAESinkALSA::GetChannelLayout(AEAudioFormat format, unsigned int minChannels, unsigned int maxChannels)
97 {
98   enum AEChannel* channelMap = ALSAChannelMap;
99   unsigned int count = 0;
100
101   if (format.m_dataFormat == AE_FMT_AC3 ||
102       format.m_dataFormat == AE_FMT_DTS ||
103       format.m_dataFormat == AE_FMT_EAC3)
104   {
105     count = 2;
106     channelMap = ALSAChannelMapPassthrough;
107   }
108   else if (format.m_dataFormat == AE_FMT_TRUEHD ||
109            format.m_dataFormat == AE_FMT_DTSHD)
110   {
111     count = 8;
112     channelMap = ALSAChannelMapPassthrough;
113   }
114   else
115   {
116     // According to CEA-861-D only RL and RR are known. In case of a format having SL and SR channels
117     // but no BR BL channels, we use the wide map in order to open only the num of channels really
118     // needed.
119     if (format.m_channelLayout.HasChannel(AE_CH_SL) && !format.m_channelLayout.HasChannel(AE_CH_BL))
120     {
121       channelMap = ALSAChannelMap51Wide;
122     }
123     for (unsigned int c = 0; c < 8; ++c)
124     {
125       for (unsigned int i = 0; i < format.m_channelLayout.Count(); ++i)
126       {
127         if (format.m_channelLayout[i] == channelMap[c])
128         {
129           count = c + 1;
130           break;
131         }
132       }
133     }
134     count = std::max(count, minChannels);
135   }
136
137   CAEChannelInfo info;
138   count = std::min(count, maxChannels);
139   for (unsigned int i = 0; i < count; ++i)
140     info += channelMap[i];
141
142   CLog::Log(LOGDEBUG, "CAESinkALSA::GetChannelLayout - Input Channel Count: %d Output Channel Count: %d", format.m_channelLayout.Count(), count);
143   CLog::Log(LOGDEBUG, "CAESinkALSA::GetChannelLayout - Requested Layout: %s", std::string(format.m_channelLayout).c_str());
144   CLog::Log(LOGDEBUG, "CAESinkALSA::GetChannelLayout - Got Layout: %s", std::string(info).c_str());
145
146   return info;
147 }
148
149 void CAESinkALSA::GetAESParams(AEAudioFormat format, std::string& params)
150 {
151   if (m_passthrough)
152     params = "AES0=0x06";
153   else
154     params = "AES0=0x04";
155
156   params += ",AES1=0x82,AES2=0x00";
157
158        if (format.m_sampleRate == 192000) params += ",AES3=0x0e";
159   else if (format.m_sampleRate == 176400) params += ",AES3=0x0c";
160   else if (format.m_sampleRate ==  96000) params += ",AES3=0x0a";
161   else if (format.m_sampleRate ==  88200) params += ",AES3=0x08";
162   else if (format.m_sampleRate ==  48000) params += ",AES3=0x02";
163   else if (format.m_sampleRate ==  44100) params += ",AES3=0x00";
164   else if (format.m_sampleRate ==  32000) params += ",AES3=0x03";
165   else params += ",AES3=0x01";
166 }
167
168 bool CAESinkALSA::Initialize(AEAudioFormat &format, std::string &device)
169 {
170   CAEChannelInfo channelLayout = GetChannelLayout(format, 2, 8);
171   m_initDevice = device;
172   m_initFormat = format;
173   ALSAConfig inconfig, outconfig;
174   inconfig.format = format.m_dataFormat;
175   inconfig.sampleRate = format.m_sampleRate;
176   inconfig.channels = channelLayout.Count();
177
178   /* if we are raw, correct the data format */
179   if (AE_IS_RAW(format.m_dataFormat))
180   {
181     inconfig.format   = AE_FMT_S16NE;
182     m_passthrough     = true;
183   }
184   else
185   {
186     m_passthrough   = false;
187   }
188 #if defined(HAS_LIBAMCODEC)
189   if (aml_present())
190   {
191     aml_set_audio_passthrough(m_passthrough);
192     device = "default";
193   }
194 #endif
195
196   if (inconfig.channels == 0)
197   {
198     CLog::Log(LOGERROR, "CAESinkALSA::Initialize - Unable to open the requested channel layout");
199     return false;
200   }
201
202   AEDeviceType devType = AEDeviceTypeFromName(device);
203
204   std::string AESParams;
205   /* digital interfaces should have AESx set, though in practice most
206    * receivers don't care */
207   if (m_passthrough || devType == AE_DEVTYPE_HDMI || devType == AE_DEVTYPE_IEC958)
208     GetAESParams(format, AESParams);
209
210   CLog::Log(LOGINFO, "CAESinkALSA::Initialize - Attempting to open device \"%s\"", device.c_str());
211
212   /* get the sound config */
213   snd_config_t *config;
214   snd_config_copy(&config, snd_config);
215
216   if (!OpenPCMDevice(device, AESParams, inconfig.channels, &m_pcm, config))
217   {
218     CLog::Log(LOGERROR, "CAESinkALSA::Initialize - failed to initialize device \"%s\"", device.c_str());
219     snd_config_delete(config);
220     return false;
221   }
222
223   /* get the actual device name that was used */
224   device = snd_pcm_name(m_pcm);
225   m_device = device;
226
227   CLog::Log(LOGINFO, "CAESinkALSA::Initialize - Opened device \"%s\"", device.c_str());
228
229   /* free the sound config */
230   snd_config_delete(config);
231
232   if (!InitializeHW(inconfig, outconfig) || !InitializeSW(outconfig))
233     return false;
234
235   // we want it blocking
236   snd_pcm_nonblock(m_pcm, 0);
237   snd_pcm_prepare (m_pcm);
238
239   if (m_passthrough && inconfig.channels != outconfig.channels)
240   {
241     CLog::Log(LOGINFO, "CAESinkALSA::Initialize - could not open required number of channels");
242     return false;
243   }
244   // adjust format to the configuration we got
245   format.m_channelLayout = GetChannelLayout(format, outconfig.channels, outconfig.channels);
246   format.m_sampleRate = outconfig.sampleRate;
247   format.m_frames = outconfig.periodSize;
248   format.m_frameSize = outconfig.frameSize;
249   format.m_frameSamples = outconfig.periodSize * outconfig.channels;
250   format.m_dataFormat = outconfig.format;
251
252   m_format              = format;
253   m_formatSampleRateMul = 1.0 / (double)m_format.m_sampleRate;
254
255   return true;
256 }
257
258 snd_pcm_format_t CAESinkALSA::AEFormatToALSAFormat(const enum AEDataFormat format)
259 {
260   if (AE_IS_RAW(format))
261     return SND_PCM_FORMAT_S16;
262
263   switch (format)
264   {
265     case AE_FMT_S8    : return SND_PCM_FORMAT_S8;
266     case AE_FMT_U8    : return SND_PCM_FORMAT_U8;
267     case AE_FMT_S16NE : return SND_PCM_FORMAT_S16;
268     case AE_FMT_S16LE : return SND_PCM_FORMAT_S16_LE;
269     case AE_FMT_S16BE : return SND_PCM_FORMAT_S16_BE;
270     case AE_FMT_S24NE4: return SND_PCM_FORMAT_S24;
271 #ifdef __BIG_ENDIAN__
272     case AE_FMT_S24NE3: return SND_PCM_FORMAT_S24_3BE;
273 #else
274     case AE_FMT_S24NE3: return SND_PCM_FORMAT_S24_3LE;
275 #endif
276     case AE_FMT_S32NE : return SND_PCM_FORMAT_S32;
277     case AE_FMT_FLOAT : return SND_PCM_FORMAT_FLOAT;
278
279     default:
280       return SND_PCM_FORMAT_UNKNOWN;
281   }
282 }
283
284 bool CAESinkALSA::InitializeHW(const ALSAConfig &inconfig, ALSAConfig &outconfig)
285 {
286   snd_pcm_hw_params_t *hw_params;
287
288   snd_pcm_hw_params_alloca(&hw_params);
289   memset(hw_params, 0, snd_pcm_hw_params_sizeof());
290
291   snd_pcm_hw_params_any(m_pcm, hw_params);
292   snd_pcm_hw_params_set_access(m_pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
293
294   unsigned int sampleRate   = inconfig.sampleRate;
295   unsigned int channelCount = inconfig.channels;
296   snd_pcm_hw_params_set_rate_near    (m_pcm, hw_params, &sampleRate, NULL);
297   snd_pcm_hw_params_set_channels_near(m_pcm, hw_params, &channelCount);
298
299   /* ensure we opened X channels or more */
300   if (inconfig.channels > channelCount)
301   {
302     CLog::Log(LOGINFO, "CAESinkALSA::InitializeHW - Unable to open the required number of channels");
303   }
304
305   /* update outconfig */
306   outconfig.channels = channelCount;
307
308   snd_pcm_format_t fmt = AEFormatToALSAFormat(inconfig.format);
309   outconfig.format = inconfig.format;
310
311   if (fmt == SND_PCM_FORMAT_UNKNOWN)
312   {
313     /* if we dont support the requested format, fallback to float */
314     fmt = SND_PCM_FORMAT_FLOAT;
315     outconfig.format = AE_FMT_FLOAT;
316   }
317
318   /* try the data format */
319   if (snd_pcm_hw_params_set_format(m_pcm, hw_params, fmt) < 0)
320   {
321     /* if the chosen format is not supported, try each one in decending order */
322     CLog::Log(LOGINFO, "CAESinkALSA::InitializeHW - Your hardware does not support %s, trying other formats", CAEUtil::DataFormatToStr(outconfig.format));
323     for (enum AEDataFormat i = AE_FMT_MAX; i > AE_FMT_INVALID; i = (enum AEDataFormat)((int)i - 1))
324     {
325       if (AE_IS_RAW(i) || i == AE_FMT_MAX)
326         continue;
327
328       if (m_passthrough && i != AE_FMT_S16BE && i != AE_FMT_S16LE)
329         continue;
330
331       fmt = AEFormatToALSAFormat(i);
332
333       if (fmt == SND_PCM_FORMAT_UNKNOWN || snd_pcm_hw_params_set_format(m_pcm, hw_params, fmt) < 0)
334       {
335         fmt = SND_PCM_FORMAT_UNKNOWN;
336         continue;
337       }
338
339       int fmtBits = CAEUtil::DataFormatToBits(i);
340       int bits    = snd_pcm_hw_params_get_sbits(hw_params);
341       if (bits != fmtBits)
342       {
343         /* if we opened in 32bit and only have 24bits, pack into 24 */
344         if (fmtBits == 32 && bits == 24)
345           i = AE_FMT_S24NE4;
346         else
347           continue;
348       }
349
350       /* record that the format fell back to X */
351       outconfig.format = i;
352       CLog::Log(LOGINFO, "CAESinkALSA::InitializeHW - Using data format %s", CAEUtil::DataFormatToStr(outconfig.format));
353       break;
354     }
355
356     /* if we failed to find a valid output format */
357     if (fmt == SND_PCM_FORMAT_UNKNOWN)
358     {
359       CLog::Log(LOGERROR, "CAESinkALSA::InitializeHW - Unable to find a suitable output format");
360       return false;
361     }
362   }
363
364   snd_pcm_uframes_t periodSize, bufferSize;
365   snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufferSize);
366   snd_pcm_hw_params_get_period_size_max(hw_params, &periodSize, NULL);
367
368   /* 
369    We want to make sure, that we have max 200 ms Buffer with 
370    a periodSize of approx 50 ms. Choosing a higher bufferSize
371    will cause problems with menu sounds. Buffer will be increased
372    after those are fixed.
373   */
374   periodSize  = std::min(periodSize, (snd_pcm_uframes_t) sampleRate / 20);
375   bufferSize  = std::min(bufferSize, (snd_pcm_uframes_t) sampleRate / 5);
376   
377   /* 
378    According to upstream we should set buffer size first - so make sure it is always at least
379    4x period size to not get underruns (some systems seem to have issues with only 2 periods)
380   */
381   periodSize = std::min(periodSize, bufferSize / 4);
382
383   CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Request: periodSize %lu, bufferSize %lu", periodSize, bufferSize);
384
385   snd_pcm_hw_params_t *hw_params_copy;
386   snd_pcm_hw_params_alloca(&hw_params_copy);
387   snd_pcm_hw_params_copy(hw_params_copy, hw_params); // copy what we have and is already working
388
389   // Make sure to not initialize too large to not cause underruns
390   snd_pcm_uframes_t periodSizeMax = bufferSize / 3;
391   if(snd_pcm_hw_params_set_period_size_max(m_pcm, hw_params_copy, &periodSizeMax, NULL) != 0)
392   {
393     snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restore working copy
394     CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Request: Failed to limit periodSize to %lu", periodSizeMax);
395   }
396   
397   // first trying bufferSize, PeriodSize
398   // for more info see here:
399   // http://mailman.alsa-project.org/pipermail/alsa-devel/2009-September/021069.html
400   // the last three tries are done as within pulseaudio
401
402   // backup periodSize and bufferSize first. Restore them after every failed try
403   snd_pcm_uframes_t periodSizeTemp, bufferSizeTemp;
404   periodSizeTemp = periodSize;
405   bufferSizeTemp = bufferSize;
406   if (snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize) != 0
407     || snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL) != 0
408     || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
409   {
410     bufferSize = bufferSizeTemp;
411     periodSize = periodSizeTemp;
412     // retry with PeriodSize, bufferSize
413     snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restore working copy
414     if (snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL) != 0
415       || snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize) != 0
416       || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
417     {
418       // try only periodSize
419       periodSize = periodSizeTemp;
420       snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restore working copy
421       if(snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL) != 0 
422         || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
423       {
424         // try only BufferSize
425         bufferSize = bufferSizeTemp;
426         snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restory working copy
427         if (snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize) != 0
428           || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
429         {
430           // set default that Alsa would choose
431           CLog::Log(LOGWARNING, "CAESinkAlsa::IntializeHW - Using default alsa values - set failed");
432           if (snd_pcm_hw_params(m_pcm, hw_params) != 0)
433           {
434             CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Could not init a valid sink");
435             return false;
436           }
437         }
438       }
439       // reread values when alsa default was kept
440       snd_pcm_get_params(m_pcm, &bufferSize, &periodSize);
441     }
442   }
443   
444   CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Got: periodSize %lu, bufferSize %lu", periodSize, bufferSize);
445
446   /* set the format parameters */
447   outconfig.sampleRate   = sampleRate;
448   outconfig.periodSize   = periodSize;
449   outconfig.frameSize    = snd_pcm_frames_to_bytes(m_pcm, 1);
450
451   m_bufferSize = (unsigned int)bufferSize;
452   m_timeout    = std::ceil((double)(bufferSize * 1000) / (double)sampleRate);
453
454   CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Setting timeout to %d ms", m_timeout);
455
456   return true;
457 }
458
459 bool CAESinkALSA::InitializeSW(const ALSAConfig &inconfig)
460 {
461   snd_pcm_sw_params_t *sw_params;
462   snd_pcm_uframes_t boundary;
463
464   snd_pcm_sw_params_alloca(&sw_params);
465   memset(sw_params, 0, snd_pcm_sw_params_sizeof());
466
467   snd_pcm_sw_params_current              (m_pcm, sw_params);
468   snd_pcm_sw_params_set_start_threshold  (m_pcm, sw_params, INT_MAX);
469   snd_pcm_sw_params_set_silence_threshold(m_pcm, sw_params, 0);
470   snd_pcm_sw_params_get_boundary         (sw_params, &boundary);
471   snd_pcm_sw_params_set_silence_size     (m_pcm, sw_params, boundary);
472   snd_pcm_sw_params_set_avail_min        (m_pcm, sw_params, inconfig.periodSize);
473
474   if (snd_pcm_sw_params(m_pcm, sw_params) < 0)
475   {
476     CLog::Log(LOGERROR, "CAESinkALSA::InitializeSW - Failed to set the parameters");
477     return false;
478   }
479
480   return true;
481 }
482
483 void CAESinkALSA::Deinitialize()
484 {
485   if (m_pcm)
486   {
487     Stop();
488     snd_pcm_close(m_pcm);
489     m_pcm = NULL;
490   }
491 }
492
493 void CAESinkALSA::Stop()
494 {
495   if (!m_pcm)
496     return;
497   snd_pcm_drop(m_pcm);
498 }
499
500 double CAESinkALSA::GetDelay()
501 {
502   if (!m_pcm)
503     return 0;
504   snd_pcm_sframes_t frames = 0;
505   snd_pcm_delay(m_pcm, &frames);
506
507   if (frames < 0)
508   {
509 #if SND_LIB_VERSION >= 0x000901 /* snd_pcm_forward() exists since 0.9.0rc8 */
510     snd_pcm_forward(m_pcm, -frames);
511 #endif
512     frames = 0;
513   }
514
515   return (double)frames * m_formatSampleRateMul;
516 }
517
518 double CAESinkALSA::GetCacheTotal()
519 {
520   return (double)m_bufferSize * m_formatSampleRateMul;
521 }
522
523 unsigned int CAESinkALSA::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio, bool blocking)
524 {
525   if (!m_pcm)
526   {
527     CLog::Log(LOGERROR, "CAESinkALSA - Tried to add packets without a sink");
528     return INT_MAX;
529   }
530
531   int ret = snd_pcm_writei(m_pcm, (void*)data, frames);
532   if (ret < 0)
533   {
534     HandleError("snd_pcm_writei(1)", ret);
535     ret = snd_pcm_writei(m_pcm, (void*)data, frames);
536     if (ret < 0)
537     {
538       HandleError("snd_pcm_writei(2)", ret);
539       ret = 0;
540     }
541   }
542
543   if ( ret > 0 && snd_pcm_state(m_pcm) == SND_PCM_STATE_PREPARED)
544     snd_pcm_start(m_pcm);
545
546   return ret;
547 }
548
549 void CAESinkALSA::HandleError(const char* name, int err)
550 {
551   switch(err)
552   {
553     case -EPIPE:
554       CLog::Log(LOGERROR, "CAESinkALSA::HandleError(%s) - underrun", name);
555       if ((err = snd_pcm_prepare(m_pcm)) < 0)
556         CLog::Log(LOGERROR, "CAESinkALSA::HandleError(%s) - snd_pcm_prepare returned %d (%s)", name, err, snd_strerror(err));
557       break;
558
559     case -ESTRPIPE:
560       CLog::Log(LOGINFO, "CAESinkALSA::HandleError(%s) - Resuming after suspend", name);
561
562       /* try to resume the stream */
563       while((err = snd_pcm_resume(m_pcm)) == -EAGAIN)
564         Sleep(1);
565
566       /* if the hardware doesnt support resume, prepare the stream */
567       if (err == -ENOSYS)
568         if ((err = snd_pcm_prepare(m_pcm)) < 0)
569           CLog::Log(LOGERROR, "CAESinkALSA::HandleError(%s) - snd_pcm_prepare returned %d (%s)", name, err, snd_strerror(err));
570       break;
571
572     default:
573       CLog::Log(LOGERROR, "CAESinkALSA::HandleError(%s) - snd_pcm_writei returned %d (%s)", name, err, snd_strerror(err));
574       break;
575   }
576 }
577
578 void CAESinkALSA::Drain()
579 {
580   if (!m_pcm)
581     return;
582
583   snd_pcm_drain(m_pcm);
584   snd_pcm_prepare(m_pcm);
585 }
586
587 void CAESinkALSA::AppendParams(std::string &device, const std::string &params)
588 {
589   /* Note: escaping, e.g. "plug:'something:X=y'" isn't handled,
590    * but it is not normally encountered at this point. */
591
592   device += (device.find(':') == std::string::npos) ? ':' : ',';
593   device += params;
594 }
595
596 bool CAESinkALSA::TryDevice(const std::string &name, snd_pcm_t **pcmp, snd_config_t *lconf)
597 {
598   /* Check if this device was already open (e.g. when checking for supported
599    * channel count in EnumerateDevice()) */
600   if (*pcmp)
601   {
602     if (name == snd_pcm_name(*pcmp))
603       return true;
604
605     snd_pcm_close(*pcmp);
606     *pcmp = NULL;
607   }
608
609   int err = snd_pcm_open_lconf(pcmp, name.c_str(), SND_PCM_STREAM_PLAYBACK, ALSA_OPTIONS, lconf);
610   if (err < 0)
611   {
612     CLog::Log(LOGINFO, "CAESinkALSA - Unable to open device \"%s\" for playback", name.c_str());
613   }
614
615   return err == 0;
616 }
617
618 bool CAESinkALSA::TryDeviceWithParams(const std::string &name, const std::string &params, snd_pcm_t **pcmp, snd_config_t *lconf)
619 {
620   if (!params.empty())
621   {
622     std::string nameWithParams = name;
623     AppendParams(nameWithParams, params);
624     if (TryDevice(nameWithParams, pcmp, lconf))
625       return true;
626   }
627
628   /* Try the variant without extra parameters.
629    * Custom devices often do not take the AESx parameters, for example.
630    */
631   return TryDevice(name, pcmp, lconf);
632 }
633
634 bool CAESinkALSA::OpenPCMDevice(const std::string &name, const std::string &params, int channels, snd_pcm_t **pcmp, snd_config_t *lconf)
635 {
636  /* Special name denoting surroundXX mangling. This is needed for some
637    * devices for multichannel to work. */
638   if (name == "@" || name.substr(0, 2) == "@:")
639   {
640     std::string openName = name.substr(1);
641
642     /* These device names allow alsa-lib to perform special routing if needed
643      * for multichannel to work with the audio hardware.
644      * Fall through in switch() so that devices with more channels are
645      * added as fallback. */
646     switch (channels)
647     {
648       case 3:
649       case 4:
650         if (TryDeviceWithParams("surround40" + openName, params, pcmp, lconf))
651           return true;
652       case 5:
653       case 6:
654         if (TryDeviceWithParams("surround51" + openName, params, pcmp, lconf))
655           return true;
656       case 7:
657       case 8:
658         if (TryDeviceWithParams("surround71" + openName, params, pcmp, lconf))
659           return true;
660     }
661
662     /* Try "sysdefault" and "default" (they provide dmix if needed, and route
663      * audio to all extra channels on subdeviced cards),
664      * unless the selected devices is not DEV=0 of the card, in which case
665      * "sysdefault" and "default" would point to another device.
666      * "sysdefault" is a newish device name that won't be overwritten in case
667      * system configuration redefines "default". "default" is still tried
668      * because "sysdefault" is rather new. */
669     size_t devPos = openName.find(",DEV=");
670     if (devPos == std::string::npos || (devPos + 5 < openName.size() && openName[devPos+5] == '0'))
671     {
672       /* "sysdefault" and "default" do not have "DEV=0", drop it */
673       std::string nameWithoutDev = openName;
674       if (devPos != std::string::npos)
675         nameWithoutDev.erase(nameWithoutDev.begin() + devPos, nameWithoutDev.begin() + devPos + 6);
676
677       if (TryDeviceWithParams("sysdefault" + nameWithoutDev, params, pcmp, lconf)
678           || TryDeviceWithParams("default" + nameWithoutDev, params, pcmp, lconf))
679         return true;
680     }
681
682     /* Try "front" (no dmix, no audio in other channels on subdeviced cards) */
683     if (TryDeviceWithParams("front" + openName, params, pcmp, lconf))
684       return true;
685
686   }
687   else
688   {
689     /* Non-surroundXX device, just add it */
690     if (TryDeviceWithParams(name, params, pcmp, lconf))
691       return true;
692   }
693
694   return false;
695 }
696
697 void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
698 {
699   /* ensure that ALSA has been initialized */
700   snd_lib_error_set_handler(sndLibErrorHandler);
701   if(!snd_config || force)
702   {
703     if(force)
704       snd_config_update_free_global();
705
706     snd_config_update();
707   }
708
709   snd_config_t *config;
710   snd_config_copy(&config, snd_config);
711
712   /* Always enumerate the default device.
713    * Note: If "default" is a stereo device, EnumerateDevice()
714    * will automatically add "@" instead to enable surroundXX mangling.
715    * We don't want to do that if "default" can handle multichannel
716    * itself (e.g. in case of a pulseaudio server). */
717   EnumerateDevice(list, "default", "", config);
718
719   void **hints;
720
721   if (snd_device_name_hint(-1, "pcm", &hints) < 0)
722   {
723     CLog::Log(LOGINFO, "CAESinkALSA - Unable to get a list of devices");
724     return;
725   }
726
727   std::string defaultDescription;
728
729   for (void** hint = hints; *hint != NULL; ++hint)
730   {
731     char *io = snd_device_name_get_hint(*hint, "IOID");
732     char *name = snd_device_name_get_hint(*hint, "NAME");
733     char *desc = snd_device_name_get_hint(*hint, "DESC");
734     if ((!io || strcmp(io, "Output") == 0) && name
735         && strcmp(name, "null") != 0)
736     {
737       std::string baseName = std::string(name);
738       baseName = baseName.substr(0, baseName.find(':'));
739
740       if (strcmp(name, "default") == 0)
741       {
742         /* added already, but lets get the description if we have one */
743         if (desc)
744           defaultDescription = desc;
745       }
746       else if (baseName == "front")
747       {
748         /* Enumerate using the surroundXX mangling */
749         /* do not enumerate basic "front", it is already handled
750          * by the default "@" entry added in the very beginning */
751         if (strcmp(name, "front") != 0)
752           EnumerateDevice(list, std::string("@") + (name+5), desc ? desc : name, config);
753       }
754
755       /* Do not enumerate "default", it is already enumerated above. */
756
757       /* Do not enumerate the sysdefault or surroundXX devices, those are
758        * always accompanied with a "front" device and it is handled above
759        * as "@". The below devices will be automatically used if available
760        * for a "@" device. */
761
762       /* Ubuntu has patched their alsa-lib so that "defaults.namehint.extended"
763        * defaults to "on" instead of upstream "off", causing lots of unwanted
764        * extra devices (many of which are not actually routed properly) to be
765        * found by the enumeration process. Skip them as well ("hw", "dmix",
766        * "plughw", "dsnoop"). */
767
768       else if (baseName != "default"
769             && baseName != "sysdefault"
770             && baseName != "surround40"
771             && baseName != "surround41"
772             && baseName != "surround50"
773             && baseName != "surround51"
774             && baseName != "surround71"
775             && baseName != "hw"
776             && baseName != "dmix"
777             && baseName != "plughw"
778             && baseName != "dsnoop")
779       {
780         EnumerateDevice(list, name, desc ? desc : name, config);
781       }
782     }
783     free(io);
784     free(name);
785     free(desc);
786   }
787   snd_device_name_free_hint(hints);
788
789   /* set the displayname for default device */
790   if (!list.empty() && list[0].m_deviceName == "default")
791   {
792     /* If we have one from a hint (DESC), use it */
793     if (!defaultDescription.empty())
794       list[0].m_displayName = defaultDescription;
795     /* Otherwise use the discovered name or (unlikely) "Default" */
796     else if (list[0].m_displayName.empty())
797       list[0].m_displayName = "Default";
798   }
799
800   /* lets check uniqueness, we may need to append DEV or CARD to DisplayName */
801   /* If even a single device of card/dev X clashes with Y, add suffixes to
802    * all devices of both them, for clarity. */
803
804   /* clashing card names, e.g. "NVidia", "NVidia_2" */
805   std::set<std::string> cardsToAppend;
806
807   /* clashing basename + cardname combinations, e.g. ("hdmi","Nvidia") */
808   std::set<std::pair<std::string, std::string> > devsToAppend;
809
810   for (AEDeviceInfoList::iterator it1 = list.begin(); it1 != list.end(); ++it1)
811   {
812     for (AEDeviceInfoList::iterator it2 = it1+1; it2 != list.end(); ++it2)
813     {
814       if (it1->m_displayName == it2->m_displayName
815        && it1->m_displayNameExtra == it2->m_displayNameExtra)
816       {
817         /* something needs to be done */
818         std::string cardString1 = GetParamFromName(it1->m_deviceName, "CARD");
819         std::string cardString2 = GetParamFromName(it2->m_deviceName, "CARD");
820
821         if (cardString1 != cardString2)
822         {
823           /* card name differs, add identifiers to all devices */
824           cardsToAppend.insert(cardString1);
825           cardsToAppend.insert(cardString2);
826           continue;
827         }
828
829         std::string devString1 = GetParamFromName(it1->m_deviceName, "DEV");
830         std::string devString2 = GetParamFromName(it2->m_deviceName, "DEV");
831
832         if (devString1 != devString2)
833         {
834           /* device number differs, add identifiers to all such devices */
835           devsToAppend.insert(std::make_pair(it1->m_deviceName.substr(0, it1->m_deviceName.find(':')), cardString1));
836           devsToAppend.insert(std::make_pair(it2->m_deviceName.substr(0, it2->m_deviceName.find(':')), cardString2));
837           continue;
838         }
839
840         /* if we got here, the configuration is really weird, just append the whole device string */
841         it1->m_displayName += " (" + it1->m_deviceName + ")";
842         it2->m_displayName += " (" + it2->m_deviceName + ")";
843       }
844     }
845   }
846
847   for (std::set<std::string>::iterator it = cardsToAppend.begin();
848        it != cardsToAppend.end(); ++it)
849   {
850     for (AEDeviceInfoList::iterator itl = list.begin(); itl != list.end(); ++itl)
851     {
852       std::string cardString = GetParamFromName(itl->m_deviceName, "CARD");
853       if (cardString == *it)
854         /* "HDA NVidia (NVidia)", "HDA NVidia (NVidia_2)", ... */
855         itl->m_displayName += " (" + cardString + ")";
856     }
857   }
858
859   for (std::set<std::pair<std::string, std::string> >::iterator it = devsToAppend.begin();
860        it != devsToAppend.end(); ++it)
861   {
862     for (AEDeviceInfoList::iterator itl = list.begin(); itl != list.end(); ++itl)
863     {
864       std::string baseName = itl->m_deviceName.substr(0, itl->m_deviceName.find(':'));
865       std::string cardString = GetParamFromName(itl->m_deviceName, "CARD");
866       if (baseName == it->first && cardString == it->second)
867       {
868         std::string devString = GetParamFromName(itl->m_deviceName, "DEV");
869         /* "HDMI #0", "HDMI #1" ... */
870         itl->m_displayNameExtra += " #" + devString;
871       }
872     }
873   }
874 }
875
876 AEDeviceType CAESinkALSA::AEDeviceTypeFromName(const std::string &name)
877 {
878   if (name.substr(0, 4) == "hdmi")
879     return AE_DEVTYPE_HDMI;
880   else if (name.substr(0, 6) == "iec958" || name.substr(0, 5) == "spdif")
881     return AE_DEVTYPE_IEC958;
882
883   return AE_DEVTYPE_PCM;
884 }
885
886 std::string CAESinkALSA::GetParamFromName(const std::string &name, const std::string &param)
887 {
888   /* name = "hdmi:CARD=x,DEV=y" param = "CARD" => return "x" */
889   size_t parPos = name.find(param + '=');
890   if (parPos != std::string::npos)
891   {
892     parPos += param.size() + 1;
893     return name.substr(parPos, name.find_first_of(",'\"", parPos)-parPos);
894   }
895
896   return "";
897 }
898
899 void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &device, const std::string &description, snd_config_t *config)
900 {
901   snd_pcm_t *pcmhandle = NULL;
902   if (!OpenPCMDevice(device, "", ALSA_MAX_CHANNELS, &pcmhandle, config))
903     return;
904
905   snd_pcm_info_t *pcminfo;
906   snd_pcm_info_alloca(&pcminfo);
907   memset(pcminfo, 0, snd_pcm_info_sizeof());
908
909   int err = snd_pcm_info(pcmhandle, pcminfo);
910   if (err < 0)
911   {
912     CLog::Log(LOGINFO, "CAESinkALSA - Unable to get pcm_info for \"%s\"", device.c_str());
913     snd_pcm_close(pcmhandle);
914   }
915
916   int cardNr = snd_pcm_info_get_card(pcminfo);
917
918   CAEDeviceInfo info;
919   info.m_deviceName = device;
920   info.m_deviceType = AEDeviceTypeFromName(device);
921
922   if (cardNr >= 0)
923   {
924     /* "HDA NVidia", "HDA Intel", "HDA ATI HDMI", "SB Live! 24-bit External", ... */
925     char *cardName;
926     if (snd_card_get_name(cardNr, &cardName) == 0)
927       info.m_displayName = cardName;
928
929     if (info.m_deviceType == AE_DEVTYPE_HDMI && info.m_displayName.size() > 5 &&
930         info.m_displayName.substr(info.m_displayName.size()-5) == " HDMI")
931     {
932       /* We already know this is HDMI, strip it */
933       info.m_displayName.erase(info.m_displayName.size()-5);
934     }
935
936     /* "CONEXANT Analog", "USB Audio", "HDMI 0", "ALC889 Digital" ... */
937     std::string pcminfoName = snd_pcm_info_get_name(pcminfo);
938
939     /*
940      * Filter "USB Audio", in those cases snd_card_get_name() is more
941      * meaningful already
942      */
943     if (pcminfoName != "USB Audio")
944       info.m_displayNameExtra = pcminfoName;
945
946     if (info.m_deviceType == AE_DEVTYPE_HDMI)
947     {
948       /* replace, this was likely "HDMI 0" */
949       info.m_displayNameExtra = "HDMI";
950
951       int dev = snd_pcm_info_get_device(pcminfo);
952
953       if (dev >= 0)
954       {
955         /* lets see if we can get ELD info */
956
957         snd_ctl_t *ctlhandle;
958         std::stringstream sstr;
959         sstr << "hw:" << cardNr;
960         std::string strHwName = sstr.str();
961
962         if (snd_ctl_open_lconf(&ctlhandle, strHwName.c_str(), 0, config) == 0)
963         {
964           snd_hctl_t *hctl;
965           if (snd_hctl_open_ctl(&hctl, ctlhandle) == 0)
966           {
967             snd_hctl_load(hctl);
968             bool badHDMI = false;
969             if (!GetELD(hctl, dev, info, badHDMI))
970               CLog::Log(LOGDEBUG, "CAESinkALSA - Unable to obtain ELD information for device \"%s\" (not supported by device, or kernel older than 3.2)",
971                         device.c_str());
972
973             /* snd_hctl_close also closes ctlhandle */
974             snd_hctl_close(hctl);
975
976             // regarding data formats we don't trust ELD
977             // push all passthrough formats to the list
978             AEDataFormatList::iterator it;
979             for (enum AEDataFormat i = AE_FMT_MAX; i > AE_FMT_INVALID; i = (enum AEDataFormat)((int)i - 1))
980             {
981               if (!AE_IS_RAW(i))
982                 continue;
983               it = find(info.m_dataFormats.begin(), info.m_dataFormats.end(), i);
984               if (it == info.m_dataFormats.end())
985                 info.m_dataFormats.push_back(i);
986             }
987
988             if (badHDMI)
989             {
990               /* 
991                * Warn about disconnected devices, but keep them enabled 
992                * Detection can go wrong on Intel, Nvidia and on all 
993                * AMD (fglrx) hardware, so it is not safe to close those
994                * handles
995                */
996               CLog::Log(LOGDEBUG, "CAESinkALSA - HDMI device \"%s\" may be unconnected (no ELD data)", device.c_str());
997             }
998           }
999           else
1000           {
1001             snd_ctl_close(ctlhandle);
1002           }
1003         }
1004       }
1005     }
1006     else if (info.m_deviceType == AE_DEVTYPE_IEC958)
1007     {
1008       /* append instead of replace, pcminfoName is useful for S/PDIF */
1009       if (!info.m_displayNameExtra.empty())
1010         info.m_displayNameExtra += ' ';
1011       info.m_displayNameExtra += "S/PDIF";
1012
1013       info.m_dataFormats.push_back(AE_FMT_AC3);
1014       info.m_dataFormats.push_back(AE_FMT_DTS);
1015     }
1016     else if (info.m_displayNameExtra.empty())
1017     {
1018       /* for USB audio, it gets a bit confusing as there is
1019        * - "SB Live! 24-bit External"
1020        * - "SB Live! 24-bit External, S/PDIF"
1021        * so add "Analog" qualifier to the first one */
1022       info.m_displayNameExtra = "Analog";
1023     }
1024
1025     /* "default" is a device that will be used for all inputs, while
1026      * "@" will be mangled to front/default/surroundXX as necessary */
1027     if (device == "@" || device == "default")
1028     {
1029       /* Make it "Default (whatever)" */
1030       info.m_displayName = "Default (" + info.m_displayName + (info.m_displayNameExtra.empty() ? "" : " " + info.m_displayNameExtra + ")");
1031       info.m_displayNameExtra = "";
1032     }
1033
1034   }
1035   else
1036   {
1037     /* virtual devices: "default", "pulse", ... */
1038     /* description can be e.g. "PulseAudio Sound Server" - for hw devices it is
1039      * normally uninteresting, like "HDMI Audio Output" or "Default Audio Device",
1040      * so we only use it for virtual devices that have no better display name */
1041     info.m_displayName = description;
1042   }
1043
1044   snd_pcm_hw_params_t *hwparams;
1045   snd_pcm_hw_params_alloca(&hwparams);
1046   memset(hwparams, 0, snd_pcm_hw_params_sizeof());
1047
1048   /* ensure we can get a playback configuration for the device */
1049   if (snd_pcm_hw_params_any(pcmhandle, hwparams) < 0)
1050   {
1051     CLog::Log(LOGINFO, "CAESinkALSA - No playback configurations available for device \"%s\"", device.c_str());
1052     snd_pcm_close(pcmhandle);
1053     return;
1054   }
1055
1056   /* detect the available sample rates */
1057   for (unsigned int *rate = ALSASampleRateList; *rate != 0; ++rate)
1058     if (snd_pcm_hw_params_test_rate(pcmhandle, hwparams, *rate, 0) >= 0)
1059       info.m_sampleRates.push_back(*rate);
1060
1061   /* detect the channels available */
1062   int channels = 0;
1063   for (int i = ALSA_MAX_CHANNELS; i >= 1; --i)
1064   {
1065     /* Reopen the device if needed on the special "surroundXX" cases */
1066     if (info.m_deviceType == AE_DEVTYPE_PCM && (i == 8 || i == 6 || i == 4))
1067       OpenPCMDevice(device, "", i, &pcmhandle, config);
1068
1069     if (snd_pcm_hw_params_test_channels(pcmhandle, hwparams, i) >= 0)
1070     {
1071       channels = i;
1072       break;
1073     }
1074   }
1075
1076   if (device == "default" && channels == 2)
1077   {
1078     /* This looks like the ALSA standard default stereo dmix device, we
1079      * probably want to use "@" instead to get surroundXX. */
1080     snd_pcm_close(pcmhandle);
1081     EnumerateDevice(list, "@", description, config);
1082     return;
1083   }
1084
1085   CAEChannelInfo alsaChannels;
1086   for (int i = 0; i < channels; ++i)
1087   {
1088     if (!info.m_channels.HasChannel(ALSAChannelMap[i]))
1089       info.m_channels += ALSAChannelMap[i];
1090     alsaChannels += ALSAChannelMap[i];
1091   }
1092
1093   /* remove the channels from m_channels that we cant use */
1094   info.m_channels.ResolveChannels(alsaChannels);
1095
1096   /* detect the PCM sample formats that are available */
1097   for (enum AEDataFormat i = AE_FMT_MAX; i > AE_FMT_INVALID; i = (enum AEDataFormat)((int)i - 1))
1098   {
1099     if (AE_IS_RAW(i) || i == AE_FMT_MAX)
1100       continue;
1101     snd_pcm_format_t fmt = AEFormatToALSAFormat(i);
1102     if (fmt == SND_PCM_FORMAT_UNKNOWN)
1103       continue;
1104
1105     if (snd_pcm_hw_params_test_format(pcmhandle, hwparams, fmt) >= 0)
1106       info.m_dataFormats.push_back(i);
1107   }
1108
1109   snd_pcm_close(pcmhandle);
1110   list.push_back(info);
1111 }
1112
1113 bool CAESinkALSA::GetELD(snd_hctl_t *hctl, int device, CAEDeviceInfo& info, bool& badHDMI)
1114 {
1115   badHDMI = false;
1116
1117   snd_ctl_elem_id_t    *id;
1118   snd_ctl_elem_info_t  *einfo;
1119   snd_ctl_elem_value_t *control;
1120   snd_hctl_elem_t      *elem;
1121
1122   snd_ctl_elem_id_alloca(&id);
1123   memset(id, 0, snd_ctl_elem_id_sizeof());
1124
1125   snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
1126   snd_ctl_elem_id_set_name     (id, "ELD" );
1127   snd_ctl_elem_id_set_device   (id, device);
1128   elem = snd_hctl_find_elem(hctl, id);
1129   if (!elem)
1130     return false;
1131
1132   snd_ctl_elem_info_alloca(&einfo);
1133   memset(einfo, 0, snd_ctl_elem_info_sizeof());
1134
1135   if (snd_hctl_elem_info(elem, einfo) < 0)
1136     return false;
1137
1138   if (!snd_ctl_elem_info_is_readable(einfo))
1139     return false;
1140
1141   if (snd_ctl_elem_info_get_type(einfo) != SND_CTL_ELEM_TYPE_BYTES)
1142     return false;
1143
1144   snd_ctl_elem_value_alloca(&control);
1145   memset(control, 0, snd_ctl_elem_value_sizeof());
1146
1147   if (snd_hctl_elem_read(elem, control) < 0)
1148     return false;
1149
1150   int dataLength = snd_ctl_elem_info_get_count(einfo);
1151   /* if there is no ELD data, then its a bad HDMI device, either nothing attached OR an invalid nVidia HDMI device
1152    * OR the driver doesn't properly support ELD (notably ATI/AMD, 2012-05) */
1153   if (!dataLength)
1154     badHDMI = true;
1155   else
1156     CAEELDParser::Parse(
1157       (const uint8_t*)snd_ctl_elem_value_get_bytes(control),
1158       dataLength,
1159       info
1160     );
1161
1162   info.m_deviceType = AE_DEVTYPE_HDMI;
1163   return true;
1164 }
1165
1166 void CAESinkALSA::sndLibErrorHandler(const char *file, int line, const char *function, int err, const char *fmt, ...)
1167 {
1168   va_list arg;
1169   va_start(arg, fmt);
1170   char *errorStr;
1171   if (vasprintf(&errorStr, fmt, arg) >= 0)
1172   {
1173     CLog::Log(LOGINFO, "CAESinkALSA - ALSA: %s:%d:(%s) %s%s%s",
1174               file, line, function, errorStr, err ? ": " : "", err ? snd_strerror(err) : "");
1175     free(errorStr);
1176   }
1177   va_end(arg);
1178 }
1179
1180 #endif