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.

335 lines
12KB

  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. #include "JackMachClientChannel.h"
  16. #include "JackRPCEngine.h"
  17. #include "JackRPCClientServer.c"
  18. #include "JackError.h"
  19. #include "JackLibClient.h"
  20. #include "JackLibGlobals.h"
  21. #include "JackMachThread.h"
  22. #include "JackConstants.h"
  23. namespace Jack
  24. {
  25. std::map<mach_port_t, JackClient*> gClientTable;
  26. JackMachClientChannel::JackMachClientChannel():fPrivatePort(0),fThread(this)
  27. {}
  28. JackMachClientChannel::~JackMachClientChannel()
  29. {}
  30. // Server <===> client
  31. int JackMachClientChannel::ServerCheck(const char* server_name)
  32. {
  33. jack_log("JackMachClientChannel::ServerCheck = %s", server_name);
  34. char jack_server_entry_name[512];
  35. snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s_%s", jack_server_entry, server_name);
  36. // Connect to server
  37. if (!fServerPort.ConnectPort(jack_server_entry_name)) {
  38. jack_error("Cannot connect to server Mach port");
  39. return -1;
  40. } else {
  41. return 0;
  42. }
  43. }
  44. int JackMachClientChannel::Open(const char* server_name, const char* name, char* name_res, JackClient* client, jack_options_t options, jack_status_t* status)
  45. {
  46. jack_log("JackMachClientChannel::Open name = %s", name);
  47. char jack_server_entry_name[512];
  48. snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s_%s", jack_server_entry, server_name);
  49. // Connect to server
  50. if (!fServerPort.ConnectPort(jack_server_entry_name)) {
  51. jack_error("Cannot connect to server Mach port");
  52. return -1;
  53. }
  54. // Check name in server
  55. int result = 0;
  56. ClientCheck(name, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result);
  57. if (result < 0) {
  58. int status1 = *status;
  59. if (status1 & JackVersionError)
  60. jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION);
  61. else
  62. jack_error("Client name = %s conflits with another running client", name);
  63. return -1;
  64. }
  65. // Prepare local port using client name
  66. char buf[JACK_CLIENT_NAME_SIZE];
  67. snprintf(buf, sizeof(buf) - 1, "%s:%s", jack_client_entry, name_res);
  68. if (!fClientPort.AllocatePort(buf, 16)) {
  69. jack_error("Cannot allocate client Mach port");
  70. return -1;
  71. }
  72. gClientTable[fClientPort.GetPort()] = client;
  73. return 0;
  74. }
  75. void JackMachClientChannel::Close()
  76. {
  77. jack_log("JackMachClientChannel::Close");
  78. gClientTable.erase(fClientPort.GetPort());
  79. fServerPort.DisconnectPort();
  80. fClientPort.DestroyPort();
  81. if (fPrivatePort != 0) {
  82. kern_return_t res;
  83. if ((res = mach_port_destroy(mach_task_self(), fPrivatePort)) != KERN_SUCCESS) {
  84. jack_error("JackMachClientChannel::Close err = %s", mach_error_string(res));
  85. }
  86. }
  87. }
  88. int JackMachClientChannel::Start()
  89. {
  90. jack_log("JackMachClientChannel::Start");
  91. /*
  92. To be sure notification thread is started before ClientOpen is called.
  93. */
  94. if (fThread.StartSync() != 0) {
  95. jack_error("Cannot start Jack client listener");
  96. return -1;
  97. } else {
  98. return 0;
  99. }
  100. }
  101. void JackMachClientChannel::Stop()
  102. {
  103. jack_log("JackMachClientChannel::Stop");
  104. fThread.Kill();
  105. }
  106. void JackMachClientChannel::ClientCheck(const char* name, char* name_res, int protocol, int options, int* status, int* result)
  107. {
  108. kern_return_t res = rpc_jack_client_check(fServerPort.GetPort(), (char*)name, name_res, protocol, options, status, result);
  109. if (res != KERN_SUCCESS) {
  110. *result = -1;
  111. jack_error("JackMachClientChannel::ClientCheck err = %s", mach_error_string(res));
  112. }
  113. }
  114. void JackMachClientChannel::ClientOpen(const char* name, int pid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
  115. {
  116. kern_return_t res = rpc_jack_client_open(fServerPort.GetPort(), (char*)name, pid, &fPrivatePort, shared_engine, shared_client, shared_graph, result);
  117. if (res != KERN_SUCCESS) {
  118. *result = -1;
  119. jack_error("JackMachClientChannel::ClientOpen err = %s", mach_error_string(res));
  120. }
  121. }
  122. void JackMachClientChannel::ClientClose(int refnum, int* result)
  123. {
  124. kern_return_t res = rpc_jack_client_close(fPrivatePort, refnum, result);
  125. if (res != KERN_SUCCESS) {
  126. *result = -1;
  127. jack_error("JackMachClientChannel::ClientClose err = %s", mach_error_string(res));
  128. }
  129. }
  130. void JackMachClientChannel::ClientActivate(int refnum, int state, int* result)
  131. {
  132. kern_return_t res = rpc_jack_client_activate(fPrivatePort, refnum, state, result);
  133. if (res != KERN_SUCCESS) {
  134. *result = -1;
  135. jack_error("JackMachClientChannel::ClientActivate err = %s", mach_error_string(res));
  136. }
  137. }
  138. void JackMachClientChannel::ClientDeactivate(int refnum, int* result)
  139. {
  140. kern_return_t res = rpc_jack_client_deactivate(fPrivatePort, refnum, result);
  141. if (res != KERN_SUCCESS) {
  142. *result = -1;
  143. jack_error("JackMachClientChannel::ClientDeactivate err = %s", mach_error_string(res));
  144. }
  145. }
  146. void JackMachClientChannel::PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result)
  147. {
  148. kern_return_t res = rpc_jack_port_register(fPrivatePort, refnum, (char*)name, (char*)type, flags, buffer_size, port_index, result);
  149. if (res != KERN_SUCCESS) {
  150. *result = -1;
  151. jack_error("JackMachClientChannel::PortRegister err = %s", mach_error_string(res));
  152. }
  153. }
  154. void JackMachClientChannel::PortUnRegister(int refnum, jack_port_id_t port_index, int* result)
  155. {
  156. kern_return_t res = rpc_jack_port_unregister(fPrivatePort, refnum, port_index, result);
  157. if (res != KERN_SUCCESS) {
  158. *result = -1;
  159. jack_error("JackMachClientChannel::PortUnRegister err = %s", mach_error_string(res));
  160. }
  161. }
  162. void JackMachClientChannel::PortConnect(int refnum, const char* src, const char* dst, int* result)
  163. {
  164. kern_return_t res = rpc_jack_port_connect_name(fPrivatePort, refnum, (char*)src, (char*)dst, result);
  165. if (res != KERN_SUCCESS) {
  166. jack_error("JackMachClientChannel::PortConnect err = %s", mach_error_string(res));
  167. }
  168. }
  169. void JackMachClientChannel::PortDisconnect(int refnum, const char* src, const char* dst, int* result)
  170. {
  171. kern_return_t res = rpc_jack_port_disconnect_name(fPrivatePort, refnum, (char*)src, (char*)dst, result);
  172. if (res != KERN_SUCCESS) {
  173. *result = -1;
  174. jack_error("JackMachClientChannel::PortDisconnect err = %s", mach_error_string(res));
  175. }
  176. }
  177. void JackMachClientChannel::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result)
  178. {
  179. kern_return_t res = rpc_jack_port_connect(fPrivatePort, refnum, src, dst, result);
  180. if (res != KERN_SUCCESS) {
  181. *result = -1;
  182. jack_error("JackMachClientChannel::PortConnect err = %s", mach_error_string(res));
  183. }
  184. }
  185. void JackMachClientChannel::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result)
  186. {
  187. kern_return_t res = rpc_jack_port_disconnect(fPrivatePort, refnum, src, dst, result);
  188. if (res != KERN_SUCCESS) {
  189. *result = -1;
  190. jack_error("JackMachClientChannel::PortDisconnect err = %s", mach_error_string(res));
  191. }
  192. }
  193. void JackMachClientChannel::PortRename(int refnum, jack_port_id_t port, const char* name, int* result)
  194. {
  195. kern_return_t res = rpc_jack_port_rename(fPrivatePort, refnum, port, (char*)name, result);
  196. if (res != KERN_SUCCESS) {
  197. *result = -1;
  198. jack_error("JackMachClientChannel::PortRename err = %s", mach_error_string(res));
  199. }
  200. }
  201. void JackMachClientChannel::SetBufferSize(jack_nframes_t buffer_size, int* result)
  202. {
  203. kern_return_t res = rpc_jack_set_buffer_size(fPrivatePort, buffer_size, result);
  204. if (res != KERN_SUCCESS) {
  205. *result = -1;
  206. jack_error("JackMachClientChannel::SetBufferSize err = %s", mach_error_string(res));
  207. }
  208. }
  209. void JackMachClientChannel::SetFreewheel(int onoff, int* result)
  210. {
  211. kern_return_t res = rpc_jack_set_freewheel(fPrivatePort, onoff, result);
  212. if (res != KERN_SUCCESS) {
  213. *result = -1;
  214. jack_error("JackMachClientChannel::SetFreewheel err = %s", mach_error_string(res));
  215. }
  216. }
  217. void JackMachClientChannel::ReleaseTimebase(int refnum, int* result)
  218. {
  219. kern_return_t res = rpc_jack_release_timebase(fPrivatePort, refnum, result);
  220. if (res != KERN_SUCCESS) {
  221. *result = -1;
  222. jack_error("JackMachClientChannel::ReleaseTimebase err = %s", mach_error_string(res));
  223. }
  224. }
  225. void JackMachClientChannel::SetTimebaseCallback(int refnum, int conditional, int* result)
  226. {
  227. kern_return_t res = rpc_jack_set_timebase_callback(fPrivatePort, refnum, conditional, result);
  228. if (res != KERN_SUCCESS) {
  229. *result = -1;
  230. jack_error("JackMachClientChannel::SetTimebaseCallback err = %s", mach_error_string(res));
  231. }
  232. }
  233. void JackMachClientChannel::GetInternalClientName(int refnum, int int_ref, char* name_res, int* result)
  234. {
  235. kern_return_t res = rpc_jack_get_internal_clientname(fPrivatePort, refnum, int_ref, name_res, result);
  236. if (res != KERN_SUCCESS) {
  237. *result = -1;
  238. jack_error("JackMachClientChannel::GetInternalClientName err = %s", mach_error_string(res));
  239. }
  240. }
  241. void JackMachClientChannel::InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result)
  242. {
  243. kern_return_t res = rpc_jack_internal_clienthandle(fPrivatePort, refnum, (char*)client_name, status, int_ref, result);
  244. if (res != KERN_SUCCESS) {
  245. *result = -1;
  246. jack_error("JackMachClientChannel::InternalClientHandle err = %s", mach_error_string(res));
  247. }
  248. }
  249. void JackMachClientChannel::InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int* result)
  250. {
  251. const char* int_client_name = (client_name) ? client_name : "";
  252. const char* int_so_name = (so_name) ? so_name : "";
  253. const char* int_objet_data = (objet_data) ? objet_data : "";
  254. kern_return_t res = rpc_jack_internal_clientload(fPrivatePort, refnum, (char*)int_client_name, (char*)int_so_name, (char*)int_objet_data, options, status, int_ref, result);
  255. if (res != KERN_SUCCESS) {
  256. *result = -1;
  257. jack_error("JackMachClientChannel::InternalClientLoad err = %s", mach_error_string(res));
  258. }
  259. }
  260. void JackMachClientChannel::InternalClientUnload(int refnum, int int_ref, int* status, int* result)
  261. {
  262. kern_return_t res = rpc_jack_internal_clientunload(fPrivatePort, refnum, int_ref, status, result);
  263. if (res != KERN_SUCCESS) {
  264. *result = -1;
  265. jack_error("JackMachClientChannel::InternalClientUnload err = %s", mach_error_string(res));
  266. }
  267. }
  268. bool JackMachClientChannel::Init()
  269. {
  270. jack_log("JackMachClientChannel::Init");
  271. JackClient* client = gClientTable[fClientPort.GetPort()];
  272. return client->Init();
  273. }
  274. bool JackMachClientChannel::Execute()
  275. {
  276. kern_return_t res;
  277. if ((res = mach_msg_server(JackRPCClient_server, 1024, fClientPort.GetPort(), 0)) != KERN_SUCCESS) {
  278. jack_error("JackMachClientChannel::Execute err = %s", mach_error_string(res));
  279. JackClient* client = gClientTable[fClientPort.GetPort()];
  280. client->ShutDown();
  281. return false;
  282. } else {
  283. return true;
  284. }
  285. }
  286. } // end of namespace