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"
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
);
50 if (!fServerPort
.ConnectPort(jack_server_entry_name
)) {
51 jack_error("Cannot connect to server Mach port");
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
);
65 if (!fServerPort
.ConnectPort(jack_server_entry_name
)) {
66 jack_error("Cannot connect to server Mach port");
70 // Check name in server
72 ClientCheck(name
, name_res
, JACK_PROTOCOL_VERSION
, (int)options
, (int*)status
, &result
);
74 int status1
= *status
;
75 if (status1
& JackVersionError
)
76 jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION
);
78 jack_error("Client name = %s conflits with another running client", name
);
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");
91 gClientTable
[fClientPort
.GetPort()] = client
;
95 void JackMachClientChannel::Close()
97 jack_log("JackMachClientChannel::Close");
98 gClientTable
.erase(fClientPort
.GetPort());
99 fServerPort
.DisconnectPort();
100 fClientPort
.DestroyPort();
102 if (fPrivatePort
!= 0) {
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");
124 void JackMachClientChannel::Stop()
126 jack_log("JackMachClientChannel::Stop");
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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()
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()];
333 } // end of namespace