/*
This file is part of Magnum .
Copyright © 2010 , 2011 , 2012 , 2013 , 2014 , 2015 , 2016 , 2017 , 2018 , 2019
Vladimír Vondruš < mosra @ centrum . cz >
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 <Corrade/Containers/Array.h>
# include <Corrade/Containers/Optional.h>
# include <Corrade/Utility/Assert.h>
# include <Corrade/Utility/Directory.h>
# include "Magnum/FileCallback.h"
# ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
# include "Magnum/Audio/configure.h"
# endif
namespace Magnum { namespace Audio {
std : : string AbstractImporter : : pluginInterface ( ) {
return " cz.mosra.magnum.Audio.AbstractImporter/0.2 " ;
}
# ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
std : : vector < std : : string > AbstractImporter : : pluginSearchPaths ( ) {
return {
# ifdef CORRADE_IS_DEBUG_BUILD
" magnum-d/audioimporters " ,
Utility : : Directory : : join ( MAGNUM_PLUGINS_DEBUG_DIR , " audioimporters " )
# else
" magnum/audioimporters " ,
Utility : : Directory : : join ( MAGNUM_PLUGINS_DIR , " audioimporters " )
# endif
} ;
}
# endif
AbstractImporter : : AbstractImporter ( ) = default ;
AbstractImporter : : AbstractImporter ( PluginManager : : Manager < AbstractImporter > & manager ) : PluginManager : : AbstractManagingPlugin < AbstractImporter > { manager } { }
AbstractImporter : : AbstractImporter ( PluginManager : : AbstractManager & manager , const std : : string & plugin ) : PluginManager : : AbstractManagingPlugin < AbstractImporter > { manager , plugin } { }
void AbstractImporter : : setFileCallback ( Containers : : Optional < Containers : : ArrayView < const char > > ( * callback ) ( const std : : string & , InputFileCallbackPolicy , void * ) , void * const userData ) {
CORRADE_ASSERT ( ! isOpened ( ) , " Audio::AbstractImporter::setFileCallback(): can't be set while a file is opened " , ) ;
CORRADE_ASSERT ( features ( ) & Feature : : OpenData , " Audio::AbstractImporter::setFileCallback(): importer doesn't support loading from data, callbacks can't be used " , ) ;
_fileCallback = callback ;
_fileCallbackUserData = userData ;
doSetFileCallback ( callback , userData ) ;
}
void AbstractImporter : : doSetFileCallback ( Containers : : Optional < Containers : : ArrayView < const char > > ( * ) ( const std : : string & , InputFileCallbackPolicy , void * ) , void * ) { }
bool AbstractImporter : : openData ( Containers : : ArrayView < const char > data ) {
CORRADE_ASSERT ( features ( ) & Feature : : OpenData ,
" Audio::AbstractImporter::openData(): feature not supported " , { } ) ;
/* We accept empty data here (instead of checking for them and failing so
the check doesn ' t be done on the plugin side ) because for some file
formats it could be valid . */
close ( ) ;
doOpenData ( data ) ;
return isOpened ( ) ;
}
void AbstractImporter : : doOpenData ( Containers : : ArrayView < const char > ) {
CORRADE_ASSERT ( false , " Audio::AbstractImporter::openData(): feature advertised but not implemented " , ) ;
}
bool AbstractImporter : : openFile ( const std : : string & filename ) {
close ( ) ;
/* If file loading callbacks are not set or the importer supports handling
them directly , call into the implementation */
if ( ! _fileCallback | | ( doFeatures ( ) & Feature : : FileCallback ) ) {
doOpenFile ( filename ) ;
/* Otherwise, if loading from data is supported, use the callback and pass
the data through to openData ( ) . Mark the file as ready to be closed once
opening is finished . */
} else if ( doFeatures ( ) & Feature : : OpenData ) {
/* This needs to be duplicated here and in the doOpenFile()
implementation in order to support both following cases :
- plugins that don ' t support FileCallback but have their own
doOpenFile ( ) implementation ( callback needs to be used here ,
because the base doOpenFile ( ) implementation might never get
called )
- plugins that support FileCallback but want to delegate the actual
file loading to the default implementation ( callback used in the
base doOpenFile ( ) implementation , because this branch is never
taken in that case ) */
const Containers : : Optional < Containers : : ArrayView < const char > > data = _fileCallback ( filename , InputFileCallbackPolicy : : LoadTemporary , _fileCallbackUserData ) ;
if ( ! data ) {
Error ( ) < < " Audio::AbstractImporter::openFile(): cannot open file " < < filename ;
return isOpened ( ) ;
}
doOpenData ( * data ) ;
_fileCallback ( filename , InputFileCallbackPolicy : : Close , _fileCallbackUserData ) ;
/* Shouldn't get here, the assert is fired already in setFileCallback() */
} else CORRADE_ASSERT_UNREACHABLE ( ) ; /* LCOV_EXCL_LINE */
return isOpened ( ) ;
}
void AbstractImporter : : doOpenFile ( const std : : string & filename ) {
CORRADE_ASSERT ( features ( ) & Feature : : OpenData , " Audio::AbstractImporter::openFile(): not implemented " , ) ;
/* If callbacks are set, use them. This is the same implementation as in
openFile ( ) , see the comment there for details . */
if ( _fileCallback ) {
const Containers : : Optional < Containers : : ArrayView < const char > > data = _fileCallback ( filename , InputFileCallbackPolicy : : LoadTemporary , _fileCallbackUserData ) ;
if ( ! data ) {
Error ( ) < < " Audio::AbstractImporter::openFile(): cannot open file " < < filename ;
return ;
}
doOpenData ( * data ) ;
_fileCallback ( filename , InputFileCallbackPolicy : : Close , _fileCallbackUserData ) ;
/* Otherwise open the file directly */
} else {
if ( ! Utility : : Directory : : exists ( filename ) ) {
Error ( ) < < " Audio::AbstractImporter::openFile(): cannot open file " < < filename ;
return ;
}
doOpenData ( Utility : : Directory : : read ( filename ) ) ;
}
}
void AbstractImporter : : close ( ) {
if ( isOpened ( ) ) {
doClose ( ) ;
CORRADE_INTERNAL_ASSERT ( ! isOpened ( ) ) ;
}
}
BufferFormat 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 < char > AbstractImporter : : data ( ) {
CORRADE_ASSERT ( isOpened ( ) , " Audio::AbstractImporter::data(): no file opened " , nullptr ) ;
return doData ( ) ;
}
} }