this repo has no description
1/*
2This file is part of Darling.
3
4Copyright (C) 2020 Lubos Dolezel
5
6Darling is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11Darling is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with Darling. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include <AudioToolbox/AudioComponent.h>
21#include <CarbonCore/Components.h>
22#include <CarbonCore/Resources.h>
23#include <CarbonCore/MacErrors.h>
24#include <CarbonCore/MacMemory.h>
25#include "AudioComponentManager.h"
26#include <iostream>
27
28AudioComponent AudioComponentRegister(const AudioComponentDescription *inDesc, CFStringRef inName,
29 UInt32 inVersion, AudioComponentFactoryFunction inFactory)
30{
31 if (!inDesc || !inName || !inFactory)
32 return nullptr;
33
34 const char* name = CFStringGetCStringPtr(inName, kCFStringEncodingUTF8);
35 return AudioComponentManager::instance()->registerComponent(inDesc, name, inVersion, inFactory);
36}
37
38AudioComponent AudioComponentFindNext(AudioComponent inComponent, const AudioComponentDescription* desc)
39{
40 auto matching = AudioComponentManager::instance()->findMatching(desc);
41 if (!matching.empty())
42 {
43 if (!inComponent)
44 return matching[0];
45
46 for (size_t i = 0; i < matching.size()-1; i++)
47 {
48 if (matching[i] == inComponent)
49 {
50 return matching[i+1];
51 }
52 }
53 }
54
55 return (AudioComponent) ::FindNextComponent(Component(inComponent), (ComponentDescription*) desc);
56}
57
58UInt32 AudioComponentCount(const AudioComponentDescription* desc)
59{
60 const UInt32 carbonComponents = ::CountComponents((ComponentDescription*) desc);
61 UInt32 numDuplicates = 0;
62 Component carbonComponent = nullptr;
63
64 while ((carbonComponent = ::FindNextComponent(carbonComponent, (ComponentDescription*) desc)) != nullptr)
65 {
66 ComponentDescription cd;
67
68 ::GetComponentInfo(carbonComponent, &cd, nullptr, nullptr, nullptr);
69
70 if (::AudioComponentFindNext(nullptr, (AudioComponentDescription*) &cd) != nullptr)
71 numDuplicates++;
72 }
73
74 return AudioComponentManager::instance()->findMatching(desc).size() + carbonComponents - numDuplicates;
75}
76
77OSStatus AudioComponentCopyName(AudioComponent component, CFStringRef* outName)
78{
79 if (AudioComponentManager::isOurInstance(component))
80 {
81 const char* name;
82 OSStatus status = AudioComponentManager::instance()->getName(component, &name);
83
84 if (status == noErr)
85 *outName = CFStringCreateWithCString(nullptr, name, kCFStringEncodingUTF8);
86 else
87 *outName = nullptr;
88
89 return status;
90 }
91 else
92 {
93 Handle handle = ::NewEmptyHandle();
94 OSStatus status = ::GetComponentInfo(Component(component), nullptr, handle, nullptr, nullptr);
95
96 if (status != noErr)
97 {
98 ::DisposeHandle(handle);
99 *outName = nullptr;
100 return status;
101 }
102 else
103 {
104 *outName = ::CFStringCreateWithPascalString(nullptr, ConstStr255Param(*handle), kCFStringEncodingMacRoman);
105 ::DisposeHandle(handle);
106 return noErr;
107 }
108 }
109}
110
111OSStatus AudioComponentGetDescription(AudioComponent component, AudioComponentDescription* outDesc)
112{
113 if (AudioComponentManager::isOurInstance(component))
114 {
115 return AudioComponentManager::instance()->getDescription(component, outDesc);
116 }
117 else
118 {
119 return ::GetComponentInfo(Component(component), (ComponentDescription*) outDesc, nullptr, nullptr, nullptr);
120 }
121}
122
123#pragma pack(push, 1)
124struct PlatformInfo
125{
126 uint32_t ComponentFlags;
127 uint32_t CodeType;
128 uint16_t CodeId;
129 uint16_t PlatformType;
130};
131
132struct CarbonThng
133{
134 uint32_t Type;
135 uint32_t Subtype;
136 uint32_t Manufacturer;
137 uint32_t ComponentFlags;
138 uint32_t ComponentFlagsMask;
139 uint32_t CodeType;
140 uint16_t CodeId;
141 uint32_t NameType;
142 uint16_t NameId;
143 uint32_t InfoType;
144 uint16_t InfoId;
145 uint32_t IconType;
146 uint16_t IconId;
147 uint32_t ComponentVersion;
148 uint32_t RegistrationFlags;
149 uint16_t IconFamilyId;
150
151 uint32_t PlatformInfoCount;
152 PlatformInfo PlatformInfos[];
153};
154#pragma pack(pop)
155#ifdef __LITTLE_ENDIAN__
156# define SWAP(x) x = _bswap(x)
157
158static inline uint16_t _bswap(uint16_t v) { return __builtin_bswap16(v); }
159static inline int16_t _bswap(int16_t v) { return __builtin_bswap16(v); }
160static inline uint32_t _bswap(uint32_t v) { return __builtin_bswap32(v); }
161
162#else
163# define SWAP(x)
164#endif
165
166OSStatus AudioComponentGetVersion(AudioComponent component, UInt32* outVersion)
167{
168 if (AudioComponentManager::isOurInstance(component))
169 {
170 return AudioComponentManager::instance()->getVersion(component, (uint32_t*) outVersion);
171 }
172 else
173 {
174 ResFileRefNum resFile, oldFile;
175 AudioComponentDescription desc;
176 OSStatus status;
177
178 status = ::AudioComponentGetDescription(component, &desc);
179 if (status != noErr)
180 return status;
181
182 status = ::OpenAComponentResFile(Component(component), &resFile);
183 if (status != noErr)
184 return status;
185
186 oldFile = ::CurResFile();
187 ::UseResFile(resFile);
188
189 const ResourceCount count = ::Count1Resources('thng');
190 bool found = false;
191
192 for (int i = 1; i <= count; i++)
193 {
194 Handle handle = ::Get1IndResource('thng', i);
195 if (handle && ::GetHandleSize(handle) >= sizeof(CarbonThng))
196 {
197 CarbonThng thng = *((CarbonThng*) *handle);
198
199 SWAP(thng.Type);
200 SWAP(thng.Subtype);
201 SWAP(thng.Manufacturer);
202
203 if (thng.Type == desc.componentType && thng.Subtype == desc.componentSubType && thng.Manufacturer == desc.componentManufacturer)
204 {
205 SWAP(thng.ComponentVersion);
206 *outVersion = thng.ComponentVersion;
207 found = true;
208 break;
209 }
210 }
211 }
212
213 ::UseResFile(oldFile);
214 ::CloseComponentResFile(resFile);
215
216 return found ? noErr : invalidComponentID;
217 }
218}
219
220#if !TARGET_OS_IPHONE
221
222NSImage* AudioComponentGetIcon(AudioComponent component)
223{
224 return nullptr;
225}
226
227#else
228
229UIImage* AudioComponentGetIcon(AudioComponent component, float desiredPointSize)
230{
231 return nullptr;
232}
233
234#endif
235
236OSStatus AudioComponentInstanceNew(AudioComponent component, AudioComponentInstance* outInstance)
237{
238 if (AudioComponentManager::isOurInstance(component))
239 {
240 return AudioComponentManager::instance()->instantiate(component, outInstance);
241 }
242 else
243 {
244 return ::OpenAComponent(Component(component), (ComponentInstance*) outInstance);
245 }
246}
247
248void AudioComponentInstantiate(AudioComponent component, AudioComponentInstantiationOptions opts, void(^handler)(AudioComponentInstance, OSStatus))
249{
250 std::cerr << "AudioComponentInstantiate(): NOT IMPLEMENTED\n";
251}
252
253OSStatus AudioComponentInstanceDispose(AudioComponentInstance inst)
254{
255 if (AudioComponentManager::isOurInstance(inst))
256 {
257 return AudioComponentManager::instance()->dispose(inst);
258 }
259 else
260 {
261 return ::CloseComponent(inst);
262 }
263}
264
265AudioComponent AudioComponentInstanceGetComponent(AudioComponentInstance inst)
266{
267 if (AudioComponentManager::isOurInstance(inst))
268 {
269 return AudioComponentManager::instance()->getComponent(inst);
270 }
271 else
272 {
273 return (AudioComponent) ::GetComponentIDFromComponentInstance(inst);
274 }
275}
276
277Boolean AudioComponentInstanceCanDo(AudioComponentInstance inst, SInt16 sel)
278{
279 if (AudioComponentManager::isOurInstance(inst))
280 {
281 AudioComponentPlugInInterface* iface = AudioComponentManager::instance()->instanceInterface(inst);
282 return iface->Lookup(sel) != nullptr;
283 }
284 else
285 {
286 return ::CallComponentCanDo(inst, sel);
287 }
288}
289
290OSStatus AudioComponentCopyConfigurationInfo(AudioComponent component, CFDictionaryRef* outInfo)
291{
292 std::cerr << "AudioComponentCopyConfigurationInfo(): NOT IMPLEMENTED\n";
293 *outInfo = CFDictionaryCreate(nullptr, nullptr, nullptr, 0, nullptr, nullptr);
294 return noErr;
295}
296
297OSStatus AudioComponentValidate(AudioComponent component, CFDictionaryRef validationParams, AudioComponentValidationResult* result)
298{
299 *result = kAudioComponentValidationResult_Passed;
300 return noErr;
301}