diff --git a/src/CoreAudio/AFAVFormatComponent/AVFormatFileObject.cpp b/src/CoreAudio/AFAVFormatComponent/AVFormatFileObject.cpp
new file mode 100644
index 000000000..043c4069f
--- /dev/null
+++ b/src/CoreAudio/AFAVFormatComponent/AVFormatFileObject.cpp
@@ -0,0 +1,94 @@
+/*
+This file is part of Darling.
+
+Copyright (C) 2020 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 "AVFormatFileObject.h"
+#include
+#include "AudioFileFormatMP3.h"
+
+extern "C" {
+#include
+}
+
+#pragma GCC visibility push(default)
+AUDIOCOMPONENT_ENTRY(AudioFileComponentFactory, AVFormatFileObject);
+#pragma GCC visibility pop
+
+AVFormatFileObject::AVFormatFileObject(AudioComponentInstance inInstance)
+: AudioFileObjectComponentBase(inInstance)
+{
+
+}
+
+// Analyze mAudioFileObject and return an AudioFileFormat based on that
+AudioFileFormat* AVFormatFileObject::GetAudioFormat() const
+{
+ uint8_t buffer[1024 + AVPROBE_PADDING_SIZE];
+ AVProbeData probeData;
+
+ probeData.filename = "";
+ probeData.buf = buffer;
+ probeData.buf_size = 1024;
+
+ if (mAudioFileObject->ReadBytes(false, 0, (UInt32*)&probeData.buf_size, probeData.buf) != noErr)
+ return nullptr;
+
+ AVInputFormat* fmt = av_probe_input_format(&probeData, true);
+ if (!fmt)
+ return nullptr;
+
+ std::istringstream ss(fmt->name);
+ std::string formatName;
+
+ while (std::getline(ss, formatName, ','))
+ {
+ if (formatName == "aac") // Raw AAC
+ {
+
+ }
+ else if (formatName == "ac3")
+ {
+
+ }
+ else if (formatName == "aiff")
+ {
+
+ }
+ else if (formatName == "caff")
+ {
+
+ }
+ else if (formatName == "mp3")
+ {
+ return AudioFileFormatMP3::instance();
+ }
+ else if (formatName == "mov" || formatName == "mp4")
+ {
+
+ }
+ else if (formatName == "au")
+ {
+
+ }
+ else if (formatName == "wav")
+ {
+
+ }
+ }
+
+ return nullptr;
+}
diff --git a/src/CoreAudio/AFAVFormatComponent/AVFormatFileObject.h b/src/CoreAudio/AFAVFormatComponent/AVFormatFileObject.h
new file mode 100644
index 000000000..2c3255d23
--- /dev/null
+++ b/src/CoreAudio/AFAVFormatComponent/AVFormatFileObject.h
@@ -0,0 +1,31 @@
+/*
+This file is part of Darling.
+
+Copyright (C) 2020 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 _AV_FORMAT_FILE_OBJECT_H
+#define _AV_FORMAT_FILE_OBJECT_H
+#include "AudioFileComponentBase.h"
+
+class AVFormatFileObject : public AudioFileObjectComponentBase
+{
+public:
+ AVFormatFileObject(AudioComponentInstance inInstance);
+ AudioFileFormat* GetAudioFormat() const override;
+};
+
+#endif
diff --git a/src/CoreAudio/AFAVFormatComponent/AudioFileFormatGeneric.cpp b/src/CoreAudio/AFAVFormatComponent/AudioFileFormatGeneric.cpp
new file mode 100644
index 000000000..46c3a88c2
--- /dev/null
+++ b/src/CoreAudio/AFAVFormatComponent/AudioFileFormatGeneric.cpp
@@ -0,0 +1,118 @@
+/*
+This file is part of Darling.
+
+Copyright (C) 2020 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 "AudioFileFormatGeneric.h"
+#include
+#include
+
+extern "C" {
+#include
+}
+
+AudioFileFormatGeneric::AudioFileFormatGeneric(UInt32 inFileType, const char* avformatShortName)
+: AudioFileFormat(inFileType), m_avformatShortName(avformatShortName)
+{
+}
+
+Boolean AudioFileFormatGeneric::ExtensionIsThisFormat(CFStringRef inExtension)
+{
+ const char* inStr = CFStringGetCStringPtr(inExtension, kCFStringEncodingUTF8);
+ const Description& desc = description();
+
+ for (const char* ext : desc.extensions)
+ {
+ if (::strcasecmp(ext, inStr) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+void AudioFileFormatGeneric::GetExtensions(CFArrayRef *outArray)
+{
+ *outArray = toCFArray(description().extensions);
+}
+
+CFArrayRef AudioFileFormatGeneric::toCFArray(const std::vector& array)
+{
+ std::vector strings;
+ strings.reserve(array.size());
+
+ for (const char* str : array)
+ strings.push_back(CFStringCreateWithCString(nullptr, str, kCFStringEncodingUTF8));
+
+ CFArrayRef rv = CFArrayCreate(nullptr, (const void**) strings.data(), array.size(), &kCFTypeArrayCallBacks);
+
+ for (CFStringRef str : strings)
+ CFRelease(str);
+
+ return rv;
+}
+
+void AudioFileFormatGeneric::GetUTIs(CFArrayRef *outArray)
+{
+ *outArray = toCFArray(description().utis);
+}
+
+void AudioFileFormatGeneric::GetMIMETypes(CFArrayRef *outArray)
+{
+ *outArray = toCFArray(description().mimeTypes);
+}
+
+void AudioFileFormatGeneric::GetFileTypeName(CFStringRef *outName)
+{
+ *outName = CFStringCreateWithCString(nullptr, description().name, kCFStringEncodingUTF8);
+}
+
+UncertainResult AudioFileFormatGeneric::FileDataIsThisFormat(UInt32 inDataByteSize, const void* inData)
+{
+ AVInputFormat* fmt = av_find_input_format(m_avformatShortName);
+ if (!fmt)
+ return false;
+
+ std::vector buf;
+ AVProbeData probeData;
+
+ buf.reserve(inDataByteSize + AVPROBE_PADDING_SIZE);
+ buf.insert(buf.end(), static_cast(inData), static_cast(inData) + inDataByteSize);
+ buf.resize(inDataByteSize + AVPROBE_PADDING_SIZE);
+
+ probeData.filename = "";
+ probeData.buf = buf.data();
+ probeData.buf_size = inDataByteSize;
+
+ return fmt->read_probe(&probeData) ? kTrue : kFalse;
+}
+
+AudioFileObject* AudioFileFormatGeneric::New()
+{
+ // TODO
+ return nullptr;
+}
+
+OSStatus AudioFileFormatGeneric::GetAvailableFormatIDs(UInt32* ioDataSize, void* outPropertyData)
+{
+ // TODO
+ return unimpErr;
+}
+
+OSStatus AudioFileFormatGeneric::GetAvailableStreamDescriptions(UInt32 inFormatID, UInt32* ioDataSize, void* outPropertyData)
+{
+ // TODO
+ return unimpErr;
+}
diff --git a/src/CoreAudio/AFAVFormatComponent/AudioFileFormatGeneric.h b/src/CoreAudio/AFAVFormatComponent/AudioFileFormatGeneric.h
new file mode 100644
index 000000000..1dee095e8
--- /dev/null
+++ b/src/CoreAudio/AFAVFormatComponent/AudioFileFormatGeneric.h
@@ -0,0 +1,55 @@
+/*
+This file is part of Darling.
+
+Copyright (C) 2020 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 _AUDIO_FILE_FORMAT_GENERIC_H
+#define _AUDIO_FILE_FORMAT_GENERIC_H
+#include "AudioFileFormat.h"
+
+class AudioFileFormatGeneric : public AudioFileFormat
+{
+public:
+ AudioFileFormatGeneric(UInt32 inFileType, const char* avformatShortName);
+ Boolean ExtensionIsThisFormat(CFStringRef inExtension) override;
+ void GetExtensions(CFArrayRef *outArray) override;
+ void GetUTIs(CFArrayRef *outArray) override;
+ void GetMIMETypes(CFArrayRef *outArray) override;
+ void GetFileTypeName(CFStringRef *outName) override;
+ UncertainResult FileDataIsThisFormat(UInt32 inDataByteSize, const void* inData) override;
+
+ AudioFileObject* New() override;
+ AudioFileStreamObject* NewStream() override { return NULL; }
+ OSStatus GetAvailableFormatIDs(UInt32* ioDataSize, void* outPropertyData) override;
+ OSStatus GetAvailableStreamDescriptions(UInt32 inFormatID, UInt32* ioDataSize, void* outPropertyData) override;
+private:
+ static CFArrayRef toCFArray(const std::vector& array);
+protected:
+ struct Description
+ {
+ const char* name;
+ std::vector extensions;
+ std::vector utis;
+ std::vector mimeTypes;
+ };
+ virtual const Description& description() const = 0;
+private:
+ const char* m_avformatShortName;
+};
+
+#endif
+
diff --git a/src/CoreAudio/AFAVFormatComponent/AudioFileFormatMP3.cpp b/src/CoreAudio/AFAVFormatComponent/AudioFileFormatMP3.cpp
new file mode 100644
index 000000000..91791c547
--- /dev/null
+++ b/src/CoreAudio/AFAVFormatComponent/AudioFileFormatMP3.cpp
@@ -0,0 +1,42 @@
+/*
+This file is part of Darling.
+
+Copyright (C) 2020 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 "AudioFileFormatMP3.h"
+
+AudioFileFormatMP3::AudioFileFormatMP3()
+: AudioFileFormatGeneric('.mp3', "mp3")
+{
+}
+
+AudioFileFormatMP3* AudioFileFormatMP3::instance()
+{
+ static AudioFileFormatMP3 inst;
+ return &inst;
+}
+
+const AudioFileFormatMP3::Description& AudioFileFormatMP3::description() const
+{
+ static const Description d = {
+ .name = "MPEG Layer 3",
+ .extensions = { "mp3" },
+ .utis = { "public.mp3", "public.audio", "public.data" },
+ .mimeTypes = { "audio/mpeg" },
+ };
+ return d;
+}
diff --git a/src/CoreAudio/AFAVFormatComponent/AudioFileFormatMP3.h b/src/CoreAudio/AFAVFormatComponent/AudioFileFormatMP3.h
new file mode 100644
index 000000000..3767ef4ae
--- /dev/null
+++ b/src/CoreAudio/AFAVFormatComponent/AudioFileFormatMP3.h
@@ -0,0 +1,35 @@
+/*
+This file is part of Darling.
+
+Copyright (C) 2020 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 _AUDIO_FILE_FORMAT_MP3_H
+#define _AUDIO_FILE_FORMAT_MP3_H
+#include "AudioFileFormatGeneric.h"
+
+class AudioFileFormatMP3 : public AudioFileFormatGeneric
+{
+private:
+ AudioFileFormatMP3();
+public:
+ static AudioFileFormatMP3* instance();
+protected:
+ const Description& description() const override;
+};
+
+#endif
+
diff --git a/src/CoreAudio/AFAVFormatComponent/CMakeLists.txt b/src/CoreAudio/AFAVFormatComponent/CMakeLists.txt
index 3ef6d4c82..607397df3 100644
--- a/src/CoreAudio/AFAVFormatComponent/CMakeLists.txt
+++ b/src/CoreAudio/AFAVFormatComponent/CMakeLists.txt
@@ -17,6 +17,9 @@ set(component_sources
AFPublic/DataSource.cpp
AUPublic/AUBase/ComponentBase.cpp
PublicUtility/CACFDictionary.cpp
+ AVFormatFileObject.cpp
+ AudioFileFormatGeneric.cpp
+ AudioFileFormatMP3.cpp
)
add_darling_bundle(AFAVFormatComponent "" ${component_sources})
diff --git a/src/CoreAudio/AFAVFormatComponent/README b/src/CoreAudio/AFAVFormatComponent/README
new file mode 100644
index 000000000..ba21c7056
--- /dev/null
+++ b/src/CoreAudio/AFAVFormatComponent/README
@@ -0,0 +1,6 @@
+This is a file format component built on top of AVFormat.
+
+The area of macOS surrounding AudioFileComponents is very badly documented, especially with regard to where this component belongs etc.
+This project may serve as an example: https://sourceforge.net/projects/coreaudio-flac/
+
+The goal is to support formats specified here: https://developer.apple.com/library/archive/documentation/MusicAudio/Conceptual/CoreAudioOverview/SupportedAudioFormatsMacOSX/SupportedAudioFormatsMacOSX.html