1 /*
2  * Copyright (c) 2009, The MilkyTracker Team.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * - Redistributions of source code must retain the above copyright notice,
9  *   this list of conditions and the following disclaimer.
10  * - Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * - Neither the name of the <ORGANIZATION> nor the names of its contributors
14  *   may be used to endorse or promote products derived from this software
15  *   without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "AudioDriverManager.h"
31 #include "AudioDriverBase.h"
32 #include "MilkyPlayCommon.h"
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 
37 #define ALLOC_DRIVERLIST(NUMDRIVERS) \
38 	enumerationIndex = -1; \
39 	numDrivers = (NUMDRIVERS); \
40 	driverList = new AudioDriverInterface*[numDrivers]; \
41 	memset(driverList, 0, numDrivers*sizeof(AudioDriverInterface*));
42 
43 #define CLEANUP_DRIVERLIST \
44 	for (mp_sint32 i = 0; i < numDrivers; i++) \
45 		delete driverList[i]; \
46 	delete[] driverList;
47 
48 #if defined(DRIVER_WIN32)
49 //////////////////////////////////////////////////////////////////
50 //					 Windows implementation
51 //////////////////////////////////////////////////////////////////
52 #include "AudioDriver_MMSYSTEM.h"
53 
54 #if !defined(_WIN32_WCE) && !defined(__SKIPRTAUDIO__)
55 #include "AudioDriver_RTAUDIO.h"
56 
57 /* Taken from VersionHelpers.h in the Windows 8 SDK; not present in the XP-compatible SDKs */
IsWindowsVistaOrGreater()58 static bool IsWindowsVistaOrGreater()
59 {
60 	OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, { 0 }, 0, 0 };
61 	DWORDLONG const dwlConditionMask = VerSetConditionMask(
62 		VerSetConditionMask(
63 		VerSetConditionMask(
64 			0,	VER_MAJORVERSION, VER_GREATER_EQUAL),
65 				VER_MINORVERSION, VER_GREATER_EQUAL),
66 				VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
67 
68 	osvi.dwMajorVersion = HIBYTE(_WIN32_WINNT_VISTA);
69 	osvi.dwMinorVersion = LOBYTE(_WIN32_WINNT_VISTA);
70 	osvi.wServicePackMajor = 0;
71 
72 	return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
73 }
74 
75 #endif
76 #if !defined(_WIN32_WCE) && defined(__WASAPI__)
77 #include "AudioDriver_PORTAUDIO.h"
78 #endif
79 
AudioDriverManager()80 AudioDriverManager::AudioDriverManager() :
81 	defaultDriverIndex(0)
82 {
83 	mp_sint32 driverListSize = 1;
84 #if !defined(_WIN32_WCE) && !defined(__SKIPRTAUDIO__)
85 	driverListSize+=4;
86 #endif
87 #if !defined(_WIN32_WCE) && defined(__WASAPI__)
88 	driverListSize++;
89 #endif
90 
91 	mp_sint32 i = 0;
92 	ALLOC_DRIVERLIST(driverListSize);
93 	driverList[i++] = new AudioDriver_MMSYSTEM();
94 #if !defined(_WIN32_WCE) && !defined(__SKIPRTAUDIO__)
95 	driverList[i++] = new AudioDriver_RTAUDIO();
96 	driverList[i++] = new AudioDriver_RTAUDIO(AudioDriver_RTAUDIO::WINDOWS_ASIO);
97 	driverList[i++] = new AudioDriver_RTAUDIO(AudioDriver_RTAUDIO::WINDOWS_DS);
98 	driverList[i++] = new AudioDriver_RTAUDIO(AudioDriver_RTAUDIO::WINDOWS_WASAPI);
99 
100 #ifndef _WIN32_WCE
101 	// On Windows Vista we set the DS driver to be the default
102 	if (IsWindowsVistaOrGreater())
103 		defaultDriverIndex = i-2;
104 #endif
105 
106 #endif
107 #if !defined(_WIN32_WCE) && defined(__WASAPI__)
108 	driverList[i++] = new AudioDriver_PORTAUDIO();
109 #endif
110 }
111 
112 #elif defined(DRIVER_OSX)
113 //////////////////////////////////////////////////////////////////
114 //					 Mac OS X implementation
115 //////////////////////////////////////////////////////////////////
116 #include "AudioDriver_COREAUDIO.h"
117 
AudioDriverManager()118 AudioDriverManager::AudioDriverManager() :
119 	defaultDriverIndex(0)
120 {
121 	mp_uint32 deviceCount = 0;
122 	AudioObjectID* deviceIDs = NULL;
123 	OSStatus err = AudioDriver_COREAUDIO::getAudioDevices(deviceCount, deviceIDs);
124 
125 	if (err)
126 		fprintf(stderr, "Core Audio: Error while enumerating devices (%d)\n", err);
127 
128 	ALLOC_DRIVERLIST(deviceCount + 1);
129 
130 	// First device: system default output
131 	driverList[0] = new AudioDriver_COREAUDIO();
132 
133 	// List all output devices
134 	int i;
135 	for (i = 0; i < deviceCount; i++)
136 	{
137 		driverList[i + 1] = new AudioDriver_COREAUDIO(deviceIDs[i]);
138 	}
139 
140 	if (deviceIDs)
141 		delete[] deviceIDs;
142 }
143 
144 #elif defined(DRIVER_UNIX)
145 //////////////////////////////////////////////////////////////////
146 //					  UNIX implementation
147 //////////////////////////////////////////////////////////////////
148 #include "AudioDriver_SDL.h"
149 // #include "AudioDriver_RTAUDIO.h"
150 #ifdef HAVE_LIBASOUND
151 #include "drivers/alsa/AudioDriver_ALSA.h"
152 #endif
153 #ifdef HAVE_JACK_JACK_H
154 #include "AudioDriver_JACK.h"
155 #endif
156 
AudioDriverManager()157 AudioDriverManager::AudioDriverManager() :
158 	defaultDriverIndex(0)
159 {
160 	int count = 1;
161 #ifdef HAVE_LIBASOUND
162 	count++;
163 #endif
164 #ifdef HAVE_JACK_JACK_H
165 	count++;
166 #endif
167 	ALLOC_DRIVERLIST(count);
168 	count = 0;
169 	driverList[count++] = new AudioDriver_SDL();
170 #ifdef HAVE_LIBASOUND
171 	driverList[count++] = new AudioDriver_ALSA();
172 #endif
173 #if HAVE_JACK_JACK_H
174 	driverList[count++] = new AudioDriver_JACK();
175 #endif
176 }
177 
178 #elif defined(DRIVER_SDL)
179 //////////////////////////////////////////////////////////////////
180 //					 	SDL implementation
181 //////////////////////////////////////////////////////////////////
182 #include "AudioDriver_SDL.h"
183 
AudioDriverManager()184 AudioDriverManager::AudioDriverManager() :
185 	defaultDriverIndex(0)
186 {
187 	ALLOC_DRIVERLIST(1);
188 	driverList[0] = new AudioDriver_SDL();
189 }
190 
191 #elif defined(DRIVER_PSP)
192 //////////////////////////////////////////////////////////////////
193 //					 	PSP implementation
194 //////////////////////////////////////////////////////////////////
195 #include "AudioDriver_PSP.h"
196 
AudioDriverManager()197 AudioDriverManager::AudioDriverManager() :
198 	defaultDriverIndex(0)
199 {
200 	ALLOC_DRIVERLIST(1);
201 	driverList[0] = new AudioDriver_PSP();
202 }
203 
204 #elif defined(DRIVER_HAIKU)
205 //////////////////////////////////////////////////////////////////
206 //					   Haiku implementation
207 //////////////////////////////////////////////////////////////////
208 #include "AudioDriver_Haiku.h"
209 
AudioDriverManager()210 AudioDriverManager::AudioDriverManager() :
211 	defaultDriverIndex(0)
212 {
213 	ALLOC_DRIVERLIST(1);
214 	driverList[0] = new AudioDriver_Haiku();
215 }
216 
217 #endif
218 
getPreferredAudioDriver()219 AudioDriverInterface* AudioDriverManager::getPreferredAudioDriver()
220 {
221 	return driverList[defaultDriverIndex];
222 }
223 
~AudioDriverManager()224 AudioDriverManager::~AudioDriverManager()
225 {
226 	CLEANUP_DRIVERLIST;
227 }
228 
getAudioDriverByName(const char * name)229 AudioDriverInterface* AudioDriverManager::getAudioDriverByName(const char* name)
230 {
231 	if (name == NULL)
232 		return NULL;
233 
234 	for (mp_sint32 i = 0; i < numDrivers; i++)
235 	{
236 		if (strcmp(driverList[i]->getDriverID(), name) == 0)
237 			return driverList[i];
238 	}
239 
240 	return NULL;
241 }
242 
getFirstDriverName() const243 const char* AudioDriverManager::getFirstDriverName() const
244 {
245 	enumerationIndex = 0;
246 	if (enumerationIndex < numDrivers)
247 		return driverList[enumerationIndex]->getDriverID();
248 	else
249 		return NULL;
250 }
251 
getNextDriverName() const252 const char* AudioDriverManager::getNextDriverName() const
253 {
254 	enumerationIndex++;
255 	if (enumerationIndex >= numDrivers)
256 	{
257 		enumerationIndex = -1;
258 		return NULL;
259 	}
260 
261 	return driverList[enumerationIndex]->getDriverID();
262 }
263 
getPreferredAudioDriverSampleRate() const264 mp_sint32 AudioDriverManager::getPreferredAudioDriverSampleRate() const
265 {
266 	return driverList[defaultDriverIndex]->getPreferredSampleRate();
267 }
268 
getPreferredAudioDriverBufferSize() const269 mp_sint32 AudioDriverManager::getPreferredAudioDriverBufferSize() const
270 {
271 	return driverList[defaultDriverIndex]->getPreferredBufferSize();
272 }
273