2 * Copyright (C) 2010-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
11 #include "cores/AudioEngine/Interfaces/AESink.h"
12 #include "cores/AudioEngine/Utils/AEDeviceInfo.h"
13 #include "threads/CriticalSection.h"
17 #include <alsa/asoundlib.h>
19 #define AE_MIN_PERIODSIZE 256
21 class CAESinkALSA
: public IAESink
24 const char *GetName() override
{ return "ALSA"; }
27 ~CAESinkALSA() override
;
29 static void Register();
30 static std::unique_ptr
<IAESink
> Create(std::string
& device
, AEAudioFormat
& desiredFormat
);
31 static void EnumerateDevicesEx(AEDeviceInfoList
&list
, bool force
= false);
32 static void Cleanup();
34 bool Initialize(AEAudioFormat
&format
, std::string
&device
) override
;
35 void Deinitialize() override
;
38 void GetDelay(AEDelayStatus
& status
) override
;
39 double GetCacheTotal() override
;
40 unsigned int AddPackets(uint8_t **data
, unsigned int frames
, unsigned int offset
) override
;
41 void Drain() override
;
44 CAEChannelInfo
GetChannelLayoutRaw(const AEAudioFormat
& format
);
45 CAEChannelInfo
GetChannelLayoutLegacy(const AEAudioFormat
& format
, unsigned int minChannels
, unsigned int maxChannels
);
46 CAEChannelInfo
GetChannelLayout(const AEAudioFormat
& format
, unsigned int channels
);
48 static AEChannel
ALSAChannelToAEChannel(unsigned int alsaChannel
);
49 static unsigned int AEChannelToALSAChannel(AEChannel aeChannel
);
50 static CAEChannelInfo
ALSAchmapToAEChannelMap(snd_pcm_chmap_t
* alsaMap
);
51 static snd_pcm_chmap_t
* AEChannelMapToALSAchmap(const CAEChannelInfo
& info
);
52 static snd_pcm_chmap_t
* CopyALSAchmap(snd_pcm_chmap_t
* alsaMap
);
53 static std::string
ALSAchmapToString(snd_pcm_chmap_t
* alsaMap
);
54 static CAEChannelInfo
GetAlternateLayoutForm(const CAEChannelInfo
& info
);
55 snd_pcm_chmap_t
* SelectALSAChannelMap(const CAEChannelInfo
& info
);
57 void GetAESParams(const AEAudioFormat
& format
, std::string
& params
);
58 void HandleError(const char* name
, int err
);
60 std::string m_initDevice
;
61 AEAudioFormat m_initFormat
;
62 AEAudioFormat m_format
;
63 unsigned int m_bufferSize
= 0;
64 double m_formatSampleRateMul
= 0.0;
65 bool m_passthrough
= false;
69 // support fragmentation, e.g. looping in the sink to get a certain amount of data onto the device
70 bool m_fragmented
= false;
71 unsigned int m_originalPeriodSize
= AE_MIN_PERIODSIZE
;
75 unsigned int sampleRate
;
76 unsigned int periodSize
;
77 unsigned int frameSize
;
78 unsigned int channels
;
82 static snd_pcm_format_t
AEFormatToALSAFormat(const enum AEDataFormat format
);
84 bool InitializeHW(const ALSAConfig
&inconfig
, ALSAConfig
&outconfig
);
85 bool InitializeSW(const ALSAConfig
&inconfig
);
87 static void AppendParams(std::string
&device
, const std::string
¶ms
);
88 static bool TryDevice(const std::string
&name
, snd_pcm_t
**pcmp
, snd_config_t
*lconf
);
89 static bool TryDeviceWithParams(const std::string
&name
, const std::string
¶ms
, snd_pcm_t
**pcmp
, snd_config_t
*lconf
);
90 static bool OpenPCMDevice(const std::string
&name
, const std::string
¶ms
, int channels
, snd_pcm_t
**pcmp
, snd_config_t
*lconf
);
92 static AEDeviceType
AEDeviceTypeFromName(const std::string
&name
);
93 static std::string
GetParamFromName(const std::string
&name
, const std::string
¶m
);
94 static void EnumerateDevice(AEDeviceInfoList
&list
, const std::string
&device
, const std::string
&description
, snd_config_t
*config
);
95 static bool SoundDeviceExists(const std::string
& device
);
96 static bool GetELD(snd_hctl_t
*hctl
, int device
, CAEDeviceInfo
& info
, bool& badHDMI
);
98 static void sndLibErrorHandler(const char *file
, int line
, const char *function
, int err
, const char *fmt
, ...);