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