Jack2  1.9.8
JackSocketClientChannel.cpp
1 /*
2 Copyright (C) 2004-2008 Grame
3 
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.
8 
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.
13 
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.
17 
18 */
19 
20 #include "JackSocketClientChannel.h"
21 #include "JackRequest.h"
22 #include "JackClient.h"
23 #include "JackGlobals.h"
24 
25 namespace Jack
26 {
27 
28 JackSocketClientChannel::JackSocketClientChannel():
29  fThread(this)
30 {
31  fNotificationSocket = NULL;
32  fClient = NULL;
33 }
34 
35 JackSocketClientChannel::~JackSocketClientChannel()
36 {
37  delete fNotificationSocket;
38 }
39 
40 int JackSocketClientChannel::ServerCheck(const char* server_name)
41 {
42  jack_log("JackSocketClientChannel::ServerCheck = %s", server_name);
43 
44  // Connect to server
45  if (fRequestSocket.Connect(jack_server_dir, server_name, 0) < 0) {
46  jack_error("Cannot connect to server socket");
47  fRequestSocket.Close();
48  return -1;
49  } else {
50  return 0;
51  }
52 }
53 
54 int JackSocketClientChannel::Open(const char* server_name, const char* name, int uuid, char* name_res, JackClient* obj, jack_options_t options, jack_status_t* status)
55 {
56  int result = 0;
57  jack_log("JackSocketClientChannel::Open name = %s", name);
58 
59  if (fRequestSocket.Connect(jack_server_dir, server_name, 0) < 0) {
60  jack_error("Cannot connect to server socket");
61  goto error;
62  }
63 
64  // Check name in server
65  ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, true);
66  if (result < 0) {
67  int status1 = *status;
68  if (status1 & JackVersionError) {
69  jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION);
70  } else {
71  jack_error("Client name = %s conflits with another running client", name);
72  }
73  goto error;
74  }
75 
76  if (fNotificationListenSocket.Bind(jack_client_dir, name_res, 0) < 0) {
77  jack_error("Cannot bind socket");
78  goto error;
79  }
80 
81  fClient = obj;
82  return 0;
83 
84 error:
85  fRequestSocket.Close();
86  fNotificationListenSocket.Close();
87  return -1;
88 }
89 
90 void JackSocketClientChannel::Close()
91 {
92  fRequestSocket.Close();
93  fNotificationListenSocket.Close();
94  if (fNotificationSocket)
95  fNotificationSocket->Close();
96 }
97 
98 int JackSocketClientChannel::Start()
99 {
100  jack_log("JackSocketClientChannel::Start");
101  /*
102  To be sure notification thread is started before ClientOpen is called.
103  */
104  if (fThread.StartSync() != 0) {
105  jack_error("Cannot start Jack client listener");
106  return -1;
107  } else {
108  return 0;
109  }
110 }
111 
112 void JackSocketClientChannel::Stop()
113 {
114  jack_log("JackSocketClientChannel::Stop");
115  fThread.Kill();
116 }
117 
118 void JackSocketClientChannel::ServerSyncCall(JackRequest* req, JackResult* res, int* result)
119 {
120  if (req->Write(&fRequestSocket) < 0) {
121  jack_error("Could not write request type = %ld", req->fType);
122  *result = -1;
123  return;
124  }
125 
126  if (res->Read(&fRequestSocket) < 0) {
127  jack_error("Could not read result type = %ld", req->fType);
128  *result = -1;
129  return;
130  }
131 
132  *result = res->fResult;
133 }
134 
135 void JackSocketClientChannel::ServerAsyncCall(JackRequest* req, JackResult* res, int* result)
136 {
137  if (req->Write(&fRequestSocket) < 0) {
138  jack_error("Could not write request type = %ld", req->fType);
139  *result = -1;
140  } else {
141  *result = 0;
142  }
143 }
144 
145 void JackSocketClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open)
146 {
147  JackClientCheckRequest req(name, protocol, options, uuid, open);
148  JackClientCheckResult res;
149  ServerSyncCall(&req, &res, result);
150  *status = res.fStatus;
151  strcpy(name_res, res.fName);
152 }
153 
154 void JackSocketClientChannel::ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
155 {
156  JackClientOpenRequest req(name, pid, uuid);
157  JackClientOpenResult res;
158  ServerSyncCall(&req, &res, result);
159  *shared_engine = res.fSharedEngine;
160  *shared_client = res.fSharedClient;
161  *shared_graph = res.fSharedGraph;
162 }
163 
164 void JackSocketClientChannel::ClientClose(int refnum, int* result)
165 {
166  JackClientCloseRequest req(refnum);
167  JackResult res;
168  ServerSyncCall(&req, &res, result);
169 }
170 
171 void JackSocketClientChannel::ClientActivate(int refnum, int is_real_time, int* result)
172 {
173  JackActivateRequest req(refnum, is_real_time);
174  JackResult res;
175  ServerSyncCall(&req, &res, result);
176 }
177 
178 void JackSocketClientChannel::ClientDeactivate(int refnum, int* result)
179 {
180  JackDeactivateRequest req(refnum);
181  JackResult res;
182  ServerSyncCall(&req, &res, result);
183 }
184 
185 void JackSocketClientChannel::PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result)
186 {
187  JackPortRegisterRequest req(refnum, name, type, flags, buffer_size);
188  JackPortRegisterResult res;
189  ServerSyncCall(&req, &res, result);
190  *port_index = res.fPortIndex;
191 }
192 
193 void JackSocketClientChannel::PortUnRegister(int refnum, jack_port_id_t port_index, int* result)
194 {
195  JackPortUnRegisterRequest req(refnum, port_index);
196  JackResult res;
197  ServerSyncCall(&req, &res, result);
198 }
199 
200 void JackSocketClientChannel::PortConnect(int refnum, const char* src, const char* dst, int* result)
201 {
202  JackPortConnectNameRequest req(refnum, src, dst);
203  JackResult res;
204  ServerSyncCall(&req, &res, result);
205 }
206 
207 void JackSocketClientChannel::PortDisconnect(int refnum, const char* src, const char* dst, int* result)
208 {
209  JackPortDisconnectNameRequest req(refnum, src, dst);
210  JackResult res;
211  ServerSyncCall(&req, &res, result);
212 }
213 
214 void JackSocketClientChannel::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result)
215 {
216  JackPortConnectRequest req(refnum, src, dst);
217  JackResult res;
218  ServerSyncCall(&req, &res, result);
219 }
220 
221 void JackSocketClientChannel::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result)
222 {
223  JackPortDisconnectRequest req(refnum, src, dst);
224  JackResult res;
225  ServerSyncCall(&req, &res, result);
226 }
227 
228 void JackSocketClientChannel::PortRename(int refnum, jack_port_id_t port, const char* name, int* result)
229 {
230  JackPortRenameRequest req(refnum, port, name);
231  JackResult res;
232  ServerSyncCall(&req, &res, result);
233 }
234 
235 void JackSocketClientChannel::SetBufferSize(jack_nframes_t buffer_size, int* result)
236 {
237  JackSetBufferSizeRequest req(buffer_size);
238  JackResult res;
239  ServerSyncCall(&req, &res, result);
240 }
241 
242 void JackSocketClientChannel::SetFreewheel(int onoff, int* result)
243 {
244  JackSetFreeWheelRequest req(onoff);
245  JackResult res;
246  ServerSyncCall(&req, &res, result);
247 }
248 
249 void JackSocketClientChannel::ComputeTotalLatencies(int* result)
250 {
251  JackComputeTotalLatenciesRequest req;
252  JackResult res;
253  ServerSyncCall(&req, &res, result);
254 }
255 
256 void JackSocketClientChannel::SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t** result)
257 {
258  JackSessionNotifyRequest req(refnum, path, type, target);
259  JackSessionNotifyResult res;
260  int intresult;
261  ServerSyncCall(&req, &res, &intresult);
262  *result = res.GetCommands();
263 }
264 
265 void JackSocketClientChannel::SessionReply(int refnum, int* result)
266 {
267  JackSessionReplyRequest req(refnum);
268  JackResult res;
269  ServerSyncCall(&req, &res, result);
270 }
271 
272 void JackSocketClientChannel::GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result)
273 {
274  JackGetUUIDRequest req(client_name);
275  JackUUIDResult res;
276  ServerSyncCall(&req, &res, result);
277  strncpy(uuid_res, res.fUUID, JACK_UUID_SIZE);
278 }
279 
280 void JackSocketClientChannel::GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result)
281 {
282  JackGetClientNameRequest req(uuid);
283  JackClientNameResult res;
284  ServerSyncCall(&req, &res, result);
285  strncpy(name_res, res.fName, JACK_CLIENT_NAME_SIZE);
286 }
287 
288 void JackSocketClientChannel::ClientHasSessionCallback(const char* client_name, int* result)
289 {
290  JackClientHasSessionCallbackRequest req(client_name);
291  JackResult res;
292  ServerSyncCall(&req, &res, result);
293 }
294 
295 void JackSocketClientChannel::ReserveClientName(int refnum, const char* client_name, const char* uuid, int* result)
296 {
297  JackReserveNameRequest req(refnum, client_name, uuid);
298  JackResult res;
299  ServerSyncCall(&req, &res, result);
300 }
301 
302 void JackSocketClientChannel::ReleaseTimebase(int refnum, int* result)
303 {
304  JackReleaseTimebaseRequest req(refnum);
305  JackResult res;
306  ServerSyncCall(&req, &res, result);
307 }
308 
309 void JackSocketClientChannel::SetTimebaseCallback(int refnum, int conditional, int* result)
310 {
311  JackSetTimebaseCallbackRequest req(refnum, conditional);
312  JackResult res;
313  ServerSyncCall(&req, &res, result);
314 }
315 
316 void JackSocketClientChannel::GetInternalClientName(int refnum, int int_ref, char* name_res, int* result)
317 {
318  JackGetInternalClientNameRequest req(refnum, int_ref);
319  JackGetInternalClientNameResult res;
320  ServerSyncCall(&req, &res, result);
321  strcpy(name_res, res.fName);
322 }
323 
324 void JackSocketClientChannel::InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result)
325 {
326  JackInternalClientHandleRequest req(refnum, client_name);
327  JackInternalClientHandleResult res;
328  ServerSyncCall(&req, &res, result);
329  *int_ref = res.fIntRefNum;
330  *status = res.fStatus;
331 }
332 
333 void JackSocketClientChannel::InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int uuid, int* result)
334 {
335  JackInternalClientLoadRequest req(refnum, client_name, so_name, objet_data, options, uuid);
336  JackInternalClientLoadResult res;
337  ServerSyncCall(&req, &res, result);
338  *int_ref = res.fIntRefNum;
339  *status = res.fStatus;
340 }
341 
342 void JackSocketClientChannel::InternalClientUnload(int refnum, int int_ref, int* status, int* result)
343 {
344  JackInternalClientUnloadRequest req(refnum, int_ref);
345  JackInternalClientUnloadResult res;
346  ServerSyncCall(&req, &res, result);
347  *status = res.fStatus;
348 }
349 
351 {
352  jack_log("JackSocketClientChannel::Init");
353  fNotificationSocket = fNotificationListenSocket.Accept();
354  // No more needed
355  fNotificationListenSocket.Close();
356 
357  if (!fNotificationSocket) {
358  jack_error("JackSocketClientChannel: cannot establish notication socket");
359  return false;
360  } else {
361  return true;
362  }
363 }
364 
365 bool JackSocketClientChannel::Execute()
366 {
368  JackResult res;
369 
370  if (event.Read(fNotificationSocket) < 0) {
371  jack_error("JackSocketClientChannel read fail");
372  goto error;
373  }
374 
375  res.fResult = fClient->ClientNotify(event.fRefNum, event.fName, event.fNotify, event.fSync, event.fMessage, event.fValue1, event.fValue2);
376 
377  if (event.fSync) {
378  if (res.Write(fNotificationSocket) < 0) {
379  jack_error("JackSocketClientChannel write fail");
380  goto error;
381  }
382  }
383  return true;
384 
385 error:
386  fNotificationSocket->Close();
387  fClient->ShutDown();
388  return false;
389 }
390 
391 } // end of namespace
392 
393 
394 
395 
396