2 * Copyright (C) 2010-2013 Team XBMC
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)
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.
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/>.
21 #include "AESinkFactory.h"
22 #include "Interfaces/AESink.h"
23 #if defined(TARGET_WINDOWS)
24 #include "Sinks/AESinkWASAPI.h"
25 #include "Sinks/AESinkDirectSound.h"
26 #elif defined(TARGET_ANDROID)
27 #include "Sinks/AESinkAUDIOTRACK.h"
28 #elif defined(TARGET_RASPBERRY_PI)
29 #include "Sinks/AESinkPi.h"
30 #elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
32 #include "Sinks/AESinkALSA.h"
34 #if defined(HAS_PULSEAUDIO)
35 #include "Sinks/AESinkPULSE.h"
37 #include "Sinks/AESinkOSS.h"
39 #pragma message("NOTICE: No audio sink for target platform. Audio output will not be available.")
41 #include "Sinks/AESinkProfiler.h"
42 #include "Sinks/AESinkNULL.h"
44 #include "settings/AdvancedSettings.h"
45 #include "utils/SystemInfo.h"
46 #include "utils/log.h"
48 void CAESinkFactory::ParseDevice(std::string &device, std::string &driver)
50 int pos = device.find_first_of(':');
53 driver = device.substr(0, pos);
54 std::transform(driver.begin(), driver.end(), driver.begin(), ::toupper);
56 // check that it is a valid driver name
58 #if defined(TARGET_WINDOWS)
60 driver == "DIRECTSOUND" ||
61 #elif defined(TARGET_ANDROID)
62 driver == "AUDIOTRACK" ||
63 #elif defined(TARGET_RASPBERRY_PI)
65 #elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
69 #if defined(HAS_PULSEAUDIO)
74 driver == "PROFILER" ||
76 device = device.substr(pos + 1, device.length() - pos - 1);
84 IAESink *CAESinkFactory::TrySink(std::string &driver, std::string &device, AEAudioFormat &format)
89 sink = new CAESinkNULL();
91 #if defined(TARGET_WINDOWS)
92 else if (driver == "WASAPI")
93 sink = new CAESinkWASAPI();
94 else if (driver == "DIRECTSOUND")
95 sink = new CAESinkDirectSound();
96 #elif defined(TARGET_ANDROID)
97 sink = new CAESinkAUDIOTRACK();
98 #elif defined(TARGET_RASPBERRY_PI)
99 sink = new CAESinkPi();
100 #elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
101 #if defined(HAS_PULSEAUDIO)
102 else if (driver == "PULSE")
103 sink = new CAESinkPULSE();
105 #if defined(HAS_ALSA)
106 else if (driver == "ALSA")
107 sink = new CAESinkALSA();
109 else if (driver == "OSS")
110 sink = new CAESinkOSS();
116 if (sink->Initialize(format, device))
120 sink->Deinitialize();
125 IAESink *CAESinkFactory::Create(std::string &device, AEAudioFormat &desiredFormat, bool rawPassthrough)
127 // extract the driver from the device string if it exists
129 ParseDevice(device, driver);
131 AEAudioFormat tmpFormat = desiredFormat;
133 std::string tmpDevice = device;
135 sink = TrySink(driver, tmpDevice, tmpFormat);
138 desiredFormat = tmpFormat;
145 void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force)
148 #if defined(TARGET_WINDOWS)
150 info.m_deviceInfoList.clear();
151 info.m_sinkName = "DirectSound";
152 CAESinkDirectSound::EnumerateDevicesEx(info.m_deviceInfoList, force);
153 if(!info.m_deviceInfoList.empty())
154 list.push_back(info);
156 info.m_deviceInfoList.clear();
157 info.m_sinkName = "WASAPI";
158 CAESinkWASAPI::EnumerateDevicesEx(info.m_deviceInfoList, force);
159 if(!info.m_deviceInfoList.empty())
160 list.push_back(info);
162 #elif defined(TARGET_ANDROID)
164 info.m_deviceInfoList.clear();
165 info.m_sinkName = "AUDIOTRACK";
166 CAESinkAUDIOTRACK::EnumerateDevicesEx(info.m_deviceInfoList, force);
167 if(!info.m_deviceInfoList.empty())
168 list.push_back(info);
170 #elif defined(TARGET_RASPBERRY_PI)
172 info.m_deviceInfoList.clear();
173 info.m_sinkName = "PI";
174 CAESinkPi::EnumerateDevicesEx(info.m_deviceInfoList, force);
175 if(!info.m_deviceInfoList.empty())
176 list.push_back(info);
178 #elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
179 // check if user wants us to do something specific
180 if (getenv("AE_SINK"))
182 std::string envSink = (std::string)getenv("AE_SINK");
183 std::transform(envSink.begin(), envSink.end(), envSink.begin(), ::toupper);
184 info.m_deviceInfoList.clear();
185 #if defined(HAS_PULSEAUDIO)
186 if (envSink == "PULSE")
187 CAESinkPULSE::EnumerateDevicesEx(info.m_deviceInfoList, force);
189 #if defined(HAS_ALSA)
190 if (envSink == "ALSA")
191 CAESinkALSA::EnumerateDevicesEx(info.m_deviceInfoList, force);
193 if (envSink == "OSS")
194 CAESinkOSS::EnumerateDevicesEx(info.m_deviceInfoList, force);
196 if(!info.m_deviceInfoList.empty())
198 info.m_sinkName = envSink;
199 list.push_back(info);
203 CLog::Log(LOGNOTICE, "User specified Sink %s could not be enumerated", envSink.c_str());
206 #if defined(HAS_PULSEAUDIO)
207 info.m_deviceInfoList.clear();
208 info.m_sinkName = "PULSE";
209 CAESinkPULSE::EnumerateDevicesEx(info.m_deviceInfoList, force);
210 if(!info.m_deviceInfoList.empty())
212 list.push_back(info);
217 #if defined(HAS_ALSA)
218 info.m_deviceInfoList.clear();
219 info.m_sinkName = "ALSA";
220 CAESinkALSA::EnumerateDevicesEx(info.m_deviceInfoList, force);
221 if(!info.m_deviceInfoList.empty())
222 list.push_back(info);
226 info.m_deviceInfoList.clear();
227 info.m_sinkName = "OSS";
228 CAESinkOSS::EnumerateDevicesEx(info.m_deviceInfoList, force);
229 if(!info.m_deviceInfoList.empty())
230 list.push_back(info);