diff --git a/src/CoreAudio/AudioHardware.cpp b/src/CoreAudio/AudioHardware.cpp
new file mode 100644
index 000000000..1363f333a
--- /dev/null
+++ b/src/CoreAudio/AudioHardware.cpp
@@ -0,0 +1,231 @@
+/*
+This file is part of Darling.
+
+Copyright (C) 2015-2016 Lubos Dolezel
+
+Darling is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Darling is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Darling. If not, see .
+*/
+
+#include "AudioHardware.h"
+#include "AudioHardwareImpl.h"
+#include
+#include
+
+static std::unique_ptr g_systemObject;
+
+static AudioHardwareImpl* GetSystemObject()
+{
+ if (!g_systemObject)
+ {
+ static std::mutex singleLock;
+ singleLock.lock();
+
+ if (!g_systemObject)
+ g_systemObject.reset(nullptr); // TODO: create ALSA or PA here
+
+ singleLock.unlock();
+ }
+
+ return g_systemObject.get();
+}
+
+static AudioHardwareImpl* GetObject(AudioObjectID objID)
+{
+ if (objID == kAudioObjectSystemObject)
+ return GetSystemObject();
+
+ return nullptr;
+}
+
+void AudioObjectShow(AudioObjectID inObjectID)
+{
+ AudioHardwareImpl* obj = GetObject(inObjectID);
+ if (obj)
+ obj->show();
+}
+
+Boolean AudioObjectHasProperty(AudioObjectID inObjectID,
+ const AudioObjectPropertyAddress* inAddress)
+{
+ AudioHardwareImpl* obj = GetObject(inObjectID);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->hasProperty(inAddress);
+}
+
+OSStatus AudioObjectIsPropertySettable(AudioObjectID inObjectID,
+ const AudioObjectPropertyAddress* inAddress, Boolean* outIsSettable)
+{
+ AudioHardwareImpl* obj = GetObject(inObjectID);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->isPropertySettable(inAddress, outIsSettable);
+}
+
+OSStatus AudioObjectGetPropertyDataSize(AudioObjectID inObjectID,
+ const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
+ const void* inQualifierData, UInt32* outDataSize)
+{
+ AudioHardwareImpl* obj = GetObject(inObjectID);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->getPropertyDataSize(inAddress, inQualifierDataSize,
+ inQualifierData, outDataSize);
+}
+
+OSStatus AudioObjectGetPropertyData(AudioObjectID inObjectID,
+ const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
+ const void* inQualifierData, UInt32* ioDataSize, void* outData)
+{
+ AudioHardwareImpl* obj = GetObject(inObjectID);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->getPropertyData(inAddress, inQualifierDataSize, inQualifierData,
+ ioDataSize, outData);
+}
+
+OSStatus AudioObjectSetPropertyData(AudioObjectID inObjectID,
+ const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
+ const void* inQualifierData, UInt32 inDataSize, const void* inData)
+{
+ AudioHardwareImpl* obj = GetObject(inObjectID);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->setPropertyData(inAddress, inQualifierDataSize, inQualifierData,
+ inDataSize, inData);
+}
+
+OSStatus AudioObjectAddPropertyListener(AudioObjectID inObjectID,
+ const AudioObjectPropertyAddress* inAddress,
+ AudioObjectPropertyListenerProc inListener, void* inClientData)
+{
+ AudioHardwareImpl* obj = GetObject(inObjectID);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->addPropertyListener(inAddress, inListener, inClientData);
+}
+
+OSStatus AudioObjectRemovePropertyListener(AudioObjectID inObjectID,
+ const AudioObjectPropertyAddress* inAddress,
+ AudioObjectPropertyListenerProc inListener, void* inClientData)
+{
+ AudioHardwareImpl* obj = GetObject(inObjectID);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->removePropertyListener(inAddress, inListener, inClientData);
+}
+
+OSStatus AudioHardwareUnload(void)
+{
+ g_systemObject.reset(nullptr);
+ return noErr;
+}
+
+OSStatus AudioHardwareCreateAggregateDevice(CFDictionaryRef, AudioObjectID* outDeviceID)
+{
+ if (outDeviceID)
+ *outDeviceID = 0;
+
+ return unimpErr;
+}
+
+OSStatus AudioHardwareDestroyAggregateDevice(AudioObjectID inDeviceID)
+{
+ return unimpErr;
+}
+
+OSStatus AudioDeviceCreateIOProcID(AudioObjectID inDevice,
+ AudioDeviceIOProc inProc, void* inClientData,
+ AudioDeviceIOProcID* outIOProcID)
+{
+ AudioHardwareImpl* obj = GetObject(inDevice);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->createIOProcID(inProc, inClientData, outIOProcID);
+}
+
+OSStatus AudioDeviceDestroyIOProcID(AudioObjectID inDevice,
+ AudioDeviceIOProcID inIOProcID)
+{
+ AudioHardwareImpl* obj = GetObject(inDevice);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->destroyIOProcID(inIOProcID);
+}
+
+OSStatus AudioDeviceStart(AudioObjectID inDevice, AudioDeviceIOProcID inProcID)
+{
+ AudioHardwareImpl* obj = GetObject(inDevice);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->start(inProcID, nullptr, 0);
+}
+
+OSStatus AudioDeviceStartAtTime(AudioObjectID inDevice, AudioDeviceIOProcID inProcID,
+ AudioTimeStamp* ioRequestedStartTime, UInt32 inFlags)
+{
+ AudioHardwareImpl* obj = GetObject(inDevice);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->start(inProcID, ioRequestedStartTime, inFlags);
+}
+
+OSStatus AudioDeviceStop(AudioObjectID inDevice, AudioDeviceIOProcID inProcID)
+{
+ AudioHardwareImpl* obj = GetObject(inDevice);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->stop(inProcID);
+}
+
+OSStatus AudioDeviceGetCurrentTime(AudioObjectID inDevice, AudioTimeStamp* outTime)
+{
+ AudioHardwareImpl* obj = GetObject(inDevice);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->getCurrentTime(outTime);
+}
+
+OSStatus AudioDeviceTranslateTime(AudioObjectID inDevice, const AudioTimeStamp* inTime,
+ AudioTimeStamp* outTime)
+{
+ AudioHardwareImpl* obj = GetObject(inDevice);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->translateTime(inTime, outTime);
+}
+
+OSStatus AudioDeviceGetNearestStartTime(AudioObjectID inDevice,
+ AudioTimeStamp* ioRequestedStartTime, UInt32 inFlags)
+{
+ AudioHardwareImpl* obj = GetObject(inDevice);
+ if (!obj)
+ return kAudioHardwareBadObjectError;
+
+ return obj->getNearestStartTime(ioRequestedStartTime, inFlags);
+}
diff --git a/src/CoreAudio/AudioHardwareBase.h b/src/CoreAudio/AudioHardwareBase.h
index 28492f6ed..cba62a3f9 100644
--- a/src/CoreAudio/AudioHardwareBase.h
+++ b/src/CoreAudio/AudioHardwareBase.h
@@ -20,6 +20,50 @@ struct AudioObjectPropertyAddress
AudioObjectPropertyElement mElement;
};
+enum
+{
+ kAudioHardwareNoError = 0,
+ kAudioHardwareNotRunningError = 'stop',
+ kAudioHardwareUnspecifiedError = 'what',
+ kAudioHardwareUnknownPropertyError = 'who?',
+ kAudioHardwareBadPropertySizeError = '!siz',
+ kAudioHardwareIllegalOperationError = 'nope',
+ kAudioHardwareBadObjectError = '!obj',
+ kAudioHardwareBadDeviceError = '!dev',
+ kAudioHardwareBadStreamError = '!str',
+ kAudioHardwareUnsupportedOperationError = 'unop',
+ kAudioDeviceUnsupportedFormatError = '!dat',
+ kAudioDevicePermissionsError = '!hog',
+};
+
+enum
+{
+ kAudioObjectPropertyScopeGlobal = 'glob',
+ kAudioObjectPropertyScopeInput = 'inpt',
+ kAudioObjectPropertyScopeOutput = 'outp',
+ kAudioObjectPropertyScopePlayThrough = 'ptru',
+ kAudioObjectPropertyElementMaster = 0,
+};
+
+enum
+{
+ kAudioObjectPropertyBaseClass = 'bcls',
+ kAudioObjectPropertyClass = 'clas',
+ kAudioObjectPropertyOwner = 'stdv',
+ kAudioObjectPropertyName = 'lnam',
+ kAudioObjectPropertyModelName = 'lmod',
+ kAudioObjectPropertyManufacturer = 'lmak',
+ kAudioObjectPropertyElementName = 'lchn',
+ kAudioObjectPropertyElementCategoryName = 'lccn',
+ kAudioObjectPropertyElementNumberName = 'lcnn',
+ kAudioObjectPropertyOwnedObjects = 'ownd',
+ kAudioObjectPropertyIdentify = 'iden',
+ kAudioObjectPropertySerialNumber = 'snum',
+ kAudioObjectPropertyFirmwareVersion = 'fwvn',
+};
+
+// TODO: A lot more is missing
+
#ifdef __cplusplus
}
#endif
diff --git a/src/CoreAudio/AudioHardwareImpl.cpp b/src/CoreAudio/AudioHardwareImpl.cpp
new file mode 100644
index 000000000..0960211d0
--- /dev/null
+++ b/src/CoreAudio/AudioHardwareImpl.cpp
@@ -0,0 +1,88 @@
+/*
+This file is part of Darling.
+
+Copyright (C) 2015-2016 Lubos Dolezel
+
+Darling is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Darling is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Darling. If not, see .
+*/
+
+#include "AudioHardwareImpl.h"
+#include
+#include
+
+AudioHardwareImpl::AudioHardwareImpl()
+{
+}
+
+
+AudioHardwareImpl::~AudioHardwareImpl()
+{
+}
+
+void AudioHardwareImpl::show()
+{
+ std::cout << typeid(*this).name() << std::endl;
+}
+
+OSStatus AudioHardwareImpl::createIOProcID(AudioDeviceIOProc inProc, void* inClientData,
+ AudioDeviceIOProcID* outIOProcID)
+{
+ std::lock_guard guard(m_procMutex);
+
+ if (!outIOProcID || !inProc)
+ return paramErr;
+
+ *outIOProcID = reinterpret_cast(m_nextProcId++);
+ m_proc[*outIOProcID] = std::pair(inProc, inClientData);
+
+ return noErr;
+}
+
+OSStatus AudioHardwareImpl::destroyIOProcID(AudioDeviceIOProcID inIOProcID)
+{
+ std::lock_guard guard(m_procMutex);
+ auto it = m_proc.find(inIOProcID);
+
+ if (it == m_proc.end())
+ return paramErr;
+
+ m_proc.erase(it);
+ return noErr;
+}
+
+OSStatus AudioHardwareImpl::start(AudioDeviceIOProcID inProcID,
+ AudioTimeStamp* ioRequestedStartTime, UInt32 inFlags)
+{
+ AudioHardwareStream* stream;
+
+ if (m_streams.find(inProcID) != m_streams.end())
+ return noErr;
+
+ stream = createStream(inProcID);
+ m_streams[inProcID] = stream;
+
+ // TODO: time
+
+ return stream;
+}
+
+OSStatus AudioHardwareImpl::stop(AudioDeviceIOProcID inProcID)
+{
+ auto it = m_streams.find(inProcID);
+ if (it == m_streams.end())
+ return kAudioHardwareNotRunningError;
+
+ m_streams.erase(it);
+ return noErr;
+}
diff --git a/src/CoreAudio/AudioHardwareImpl.h b/src/CoreAudio/AudioHardwareImpl.h
new file mode 100644
index 000000000..47a4cde6d
--- /dev/null
+++ b/src/CoreAudio/AudioHardwareImpl.h
@@ -0,0 +1,78 @@
+/*
+This file is part of Darling.
+
+Copyright (C) 2015-2016 Lubos Dolezel
+
+Darling is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Darling is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Darling. If not, see .
+*/
+
+#ifndef AUDIOHARDWAREIMPL_H
+#define AUDIOHARDWAREIMPL_H
+#include
+#include