From: <man...@us...> - 2014-10-22 10:36:13
|
Revision: 4461 http://sourceforge.net/p/modplug/code/4461 Author: manxorist Date: 2014-10-22 10:36:01 +0000 (Wed, 22 Oct 2014) Log Message: ----------- [Imp] Add ComponentManager that handles loading of all optional OpenMPT components in a generic way. When introducing mpt::Library, most external libraries had been converted to be loaded (and unloaded) on demand for each and every use. This is inefficient, especially for browsing a folder containing mp3 samples. Now, each component class inherits from IComponent (or a subclass thereof). Each component can contain multiple mpt::Library-s. Additionally, each component defines MPT_REGISTERED_COMPONENT(ComponentImplClass) in a cpp file, which globally registers the component in a list of components that the ComponentManager knows about and initializes when starting up. The list is built pre-main(). Two settings affect the behaviour of ComponentManager: [Components]LoadOnStartup (default false) and [Components]KeepLoaded (default true). Setting both to false results in the same behaviour in respect to loading components as before this commit. Additionally, each individual component can be blocked completely from being loaded (which restores the functionalty of being able to block MP3 ACM codecs). For libopenmpt builds, the ComponentManager is not included because libopenmpt is not allowed to contain global state. The interface for accessing components (required for unmo3), however, is the same. A component is accessed via MPT_SHARED_PTR<ComponentImplClass> comp = MPT_GET_COMPONENT(ComponentImplClass); if(IsComponentAvailable(comp)) { dostuff(); }. If the component had not been preloaded before reaching MPT_GET_COMPONENT, it gets loaded right there (which is always the behaviour for libopenmpt). [Ref] Convert from mpt::Library to IComponent for the following optional components: SoundTouch, Lame, Blade, MP3 ACM, Vorbis, Opus, UXTheme, MPG123, UnMO3. [Ref] Convert uxtheme.dll to be delay loaded. [Mod] OpenMPT: Version is now 1.24.00.13 Modified Paths: -------------- trunk/OpenMPT/build/android_ndk/Android.mk trunk/OpenMPT/build/autotools/Makefile.am trunk/OpenMPT/build/vs2008/libopenmpt/libopenmpt.vcproj trunk/OpenMPT/common/versionNumber.h trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/MPTrackLink.cpp trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/Mptrack.h trunk/OpenMPT/mptrack/StreamEncoderMP3.cpp trunk/OpenMPT/mptrack/StreamEncoderMP3.h trunk/OpenMPT/mptrack/StreamEncoderOpus.cpp trunk/OpenMPT/mptrack/StreamEncoderOpus.h trunk/OpenMPT/mptrack/StreamEncoderVorbis.cpp trunk/OpenMPT/mptrack/StreamEncoderVorbis.h trunk/OpenMPT/mptrack/TrackerSettings.cpp trunk/OpenMPT/mptrack/TrackerSettings.h trunk/OpenMPT/mptrack/View_gen.cpp trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters trunk/OpenMPT/soundlib/Load_mo3.cpp trunk/OpenMPT/soundlib/SampleFormats.cpp Added Paths: ----------- trunk/OpenMPT/common/ComponentManager.cpp trunk/OpenMPT/common/ComponentManager.h Modified: trunk/OpenMPT/build/android_ndk/Android.mk =================================================================== --- trunk/OpenMPT/build/android_ndk/Android.mk 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/build/android_ndk/Android.mk 2014-10-22 10:36:01 UTC (rev 4461) @@ -15,8 +15,9 @@ LOCAL_LDLIBS := -lz LOCAL_SRC_FILES := \ + common/stdafx.cpp \ common/AudioCriticalSection.cpp \ - common/stdafx.cpp \ + common/ComponentManager.cpp \ common/Logging.cpp \ common/misc_util.cpp \ common/mptIO.cpp \ Modified: trunk/OpenMPT/build/autotools/Makefile.am =================================================================== --- trunk/OpenMPT/build/autotools/Makefile.am 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/build/autotools/Makefile.am 2014-10-22 10:36:01 UTC (rev 4461) @@ -78,6 +78,8 @@ libopenmpt_la_SOURCES += common/AudioCriticalSection.h libopenmpt_la_SOURCES += common/BuildSettings.h libopenmpt_la_SOURCES += common/CompilerDetect.h +libopenmpt_la_SOURCES += common/ComponentManager.cpp +libopenmpt_la_SOURCES += common/ComponentManager.h libopenmpt_la_SOURCES += common/Endianness.h libopenmpt_la_SOURCES += common/FlagSet.h libopenmpt_la_SOURCES += common/Logging.cpp @@ -276,6 +278,8 @@ libopenmpttest_SOURCES += common/AudioCriticalSection.h libopenmpttest_SOURCES += common/BuildSettings.h libopenmpttest_SOURCES += common/CompilerDetect.h +libopenmpttest_SOURCES += common/ComponentManager.cpp +libopenmpttest_SOURCES += common/ComponentManager.h libopenmpttest_SOURCES += common/Endianness.h libopenmpttest_SOURCES += common/FlagSet.h libopenmpttest_SOURCES += common/Logging.cpp Modified: trunk/OpenMPT/build/vs2008/libopenmpt/libopenmpt.vcproj =================================================================== --- trunk/OpenMPT/build/vs2008/libopenmpt/libopenmpt.vcproj 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/build/vs2008/libopenmpt/libopenmpt.vcproj 2014-10-22 10:36:01 UTC (rev 4461) @@ -162,6 +162,14 @@ > </File> <File + RelativePath="..\..\..\common\ComponentManager.cpp" + > + </File> + <File + RelativePath="..\..\..\common\ComponentManager.h" + > + </File> + <File RelativePath="..\..\..\common\Endianness.h" > </File> Added: trunk/OpenMPT/common/ComponentManager.cpp =================================================================== --- trunk/OpenMPT/common/ComponentManager.cpp (rev 0) +++ trunk/OpenMPT/common/ComponentManager.cpp 2014-10-22 10:36:01 UTC (rev 4461) @@ -0,0 +1,356 @@ +/* + * ComponentManager.cpp + * -------------------- + * Purpose: Manages loading of optional components. + * Notes : (currently none) + * Authors: Joern Heusipp + * OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#include "stdafx.h" +#include "ComponentManager.h" + +#include "mutex.h" + +OPENMPT_NAMESPACE_BEGIN + + +#if defined(MPT_WITH_DYNBIND) + + +ComponentBase::ComponentBase(ComponentType type, bool delayLoaded) +//---------------------------------------------------------------- + : m_Type(type) + , m_DelayLoaded(delayLoaded) + , m_Initialized(false) + , m_Available(false) + , m_BindFailed(false) +{ + return; +} + + +ComponentBase::~ComponentBase() +//----------------------------- +{ + return; +} + + +void ComponentBase::SetName(const std::string &name) +//-------------------------------------------------- +{ + m_Name = name; +} + + +void ComponentBase::SetInitialized() +//---------------------------------- +{ + m_Initialized = true; +} + + +void ComponentBase::SetAvailable() +//-------------------------------- +{ + m_Available = true; +} + + +bool ComponentBase::AddLibrary(const std::string &libName, const mpt::LibraryPath &libPath) +//----------------------------------------------------------------------------------------- +{ + if(m_Libraries[libName].IsValid()) + { + // prefer previous + return true; + } + mpt::Library lib(libPath); + if(!lib.IsValid()) + { + return false; + } + m_Libraries[libName] = lib; + return true; +} + + +void ComponentBase::ClearLibraries() +//---------------------------------- +{ + m_Libraries.clear(); +} + + +void ComponentBase::SetBindFailed() +//--------------------------------- +{ + m_BindFailed = true; +} + + +void ComponentBase::ClearBindFailed() +//----------------------------------- +{ + m_BindFailed = false; +} + + +bool ComponentBase::HasBindFailed() const +//--------------------------------------- +{ + return m_BindFailed; +} + + +std::string ComponentBase::GetName() const +//---------------------------------------- +{ + return m_Name; +} + + +ComponentType ComponentBase::GetType() const +//------------------------------------------ +{ + return m_Type; +} + + +bool ComponentBase::IsDelayLoaded() const +//--------------------------------------- +{ + return m_DelayLoaded; +} + + +bool ComponentBase::IsInitialized() const +//--------------------------------------- +{ + return m_Initialized; +} + + +bool ComponentBase::IsAvailable() const +//------------------------------------- +{ + return m_Initialized && m_Available; +} + + +mpt::ustring ComponentBase::GetVersion() const +//-------------------------------------------- +{ + return mpt::ustring(); +} + + +mpt::Library ComponentBase::GetLibrary(const std::string &libName) const +//---------------------------------------------------------------------- +{ + TLibraryMap::const_iterator it = m_Libraries.find(libName); + if(it == m_Libraries.end()) + { + return mpt::Library(); + } + return it->second; +} + + +void ComponentBase::Initialize() +//------------------------------ +{ + if(IsInitialized()) + { + return; + } + if(DoInitialize()) + { + SetAvailable(); + } + SetInitialized(); +} + + +#if MPT_COMPONENT_MANAGER + + +ComponentFactoryBase::ComponentFactoryBase(const std::string &name) +//----------------------------------------------------------------- + : m_Name(name) +{ + return; +} + + +ComponentFactoryBase::~ComponentFactoryBase() +//------------------------------------------- +{ + return; +} + + +std::string ComponentFactoryBase::GetName() const +{ + return m_Name; +} + + +MPT_SHARED_PTR<IComponent> ComponentFactoryBase::Construct() const +//---------------------------------------------------------------- +{ + MPT_SHARED_PTR<IComponent> result = DoConstruct(); + if(result) + { + result->SetName(GetName()); + } + return result; +} + + +// Global list of component register functions. +// We do not use a global scope static list head because the corresponding +// mutex would be no POD type and would thus not be safe to be usable in +// zero-initialized state. +// Function scope static initialization is guaranteed to be thread safe +// in C++11. +// We use this implementation to be future-proof. +// MSVC currently does not exploit the possibility of using multiple threads +// for global lifetime object's initialization. +// An implementation with a simple global list head and no mutex at all would +// thus work fine for MSVC (currently). + +static Util::mutex & ComponentListMutex() +//--------------------------------------- +{ + static Util::mutex g_ComponentListMutex; + return g_ComponentListMutex; +} + +static ComponentListEntry * & ComponentListHead() +//----------------------------------------------- +{ + static ComponentListEntry *g_ComponentListHead = nullptr; + return g_ComponentListHead; +} + +bool ComponentListPush(ComponentListEntry *entry) +//----------------------------------------------- +{ + Util::lock_guard<Util::mutex> guard(ComponentListMutex()); + entry->next = ComponentListHead(); + ComponentListHead() = entry; + return true; +} + + +static MPT_SHARED_PTR<ComponentManager> g_ComponentManager; + + +void ComponentManager::Init(const IComponentManagerSettings &settings) +//-------------------------------------------------------------------- +{ + // cannot use make_shared because the constructor is private + g_ComponentManager = MPT_SHARED_PTR<ComponentManager>(new ComponentManager(settings)); +} + + +void ComponentManager::Release() +//------------------------------ +{ + g_ComponentManager = MPT_SHARED_PTR<ComponentManager>(); +} + + +MPT_SHARED_PTR<ComponentManager> ComponentManager::Instance() +//----------------------------------------------------------- +{ + return g_ComponentManager; +} + + +ComponentManager::ComponentManager(const IComponentManagerSettings &settings) +//--------------------------------------------------------------------------- + : m_Settings(settings) +{ + return; +} + + +void ComponentManager::Register(const IComponentFactory &componentFactory) +//------------------------------------------------------------------------ +{ + std::string name = componentFactory.GetName(); + TComponentMap::const_iterator it = m_Components.find(name); + if(it != m_Components.end()) + { + return; + } + m_Components.insert(std::make_pair(name, componentFactory.Construct())); +} + + +void ComponentManager::InitializeComponent(MPT_SHARED_PTR<IComponent> component) const +//------------------------------------------------------------------------------------ +{ + if(!component) + { + return; + } + if(component->IsInitialized()) + { + return; + } + if(m_Settings.IsBlocked(component->GetSettingsKey())) + { + return; + } + component->Initialize(); +} + + +void ComponentManager::Startup() +//------------------------------ +{ + if(m_Settings.LoadOnStartup() || m_Settings.KeepLoaded()) + { + Util::lock_guard<Util::mutex> guard(ComponentListMutex()); + for(ComponentListEntry *entry = ComponentListHead(); entry; entry = entry->next) + { + entry->reg(this); + } + } + if(m_Settings.LoadOnStartup()) + { + for(TComponentMap::iterator it = m_Components.begin(); it != m_Components.end(); ++it) + { + InitializeComponent((*it).second); + } + } + if(!m_Settings.KeepLoaded()) + { + m_Components.clear(); + } +} + + +MPT_SHARED_PTR<IComponent> ComponentManager::GetComponent(const IComponentFactory &componentFactory) const +//-------------------------------------------------------------------------------------------------------- +{ + TComponentMap::const_iterator it = m_Components.find(componentFactory.GetName()); + MPT_SHARED_PTR<IComponent> component = (it != m_Components.end()) ? it->second : componentFactory.Construct(); + ASSERT(component); + InitializeComponent(component); + return component; +} + + +#endif // MPT_COMPONENT_MANAGER + + +#endif // MPT_WITH_DYNBIND + + +OPENMPT_NAMESPACE_END Property changes on: trunk/OpenMPT/common/ComponentManager.cpp ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/x-c++src \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: trunk/OpenMPT/common/ComponentManager.h =================================================================== --- trunk/OpenMPT/common/ComponentManager.h (rev 0) +++ trunk/OpenMPT/common/ComponentManager.h 2014-10-22 10:36:01 UTC (rev 4461) @@ -0,0 +1,335 @@ +/* + * ComponentManager.h + * ------------------ + * Purpose: Manages loading of optional components. + * Notes : (currently none) + * Authors: Joern Heusipp + * OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#pragma once + +#include <map> +#include <vector> +#include "../common/misc_util.h" + + +OPENMPT_NAMESPACE_BEGIN + + +#if defined(MPT_WITH_DYNBIND) + + +#ifdef MODPLUG_TRACKER +#define MPT_COMPONENT_MANAGER 1 +#else +#define MPT_COMPONENT_MANAGER 0 +#endif + + +enum ComponentType +{ + ComponentTypeSystem, // uxtheme.dll, mf.dll + ComponentTypeSystemInstallable, // acm mp3 codec + ComponentTypeBundled, // libsoundtouch + ComponentTypeForeign, // libmp3lame +}; + + +class ComponentFactoryBase; + + +class IComponent +{ + + friend class ComponentFactoryBase; + +protected: + + IComponent() { } + +public: + + virtual ~IComponent() { } + +protected: + + virtual void SetName(const std::string &name) = 0; + +public: + + virtual std::string GetName() const = 0; + virtual std::string GetSettingsKey() const = 0; + virtual ComponentType GetType() const = 0; + virtual bool IsDelayLoaded() const = 0; // openmpt is linked against the component dlls which get delay loaded + + virtual bool IsInitialized() const = 0; // Initialize() has been called + virtual bool IsAvailable() const = 0; // Initialize() has been successfull + virtual mpt::ustring GetVersion() const = 0; + + virtual void Initialize() = 0; // try to load the component + + virtual mpt::Library GetLibrary(const std::string &libName) const = 0; + +}; + + +class ComponentBase + : public IComponent +{ + +private: + std::string m_Name; + ComponentType m_Type; + bool m_DelayLoaded; + + bool m_Initialized; + bool m_Available; + typedef std::map<std::string, mpt::Library> TLibraryMap; + TLibraryMap m_Libraries; + + bool m_BindFailed; + +protected: + + ComponentBase(ComponentType type, bool delayLoaded = false); + +public: + + virtual ~ComponentBase(); + +protected: + + void SetName(const std::string &name); + void SetInitialized(); + void SetAvailable(); + bool AddLibrary(const std::string &libName, const mpt::LibraryPath &libPath); + void ClearLibraries(); + void SetBindFailed(); + void ClearBindFailed(); + bool HasBindFailed() const; + +public: + + virtual std::string GetName() const; + virtual ComponentType GetType() const; + virtual bool IsDelayLoaded() const; + virtual bool IsInitialized() const; + virtual bool IsAvailable() const; + + virtual mpt::ustring GetVersion() const; + + virtual mpt::Library GetLibrary(const std::string &libName) const; + + virtual void Initialize(); + + template <typename Tfunc> + bool Bind(Tfunc * & f, const std::string &libName, const std::string &symbol) const + { + return GetLibrary(libName).Bind(f, symbol); + } + +protected: + + virtual bool DoInitialize() = 0; + +}; + +#define MPT_COMPONENT_BIND(libName, func) do { if(!Bind( func , libName , #func )) { SetBindFailed(); } } while(0) +#define MPT_COMPONENT_BIND_OPTIONAL(libName, func) Bind( func , libName , #func ) +#define MPT_COMPONENT_BIND_SYMBOL(libName, symbol, func) do { if(!Bind( func , libName , symbol )) { SetBindFailed(); } } while(0) +#define MPT_COMPONENT_BIND_SYMBOL_OPTIONAL(libName, symbol, func) Bind( func , libName , symbol ) + + +class ComponentSystemDLL : public ComponentBase +{ +private: + mpt::PathString m_BaseName; +public: + ComponentSystemDLL(const mpt::PathString &baseName, bool delayLoaded = false) + : ComponentBase(ComponentTypeSystem, delayLoaded) + , m_BaseName(baseName) + { + return; + } + virtual bool DoInitialize() + { + AddLibrary(m_BaseName.ToUTF8(), mpt::LibraryPath::System(m_BaseName)); + return GetLibrary(m_BaseName.ToUTF8()).IsValid(); + } +}; + + +class ComponentDelayLoadedBundledDLL : public ComponentBase +{ +private: + mpt::PathString m_FullName; +public: + ComponentDelayLoadedBundledDLL(const mpt::PathString &fullName) + : ComponentBase(ComponentTypeBundled, true) + , m_FullName(fullName) + { + return; + } + virtual bool DoInitialize() + { + AddLibrary(m_FullName.ToUTF8(), mpt::LibraryPath::AppFullName(m_FullName)); + return GetLibrary(m_FullName.ToUTF8()).IsValid(); + } +}; + + +#if MPT_COMPONENT_MANAGER + + +class IComponentFactory +{ +protected: + IComponentFactory() { } +public: + virtual ~IComponentFactory() { } +public: + virtual std::string GetName() const = 0; + virtual MPT_SHARED_PTR<IComponent> Construct() const = 0; +}; + + +class ComponentFactoryBase + : public IComponentFactory +{ +private: + std::string m_Name; +protected: + ComponentFactoryBase(const std::string &name); +public: + virtual ~ComponentFactoryBase(); + virtual std::string GetName() const; + virtual MPT_SHARED_PTR<IComponent> Construct() const; + virtual MPT_SHARED_PTR<IComponent> DoConstruct() const = 0; +}; + + +template <typename T> +class ComponentFactory + : public ComponentFactoryBase +{ +public: + ComponentFactory(const std::string &name) + : ComponentFactoryBase(name) + { + return; + } + virtual ~ComponentFactory() + { + return; + } +public: + virtual MPT_SHARED_PTR<IComponent> DoConstruct() const + { + return mpt::make_shared<T>(); + } +}; + + +class IComponentManagerSettings +{ +public: + virtual bool LoadOnStartup() const = 0; + virtual bool KeepLoaded() const = 0; + virtual bool IsBlocked(const std::string &key) const = 0; +}; + + +class ComponentManagerSettingsDefault + : public IComponentManagerSettings +{ +public: + virtual bool LoadOnStartup() const { return false; } + virtual bool KeepLoaded() const { return true; } + virtual bool IsBlocked(const std::string & /*key*/ ) const { return false; } +}; + + +class ComponentManager +{ +public: + static void Init(const IComponentManagerSettings &settings); + static void Release(); + static MPT_SHARED_PTR<ComponentManager> Instance(); +private: + ComponentManager(const IComponentManagerSettings &settings); +private: + typedef std::map<std::string, MPT_SHARED_PTR<IComponent> > TComponentMap; + const IComponentManagerSettings &m_Settings; + TComponentMap m_Components; +private: + void InitializeComponent(MPT_SHARED_PTR<IComponent> component) const; +public: + void Register(const IComponentFactory &componentFactory); + void Startup(); + MPT_SHARED_PTR<IComponent> GetComponent(const IComponentFactory &componentFactory) const; +}; + + +struct ComponentListEntry +{ + ComponentListEntry *next; + void (*reg)(ComponentManager *componentManager); +}; + +bool ComponentListPush(ComponentListEntry *entry); + +#define MPT_REGISTERED_COMPONENT(name) \ + static void RegisterComponent ## name (ComponentManager *componentManager) \ + { \ + componentManager->Register(ComponentFactory< name >( #name )); \ + } \ + static ComponentListEntry Component ## name ## ListEntry = { nullptr, & RegisterComponent ## name }; \ + static bool Component ## name ## Registered = ComponentListPush(& Component ## name ## ListEntry ); +/**/ + + +template <typename type> +MPT_SHARED_PTR<type> GetComponent(const std::string &name) +{ + return MPT_DYNAMIC_POINTER_CAST<type>(ComponentManager::Instance()->GetComponent(ComponentFactory<type>(name))); +} + + +#else // !MPT_COMPONENT_MANAGER + + +#define MPT_REGISTERED_COMPONENT(name) + + +template <typename type> +MPT_SHARED_PTR<type> GetComponent(const std::string &name) +{ + MPT_SHARED_PTR<type> component = mpt::make_shared<type>(); + if(!component) + { + return component; + } + component->Initialize(); + return component; +} + + +#endif // MPT_COMPONENT_MANAGER + + +#define MPT_GET_COMPONENT(name) GetComponent< name >( #name ) + + +template <typename T> +bool IsComponentAvailable(MPT_SHARED_PTR<T> component) +{ + return component && component->IsAvailable(); +} + + +#endif // MPT_WITH_DYNBIND + + +OPENMPT_NAMESPACE_END Property changes on: trunk/OpenMPT/common/ComponentManager.h ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/x-chdr \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Modified: trunk/OpenMPT/common/versionNumber.h =================================================================== --- trunk/OpenMPT/common/versionNumber.h 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/common/versionNumber.h 2014-10-22 10:36:01 UTC (rev 4461) @@ -19,7 +19,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 24 #define VER_MINOR 00 -#define VER_MINORMINOR 12 +#define VER_MINORMINOR 13 //Version string. For example "1.17.02.28" #define MPT_VERSION_STR VER_STRINGIZE(VER_MAJORMAJOR) "." VER_STRINGIZE(VER_MAJOR) "." VER_STRINGIZE(VER_MINOR) "." VER_STRINGIZE(VER_MINORMINOR) Modified: trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj 2014-10-22 10:36:01 UTC (rev 4461) @@ -179,6 +179,7 @@ <ClInclude Include="..\common\AudioCriticalSection.h" /> <ClInclude Include="..\common\BuildSettings.h" /> <ClInclude Include="..\common\CompilerDetect.h" /> + <ClInclude Include="..\common\ComponentManager.h" /> <ClInclude Include="..\common\Endianness.h" /> <ClInclude Include="..\common\FlagSet.h" /> <ClInclude Include="..\common\Logging.h" /> @@ -257,6 +258,7 @@ </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp" /> + <ClCompile Include="..\common\ComponentManager.cpp" /> <ClCompile Include="..\common\Logging.cpp" /> <ClCompile Include="..\common\misc_util.cpp" /> <ClCompile Include="..\common\mptIO.cpp" /> Modified: trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters 2014-10-22 10:36:01 UTC (rev 4461) @@ -266,6 +266,9 @@ <ClInclude Include="..\common\mptIO.h"> <Filter>Header Files\common</Filter> </ClInclude> + <ClInclude Include="..\common\ComponentManager.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> @@ -517,6 +520,9 @@ <ClCompile Include="..\test\TestToolsLib.cpp"> <Filter>Source Files\test</Filter> </ClCompile> + <ClCompile Include="..\common\ComponentManager.cpp"> + <Filter>Source Files\common</Filter> + </ClCompile> <ClCompile Include="..\common\mptIO.cpp"> <Filter>Source Files\common</Filter> </ClCompile> Modified: trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj 2014-10-22 10:36:01 UTC (rev 4461) @@ -187,6 +187,7 @@ <ClInclude Include="..\common\AudioCriticalSection.h" /> <ClInclude Include="..\common\BuildSettings.h" /> <ClInclude Include="..\common\CompilerDetect.h" /> + <ClInclude Include="..\common\ComponentManager.h" /> <ClInclude Include="..\common\Endianness.h" /> <ClInclude Include="..\common\FlagSet.h" /> <ClInclude Include="..\common\Logging.h" /> @@ -267,6 +268,7 @@ </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp" /> + <ClCompile Include="..\common\ComponentManager.cpp" /> <ClCompile Include="..\common\Logging.cpp" /> <ClCompile Include="..\common\misc_util.cpp" /> <ClCompile Include="..\common\mptIO.cpp" /> Modified: trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters 2014-10-22 10:36:01 UTC (rev 4461) @@ -272,6 +272,9 @@ <ClInclude Include="..\common\mptIO.h"> <Filter>Header Files\common</Filter> </ClInclude> + <ClInclude Include="..\common\ComponentManager.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> @@ -523,6 +526,9 @@ <ClCompile Include="..\test\TestToolsLib.cpp"> <Filter>Source Files\test</Filter> </ClCompile> + <ClCompile Include="..\common\ComponentManager.cpp"> + <Filter>Source Files\common</Filter> + </ClCompile> <ClCompile Include="..\common\mptIO.cpp"> <Filter>Source Files\common</Filter> </ClCompile> Modified: trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj 2014-10-22 10:36:01 UTC (rev 4461) @@ -183,6 +183,7 @@ <ClInclude Include="..\common\AudioCriticalSection.h" /> <ClInclude Include="..\common\BuildSettings.h" /> <ClInclude Include="..\common\CompilerDetect.h" /> + <ClInclude Include="..\common\ComponentManager.h" /> <ClInclude Include="..\common\Endianness.h" /> <ClInclude Include="..\common\FlagSet.h" /> <ClInclude Include="..\common\Logging.h" /> @@ -261,6 +262,7 @@ </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp" /> + <ClCompile Include="..\common\ComponentManager.cpp" /> <ClCompile Include="..\common\Logging.cpp" /> <ClCompile Include="..\common\misc_util.cpp" /> <ClCompile Include="..\common\mptIO.cpp" /> Modified: trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters 2014-10-22 10:36:01 UTC (rev 4461) @@ -266,6 +266,9 @@ <ClInclude Include="..\common\mptIO.h"> <Filter>Header Files\common</Filter> </ClInclude> + <ClInclude Include="..\common\ComponentManager.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> @@ -520,6 +523,9 @@ <ClCompile Include="..\test\TestToolsLib.cpp"> <Filter>Source Files\test</Filter> </ClCompile> + <ClCompile Include="..\common\ComponentManager.cpp"> + <Filter>Source Files\common</Filter> + </ClCompile> <ClCompile Include="..\common\mptIO.cpp"> <Filter>Source Files\common</Filter> </ClCompile> Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-10-22 10:36:01 UTC (rev 4461) @@ -31,6 +31,7 @@ #include "../soundlib/FileReader.h" #include "../soundlib/SampleFormatConverters.h" #include "FileDialog.h" +#include "../common/ComponentManager.h" #ifdef _DEBUG #include <math.h> #endif @@ -1735,6 +1736,22 @@ } +//======================= +class ComponentSoundTouch +//======================= + : public ComponentDelayLoadedBundledDLL +{ +public: + ComponentSoundTouch() + : ComponentDelayLoadedBundledDLL(MPT_PATHSTRING("OpenMPT_SoundTouch_f32")) + { + return; + } + std::string GetSettingsKey() const { return "SoundTouch"; } +}; +MPT_REGISTERED_COMPONENT(ComponentSoundTouch) + + int CCtrlSamples::TimeStretch(float ratio) //---------------------------------------- { @@ -1753,12 +1770,13 @@ if(pitch > 2.0f) return 2 + (2<<8); // Check whether the DLL file exists. - mpt::Library libSoundTouch = mpt::Library(mpt::LibraryPath::AppFullName(MPT_PATHSTRING("OpenMPT_SoundTouch_f32"))); - if(!libSoundTouch.IsValid()) + MPT_SHARED_PTR<ComponentSoundTouch> soundTouch = MPT_GET_COMPONENT(ComponentSoundTouch); + if(!IsComponentAvailable(soundTouch)) { MsgBox(IDS_SOUNDTOUCH_LOADFAILURE); return -1; } + HANDLE handleSt = soundtouch_createInstance(); if(handleSt == NULL) { Modified: trunk/OpenMPT/mptrack/MPTrackLink.cpp =================================================================== --- trunk/OpenMPT/mptrack/MPTrackLink.cpp 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/mptrack/MPTrackLink.cpp 2014-10-22 10:36:01 UTC (rev 4461) @@ -20,6 +20,7 @@ #pragma comment(lib, "rpcrt4.lib") #pragma comment(lib, "wininet.lib") #pragma comment(lib, "htmlhelp.lib") +#pragma comment(lib, "uxtheme.lib") #pragma comment(lib, "dmoguids.lib") #pragma comment(lib, "strmiids.lib") Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2014-10-22 10:36:01 UTC (rev 4461) @@ -30,6 +30,7 @@ #include "AutoSaver.h" #include "FileDialog.h" #include "PNG.h" +#include "../common/ComponentManager.h" // rewbs.memLeak #define _CRTDBG_MAP_ALLOC @@ -640,10 +641,10 @@ //-------------------- : m_GuiThreadId(0) , m_pTrackerDirectories(nullptr) - , m_pUXThemeDLL(nullptr) , m_pSettingsIniFile(nullptr) , m_pSettings(nullptr) , m_pTrackerSettings(nullptr) + , m_pComponentManagerSettings(nullptr) , m_pPluginCache(nullptr) { #if MPT_COMPILER_MSVC @@ -711,6 +712,38 @@ ///////////////////////////////////////////////////////////////////////////// // CTrackApp initialization + +//============================ +class ComponentManagerSettings +//============================ + : public IComponentManagerSettings +{ +private: + mutable TrackerSettings &conf; +public: + ComponentManagerSettings(TrackerSettings &conf) + : conf(conf) + { + return; + } + virtual bool LoadOnStartup() const + { + return conf.ComponentsLoadOnStartup; + } + virtual bool KeepLoaded() const + { + return conf.ComponentsKeepLoaded; + } + virtual bool IsBlocked(const std::string &key) const + { + return conf.IsComponentBlocked(key); + } +}; + + +MPT_REGISTERED_COMPONENT(ComponentUXTheme) + + #ifdef WIN32 // Legacy stuff // Move a config file called sFileName from the App's directory (or one of its sub directories specified by sSubDir) to // %APPDATA%. If specified, it will be renamed to sNewFileName. Existing files are never overwritten. @@ -889,10 +922,6 @@ // Set up paths to store configuration in SetupPaths(cmdInfo.m_bPortable); - // Load UXTheme.DLL - m_pUXThemeDLL = new mpt::Library(mpt::LibraryPath::System(MPT_PATHSTRING("uxtheme"))); - m_pUXThemeDLL->Bind(m_pEnableThemeDialogTexture, "EnableThemeDialogTexture"); - // Construct auto saver instance, class TrackerSettings expects it being available. CMainFrame::m_pAutoSaver = new CAutoSaver(); @@ -909,10 +938,18 @@ } MPT_TRACE(); + m_pComponentManagerSettings = new ComponentManagerSettings(TrackerSettings::Instance()); + m_pPluginCache = new IniFileSettingsContainer(m_szPluginCacheFileName); LoadStdProfileSettings(0); // Load standard INI file options (without MRU) + // create component manager + ComponentManager::Init(*m_pComponentManagerSettings); + + // load components + ComponentManager::Instance()->Startup(); + // Register document templates m_pModTemplate = new CModDocTemplate( IDR_MODULETYPE, @@ -1021,17 +1058,18 @@ // Uninitialize Plugins UninitializeDXPlugins(); + ComponentManager::Release(); + delete m_pPluginCache; m_pPluginCache = nullptr; + delete m_pComponentManagerSettings; + m_pComponentManagerSettings = nullptr; delete m_pTrackerSettings; m_pTrackerSettings = nullptr; delete m_pSettings; m_pSettings = nullptr; delete m_pSettingsIniFile; m_pSettingsIniFile = nullptr; - m_pEnableThemeDialogTexture = nullptr; - delete m_pUXThemeDLL; - m_pUXThemeDLL = nullptr; delete m_pTrackerDirectories; m_pTrackerDirectories = nullptr; Modified: trunk/OpenMPT/mptrack/Mptrack.h =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.h 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/mptrack/Mptrack.h 2014-10-22 10:36:01 UTC (rev 4461) @@ -17,6 +17,7 @@ #include "../mptrack/Reporting.h" #include "../soundlib/MIDIMacros.h" #include "../soundlib/modcommand.h" +#include "../common/ComponentManager.h" #include <vector> OPENMPT_NAMESPACE_BEGIN @@ -29,7 +30,9 @@ class CDLSBank; class TrackerDirectories; class TrackerSettings; +class ComponentManagerSettings; + ///////////////////////////////////////////////////////////////////////////// // 16-colors DIB typedef struct MODPLUGDIB @@ -144,6 +147,13 @@ // See mptrack.cpp for the implementation of this class // +class ComponentUXTheme : public ComponentSystemDLL +{ +public: + ComponentUXTheme() : ComponentSystemDLL(MPT_PATHSTRING("uxtheme"), true) { } + std::string GetSettingsKey() const { return "UXTheme"; } +}; + //============================= class CTrackApp: public CWinApp //============================= @@ -193,12 +203,10 @@ DWORD m_GuiThreadId; TrackerDirectories *m_pTrackerDirectories; - mpt::Library *m_pUXThemeDLL; - typedef HRESULT (WINAPI * pfEnableThemeDialogTexture)(HWND, DWORD); - pfEnableThemeDialogTexture m_pEnableThemeDialogTexture; IniFileSettingsBackend *m_pSettingsIniFile; SettingsContainer *m_pSettings; TrackerSettings *m_pTrackerSettings; + ComponentManagerSettings *m_pComponentManagerSettings; IniFileSettingsContainer *m_pPluginCache; CModDocTemplate *m_pModTemplate; CVstPluginManager *m_pPluginManager; @@ -248,7 +256,6 @@ public: bool InGuiThread() const { return GetCurrentThreadId() == m_GuiThreadId; } - HRESULT EnableThemeDialogTexture(HWND hwnd, DWORD dwFlags) { if(m_pEnableThemeDialogTexture) return m_pEnableThemeDialogTexture(hwnd, dwFlags); else return S_OK; } CModDocTemplate *GetModDocTemplate() const { return m_pModTemplate; } CVstPluginManager *GetPluginManager() const { return m_pPluginManager; } SoundDevice::Manager *GetSoundDevicesManager() const { return m_pSoundDevicesManager; } Modified: trunk/OpenMPT/mptrack/StreamEncoderMP3.cpp =================================================================== --- trunk/OpenMPT/mptrack/StreamEncoderMP3.cpp 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/mptrack/StreamEncoderMP3.cpp 2014-10-22 10:36:01 UTC (rev 4461) @@ -13,6 +13,8 @@ #include "StreamEncoder.h" #include "StreamEncoderMP3.h" +#include "../common/ComponentManager.h" + #include "Mptrack.h" #include "../soundlib/Sndfile.h" @@ -252,10 +254,11 @@ typedef struct lame_global_struct lame_global_flags; typedef lame_global_flags *lame_t; -struct LameDynBind +class ComponentLame + : public ComponentBase { - mpt::Library hLame; +public: const char* (CDECL * get_lame_version)(); const char* (CDECL * get_lame_short_version)(); @@ -314,89 +317,109 @@ int (CDECL * lame_close) (lame_global_flags *); +private: + void Reset() { + ClearLibraries(); + } + +public: + + ComponentLame() + : ComponentBase(ComponentTypeForeign, false) + { return; } - LameDynBind() + + std::string GetSettingsKey() const { return "LibMP3Lame"; } + +protected: + + bool DoInitialize() { Reset(); - if(!hLame.IsValid()) TryLoad(MPT_PATHSTRING("libmp3lame"), true); - if(!hLame.IsValid()) TryLoad(MPT_PATHSTRING("liblame"), true); - if(!hLame.IsValid()) TryLoad(MPT_PATHSTRING("mp3lame"), true); - if(!hLame.IsValid()) TryLoad(MPT_PATHSTRING("lame"), true); - if(!hLame.IsValid()) TryLoad(MPT_PATHSTRING("lame_enc"), false); + struct dll_names_t { + const char *lame; + }; + static const dll_names_t dll_names[] = { + { "libmp3lame" }, + { "liblame" }, + { "mp3lame" }, + { "lame" }, + { "lame_enc" }, + }; + bool ok = false; + for(std::size_t i=0; i<CountOf(dll_names); ++i) + { + if(TryLoad(mpt::PathString::FromUTF8(dll_names[i].lame))) + { + ok = true; + break; + } + } + return ok; } - void TryLoad(const mpt::PathString &filename, bool warn) + +private: + + bool TryLoad(const mpt::PathString &filename) { - hLame = mpt::Library(mpt::LibraryPath::AppFullName(filename)); - if(!hLame.IsValid()) + Reset(); + ClearBindFailed(); + if(!AddLibrary("libmp3lame", mpt::LibraryPath::AppFullName(filename))) { - return; + Reset(); + return false; } - bool ok = true; - #define LAME_BIND(f) do { \ - if(!hLame.Bind( f , #f )) \ - { \ - ok = false; \ - if(warn) \ - { \ - Reporting::Error(mpt::String::PrintW(L"Your '%1' is missing '%2'.\n\nPlease copy a newer 'libmp3lame.dll' into OpenMPT's root directory.", filename.ToWide(), L ## #f ).c_str(), L"OpenMPT - MP3 Export"); \ - } \ - } \ - } while(0) - LAME_BIND(get_lame_version); - LAME_BIND(get_lame_short_version); - LAME_BIND(get_lame_very_short_version); - LAME_BIND(get_psy_version); - LAME_BIND(get_lame_url); - LAME_BIND(lame_init); - LAME_BIND(lame_set_in_samplerate); - LAME_BIND(lame_set_num_channels); - LAME_BIND(lame_get_num_channels); - LAME_BIND(lame_get_quality); - LAME_BIND(lame_set_quality); - LAME_BIND(lame_set_out_samplerate); - LAME_BIND(lame_set_brate); - LAME_BIND(lame_set_VBR_quality); - LAME_BIND(lame_set_VBR); - LAME_BIND(lame_set_bWriteVbrTag); - LAME_BIND(lame_set_strict_ISO); - LAME_BIND(lame_set_disable_reservoir); - LAME_BIND(id3tag_genre_list); - LAME_BIND(id3tag_init); - LAME_BIND(id3tag_v1_only); - LAME_BIND(id3tag_add_v2); - LAME_BIND(id3tag_v2_only); - LAME_BIND(lame_set_write_id3tag_automatic); - LAME_BIND(id3tag_set_title); - LAME_BIND(id3tag_set_artist); - LAME_BIND(id3tag_set_album); - LAME_BIND(id3tag_set_year); - LAME_BIND(id3tag_set_comment); - LAME_BIND(id3tag_set_track); - LAME_BIND(id3tag_set_genre); - LAME_BIND(lame_init_params); - LAME_BIND(lame_encode_buffer_ieee_float); - LAME_BIND(lame_encode_buffer_interleaved_ieee_float); - LAME_BIND(lame_encode_flush); - LAME_BIND(lame_get_lametag_frame); - LAME_BIND(lame_get_id3v2_tag); - LAME_BIND(lame_close); - #undef LAME_BIND - if(!ok) + MPT_COMPONENT_BIND("libmp3lame", get_lame_version); + MPT_COMPONENT_BIND("libmp3lame", get_lame_short_version); + MPT_COMPONENT_BIND("libmp3lame", get_lame_very_short_version); + MPT_COMPONENT_BIND("libmp3lame", get_psy_version); + MPT_COMPONENT_BIND("libmp3lame", get_lame_url); + MPT_COMPONENT_BIND("libmp3lame", lame_init); + MPT_COMPONENT_BIND("libmp3lame", lame_set_in_samplerate); + MPT_COMPONENT_BIND("libmp3lame", lame_set_num_channels); + MPT_COMPONENT_BIND("libmp3lame", lame_get_num_channels); + MPT_COMPONENT_BIND("libmp3lame", lame_get_quality); + MPT_COMPONENT_BIND("libmp3lame", lame_set_quality); + MPT_COMPONENT_BIND("libmp3lame", lame_set_out_samplerate); + MPT_COMPONENT_BIND("libmp3lame", lame_set_brate); + MPT_COMPONENT_BIND("libmp3lame", lame_set_VBR_quality); + MPT_COMPONENT_BIND("libmp3lame", lame_set_VBR); + MPT_COMPONENT_BIND("libmp3lame", lame_set_bWriteVbrTag); + MPT_COMPONENT_BIND("libmp3lame", lame_set_strict_ISO); + MPT_COMPONENT_BIND("libmp3lame", lame_set_disable_reservoir); + MPT_COMPONENT_BIND("libmp3lame", id3tag_genre_list); + MPT_COMPONENT_BIND("libmp3lame", id3tag_init); + MPT_COMPONENT_BIND("libmp3lame", id3tag_v1_only); + MPT_COMPONENT_BIND("libmp3lame", id3tag_add_v2); + MPT_COMPONENT_BIND("libmp3lame", id3tag_v2_only); + MPT_COMPONENT_BIND("libmp3lame", lame_set_write_id3tag_automatic); + MPT_COMPONENT_BIND("libmp3lame", id3tag_set_title); + MPT_COMPONENT_BIND("libmp3lame", id3tag_set_artist); + MPT_COMPONENT_BIND("libmp3lame", id3tag_set_album); + MPT_COMPONENT_BIND("libmp3lame", id3tag_set_year); + MPT_COMPONENT_BIND("libmp3lame", id3tag_set_comment); + MPT_COMPONENT_BIND("libmp3lame", id3tag_set_track); + MPT_COMPONENT_BIND("libmp3lame", id3tag_set_genre); + MPT_COMPONENT_BIND("libmp3lame", lame_init_params); + MPT_COMPONENT_BIND("libmp3lame", lame_encode_buffer_ieee_float); + MPT_COMPONENT_BIND("libmp3lame", lame_encode_buffer_interleaved_ieee_float); + MPT_COMPONENT_BIND("libmp3lame", lame_encode_flush); + MPT_COMPONENT_BIND("libmp3lame", lame_get_lametag_frame); + MPT_COMPONENT_BIND("libmp3lame", lame_get_id3v2_tag); + MPT_COMPONENT_BIND("libmp3lame", lame_close); + if(HasBindFailed()) { - hLame.Unload(); Reset(); - return; + return false; } + return true; } - operator bool () const { return hLame.IsValid() ? true : false; } - ~LameDynBind() - { - hLame.Unload(); - Reset(); - } + +public: + static void GenreEnumCallback(int num, const char *name, void *cookie) { MPT_UNREFERENCED_PARAMETER(num); @@ -409,7 +432,7 @@ Encoder::Traits BuildTraits() { Encoder::Traits traits; - if(!*this) + if(!IsAvailable()) { return traits; } @@ -445,16 +468,17 @@ return traits; } }; +MPT_REGISTERED_COMPONENT(ComponentLame) class MP3LameStreamWriter : public StreamWriterBase { private: - LameDynBind &lame; + ComponentLame &lame; Encoder::Mode Mode; bool gfp_inited; lame_t gfp; public: - MP3LameStreamWriter(LameDynBind &lame_, std::ostream &stream) + MP3LameStreamWriter(ComponentLame &lame_, std::ostream &stream) : StreamWriterBase(stream) , lame(lame_) { @@ -618,10 +642,11 @@ #ifdef MPT_MP3ENCODER_BLADE -struct BladeDynBind +class ComponentBlade + : public ComponentBase { - mpt::Library hBlade; +public: int lame; @@ -631,61 +656,71 @@ BE_ERR (*beDeinitStream) (HBE_STREAM, PBYTE, PDWORD); BE_ERR (*beCloseStream) (HBE_STREAM); +private: + void Reset() { + ClearLibraries(); lame = 0; } - BladeDynBind() + +public: + + ComponentBlade() + : ComponentBase(ComponentTypeForeign, false) { + return; + } + + std::string GetSettingsKey() const { return "BladeEnc"; } + +protected: + + bool DoInitialize() + { Reset(); - if(!hBlade.IsValid()) + if(TryLoad(MPT_PATHSTRING("lame_enc"))) { - TryLoad(MPT_PATHSTRING("lame_enc")); - if(hBlade.IsValid()) lame = 1; - } - if(!hBlade.IsValid()) + lame = 1; + return true; + } else if(TryLoad(MPT_PATHSTRING("bladeenc"))) { - TryLoad(MPT_PATHSTRING("bladeenc")); - if(hBlade.IsValid()) lame = 0; + lame = 0; + return true; } + return false; } - void TryLoad(const mpt::PathString &filename) + +private: + + bool TryLoad(const mpt::PathString &filename) { - hBlade = mpt::Library(mpt::LibraryPath::AppFullName(filename)); - if(!hBlade.IsValid()) + Reset(); + ClearBindFailed(); + if(!AddLibrary("BladeEnc", mpt::LibraryPath::AppFullName(filename))) { - return; + Reset(); + return false; } - bool ok = true; - #define BLADE_BIND(f) do { \ - if(!hBlade.Bind( f , #f )) \ - { \ - ok = false; \ - } \ - } while(0) - BLADE_BIND(beVersion); - BLADE_BIND(beInitStream); - BLADE_BIND(beEncodeChunk); - BLADE_BIND(beDeinitStream); - BLADE_BIND(beCloseStream); - #undef BLADE_BIND - if(!ok) + MPT_COMPONENT_BIND("BladeEnc", beVersion); + MPT_COMPONENT_BIND("BladeEnc", beInitStream); + MPT_COMPONENT_BIND("BladeEnc", beEncodeChunk); + MPT_COMPONENT_BIND("BladeEnc", beDeinitStream); + MPT_COMPONENT_BIND("BladeEnc", beCloseStream); + if(HasBindFailed()) { - hBlade.Unload(); Reset(); - return; + return false; } + return true; } - operator bool () const { return hBlade.IsValid(); } - ~BladeDynBind() - { - hBlade.Unload(); - Reset(); - } + +public: + Encoder::Traits BuildTraits() { Encoder::Traits traits; - if(!*this) + if(!IsAvailable()) { return traits; } @@ -718,11 +753,12 @@ return traits; } }; +MPT_REGISTERED_COMPONENT(ComponentBlade) class MP3BladeStreamWriter : public StreamWriterBase { private: - BladeDynBind &blade; + ComponentBlade &blade; DWORD blade_inputsamples; DWORD blade_outputbytes; SC::Convert<int16,float> sampleConv[2]; @@ -733,7 +769,7 @@ std::vector<float> interleaved; std::vector<SHORT> samples; public: - MP3BladeStreamWriter(BladeDynBind &blade_, std::ostream &stream) + MP3BladeStreamWriter(ComponentBlade &blade_, std::ostream &stream) : StreamWriterBase(stream) , blade(blade_) { @@ -866,8 +902,12 @@ #ifdef MPT_MP3ENCODER_ACM -struct AcmDynBind +class ComponentAcmMP3 + : public ComponentBase { + +public: + bool found_codec; int samplerates[CountOf(layer3_samplerates)]; @@ -876,6 +916,8 @@ std::vector<std::vector<char> > formats_waveformats; std::set<std::string> drivers; +private: + void Reset() { found_codec = false; @@ -884,14 +926,30 @@ formats_driverids.clear(); formats_waveformats.clear(); } - AcmDynBind() + +public: + + ComponentAcmMP3() + : ComponentBase(ComponentTypeSystemInstallable, false) { + return; + } + + std::string GetSettingsKey() const { return "ACM_MP3"; } + +protected: + + bool DoInitialize() + { Reset(); - TryLoad(); + return TryLoad(); } + +private: + static BOOL CALLBACK AcmFormatEnumCallback(HACMDRIVERID driver, LPACMFORMATDETAILS pafd, DWORD_PTR inst, DWORD fdwSupport) { - return reinterpret_cast<AcmDynBind*>(inst)->AcmFormatEnumCB(driver, pafd, fdwSupport); + return reinterpret_cast<ComponentAcmMP3*>(inst)->AcmFormatEnumCB(driver, pafd, fdwSupport); } template<size_t size> static void AppendField(std::string &s, const std::string &field, const CHAR(&val)[size]) @@ -1073,12 +1131,15 @@ pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign; acmFormatEnum(NULL, &afd, AcmFormatEnumCallback, reinterpret_cast<DWORD_PTR>(this), ACM_FORMATENUMF_CONVERT); } - void TryLoad() + +private: + + bool TryLoad() { if(acmGetVersion() <= 0x03320000) { Reset(); - return; + return false; } try { @@ -1103,18 +1164,17 @@ if(!found_codec) { Reset(); - return; + return false; } + return true; } - operator bool () const { return found_codec ? true : false; } - ~AcmDynBind() - { - Reset(); - } + +public: + Encoder::Traits BuildTraits() { Encoder::Traits traits; - if(!*this) + if(!IsAvailable()) { return traits; } @@ -1154,11 +1214,12 @@ return traits; } }; +MPT_REGISTERED_COMPONENT(ComponentAcmMP3) class MP3AcmStreamWriter : public StreamWriterBase { private: - AcmDynBind &acm; + ComponentAcmMP3 &acm; static const size_t acmBufSize = 1024; int acmChannels; SC::Convert<int16,float> sampleConv[2]; @@ -1172,7 +1233,7 @@ std::vector<float> interleaved; std::vector<int16> samples; public: - MP3AcmStreamWriter(AcmDynBind &acm_, std::ostream &stream) + MP3AcmStreamWriter(ComponentAcmMP3 &acm_, std::ostream &stream) : StreamWriterBase(stream) , acm(acm_) { @@ -1354,22 +1415,13 @@ MP3Encoder::MP3Encoder(MP3EncoderType type) //----------------------------------------- -#ifdef MPT_MP3ENCODER_LAME - : m_Lame(nullptr) -#endif // MPT_MP3ENCODER_LAME -#ifdef MPT_MP3ENCODER_BLADE - , m_Blade(nullptr) -#endif // MPT_MP3ENCODER_BLADE -#ifdef MPT_MP3ENCODER_ACM - , m_Acm(nullptr) -#endif // MPT_MP3ENCODER_ACM - , m_Type(MP3EncoderDefault) + : m_Type(MP3EncoderDefault) { #ifdef MPT_MP3ENCODER_LAME if(type == MP3EncoderDefault || type == MP3EncoderLame) { - m_Lame = new LameDynBind(); - if(*m_Lame) + m_Lame = MPT_GET_COMPONENT(ComponentLame); + if(IsComponentAvailable(m_Lame)) { m_Type = MP3EncoderLame; SetTraits(m_Lame->BuildTraits()); @@ -1380,8 +1432,8 @@ #ifdef MPT_MP3ENCODER_BLADE if(type == MP3EncoderDefault || type == MP3EncoderBlade) { - m_Blade = new BladeDynBind(); - if(*m_Blade) + m_Blade = MPT_GET_COMPONENT(ComponentBlade); + if(IsComponentAvailable(m_Blade)) { m_Type = MP3EncoderBlade; SetTraits(m_Blade->BuildTraits()); @@ -1392,8 +1444,8 @@ #ifdef MPT_MP3ENCODER_ACM if(type == MP3EncoderDefault || type == MP3EncoderACM) { - m_Acm = new AcmDynBind(); - if(*m_Acm) + m_Acm = MPT_GET_COMPONENT(ComponentAcmMP3); + if(IsComponentAvailable(m_Acm)) { m_Type = MP3EncoderACM; SetTraits(m_Acm->BuildTraits()); @@ -1409,13 +1461,13 @@ { return false #ifdef MPT_MP3ENCODER_LAME - || (m_Lame && *m_Lame) + || IsComponentAvailable(m_Lame) #endif // MPT_MP3ENCODER_ACM #ifdef MPT_MP3ENCODER_BLADE - || (m_Blade && *m_Blade) + || IsComponentAvailable(m_Blade) #endif // MPT_MP3ENCODER_BLADE #ifdef MPT_MP3ENCODER_ACM - || (m_Acm && *m_Acm) + || IsComponentAvailable(m_Acm) #endif // MPT_MP3ENCODER_ACM ; } @@ -1424,27 +1476,7 @@ MP3Encoder::~MP3Encoder() //----------------------- { -#ifdef MPT_MP3ENCODER_ACM - if(m_Acm) - { - delete m_Acm; - m_Acm = nullptr; - } -#endif // MPT_MP3ENCODER_ACM -#ifdef MPT_MP3ENCODER_BLADE - if(m_Blade) - { - delete m_Blade; - m_Blade = nullptr; - } -#endif // MPT_MP3ENCODER_BLADE -#ifdef MPT_MP3ENCODER_LAME - if(m_Lame) - { - delete m_Lame; - m_Lame = nullptr; - } -#endif // MPT_MP3ENCODER_LAME + return; } Modified: trunk/OpenMPT/mptrack/StreamEncoderMP3.h =================================================================== --- trunk/OpenMPT/mptrack/StreamEncoderMP3.h 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/mptrack/StreamEncoderMP3.h 2014-10-22 10:36:01 UTC (rev 4461) @@ -22,13 +22,13 @@ #ifdef MPT_MP3ENCODER_LAME -struct LameDynBind; +class ComponentLame; #endif #ifdef MPT_MP3ENCODER_BLADE -struct BladeDynBind; +class ComponentBlade; #endif #ifdef MPT_MP3ENCODER_ACM -struct AcmDynBind; +class ComponentAcmMP3; #endif enum MP3EncoderType @@ -45,13 +45,13 @@ private: #ifdef MPT_MP3ENCODER_LAME - LameDynBind *m_Lame; + MPT_SHARED_PTR<ComponentLame> m_Lame; #endif #ifdef MPT_MP3ENCODER_BLADE - BladeDynBind *m_Blade; + MPT_SHARED_PTR<ComponentBlade> m_Blade; #endif #ifdef MPT_MP3ENCODER_ACM - AcmDynBind *m_Acm; + MPT_SHARED_PTR<ComponentAcmMP3> m_Acm; #endif MP3EncoderType m_Type; Modified: trunk/OpenMPT/mptrack/StreamEncoderOpus.cpp =================================================================== --- trunk/OpenMPT/mptrack/StreamEncoderOpus.cpp 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/mptrack/StreamEncoderOpus.cpp 2014-10-22 10:36:01 UTC (rev 4461) @@ -13,6 +13,8 @@ #include "StreamEncoder.h" #include "StreamEncoderOpus.h" +#include "../common/ComponentManager.h" + #include "Mptrack.h" #include <deque> @@ -38,11 +40,11 @@ -struct OpusDynBind +class ComponentOpus + : public ComponentBase { - mpt::Library hOgg; - mpt::Library hOpus; +public: // ogg int (*ogg_stream_init)(ogg_stream_state *os,int serialno); @@ -64,11 +66,26 @@ // 1.1 OpusMSEncoder * (*opus_multistream_surround_encoder_create)(opus_int32 Fs, int channels, int mapping_family, int *streams, int *coupled_streams, unsigned char *mapping, int application, int *error); +private: + void Reset() { + ClearLibraries(); + } + +public: + + ComponentOpus() + : ComponentBase(ComponentTypeForeign, false) + { return; } - OpusDynBind() + + std::string GetSettingsKey() const { return "Opus"; } + +protected: + + bool DoInitialize() { Reset(); struct dll_names_t { @@ -84,70 +101,59 @@ { "libogg" , "libopus" }, { "ogg" , "opus" } }; + bool ok = false; for(std::size_t i=0; i<CountOf(dll_names); ++i) { if(TryLoad(mpt::PathString::FromUTF8(dll_names[i].ogg), mpt::PathString::FromUTF8(dll_names[i].opus))) { - // success + ok = true; break; } } + return ok; } + +private: + bool TryLoad(const mpt::PathString &Ogg_fn, const mpt::PathString &Opus_fn) { - hOgg = mpt::Library(mpt::LibraryPath::AppFullName(Ogg_fn)); - if(!hOgg.IsValid()) + Reset(); + ClearBindFailed(); + if(!AddLibrary("ogg", mpt::LibraryPath::AppFullName(Ogg_fn))) { - if(hOgg.IsValid()) { hOgg.Unload(); } - if(hOpus.IsValid()) { hOpus.Unload(); } + Reset(); return false; } - hOpus = mpt::Library(mpt::LibraryPath::AppFullName(Opus_fn)); - if(!hOpus.IsValid()) + if(!AddLibrary("opus", mpt::LibraryPath::AppFullName(Opus_fn))) { - if(hOgg.IsValid()) { hOgg.Unload(); } - if(hOpus.IsValid()) { hOpus.Unload(); } + Reset(); return false; } - bool ok = true; - #define OPUS_BIND(l,f,req) do { \ - if(!l.Bind( f , #f ) && req) \ - { \ - ok = false; \ - } \ - } while(0) - OPUS_BIND(hOgg,ogg_stream_init,true); - OPUS_BIND(hOgg,ogg_stream_packetin,true); - OPUS_BIND(hOgg,ogg_stream_flush,true); - OPUS_BIND(hOgg,ogg_stream_pageout,true); - OPUS_BIND(hOgg,ogg_stream_clear,true); - OPUS_BIND(hOpus,opus_get_version_string,false); - OPUS_BIND(hOpus,opus_multistream_encoder_ctl,true); - OPUS_BIND(hOpus,opus_multistream_encode_float,true); - OPUS_BIND(hOpus,opus_multistream_encoder_destroy,true); - OPUS_BIND(hOpus,opus_multistream_encoder_create,true); - OPUS_BIND(hOpus,opus_multistream_surround_encoder_create,false); - #undef OPUS_BIND - if(!ok) + MPT_COMPONENT_BIND("ogg", ogg_stream_init); + MPT_COMPONENT_BIND("ogg", ogg_stream_packetin); + MPT_COMPONENT_BIND("ogg", ogg_stream_flush); + MPT_COMPONENT_BIND("ogg", ogg_stream_pageout); + MPT_COMPONENT_BIND("ogg", ogg_stream_clear); + MPT_COMPONENT_BIND_OPTIONAL("opus", opus_get_version_string); + MPT_COMPONENT_BIND("opus", opus_multistream_encoder_ctl); + MPT_COMPONENT_BIND("opus", opus_multistream_encode_float); + MPT_COMPONENT_BIND("opus", opus_multistream_encoder_destroy); + MPT_COMPONENT_BIND("opus", opus_multistream_encoder_create); + MPT_COMPONENT_BIND_OPTIONAL("opus", opus_multistream_surround_encoder_create); + if(HasBindFailed()) { - if(hOgg.IsValid()) { hOgg.Unload(); } - if(hOpus.IsValid()) { hOpus.Unload(); } Reset(); return false; } return true; } - operator bool () const { return hOgg.IsValid() && hOpus.IsValid(); } - ~OpusDynBind() - { - if(hOgg.IsValid()) { hOgg.Unload(); } - if(hOpus.IsValid()) { hOpus.Unload(); } - Reset(); - } + +public: + Encoder::Traits BuildTraits() { Encoder::Traits traits; - if(!*this) + if(!IsAvailable()) { return traits; } @@ -170,14 +176,16 @@ traits.defaultBitrate = 128; return traits; } + }; +MPT_REGISTERED_COMPONENT(ComponentOpus) class OpusStreamWriter : public StreamWriterBase { private: - OpusDynBind &opus; + ComponentOpus &opus; ogg_stream_state os; ogg_page og; ogg_packet op; @@ -330,7 +338,7 @@ } } public: - OpusStreamWriter(OpusDynBind &opus_, std::ostream &stream) + OpusStreamWriter(ComponentOpus &opus_, std::ostream &stream) : StreamWriterBase(stream) , opus(opus_) { @@ -555,10 +563,9 @@ OggOpusEncoder::OggOpusEncoder() //------------------------------ - : m_Opus(nullptr) { - m_Opus = new OpusDynBind(); - if(*m_Opus) + m_Opus = MPT_GET_COMPONENT(ComponentOpus); + if(IsComponentAvailable(m_Opus)) { SetTraits(m_Opus->BuildTraits()); } @@ -568,18 +575,14 @@ bool OggOpusEncoder::IsAvailable() const //-------------------------------------- { - return m_Opus && *m_Opus; + return IsComponentAvailable(m_Opus); } OggOpusEncoder::~OggOpusEncoder() //------------------------------- { - if(m_Opus) - { - delete m_Opus; - m_Opus = nullptr; - } + return; } Modified: trunk/OpenMPT/mptrack/StreamEncoderOpus.h =================================================================== --- trunk/OpenMPT/mptrack/StreamEncoderOpus.h 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/mptrack/StreamEncoderOpus.h 2014-10-22 10:36:01 UTC (rev 4461) @@ -16,14 +16,14 @@ OPENMPT_NAMESPACE_BEGIN -struct OpusDynBind; +class ComponentOpus; class OggOpusEncoder : public EncoderFactoryBase { private: - OpusDynBind *m_Opus; + MPT_SHARED_PTR<ComponentOpus> m_Opus; public: Modified: trunk/OpenMPT/mptrack/StreamEncoderVorbis.cpp =================================================================== --- trunk/OpenMPT/mptrack/StreamEncoderVorbis.cpp 2014-10-22 10:32:52 UTC (rev 4460) +++ trunk/OpenMPT/mptrack/StreamEncoderVorbis.cpp 2014-10-22 10:36:01 UTC (rev 4461) @@ -13,6 +13,8 @@ #include "StreamEncoder.h" #include "StreamEncoderVorbis.h" +#include "../common/ComponentManager.h" + #include "Mptrack.h" #include <vorbis/vorbisenc.h> @@ -23,12 +25,11 @@ -struct VorbisDynBind +class ComponentVorbis + : public ComponentBase { - mpt::Library hOgg; - mpt::Library hVorbis; - mpt::Library hVorbisEnc; +public: // ogg int (*ogg_stream_init)(ogg_stream_state *os,int serialno); @@ -61,11 +62,26 @@ int (*vorbis_encode_init)(vorbis_info *vi, long channels, long rate, long max_bitrate, long nominal_bitrate, long min_bitrate); int (*vorbis_encode_init_vbr)(vorbis_info *vi, long channels, long rate, float base_quality); +private: + void Reset() { + ClearLibraries(); + } + +public: + + ComponentVorbis() + : ComponentBase(ComponentTypeForeign, false) + { return; } - VorbisDynBind() + + std::string GetSettingsKey() const { return "Vorbis"; } + +protected: + + bool DoInitialize() { Reset(); struct dll_names_t { @@ -85,100 +101,75 @@ { "libogg-0" , "libvorbis-0", "libvorbisenc-0"}, // mingw builds { "libogg-0" , "libvorbis-0", "libvorbisenc-2"} // mingw 64-bit builds }; + bool ok = false; for(std::size_t i=0; i<CountOf(dll_names); ++i) { if(TryLoad(mpt::PathString::FromUTF8(dll_names[i].ogg), mpt::PathString::FromUTF8(dll_names[i].vorbis), mpt::PathString::FromUTF8(dll_names[i].vorbisenc))) { - // success + ok = true; break; } } + return ok; } bool TryLoad(const mpt::PathString &Ogg_fn, const mpt::PathString &Vorbis_fn, const mpt::PathString &VorbisEnc_fn) { - hOgg = mpt::Library(mpt::LibraryPath::AppFullName(Ogg_fn)); - if(!hOgg.IsValid()) + Reset(); + ClearBindFailed(); + if(!AddLibrary("ogg", mpt::LibraryPath::AppFullName(Ogg_fn))) { - if(hOgg.IsValid()) { hOgg.Unload(); } - if(hVorbis.IsValid()) { hVorbis.Unload(); } - if(hVorbisEnc.IsValid()) { hVorbisEnc.Unload(); } + Reset(); return false; } - hVorbis = mpt::Library(mpt::LibraryPath::AppFullName(Vorbis_fn)); - if(!hVorbis.IsValid()) + if(!AddLibrary("vorbis", mpt::LibraryPath::App... [truncated message content] |