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