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"
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
);
49 if (!fServerPort
.ConnectPort(jack_server_entry_name
)) {
50 jack_error("Cannot connect to server Mach port");
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
);
64 if (!fServerPort
.ConnectPort(jack_server_entry_name
)) {
65 jack_error("Cannot connect to server Mach port");
69 // Check name in server
71 ClientCheck(name
, name_res
, JACK_PROTOCOL_VERSION
, (int)options
, (int*)status
, &result
);
73 int status1
= *status
;
74 if (status1
& JackVersionError
)
75 jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION
);
77 jack_error("Client name = %s conflits with another running client", name
);
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");
90 gClientTable
[fClientPort
.GetPort()] = client
;
94 void JackMachClientChannel::Close()
96 jack_log("JackMachClientChannel::Close");
97 gClientTable
.erase(fClientPort
.GetPort());
98 fServerPort
.DisconnectPort();
99 fClientPort
.DestroyPort();
101 if (fPrivatePort
!= 0) {
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");
123 void JackMachClientChannel::Stop()
125 jack_log("JackMachClientChannel::Stop");
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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()
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()];
332 } // end of namespace