Better isolation of server and clients system resources to allow starting the server...
[jack2.git] / macosx / JackMachClientChannel.cpp
blob360c82313aad0d8255929d87bdee900c6600a251
1 /*
2 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.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "JackMachClientChannel.h"
21 #include "JackRPCEngine.h"
22 #include "JackTools.h"
23 #include "JackRPCClientServer.c"
24 #include "JackError.h"
25 #include "JackLibClient.h"
26 #include "JackLibGlobals.h"
27 #include "JackMachThread.h"
28 #include "JackConstants.h"
30 namespace Jack
33 std::map<mach_port_t, JackClient*> gClientTable;
35 JackMachClientChannel::JackMachClientChannel():fPrivatePort(0),fThread(this)
38 JackMachClientChannel::~JackMachClientChannel()
41 // Server <===> client
43 int JackMachClientChannel::ServerCheck(const char* server_name)
45 jack_log("JackMachClientChannel::ServerCheck = %s", server_name);
46 char jack_server_entry_name[512];
47 snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s.%d_%s", jack_server_entry, JackTools::GetUID(), 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 } else {
54 return 0;
58 int JackMachClientChannel::Open(const char* server_name, const char* name, char* name_res, JackClient* client, jack_options_t options, jack_status_t* status)
60 jack_log("JackMachClientChannel::Open name = %s", name);
61 char jack_server_entry_name[512];
62 snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s.%d_%s", jack_server_entry, JackTools::GetUID(), server_name);
64 // Connect to server
65 if (!fServerPort.ConnectPort(jack_server_entry_name)) {
66 jack_error("Cannot connect to server Mach port");
67 return -1;
70 // Check name in server
71 int result = 0;
72 ClientCheck(name, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result);
73 if (result < 0) {
74 int status1 = *status;
75 if (status1 & JackVersionError)
76 jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION);
77 else
78 jack_error("Client name = %s conflits with another running client", name);
79 return -1;
82 // Prepare local port using client name
83 char buf[JACK_CLIENT_NAME_SIZE];
84 snprintf(buf, sizeof(buf) - 1, "%s:%s", jack_client_entry, name_res);
86 if (!fClientPort.AllocatePort(buf, 16)) {
87 jack_error("Cannot allocate client Mach port");
88 return -1;
91 gClientTable[fClientPort.GetPort()] = client;
92 return 0;
95 void JackMachClientChannel::Close()
97 jack_log("JackMachClientChannel::Close");
98 gClientTable.erase(fClientPort.GetPort());
99 fServerPort.DisconnectPort();
100 fClientPort.DestroyPort();
102 if (fPrivatePort != 0) {
103 kern_return_t res;
104 if ((res = mach_port_destroy(mach_task_self(), fPrivatePort)) != KERN_SUCCESS) {
105 jack_error("JackMachClientChannel::Close err = %s", mach_error_string(res));
110 int JackMachClientChannel::Start()
112 jack_log("JackMachClientChannel::Start");
114 To be sure notification thread is started before ClientOpen is called.
116 if (fThread.StartSync() != 0) {
117 jack_error("Cannot start Jack client listener");
118 return -1;
119 } else {
120 return 0;
124 void JackMachClientChannel::Stop()
126 jack_log("JackMachClientChannel::Stop");
127 fThread.Kill();
130 void JackMachClientChannel::ClientCheck(const char* name, char* name_res, int protocol, int options, int* status, int* result)
132 kern_return_t res = rpc_jack_client_check(fServerPort.GetPort(), (char*)name, name_res, protocol, options, status, result);
133 if (res != KERN_SUCCESS) {
134 *result = -1;
135 jack_error("JackMachClientChannel::ClientCheck err = %s", mach_error_string(res));
139 void JackMachClientChannel::ClientOpen(const char* name, int pid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
141 kern_return_t res = rpc_jack_client_open(fServerPort.GetPort(), (char*)name, pid, &fPrivatePort, shared_engine, shared_client, shared_graph, result);
142 if (res != KERN_SUCCESS) {
143 *result = -1;
144 jack_error("JackMachClientChannel::ClientOpen err = %s", mach_error_string(res));
148 void JackMachClientChannel::ClientClose(int refnum, int* result)
150 kern_return_t res = rpc_jack_client_close(fPrivatePort, refnum, result);
151 if (res != KERN_SUCCESS) {
152 *result = -1;
153 jack_error("JackMachClientChannel::ClientClose err = %s", mach_error_string(res));
157 void JackMachClientChannel::ClientActivate(int refnum, int state, int* result)
159 kern_return_t res = rpc_jack_client_activate(fPrivatePort, refnum, state, result);
160 if (res != KERN_SUCCESS) {
161 *result = -1;
162 jack_error("JackMachClientChannel::ClientActivate err = %s", mach_error_string(res));
166 void JackMachClientChannel::ClientDeactivate(int refnum, int* result)
168 kern_return_t res = rpc_jack_client_deactivate(fPrivatePort, refnum, result);
169 if (res != KERN_SUCCESS) {
170 *result = -1;
171 jack_error("JackMachClientChannel::ClientDeactivate err = %s", mach_error_string(res));
175 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)
177 kern_return_t res = rpc_jack_port_register(fPrivatePort, refnum, (char*)name, (char*)type, flags, buffer_size, port_index, result);
178 if (res != KERN_SUCCESS) {
179 *result = -1;
180 jack_error("JackMachClientChannel::PortRegister err = %s", mach_error_string(res));
184 void JackMachClientChannel::PortUnRegister(int refnum, jack_port_id_t port_index, int* result)
186 kern_return_t res = rpc_jack_port_unregister(fPrivatePort, refnum, port_index, result);
187 if (res != KERN_SUCCESS) {
188 *result = -1;
189 jack_error("JackMachClientChannel::PortUnRegister err = %s", mach_error_string(res));
193 void JackMachClientChannel::PortConnect(int refnum, const char* src, const char* dst, int* result)
195 kern_return_t res = rpc_jack_port_connect_name(fPrivatePort, refnum, (char*)src, (char*)dst, result);
196 if (res != KERN_SUCCESS) {
197 jack_error("JackMachClientChannel::PortConnect err = %s", mach_error_string(res));
201 void JackMachClientChannel::PortDisconnect(int refnum, const char* src, const char* dst, int* result)
203 kern_return_t res = rpc_jack_port_disconnect_name(fPrivatePort, refnum, (char*)src, (char*)dst, result);
204 if (res != KERN_SUCCESS) {
205 *result = -1;
206 jack_error("JackMachClientChannel::PortDisconnect err = %s", mach_error_string(res));
210 void JackMachClientChannel::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result)
212 kern_return_t res = rpc_jack_port_connect(fPrivatePort, refnum, src, dst, result);
213 if (res != KERN_SUCCESS) {
214 *result = -1;
215 jack_error("JackMachClientChannel::PortConnect err = %s", mach_error_string(res));
219 void JackMachClientChannel::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result)
221 kern_return_t res = rpc_jack_port_disconnect(fPrivatePort, refnum, src, dst, result);
222 if (res != KERN_SUCCESS) {
223 *result = -1;
224 jack_error("JackMachClientChannel::PortDisconnect err = %s", mach_error_string(res));
228 void JackMachClientChannel::PortRename(int refnum, jack_port_id_t port, const char* name, int* result)
230 kern_return_t res = rpc_jack_port_rename(fPrivatePort, refnum, port, (char*)name, result);
231 if (res != KERN_SUCCESS) {
232 *result = -1;
233 jack_error("JackMachClientChannel::PortRename err = %s", mach_error_string(res));
237 void JackMachClientChannel::SetBufferSize(jack_nframes_t buffer_size, int* result)
239 kern_return_t res = rpc_jack_set_buffer_size(fPrivatePort, buffer_size, result);
240 if (res != KERN_SUCCESS) {
241 *result = -1;
242 jack_error("JackMachClientChannel::SetBufferSize err = %s", mach_error_string(res));
246 void JackMachClientChannel::SetFreewheel(int onoff, int* result)
248 kern_return_t res = rpc_jack_set_freewheel(fPrivatePort, onoff, result);
249 if (res != KERN_SUCCESS) {
250 *result = -1;
251 jack_error("JackMachClientChannel::SetFreewheel err = %s", mach_error_string(res));
255 void JackMachClientChannel::ReleaseTimebase(int refnum, int* result)
257 kern_return_t res = rpc_jack_release_timebase(fPrivatePort, refnum, result);
258 if (res != KERN_SUCCESS) {
259 *result = -1;
260 jack_error("JackMachClientChannel::ReleaseTimebase err = %s", mach_error_string(res));
264 void JackMachClientChannel::SetTimebaseCallback(int refnum, int conditional, int* result)
266 kern_return_t res = rpc_jack_set_timebase_callback(fPrivatePort, refnum, conditional, result);
267 if (res != KERN_SUCCESS) {
268 *result = -1;
269 jack_error("JackMachClientChannel::SetTimebaseCallback err = %s", mach_error_string(res));
273 void JackMachClientChannel::GetInternalClientName(int refnum, int int_ref, char* name_res, int* result)
275 kern_return_t res = rpc_jack_get_internal_clientname(fPrivatePort, refnum, int_ref, name_res, result);
276 if (res != KERN_SUCCESS) {
277 *result = -1;
278 jack_error("JackMachClientChannel::GetInternalClientName err = %s", mach_error_string(res));
282 void JackMachClientChannel::InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result)
284 kern_return_t res = rpc_jack_internal_clienthandle(fPrivatePort, refnum, (char*)client_name, status, int_ref, result);
285 if (res != KERN_SUCCESS) {
286 *result = -1;
287 jack_error("JackMachClientChannel::InternalClientHandle err = %s", mach_error_string(res));
291 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)
293 const char* int_client_name = (client_name) ? client_name : "";
294 const char* int_so_name = (so_name) ? so_name : "";
295 const char* int_objet_data = (objet_data) ? objet_data : "";
297 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);
298 if (res != KERN_SUCCESS) {
299 *result = -1;
300 jack_error("JackMachClientChannel::InternalClientLoad err = %s", mach_error_string(res));
304 void JackMachClientChannel::InternalClientUnload(int refnum, int int_ref, int* status, int* result)
306 kern_return_t res = rpc_jack_internal_clientunload(fPrivatePort, refnum, int_ref, status, result);
307 if (res != KERN_SUCCESS) {
308 *result = -1;
309 jack_error("JackMachClientChannel::InternalClientUnload err = %s", mach_error_string(res));
313 bool JackMachClientChannel::Init()
315 jack_log("JackMachClientChannel::Init");
316 JackClient* client = gClientTable[fClientPort.GetPort()];
317 return client->Init();
320 bool JackMachClientChannel::Execute()
322 kern_return_t res;
323 if ((res = mach_msg_server(JackRPCClient_server, 1024, fClientPort.GetPort(), 0)) != KERN_SUCCESS) {
324 jack_error("JackMachClientChannel::Execute err = %s", mach_error_string(res));
325 JackClient* client = gClientTable[fClientPort.GetPort()];
326 client->ShutDown();
327 return false;
328 } else {
329 return true;
333 } // end of namespace