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.

334 lines
11KB

  1. /*
  2. Copyright (C) 2001-2003 Paul Davis
  3. Copyright (C) 2004-2008 Grame
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. */
  16. #include "JackDebugClient.h"
  17. #include "JackLibClient.h"
  18. #include "JackChannel.h"
  19. #include "JackLibGlobals.h"
  20. #include "JackGlobals.h"
  21. #include "JackCompilerDeps.h"
  22. #include "JackTools.h"
  23. #include "JackSystemDeps.h"
  24. #include "JackServerLaunch.h"
  25. #include "JackMetadata.h"
  26. #include <assert.h>
  27. using namespace Jack;
  28. #ifdef __cplusplus
  29. extern "C"
  30. {
  31. #endif
  32. jack_client_t * jack_client_new_aux (const char *client_name,
  33. jack_options_t options,
  34. jack_status_t *status);
  35. LIB_EXPORT jack_client_t * jack_client_open (const char *client_name,
  36. jack_options_t options,
  37. jack_status_t *status, ...);
  38. LIB_EXPORT int jack_client_close (jack_client_t *client);
  39. LIB_EXPORT int jack_get_client_pid (const char *name);
  40. LIB_EXPORT int jack_set_property(jack_client_t*, jack_uuid_t subject, const char* key, const char* value, const char* type);
  41. LIB_EXPORT int jack_get_property(jack_uuid_t subject, const char* key, char** value, char** type);
  42. LIB_EXPORT void jack_free_description(jack_description_t* desc, int free_description_itself);
  43. LIB_EXPORT int jack_get_properties(jack_uuid_t subject, jack_description_t* desc);
  44. LIB_EXPORT int jack_get_all_properties(jack_description_t** descs);
  45. LIB_EXPORT int jack_remove_property(jack_client_t* client, jack_uuid_t subject, const char* key);
  46. LIB_EXPORT int jack_remove_properties(jack_client_t* client, jack_uuid_t subject);
  47. LIB_EXPORT int jack_remove_all_properties(jack_client_t* client);
  48. LIB_EXPORT int jack_set_property_change_callback(jack_client_t* client, JackPropertyChangeCallback callback, void* arg);
  49. #ifdef __cplusplus
  50. }
  51. #endif
  52. static jack_client_t * jack_client_open_aux (const char *client_name,
  53. jack_options_t options,
  54. jack_status_t *status, va_list ap);
  55. JackLibGlobals* JackLibGlobals::fGlobals = NULL;
  56. int JackLibGlobals::fClientCount = 0;
  57. jack_client_t* jack_client_new_aux(const char* client_name, jack_options_t options, jack_status_t* status)
  58. {
  59. jack_varargs_t va; /* variable arguments */
  60. jack_status_t my_status;
  61. JackClient* client;
  62. if (client_name == NULL) {
  63. jack_error("jack_client_new called with a NULL client_name");
  64. return NULL;
  65. }
  66. jack_log("jack_client_new %s", client_name);
  67. if (status == NULL) /* no status from caller? */
  68. status = &my_status; /* use local status word */
  69. *status = (jack_status_t)0;
  70. /* validate parameters */
  71. if ((options & ~JackOpenOptions)) {
  72. int my_status1 = *status | (JackFailure | JackInvalidOption);
  73. *status = (jack_status_t)my_status1;
  74. return NULL;
  75. }
  76. /* parse variable arguments */
  77. jack_varargs_init(&va);
  78. JackLibGlobals::Init(); // jack library initialisation
  79. if (try_start_server(&va, options, status)) {
  80. jack_error("jack server is not running or cannot be started");
  81. JackLibGlobals::Destroy(); // jack library destruction
  82. return 0;
  83. }
  84. if (JACK_DEBUG) {
  85. client = new JackDebugClient(new JackLibClient(GetSynchroTable())); // Debug mode
  86. } else {
  87. client = new JackLibClient(GetSynchroTable());
  88. }
  89. int res = client->Open(va.server_name, client_name, va.session_id, options, status);
  90. if (res < 0) {
  91. delete client;
  92. JackLibGlobals::Destroy(); // jack library destruction
  93. int my_status1 = (JackFailure | JackServerError);
  94. *status = (jack_status_t)my_status1;
  95. return NULL;
  96. } else {
  97. return (jack_client_t*)client;
  98. }
  99. }
  100. static jack_client_t* jack_client_open_aux(const char* client_name, jack_options_t options, jack_status_t* status, va_list ap)
  101. {
  102. jack_varargs_t va; /* variable arguments */
  103. jack_status_t my_status;
  104. JackClient* client;
  105. if (client_name == NULL) {
  106. jack_error("jack_client_open called with a NULL client_name");
  107. return NULL;
  108. }
  109. jack_log("jack_client_open %s", client_name);
  110. if (status == NULL) /* no status from caller? */
  111. status = &my_status; /* use local status word */
  112. *status = (jack_status_t)0;
  113. /* validate parameters */
  114. if ((options & ~JackOpenOptions)) {
  115. int my_status1 = *status | (JackFailure | JackInvalidOption);
  116. *status = (jack_status_t)my_status1;
  117. return NULL;
  118. }
  119. /* parse variable arguments */
  120. jack_varargs_parse(options, ap, &va);
  121. JackLibGlobals::Init(); // jack library initialisation
  122. if (try_start_server(&va, options, status)) {
  123. jack_error("jack server is not running or cannot be started");
  124. JackLibGlobals::Destroy(); // jack library destruction
  125. return 0;
  126. }
  127. if (JACK_DEBUG) {
  128. client = new JackDebugClient(new JackLibClient(GetSynchroTable())); // Debug mode
  129. } else {
  130. client = new JackLibClient(GetSynchroTable());
  131. }
  132. int res = client->Open(va.server_name, client_name, va.session_id, options, status);
  133. if (res < 0) {
  134. delete client;
  135. JackLibGlobals::Destroy(); // jack library destruction
  136. int my_status1 = (JackFailure | JackServerError);
  137. *status = (jack_status_t)my_status1;
  138. return NULL;
  139. } else {
  140. return (jack_client_t*)client;
  141. }
  142. }
  143. LIB_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...)
  144. {
  145. JackGlobals::CheckContext("jack_client_open");
  146. try {
  147. assert(JackGlobals::fOpenMutex);
  148. JackGlobals::fOpenMutex->Lock();
  149. va_list ap;
  150. va_start(ap, status);
  151. jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap);
  152. va_end(ap);
  153. JackGlobals::fOpenMutex->Unlock();
  154. return res;
  155. } catch (std::bad_alloc& e) {
  156. jack_error("Memory allocation error...");
  157. return NULL;
  158. } catch (...) {
  159. jack_error("Unknown error...");
  160. return NULL;
  161. }
  162. }
  163. LIB_EXPORT int jack_client_close(jack_client_t* ext_client)
  164. {
  165. JackGlobals::CheckContext("jack_client_close");
  166. assert(JackGlobals::fOpenMutex);
  167. JackGlobals::fOpenMutex->Lock();
  168. int res = -1;
  169. jack_log("jack_client_close");
  170. JackClient* client = (JackClient*)ext_client;
  171. if (client == NULL) {
  172. jack_error("jack_client_close called with a NULL client");
  173. } else {
  174. res = client->Close();
  175. delete client;
  176. JackLibGlobals::Destroy(); // jack library destruction
  177. jack_log("jack_client_close res = %d", res);
  178. }
  179. JackGlobals::fOpenMutex->Unlock();
  180. return res;
  181. }
  182. LIB_EXPORT int jack_get_client_pid(const char *name)
  183. {
  184. jack_error("jack_get_client_pid : not implemented on library side");
  185. return 0;
  186. }
  187. // Metadata API
  188. LIB_EXPORT int jack_set_property(jack_client_t* ext_client, jack_uuid_t subject, const char* key, const char* value, const char* type)
  189. {
  190. JackGlobals::CheckContext("jack_set_property");
  191. JackClient* client = (JackClient*)ext_client;
  192. jack_log("jack_set_property ext_client %x client %x ", ext_client, client);
  193. if (client == NULL) {
  194. jack_error("jack_set_property called with a NULL client");
  195. return -1;
  196. } else {
  197. JackMetadata* metadata = GetMetadata();
  198. return (metadata ? metadata->SetProperty(client, subject, key, value, type) : -1);
  199. }
  200. }
  201. LIB_EXPORT int jack_get_property(jack_uuid_t subject, const char* key, char** value, char** type)
  202. {
  203. JackGlobals::CheckContext("jack_get_property");
  204. JackMetadata* metadata = GetMetadata();
  205. return (metadata ? metadata->GetProperty(subject, key, value, type) : -1);
  206. }
  207. LIB_EXPORT void jack_free_description(jack_description_t* desc, int free_actual_description_too)
  208. {
  209. JackGlobals::CheckContext("jack_free_description");
  210. JackMetadata* metadata = GetMetadata();
  211. if (metadata)
  212. metadata->FreeDescription(desc, free_actual_description_too);
  213. }
  214. LIB_EXPORT int jack_get_properties(jack_uuid_t subject, jack_description_t* desc)
  215. {
  216. JackGlobals::CheckContext("jack_get_properties");
  217. JackMetadata* metadata = GetMetadata();
  218. return (metadata ? metadata->GetProperties(subject, desc) : -1);
  219. }
  220. LIB_EXPORT int jack_get_all_properties(jack_description_t** descriptions)
  221. {
  222. JackGlobals::CheckContext("jack_get_all_properties");
  223. JackMetadata* metadata = GetMetadata();
  224. return (metadata ? metadata->GetAllProperties(descriptions) : -1);
  225. }
  226. LIB_EXPORT int jack_remove_property(jack_client_t* ext_client, jack_uuid_t subject, const char* key)
  227. {
  228. JackGlobals::CheckContext("jack_remove_property");
  229. JackClient* client = (JackClient*)ext_client;
  230. jack_log("jack_remove_property ext_client %x client %x ", ext_client, client);
  231. if (client == NULL) {
  232. jack_error("jack_remove_property called with a NULL client");
  233. return -1;
  234. } else {
  235. JackMetadata* metadata = GetMetadata();
  236. return (metadata ? metadata->RemoveProperty(client, subject, key) : -1);
  237. }
  238. }
  239. LIB_EXPORT int jack_remove_properties(jack_client_t* ext_client, jack_uuid_t subject)
  240. {
  241. JackGlobals::CheckContext("jack_remove_properties");
  242. JackClient* client = (JackClient*)ext_client;
  243. jack_log("jack_remove_properties ext_client %x client %x ", ext_client, client);
  244. if (client == NULL) {
  245. jack_error("jack_remove_properties called with a NULL client");
  246. return -1;
  247. } else {
  248. JackMetadata* metadata = GetMetadata();
  249. return (metadata ? metadata->RemoveProperties(client, subject) : -1);
  250. }
  251. }
  252. LIB_EXPORT int jack_remove_all_properties(jack_client_t* ext_client)
  253. {
  254. JackGlobals::CheckContext("jack_remove_all_properties");
  255. JackClient* client = (JackClient*)ext_client;
  256. jack_log("jack_remove_all_properties ext_client %x client %x ", ext_client, client);
  257. if (client == NULL) {
  258. jack_error("jack_remove_all_properties called with a NULL client");
  259. return -1;
  260. } else {
  261. JackMetadata* metadata = GetMetadata();
  262. return (metadata ? metadata->RemoveAllProperties(client) : -1);
  263. }
  264. }
  265. LIB_EXPORT int jack_set_property_change_callback(jack_client_t* ext_client, JackPropertyChangeCallback callback, void* arg)
  266. {
  267. JackGlobals::CheckContext("jack_set_property_change_callback");
  268. JackClient* client = (JackClient*)ext_client;
  269. jack_log("jack_set_property_change_callback ext_client %x client %x ", ext_client, client);
  270. if (client == NULL) {
  271. jack_error("jack_set_property_change_callback called with a NULL client");
  272. return -1;
  273. } else {
  274. return client->SetPropertyChangeCallback(callback, arg);
  275. }
  276. }