jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

280 lines
7.2KB

  1. /*
  2. Copyright (C) 2004-2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 2.1 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #ifndef __JackGlobals__
  16. #define __JackGlobals__
  17. #include <memory>
  18. #include <vector>
  19. #include <string>
  20. #include <algorithm>
  21. #include <mutex>
  22. #include "JackPlatformPlug.h"
  23. #include "JackSystemDeps.h"
  24. #include "JackConstants.h"
  25. #include "JackError.h"
  26. #ifdef __CLIENTDEBUG__
  27. #include <iostream>
  28. #include <fstream>
  29. #include <string>
  30. #include <time.h>
  31. #endif
  32. namespace Jack
  33. {
  34. class JackGlobals;
  35. class JackGraphManager;
  36. class JackServer;
  37. struct JackEngineControl;
  38. // Globals used for client management on server or library side.
  39. class JackGlobalsManager
  40. {
  41. /* This object is managed by JackGlobalsManager */
  42. private:
  43. static JackGlobalsManager fInstance;
  44. JackGlobalsManager() {}
  45. ~JackGlobalsManager() {}
  46. public:
  47. std::vector<JackGlobals*> fContexts;
  48. inline static JackGlobalsManager* Instance()
  49. {
  50. return &fInstance;
  51. }
  52. template <class T>
  53. inline T* CreateGlobal(const std::string &server_name);
  54. inline void DestroyGlobal(const std::string &server_name);
  55. };
  56. // Globals used for client management on server or library side.
  57. class JackGlobals
  58. {
  59. friend class JackGlobalsManager;
  60. protected:
  61. JackGlobals(const std::string &server_name);
  62. virtual ~JackGlobals();
  63. public:
  64. static jack_tls_key fRealTimeThread;
  65. static jack_tls_key fNotificationThread;
  66. static jack_tls_key fKeyLogFunction;
  67. static JackMutex* fOpenMutex;
  68. static bool fVerbose;
  69. #ifndef WIN32
  70. static jack_thread_creator_t fJackThreadCreator;
  71. #endif
  72. #ifdef __CLIENTDEBUG__
  73. static std::ofstream* fStream;
  74. #endif
  75. static void CheckContext(const char* name);
  76. volatile bool fServerRunning;
  77. JackMutex* fSynchroMutex;
  78. std::mutex fMutex;
  79. std::string fServerName;
  80. JackClient* fClientTable[CLIENT_NUM];
  81. /* is called each time a context for specific server is added */
  82. virtual bool AddContext(const uint32_t &cntx_num, const std::string &server_name) = 0;
  83. /* is called each time a context for specific server is removed */
  84. virtual bool DelContext(const uint32_t &cntx_num) = 0;
  85. virtual JackGraphManager* GetGraphManager() = 0;
  86. virtual JackEngineControl* GetEngineControl() = 0;
  87. virtual JackSynchro* GetSynchroTable() = 0;
  88. virtual JackServer* GetServer() = 0;
  89. inline static jack_port_id_t PortId(const jack_port_t* port)
  90. {
  91. uintptr_t port_aux = (uintptr_t)port;
  92. jack_port_id_t port_masked = (jack_port_id_t)port_aux;
  93. jack_port_id_t port_id = port_masked & ~PORT_SERVER_CONTEXT_MASK;
  94. return port_id;
  95. }
  96. inline static JackGlobals* PortGlobal(const jack_port_t* port)
  97. {
  98. jack_port_id_t context_id = PortContext(port);
  99. if (context_id >= JackGlobalsManager::Instance()->fContexts.size())
  100. {
  101. jack_error("invalid context for port '%p' requested", port);
  102. return nullptr;
  103. }
  104. return JackGlobalsManager::Instance()->fContexts[context_id];
  105. }
  106. inline static jack_port_id_t PortContext(const jack_port_t* port)
  107. {
  108. uintptr_t port_aux = (uintptr_t)port;
  109. jack_port_id_t port_masked = (jack_port_id_t)port_aux;
  110. jack_port_id_t port_context = (port_masked & PORT_SERVER_CONTEXT_MASK) >> PORT_SERVER_CONTEXT_SHIFT;
  111. return port_context;
  112. }
  113. inline jack_port_id_t PortContext()
  114. {
  115. std::vector<JackGlobals*> &contexts = JackGlobalsManager::Instance()->fContexts;
  116. auto it = std::find_if(contexts.begin(), contexts.end(), [this] (JackGlobals* i) {
  117. return (i && i->fServerName.compare(this->fServerName) == 0);
  118. });
  119. if (it == contexts.end()) {
  120. return PORT_SERVER_CONTEXT_MAX;
  121. }
  122. return it - contexts.begin();
  123. }
  124. inline jack_port_t* PortById(const jack_port_id_t &port_id)
  125. {
  126. jack_port_id_t context_id = PortContext();
  127. if (context_id > PORT_SERVER_CONTEXT_MAX) {
  128. return NULL;
  129. }
  130. /* cast to uintptr_t required to avoid [-Wint-to-pointer-cast] warning */
  131. const uintptr_t port = ((context_id << PORT_SERVER_CONTEXT_SHIFT) | port_id);
  132. return (jack_port_t*)port;
  133. }
  134. };
  135. class JackGlobalsInterface
  136. {
  137. private:
  138. JackGlobals *fGlobal;
  139. public:
  140. JackGlobalsInterface(JackGlobals *global = nullptr)
  141. : fGlobal(global)
  142. {
  143. }
  144. ~JackGlobalsInterface()
  145. {
  146. }
  147. inline JackGlobals* GetGlobal() const
  148. {
  149. return fGlobal;
  150. }
  151. inline void SetGlobal(JackGlobals *global)
  152. {
  153. fGlobal = global;
  154. }
  155. };
  156. template <class T>
  157. inline T* JackGlobalsManager::CreateGlobal(const std::string &server_name)
  158. {
  159. uint32_t context_num = fContexts.size();
  160. std::vector<JackGlobals*>::iterator it = std::find_if(fContexts.begin(), fContexts.end(), [&server_name] (JackGlobals* i) {
  161. return (i && (i->fServerName.compare(server_name) == 0));
  162. });
  163. T* global = nullptr;
  164. if (it == fContexts.end()) {
  165. global = new T(server_name);
  166. it = std::find(fContexts.begin(), fContexts.end(), nullptr);
  167. if (it == fContexts.end()) {
  168. fContexts.push_back(static_cast<JackGlobals*>(global));
  169. } else {
  170. *it = global;
  171. }
  172. } else {
  173. global = dynamic_cast<T*>(*it);
  174. }
  175. if (global == nullptr) {
  176. return global;
  177. }
  178. bool success = false;
  179. {
  180. std::lock_guard<std::mutex> lock(global->fMutex);
  181. success = global->AddContext(context_num, server_name);
  182. }
  183. if (success == false) {
  184. DestroyGlobal(server_name);
  185. return nullptr;
  186. }
  187. return global;
  188. }
  189. inline void JackGlobalsManager::DestroyGlobal(const std::string &server_name)
  190. {
  191. std::vector<JackGlobals*>::iterator it = std::find_if(fContexts.begin(), fContexts.end(), [&server_name] (JackGlobals* i) {
  192. return (i && (i->fServerName.compare(server_name) == 0));
  193. });
  194. if (it == fContexts.end()) {
  195. return;
  196. }
  197. JackGlobals *global = *it;
  198. {
  199. std::lock_guard<std::mutex> lock(global->fMutex);
  200. if (global->DelContext(fContexts.size()) == false) {
  201. return;
  202. }
  203. }
  204. delete global;
  205. *it = nullptr;
  206. }
  207. } // end of namespace
  208. #endif