Add a string parameter to server ==> client notification, add a new InfoShutdown...
[jack2.git] / windows / JackWinNamedPipeClientChannel.cpp
blob5a49d5f0b39fb1588248b4ee1605750739d49607
1 /*
2 Copyright (C) 2004-2006 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 "JackWinNamedPipeClientChannel.h"
21 #include "JackRequest.h"
22 #include "JackClient.h"
23 #include "JackGlobals.h"
24 #include "JackError.h"
26 namespace Jack
29 JackWinNamedPipeClientChannel::JackWinNamedPipeClientChannel():fThread(this)
31 fClient = NULL;
34 JackWinNamedPipeClientChannel::~JackWinNamedPipeClientChannel()
37 int JackWinNamedPipeClientChannel::ServerCheck(const char* server_name)
39 jack_log("JackWinNamedPipeClientChannel::ServerCheck = %s", server_name);
41 // Connect to server
42 if (fRequestPipe.Connect(jack_server_dir, server_name, 0) < 0) {
43 jack_error("Cannot connect to server pipe");
44 return -1;
45 } else {
46 return 0;
50 int JackWinNamedPipeClientChannel::Open(const char* server_name, const char* name, char* name_res, JackClient* obj, jack_options_t options, jack_status_t* status)
52 int result = 0;
53 jack_log("JackWinNamedPipeClientChannel::Open name = %s", name);
56 16/08/07: was called before doing "fRequestPipe.Connect" .... still necessary?
57 if (fNotificationListenPipe.Bind(jack_client_dir, name, 0) < 0) {
58 jack_error("Cannot bind pipe");
59 goto error;
63 if (fRequestPipe.Connect(jack_server_dir, server_name, 0) < 0) {
64 jack_error("Cannot connect to server pipe");
65 goto error;
68 // Check name in server
69 ClientCheck(name, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result);
70 if (result < 0) {
71 jack_error("Client name = %s conflits with another running client", name);
72 goto error;
75 if (fNotificationListenPipe.Bind(jack_client_dir, name_res, 0) < 0) {
76 jack_error("Cannot bind pipe");
77 goto error;
80 fClient = obj;
81 return 0;
83 error:
84 fRequestPipe.Close();
85 fNotificationListenPipe.Close();
86 return -1;
89 void JackWinNamedPipeClientChannel::Close()
91 fRequestPipe.Close();
92 fNotificationListenPipe.Close();
93 // Here the thread will correctly stop when the pipe are closed
94 fThread.Stop();
97 int JackWinNamedPipeClientChannel::Start()
99 jack_log("JackWinNamedPipeClientChannel::Start");
101 To be sure notification thread is started before ClientOpen is called.
103 if (fThread.StartSync() != 0) {
104 jack_error("Cannot start Jack client listener");
105 return -1;
106 } else {
107 return 0;
111 void JackWinNamedPipeClientChannel::Stop()
113 jack_log("JackWinNamedPipeClientChannel::Stop");
114 fThread.Kill(); // Unsafe on WIN32... TODO : solve WIN32 thread Kill issue
117 void JackWinNamedPipeClientChannel::ServerSyncCall(JackRequest* req, JackResult* res, int* result)
119 if (req->Write(&fRequestPipe) < 0) {
120 jack_error("Could not write request type = %ld", req->fType);
121 *result = -1;
122 return ;
125 if (res->Read(&fRequestPipe) < 0) {
126 jack_error("Could not read result type = %ld", req->fType);
127 *result = -1;
128 return ;
131 *result = res->fResult;
134 void JackWinNamedPipeClientChannel::ServerAsyncCall(JackRequest* req, JackResult* res, int* result)
136 if (req->Write(&fRequestPipe) < 0) {
137 jack_error("Could not write request type = %ld", req->fType);
138 *result = -1;
139 } else {
140 *result = 0;
144 void JackWinNamedPipeClientChannel::ClientCheck(const char* name, char* name_res, int protocol, int options, int* status, int* result)
146 JackClientCheckRequest req(name, protocol, options);
147 JackClientCheckResult res;
148 ServerSyncCall(&req, &res, result);
149 *status = res.fStatus;
150 strcpy(name_res, res.fName);
153 void JackWinNamedPipeClientChannel::ClientOpen(const char* name, int pid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
155 JackClientOpenRequest req(name, pid);
156 JackClientOpenResult res;
157 ServerSyncCall(&req, &res, result);
158 *shared_engine = res.fSharedEngine;
159 *shared_client = res.fSharedClient;
160 *shared_graph = res.fSharedGraph;
163 void JackWinNamedPipeClientChannel::ClientClose(int refnum, int* result)
165 JackClientCloseRequest req(refnum);
166 JackResult res;
167 ServerSyncCall(&req, &res, result);
170 void JackWinNamedPipeClientChannel::ClientActivate(int refnum, int state, int* result)
172 JackActivateRequest req(refnum, state);
173 JackResult res;
174 ServerSyncCall(&req, &res, result);
177 void JackWinNamedPipeClientChannel::ClientDeactivate(int refnum, int* result)
179 JackDeactivateRequest req(refnum);
180 JackResult res;
181 ServerSyncCall(&req, &res, result);
184 void JackWinNamedPipeClientChannel::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 JackPortRegisterRequest req(refnum, name, type, flags, buffer_size);
187 JackPortRegisterResult res;
188 ServerSyncCall(&req, &res, result);
189 *port_index = res.fPortIndex;
192 void JackWinNamedPipeClientChannel::PortUnRegister(int refnum, jack_port_id_t port_index, int* result)
194 JackPortUnRegisterRequest req(refnum, port_index);
195 JackResult res;
196 ServerSyncCall(&req, &res, result);
199 void JackWinNamedPipeClientChannel::PortConnect(int refnum, const char* src, const char* dst, int* result)
201 JackPortConnectNameRequest req(refnum, src, dst);
202 JackResult res;
203 ServerSyncCall(&req, &res, result);
206 void JackWinNamedPipeClientChannel::PortDisconnect(int refnum, const char* src, const char* dst, int* result)
208 JackPortDisconnectNameRequest req(refnum, src, dst);
209 JackResult res;
210 ServerSyncCall(&req, &res, result);
213 void JackWinNamedPipeClientChannel::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result)
215 JackPortConnectRequest req(refnum, src, dst);
216 JackResult res;
217 ServerSyncCall(&req, &res, result);
220 void JackWinNamedPipeClientChannel::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result)
222 JackPortDisconnectRequest req(refnum, src, dst);
223 JackResult res;
224 ServerSyncCall(&req, &res, result);
227 void JackWinNamedPipeClientChannel::PortRename(int refnum, jack_port_id_t port, const char* name, int* result)
229 JackPortRenameRequest req(refnum, port, name);
230 JackResult res;
231 ServerSyncCall(&req, &res, result);
234 void JackWinNamedPipeClientChannel::SetBufferSize(jack_nframes_t buffer_size, int* result)
236 JackSetBufferSizeRequest req(buffer_size);
237 JackResult res;
238 ServerSyncCall(&req, &res, result);
241 void JackWinNamedPipeClientChannel::SetFreewheel(int onoff, int* result)
243 JackSetFreeWheelRequest req(onoff);
244 JackResult res;
245 ServerSyncCall(&req, &res, result);
248 void JackWinNamedPipeClientChannel::ReleaseTimebase(int refnum, int* result)
250 JackReleaseTimebaseRequest req(refnum);
251 JackResult res;
252 ServerSyncCall(&req, &res, result);
255 void JackWinNamedPipeClientChannel::SetTimebaseCallback(int refnum, int conditional, int* result)
257 JackSetTimebaseCallbackRequest req(refnum, conditional);
258 JackResult res;
259 ServerSyncCall(&req, &res, result);
262 void JackWinNamedPipeClientChannel::GetInternalClientName(int refnum, int int_ref, char* name_res, int* result)
264 JackGetInternalClientNameRequest req(refnum, int_ref);
265 JackGetInternalClientNameResult res;
266 ServerSyncCall(&req, &res, result);
267 strcpy(name_res, res.fName);
270 void JackWinNamedPipeClientChannel::InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result)
272 JackInternalClientHandleRequest req(refnum, client_name);
273 JackInternalClientHandleResult res;
274 ServerSyncCall(&req, &res, result);
275 *int_ref = res.fIntRefNum;
276 *status = res.fStatus;
279 void JackWinNamedPipeClientChannel::InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int* result)
281 JackInternalClientLoadRequest req(refnum, client_name, so_name, objet_data, options);
282 JackInternalClientLoadResult res;
283 ServerSyncCall(&req, &res, result);
284 *int_ref = res.fIntRefNum;
285 *status = res.fStatus;
288 void JackWinNamedPipeClientChannel::InternalClientUnload(int refnum, int int_ref, int* status, int* result)
290 JackInternalClientUnloadRequest req(refnum, int_ref);
291 JackInternalClientUnloadResult res;
292 ServerSyncCall(&req, &res, result);
293 *status = res.fStatus;
296 bool JackWinNamedPipeClientChannel::Init()
298 jack_log("JackWinNamedPipeClientChannel::Init");
300 if (!fNotificationListenPipe.Accept()) {
301 jack_error("JackWinNamedPipeClientChannel: cannot establish notification pipe");
302 return false;
303 } else {
304 return fClient->Init();
308 bool JackWinNamedPipeClientChannel::Execute()
310 JackClientNotification event;
311 JackResult res;
313 if (event.Read(&fNotificationListenPipe) < 0) {
314 jack_error("JackWinNamedPipeClientChannel read fail");
315 goto error;
318 res.fResult = fClient->ClientNotify(event.fRefNum, event.fName, event.fNotify, event.fSync, event.fMessage, event.fValue1, event.fValue2);
320 if (event.fSync) {
321 if (res.Write(&fNotificationListenPipe) < 0) {
322 jack_error("JackWinNamedPipeClientChannel write fail");
323 goto error;
326 return true;
328 error:
329 // Close the pipes, server wont be able to create them otherwise.
330 fNotificationListenPipe.Close();
331 fRequestPipe.Close();
332 fClient->ShutDown();
333 return false;
336 } // end of namespace