diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 0be6ab1b0..060f80595 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -15,6 +15,7 @@ # MAGNUM_PLUGINS_FONTCONVERTER_DIR - Directory with font converter plugins # MAGNUM_PLUGINS_IMAGECONVERTER_DIR - Directory with image converter plugins # MAGNUM_PLUGINS_IMPORTER_DIR - Directory with importer plugins +# MAGNUM_PLUGINS_AUDIOIMPORTER_DIR - Directory with audio importer plugins # This command will try to find only the base library, not the optional # components. The base library depends on Corrade, OpenGL and GLEW # libraries. Additional dependencies are specified by the components. The @@ -75,6 +76,8 @@ # installation directory # MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR - Importer plugin installation # directory +# MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR - Audio omporter plugin +# installation directory # MAGNUM_CMAKE_MODULE_INSTALL_DIR - Installation dir for CMake # modules # MAGNUM_INCLUDE_INSTALL_DIR - Header installation directory @@ -343,6 +346,7 @@ set(MAGNUM_PLUGINS_FONT_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/fonts) set(MAGNUM_PLUGINS_FONTCONVERTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/fontconverters) set(MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/imageconverters) set(MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/audioimporters) set(MAGNUM_CMAKE_MODULE_INSTALL_DIR ${CMAKE_ROOT}/Modules) set(MAGNUM_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/Magnum) set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/Magnum/Plugins) @@ -355,6 +359,7 @@ mark_as_advanced(FORCE MAGNUM_PLUGINS_FONTCONVERTER_INSTALL_DIR MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR + MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR MAGNUM_CMAKE_MODULE_INSTALL_DIR MAGNUM_INCLUDE_INSTALL_DIR MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR) @@ -367,3 +372,4 @@ set(MAGNUM_PLUGINS_FONT_DIR ${MAGNUM_PLUGINS_DIR}/fonts) set(MAGNUM_PLUGINS_FONTCONVERTER_DIR ${MAGNUM_PLUGINS_DIR}/fontconverters) set(MAGNUM_PLUGINS_IMAGECONVERTER_DIR ${MAGNUM_PLUGINS_DIR}/imageconverters) set(MAGNUM_PLUGINS_IMPORTER_DIR ${MAGNUM_PLUGINS_DIR}/importers) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_DIR ${MAGNUM_PLUGINS_DIR}/audioimporters) diff --git a/src/Audio/AbstractImporter.cpp b/src/Audio/AbstractImporter.cpp new file mode 100644 index 000000000..2e0ced0e3 --- /dev/null +++ b/src/Audio/AbstractImporter.cpp @@ -0,0 +1,97 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír VondruÅ¡ + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "AbstractImporter.h" + +#include +#include +#include + +namespace Magnum { namespace Audio { + +AbstractImporter::AbstractImporter() = default; + +AbstractImporter::AbstractImporter(PluginManager::AbstractManager* manager, std::string plugin): PluginManager::AbstractPlugin(manager, std::move(plugin)) {} + +bool AbstractImporter::openData(Containers::ArrayReference data) { + CORRADE_ASSERT(features() & Feature::OpenData, + "Audio::AbstractImporter::openData(): feature not supported", nullptr); + + close(); + doOpenData(data); + return isOpened(); +} + +void AbstractImporter::doOpenData(Containers::ArrayReference) { + CORRADE_ASSERT(false, "Audio::AbstractImporter::openData(): feature advertised but not implemented", ); +} + +bool AbstractImporter::openFile(const std::string& filename) { + close(); + doOpenFile(filename); + return isOpened(); +} + +void AbstractImporter::doOpenFile(const std::string& filename) { + CORRADE_ASSERT(features() & Feature::OpenData, "Audio::AbstractImporter::openFile(): not implemented", ); + + /* Open file */ + std::ifstream in(filename.data(), std::ios::binary); + if(!in.good()) { + Error() << "Trade::AbstractImporter::openFile(): cannot open file" << filename; + return; + } + + /* Create array to hold file contents */ + in.seekg(0, std::ios::end); + Containers::Array data(in.tellg()); + + /* Read data, close */ + in.seekg(0, std::ios::beg); + in.read(reinterpret_cast(data.begin()), data.size()); + in.close(); + + doOpenData(data); +} + +void AbstractImporter::close() { + if(isOpened()) doClose(); +} + +Buffer::Format AbstractImporter::format() const { + CORRADE_ASSERT(isOpened(), "Audio::AbstractImporter::format(): no file opened", {}); + return doFormat(); +} + +UnsignedInt AbstractImporter::frequency() const { + CORRADE_ASSERT(isOpened(), "Audio::AbstractImporter::frequency(): no file opened", {}); + return doFrequency(); +} + +Containers::Array AbstractImporter::data() { + CORRADE_ASSERT(isOpened(), "Audio::AbstractImporter::data(): no file opened", {}); + return doData(); +} + +}} diff --git a/src/Audio/AbstractImporter.h b/src/Audio/AbstractImporter.h new file mode 100644 index 000000000..9e49fc8bf --- /dev/null +++ b/src/Audio/AbstractImporter.h @@ -0,0 +1,163 @@ +#ifndef Magnum_Audio_AbstractImporter_h +#define Magnum_Audio_AbstractImporter_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír VondruÅ¡ + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file Audio/AbstractImporter.h + * @brief Class Magnum::Audio::AbstractImporter + */ + +#include + +#include "Magnum.h" +#include "Audio/Buffer.h" + +namespace Magnum { namespace Audio { + +/** +@brief Base for audio importer plugins + +@section Audio-AbstractImporter-subclassing Subclassing + +Plugin implements function doFeatures(), doIsOpened(), one of or both +doOpenData() and doOpenFile() functions, function doClose() and data access +functions doFormat(), doFrequency() and doData(). + +You don't need to do most of the redundant sanity checks, these things are +checked by the implementation: + +- Functions doOpenData() and doOpenFile() are called after the previous file + was closed, function doClose() is called only if there is any file opened. +- Function doOpenData() is called only if @ref Feature "Feature::OpenData" + is supported. +- All `do*()` implementations working on opened file are called only if + there is any file opened. +*/ +class MAGNUM_AUDIO_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { + CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Audio.AbstractImporter/0.1") + + public: + /** + * @brief Features supported by this importer + * + * @see Features, features() + */ + enum class Feature: UnsignedByte { + /** Opening files from raw data using openData() */ + OpenData = 1 << 0 + }; + + /** + * @brief Features supported by this importer + * + * @see features() + */ + typedef Containers::EnumSet Features; + + /** @brief Default constructor */ + explicit AbstractImporter(); + + /** @brief Plugin manager constructor */ + explicit AbstractImporter(PluginManager::AbstractManager* manager, std::string plugin); + + /** @brief Features supported by this importer */ + Features features() const { return doFeatures(); } + + /** @brief Whether any file is opened */ + bool isOpened() const { return doIsOpened(); } + + /** + * @brief Open raw data + * + * Closes previous file, if it was opened, and tries to open given + * file. Available only if @ref Feature "Feature::OpenData" is + * supported. Returns `true` on success, `false` otherwise. + * @see features(), openFile() + */ + bool openData(Containers::ArrayReference data); + + /** + * @brief Open file + * + * Closes previous file, if it was opened, and tries to open given + * file. Returns `true` on success, `false` otherwise. + * @see features(), openData() + */ + bool openFile(const std::string& filename); + + /** @brief Close file */ + void close(); + + /** @{ @name Data access */ + + /** @brief Sample format */ + Buffer::Format format() const; + + /** @brief Sample frequency */ + UnsignedInt frequency() const; + + /** @brief Sample data */ + Containers::Array data(); + + /*@}*/ + + #ifndef DOXYGEN_GENERATING_OUTPUT + private: + #else + protected: + #endif + /** @brief Implementation for features() */ + virtual Features doFeatures() const = 0; + + /** @brief Implementation for isOpened() */ + virtual bool doIsOpened() const = 0; + + /** @brief Implementation for openData() */ + virtual void doOpenData(Containers::ArrayReference data); + + /** + * @brief Implementation for openFile() + * + * If @ref Feature "Feature::OpenData" is supported, default + * implementation opens the file and calls doOpenData() with its + * contents. + */ + virtual void doOpenFile(const std::string& filename); + + /** @brief Implementation for close() */ + virtual void doClose() = 0; + + /** @brief Implementation for format() */ + virtual Buffer::Format doFormat() const = 0; + + /** @brief Implementation for frequency() */ + virtual UnsignedInt doFrequency() const = 0; + + /** @brief Implementation for data() */ + virtual Containers::Array doData() = 0; +}; + +}} + +#endif diff --git a/src/Audio/Audio.h b/src/Audio/Audio.h index 5fc044cd0..fb332b3c4 100644 --- a/src/Audio/Audio.h +++ b/src/Audio/Audio.h @@ -30,6 +30,7 @@ namespace Magnum { namespace Audio { +class AbstractImporter; class Buffer; class Source; /* Renderer used only statically */ diff --git a/src/Audio/CMakeLists.txt b/src/Audio/CMakeLists.txt index eeafc6e22..ee770a512 100644 --- a/src/Audio/CMakeLists.txt +++ b/src/Audio/CMakeLists.txt @@ -27,12 +27,14 @@ find_package(OpenAL REQUIRED) include_directories(${OPENAL_INCLUDE_DIR}) set(MagnumAudio_SOURCES + AbstractImporter.cpp Audio.cpp Buffer.cpp Renderer.cpp Source.cpp) set(MagnumAudio_HEADERS + AbstractImporter.h Audio.h Buffer.h Renderer.h @@ -41,7 +43,7 @@ set(MagnumAudio_HEADERS magnumAudioVisibility.h) add_library(MagnumAudio ${SHARED_OR_STATIC} ${MagnumAudio_SOURCES}) -target_link_libraries(MagnumAudio ${OPENAL_LIBRARY}) +target_link_libraries(MagnumAudio ${CORRADE_PLUGINMANAGER_LIBRARIES} ${OPENAL_LIBRARY}) install(TARGETS MagnumAudio DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) install(FILES ${MagnumAudio_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Audio) diff --git a/src/Audio/Test/AbstractImporterTest.cpp b/src/Audio/Test/AbstractImporterTest.cpp new file mode 100644 index 000000000..ff479d654 --- /dev/null +++ b/src/Audio/Test/AbstractImporterTest.cpp @@ -0,0 +1,76 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír VondruÅ¡ + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include + +#include "Audio/AbstractImporter.h" + +#include "testConfigure.h" + +namespace Magnum { namespace Audio { namespace Test { + +class AbstractImporterTest: public TestSuite::Tester { + public: + explicit AbstractImporterTest(); + + void openFile(); +}; + +AbstractImporterTest::AbstractImporterTest() { + addTests({&AbstractImporterTest::openFile}); +} + +void AbstractImporterTest::openFile() { + class DataImporter: public Audio::AbstractImporter { + public: + explicit DataImporter(): opened(false) {} + + private: + Features doFeatures() const override { return Feature::OpenData; } + bool doIsOpened() const override { return opened; } + void doClose() override {} + + void doOpenData(Containers::ArrayReference data) override { + opened = (data.size() == 1 && data[0] == 0xa5); + } + + Buffer::Format doFormat() const override { return {}; } + UnsignedInt doFrequency() const override { return {}; } + Corrade::Containers::Array doData() override { return nullptr; } + + bool opened; + }; + + /* doOpenFile() should call doOpenData() */ + DataImporter importer; + CORRADE_VERIFY(!importer.isOpened()); + importer.openFile(Utility::Directory::join(AUDIO_TEST_DIR, "file.bin")); + CORRADE_VERIFY(importer.isOpened()); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Audio::Test::AbstractImporterTest) diff --git a/src/Audio/Test/CMakeLists.txt b/src/Audio/Test/CMakeLists.txt index c53624b53..3a42d1f27 100644 --- a/src/Audio/Test/CMakeLists.txt +++ b/src/Audio/Test/CMakeLists.txt @@ -22,6 +22,12 @@ # DEALINGS IN THE SOFTWARE. # +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testConfigure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/testConfigure.h) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +corrade_add_test(AudioAbstractImporterTest AbstractImporterTest.cpp LIBRARIES MagnumAudio) corrade_add_test(AudioBufferTest BufferTest.cpp LIBRARIES MagnumAudio) corrade_add_test(AudioRendererTest RendererTest.cpp LIBRARIES MagnumAudio) corrade_add_test(AudioSourceTest SourceTest.cpp LIBRARIES MagnumAudio) diff --git a/src/Audio/Test/file.bin b/src/Audio/Test/file.bin new file mode 100644 index 000000000..dd6737691 --- /dev/null +++ b/src/Audio/Test/file.bin @@ -0,0 +1 @@ +¥ \ No newline at end of file diff --git a/src/Audio/Test/testConfigure.h.cmake b/src/Audio/Test/testConfigure.h.cmake new file mode 100644 index 000000000..29272db06 --- /dev/null +++ b/src/Audio/Test/testConfigure.h.cmake @@ -0,0 +1,25 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír VondruÅ¡ + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#define AUDIO_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}"