Merge branch 'master' into port_register_notification_defer
[jack2.git] / macosx / JackMachClientChannel.cpp
blobf5f88504ee416e14bd06e82dbf0bdda70e44ffae
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 "JackMachThread.h"
27 #include "JackConstants.h"
29 namespace Jack
32 std::map<mach_port_t, JackClient*> gClientTable;
34 JackMachClientChannel::JackMachClientChannel():fPrivatePort(0),fThread(this)
37 JackMachClientChannel::~JackMachClientChannel()
40 // Server <===> client
42 int JackMachClientChannel::ServerCheck(const char* server_name)
44 jack_log("JackMachClientChannel::ServerCheck = %s", server_name);
45 char jack_server_entry_name[512];
46 snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s.%d_%s", jack_server_entry, JackTools::GetUID(), server_name);
48 // Connect to server
49 if (!fServerPort.ConnectPort(jack_server_entry_name)) {
50 jack_error("Cannot connect to server Mach port");
51 return -1;
52 } else {
53 return 0;
57 int JackMachClientChannel::Open(const char* server_name, const char* name, char* name_res, JackClient* client, jack_options_t options, jack_status_t* status)
59 jack_log("JackMachClientChannel::Open name = %s", name);
60 char jack_server_entry_name[512];
61 snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s.%d_%s", jack_server_entry, JackTools::GetUID(), server_name);
63 // Connect to server
64 if (!fServerPort.ConnectPort(jack_server_entry_name)) {
65 jack_error("Cannot connect to server Mach port");
66 return -1;
69 // Check name in server
70 int result = 0;
71 ClientCheck(name, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result);
72 if (result < 0) {
73 int status1 = *status;
74 if (status1 & JackVersionError)
75 jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION);
76 else
77 jack_error("Client name = %s conflits with another running client", name);
78 return -1;
81 // Prepare local port using client name
82 char buf[JACK_CLIENT_NAME_SIZE + 1];
83 snprintf(buf, sizeof(buf) - 1, "%s:%s", jack_client_entry, name_res);
85 if (!fClientPort.AllocatePort(buf, 16)) {
86 jack_error("Cannot allocate client Mach port");
87 return -1;
90 gClientTable[fClientPort.GetPort()] = client;
91 return 0;
94 void JackMachClientChannel::Close()
96 jack_log("JackMachClientChannel::Close");
97 gClientTable.erase(fClientPort.GetPort());
98 fServerPort.DisconnectPort();
99 fClientPort.DestroyPort();
101 if (fPrivatePort != 0) {
102 kern_return_t res;
103 if ((res = mach_port_destroy(mach_task_self(), fPrivatePort)) != KERN_SUCCESS) {
104 jack_error("JackMachClientChannel::Close err = %s", mach_error_string(res));
109 int JackMachClientChannel::Start()
111 jack_log("JackMachClientChannel::Start");
113 To be sure notification thread is started before ClientOpen is called.
115 if (fThread.StartSync() != 0) {
116 jack_error("Cannot start Jack client listener");
117 return -1;
118 } else {
119 return 0;
123 void JackMachClientChannel::Stop()
125 jack_log("JackMachClientChannel::Stop");
126 fThread.Kill();
129 void JackMachClientChannel::ClientCheck(const char* name, char* name_res, int protocol, int options, int* status, int* result)
131 kern_return_t res = rpc_jack_client_check(fServerPort.GetPort(), (char*)name, name_res, protocol, options, status, result);
132 if (res != KERN_SUCCESS) {
133 *result = -1;
134 jack_error("JackMachClientChannel::ClientCheck err = %s", mach_error_string(res));
138 void JackMachClientChannel::ClientOpen(const char* name, int pid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
140 kern_return_t res = rpc_jack_client_open(fServerPort.GetPort(), (char*)name, pid, &fPrivatePort, shared_engine, shared_client, shared_graph, result);
141 if (res != KERN_SUCCESS) {
142 *result = -1;
143 jack_error("JackMachClientChannel::ClientOpen err = %s", mach_error_string(res));
147 void JackMachClientChannel::ClientClose(int refnum, int* result)
149 kern_return_t res = rpc_jack_client_close(fPrivatePort, refnum, result);
150 if (res != KERN_SUCCESS) {
151 *result = -1;
152 jack_error("JackMachClientChannel::ClientClose err = %s", mach_error_string(res));
156 void JackMachClientChannel::ClientActivate(int refnum, int is_real_time, int* result)
158 kern_return_t res = rpc_jack_client_activate(fPrivatePort, refnum, is_real_time, result);
159 if (res != KERN_SUCCESS) {
160 *result = -1;
161 jack_error("JackMachClientChannel::ClientActivate err = %s", mach_error_string(res));
165 void JackMachClientChannel::ClientDeactivate(int refnum, int* result)
167 kern_return_t res = rpc_jack_client_deactivate(fPrivatePort, refnum, result);
168 if (res != KERN_SUCCESS) {
169 *result = -1;
170 jack_error("JackMachClientChannel::ClientDeactivate err = %s", mach_error_string(res));
174 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)
176 kern_return_t res = rpc_jack_port_register(fPrivatePort, refnum, (char*)name, (char*)type, flags, buffer_size, port_index, result);
177 if (res != KERN_SUCCESS) {
178 *result = -1;
179 jack_error("JackMachClientChannel::PortRegister err = %s", mach_error_string(res));
183 void JackMachClientChannel::PortUnRegister(int refnum, jack_port_id_t port_index, int* result)
185 kern_return_t res = rpc_jack_port_unregister(fPrivatePort, refnum, port_index, result);
186 if (res != KERN_SUCCESS) {
187 *result = -1;
188 jack_error("JackMachClientChannel::PortUnRegister err = %s", mach_error_string(res));
192 void JackMachClientChannel::PortConnect(int refnum, const char* src, const char* dst, int* result)
194 kern_return_t res = rpc_jack_port_connect_name(fPrivatePort, refnum, (char*)src, (char*)dst, result);
195 if (res != KERN_SUCCESS) {
196 jack_error("JackMachClientChannel::PortConnect err = %s", mach_error_string(res));
200 void JackMachClientChannel::PortDisconnect(int refnum, const char* src, const char* dst, int* result)
202 kern_return_t res = rpc_jack_port_disconnect_name(fPrivatePort, refnum, (char*)src, (char*)dst, result);
203 if (res != KERN_SUCCESS) {
204 *result = -1;
205 jack_error("JackMachClientChannel::PortDisconnect err = %s", mach_error_string(res));
209 void JackMachClientChannel::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result)
211 kern_return_t res = rpc_jack_port_connect(fPrivatePort, refnum, src, dst, result);
212 if (res != KERN_SUCCESS) {
213 *result = -1;
214 jack_error("JackMachClientChannel::PortConnect err = %s", mach_error_string(res));
218 void JackMachClientChannel::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result)
220 kern_return_t res = rpc_jack_port_disconnect(fPrivatePort, refnum, src, dst, result);
221 if (res != KERN_SUCCESS) {
222 *result = -1;
223 jack_error("JackMachClientChannel::PortDisconnect err = %s", mach_error_string(res));
227 void JackMachClientChannel::PortRename(int refnum, jack_port_id_t port, const char* name, int* result)
229 kern_return_t res = rpc_jack_port_rename(fPrivatePort, refnum, port, (char*)name, result);
230 if (res != KERN_SUCCESS) {
231 *result = -1;
232 jack_error("JackMachClientChannel::PortRename err = %s", mach_error_string(res));
236 void JackMachClientChannel::SetBufferSize(jack_nframes_t buffer_size, int* result)
238 kern_return_t res = rpc_jack_set_buffer_size(fPrivatePort, buffer_size, result);
239 if (res != KERN_SUCCESS) {
240 *result = -1;
241 jack_error("JackMachClientChannel::SetBufferSize err = %s", mach_error_string(res));
245 void JackMachClientChannel::SetFreewheel(int onoff, int* result)
247 kern_return_t res = rpc_jack_set_freewheel(fPrivatePort, onoff, result);
248 if (res != KERN_SUCCESS) {
249 *result = -1;
250 jack_error("JackMachClientChannel::SetFreewheel err = %s", mach_error_string(res));
254 void JackMachClientChannel::ReleaseTimebase(int refnum, int* result)
256 kern_return_t res = rpc_jack_release_timebase(fPrivatePort, refnum, result);
257 if (res != KERN_SUCCESS) {
258 *result = -1;
259 jack_error("JackMachClientChannel::ReleaseTimebase err = %s", mach_error_string(res));
263 void JackMachClientChannel::SetTimebaseCallback(int refnum, int conditional, int* result)
265 kern_return_t res = rpc_jack_set_timebase_callback(fPrivatePort, refnum, conditional, result);
266 if (res != KERN_SUCCESS) {
267 *result = -1;
268 jack_error("JackMachClientChannel::SetTimebaseCallback err = %s", mach_error_string(res));
272 void JackMachClientChannel::GetInternalClientName(int refnum, int int_ref, char* name_res, int* result)
274 kern_return_t res = rpc_jack_get_internal_clientname(fPrivatePort, refnum, int_ref, name_res, result);
275 if (res != KERN_SUCCESS) {
276 *result = -1;
277 jack_error("JackMachClientChannel::GetInternalClientName err = %s", mach_error_string(res));
281 void JackMachClientChannel::InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result)
283 kern_return_t res = rpc_jack_internal_clienthandle(fPrivatePort, refnum, (char*)client_name, status, int_ref, result);
284 if (res != KERN_SUCCESS) {
285 *result = -1;
286 jack_error("JackMachClientChannel::InternalClientHandle err = %s", mach_error_string(res));
290 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)
292 const char* int_client_name = (client_name) ? client_name : "";
293 const char* int_so_name = (so_name) ? so_name : "";
294 const char* int_objet_data = (objet_data) ? objet_data : "";
296 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);
297 if (res != KERN_SUCCESS) {
298 *result = -1;
299 jack_error("JackMachClientChannel::InternalClientLoad err = %s", mach_error_string(res));
303 void JackMachClientChannel::InternalClientUnload(int refnum, int int_ref, int* status, int* result)
305 kern_return_t res = rpc_jack_internal_clientunload(fPrivatePort, refnum, int_ref, status, result);
306 if (res != KERN_SUCCESS) {
307 *result = -1;
308 jack_error("JackMachClientChannel::InternalClientUnload err = %s", mach_error_string(res));
312 bool JackMachClientChannel::Init()
314 jack_log("JackMachClientChannel::Init");
315 JackClient* client = gClientTable[fClientPort.GetPort()];
316 return client->Init();
319 bool JackMachClientChannel::Execute()
321 kern_return_t res;
322 if ((res = mach_msg_server(JackRPCClient_server, 1024, fClientPort.GetPort(), 0)) != KERN_SUCCESS) {
323 jack_error("JackMachClientChannel::Execute err = %s", mach_error_string(res));
324 JackClient* client = gClientTable[fClientPort.GetPort()];
325 client->ShutDown();
326 return false;
327 } else {
328 return true;
332 } // end of namespace