1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (c) 2004-2021 musikcube team 4 // 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions are met: 9 // 10 // * Redistributions of source code must retain the above copyright notice, 11 // this list of conditions and the following disclaimer. 12 // 13 // * Redistributions in binary form must reproduce the above copyright 14 // notice, this list of conditions and the following disclaimer in the 15 // documentation and/or other materials provided with the distribution. 16 // 17 // * Neither the name of the author nor the names of other contributors may 18 // be used to endorse or promote products derived from this software 19 // without specific prior written permission. 20 // 21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 // POSSIBILITY OF SUCH DAMAGE. 32 // 33 ////////////////////////////////////////////////////////////////////////////// 34 35 #pragma once 36 37 #include <musikcore/config.h> 38 #include <musikcore/sdk/IPlugin.h> 39 #include <musikcore/sdk/IPreferences.h> 40 41 #include <vector> 42 #include <iostream> 43 #include <string> 44 #include <memory> 45 #include <mutex> 46 47 #ifdef WIN32 48 #define STDCALL(fp) (__stdcall* fp)() 49 #else 50 #include <dlfcn.h> 51 #define STDCALL(fp) (* fp)() 52 #endif 53 54 namespace musik { namespace core { 55 56 class PluginFactory { 57 public: 58 static PluginFactory& Instance(); 59 60 template <typename T> 61 struct ReleaseDeleter { operatorReleaseDeleter62 void operator()(T* t) { 63 t->Release(); 64 } 65 }; 66 67 template <typename T> 68 struct NullDeleter { operatorNullDeleter69 void operator()(T* t) { 70 } 71 }; 72 QueryInterface(const std::string & functionName,std::function<void (musik::core::sdk::IPlugin *,std::shared_ptr<T>,const std::string &)> handler)73 template <class T, class D> void QueryInterface( 74 const std::string& functionName, 75 std::function<void(musik::core::sdk::IPlugin*, std::shared_ptr<T>, const std::string&)> handler) 76 { 77 std::unique_lock<std::mutex> lock(this->mutex); 78 79 typedef T* STDCALL(PluginInterfaceCall); 80 81 for (std::shared_ptr<Descriptor> descriptor : this->plugins) { 82 if (functionName == "GetPlugin" || prefs->GetBool(descriptor->key.c_str(), true)) { /* enabled */ 83 PluginInterfaceCall funcPtr = 84 #ifdef WIN32 85 (PluginInterfaceCall) GetProcAddress((HMODULE)(descriptor->nativeHandle), functionName.c_str()); 86 #else 87 (PluginInterfaceCall)dlsym(descriptor->nativeHandle, functionName.c_str()); 88 #endif 89 if (funcPtr) { 90 T* result = funcPtr(); 91 92 if (result) { 93 handler(descriptor->plugin, std::shared_ptr<T>(result, D()), descriptor->filename); 94 } 95 } 96 } 97 } 98 } 99 QueryInterface(const std::string & functionName)100 template <class T, class D> std::vector<std::shared_ptr<T> > QueryInterface(const std::string& functionName) { 101 std::vector<std::shared_ptr<T> > plugins; 102 103 QueryInterface<T, D>( 104 functionName, 105 [&plugins]( 106 musik::core::sdk::IPlugin* unused, 107 std::shared_ptr<T> plugin, 108 const std::string& fn) 109 { 110 plugins.push_back(plugin); 111 }); 112 113 return plugins; 114 } 115 QueryFunction(const std::string & functionName,std::function<void (musik::core::sdk::IPlugin *,T)> handler)116 template <class T> void QueryFunction( 117 const std::string& functionName, 118 std::function<void(musik::core::sdk::IPlugin*, T)> handler) 119 { 120 std::unique_lock<std::mutex> lock(this->mutex); 121 122 for (std::shared_ptr<Descriptor> descriptor : this->plugins) { 123 if (prefs->GetBool(descriptor->key.c_str(), true)) { /* if enabled by prefs */ 124 T funcPtr = 125 #ifdef WIN32 126 (T) GetProcAddress((HMODULE)(descriptor->nativeHandle), functionName.c_str()); 127 #else 128 (T)dlsym(descriptor->nativeHandle, functionName.c_str()); 129 #endif 130 if (funcPtr) { 131 handler(descriptor->plugin, funcPtr); 132 } 133 } 134 } 135 } 136 QueryGuid(const std::string & guid)137 std::shared_ptr<musik::core::sdk::IPlugin> QueryGuid(const std::string& guid) { 138 using T = musik::core::sdk::IPlugin; 139 std::shared_ptr<T> result; 140 using Deleter = PluginFactory::ReleaseDeleter<T>; 141 Instance().QueryInterface<T, Deleter>( 142 "GetPlugin", 143 [&result, guid](T* unused, std::shared_ptr<T> plugin, const std::string& fn) { 144 if (std::string(plugin->Guid()) == guid) { 145 result = plugin; 146 } 147 }); 148 return result; 149 } 150 151 private: 152 struct Descriptor { 153 musik::core::sdk::IPlugin* plugin; 154 void* nativeHandle; 155 std::string filename; 156 std::string key; 157 }; 158 159 PluginFactory(); 160 ~PluginFactory(); 161 void LoadPlugins(); 162 163 std::vector<std::shared_ptr<Descriptor> > plugins; 164 std::mutex mutex; 165 std::shared_ptr<musik::core::sdk::IPreferences> prefs; 166 }; 167 } } 168