Jack2 1.9.8
|
00001 /* 00002 Copyright (C) 2004-2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as published by 00006 the Free Software Foundation; either version 2.1 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 00018 */ 00019 00020 00021 #include "JackWinNamedPipeClientChannel.h" 00022 #include "JackRequest.h" 00023 #include "JackClient.h" 00024 #include "JackGlobals.h" 00025 #include "JackError.h" 00026 00027 namespace Jack 00028 { 00029 00030 JackWinNamedPipeClientChannel::JackWinNamedPipeClientChannel():fThread(this) 00031 { 00032 fClient = NULL; 00033 } 00034 00035 JackWinNamedPipeClientChannel::~JackWinNamedPipeClientChannel() 00036 {} 00037 00038 int JackWinNamedPipeClientChannel::ServerCheck(const char* server_name) 00039 { 00040 jack_log("JackWinNamedPipeClientChannel::ServerCheck = %s", server_name); 00041 00042 // Connect to server 00043 if (fRequestPipe.Connect(jack_server_dir, server_name, 0) < 0) { 00044 jack_error("Cannot connect to server pipe"); 00045 return -1; 00046 } else { 00047 return 0; 00048 } 00049 } 00050 00051 int JackWinNamedPipeClientChannel::Open(const char* server_name, const char* name, int uuid, char* name_res, JackClient* obj, jack_options_t options, jack_status_t* status) 00052 { 00053 int result = 0; 00054 jack_log("JackWinNamedPipeClientChannel::Open name = %s", name); 00055 00056 /* 00057 16/08/07: was called before doing "fRequestPipe.Connect" .... still necessary? 00058 if (fNotificationListenPipe.Bind(jack_client_dir, name, 0) < 0) { 00059 jack_error("Cannot bind pipe"); 00060 goto error; 00061 } 00062 */ 00063 00064 if (fRequestPipe.Connect(jack_server_dir, server_name, 0) < 0) { 00065 jack_error("Cannot connect to server pipe"); 00066 goto error; 00067 } 00068 00069 // Check name in server 00070 ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, true); 00071 if (result < 0) { 00072 int status1 = *status; 00073 if (status1 & JackVersionError) { 00074 jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION); 00075 } else { 00076 jack_error("Client name = %s conflits with another running client", name); 00077 } 00078 } 00079 00080 if (fNotificationListenPipe.Bind(jack_client_dir, name_res, 0) < 0) { 00081 jack_error("Cannot bind pipe"); 00082 goto error; 00083 } 00084 00085 fClient = obj; 00086 return 0; 00087 00088 error: 00089 fRequestPipe.Close(); 00090 fNotificationListenPipe.Close(); 00091 return -1; 00092 } 00093 00094 void JackWinNamedPipeClientChannel::Close() 00095 { 00096 fRequestPipe.Close(); 00097 fNotificationListenPipe.Close(); 00098 // Here the thread will correctly stop when the pipe are closed 00099 fThread.Stop(); 00100 } 00101 00102 int JackWinNamedPipeClientChannel::Start() 00103 { 00104 jack_log("JackWinNamedPipeClientChannel::Start"); 00105 /* 00106 To be sure notification thread is started before ClientOpen is called. 00107 */ 00108 if (fThread.StartSync() != 0) { 00109 jack_error("Cannot start Jack client listener"); 00110 return -1; 00111 } else { 00112 return 0; 00113 } 00114 } 00115 00116 void JackWinNamedPipeClientChannel::Stop() 00117 { 00118 jack_log("JackWinNamedPipeClientChannel::Stop"); 00119 fThread.Kill(); // Unsafe on WIN32... TODO : solve WIN32 thread Kill issue 00120 } 00121 00122 void JackWinNamedPipeClientChannel::ServerSyncCall(JackRequest* req, JackResult* res, int* result) 00123 { 00124 if (req->Write(&fRequestPipe) < 0) { 00125 jack_error("Could not write request type = %ld", req->fType); 00126 *result = -1; 00127 return ; 00128 } 00129 00130 if (res->Read(&fRequestPipe) < 0) { 00131 jack_error("Could not read result type = %ld", req->fType); 00132 *result = -1; 00133 return ; 00134 } 00135 00136 *result = res->fResult; 00137 } 00138 00139 void JackWinNamedPipeClientChannel::ServerAsyncCall(JackRequest* req, JackResult* res, int* result) 00140 { 00141 if (req->Write(&fRequestPipe) < 0) { 00142 jack_error("Could not write request type = %ld", req->fType); 00143 *result = -1; 00144 } else { 00145 *result = 0; 00146 } 00147 } 00148 00149 void JackWinNamedPipeClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open) 00150 { 00151 JackClientCheckRequest req(name, protocol, options, uuid, open); 00152 JackClientCheckResult res; 00153 ServerSyncCall(&req, &res, result); 00154 *status = res.fStatus; 00155 strcpy(name_res, res.fName); 00156 } 00157 00158 void JackWinNamedPipeClientChannel::ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result) 00159 { 00160 JackClientOpenRequest req(name, pid, uuid); 00161 JackClientOpenResult res; 00162 ServerSyncCall(&req, &res, result); 00163 *shared_engine = res.fSharedEngine; 00164 *shared_client = res.fSharedClient; 00165 *shared_graph = res.fSharedGraph; 00166 } 00167 00168 void JackWinNamedPipeClientChannel::ClientClose(int refnum, int* result) 00169 { 00170 JackClientCloseRequest req(refnum); 00171 JackResult res; 00172 ServerSyncCall(&req, &res, result); 00173 } 00174 00175 void JackWinNamedPipeClientChannel::ClientActivate(int refnum, int is_real_time, int* result) 00176 { 00177 JackActivateRequest req(refnum, is_real_time); 00178 JackResult res; 00179 ServerSyncCall(&req, &res, result); 00180 } 00181 00182 void JackWinNamedPipeClientChannel::ClientDeactivate(int refnum, int* result) 00183 { 00184 JackDeactivateRequest req(refnum); 00185 JackResult res; 00186 ServerSyncCall(&req, &res, result); 00187 } 00188 00189 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) 00190 { 00191 JackPortRegisterRequest req(refnum, name, type, flags, buffer_size); 00192 JackPortRegisterResult res; 00193 ServerSyncCall(&req, &res, result); 00194 *port_index = res.fPortIndex; 00195 } 00196 00197 void JackWinNamedPipeClientChannel::PortUnRegister(int refnum, jack_port_id_t port_index, int* result) 00198 { 00199 JackPortUnRegisterRequest req(refnum, port_index); 00200 JackResult res; 00201 ServerSyncCall(&req, &res, result); 00202 } 00203 00204 void JackWinNamedPipeClientChannel::PortConnect(int refnum, const char* src, const char* dst, int* result) 00205 { 00206 JackPortConnectNameRequest req(refnum, src, dst); 00207 JackResult res; 00208 ServerSyncCall(&req, &res, result); 00209 } 00210 00211 void JackWinNamedPipeClientChannel::PortDisconnect(int refnum, const char* src, const char* dst, int* result) 00212 { 00213 JackPortDisconnectNameRequest req(refnum, src, dst); 00214 JackResult res; 00215 ServerSyncCall(&req, &res, result); 00216 } 00217 00218 void JackWinNamedPipeClientChannel::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result) 00219 { 00220 JackPortConnectRequest req(refnum, src, dst); 00221 JackResult res; 00222 ServerSyncCall(&req, &res, result); 00223 } 00224 00225 void JackWinNamedPipeClientChannel::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result) 00226 { 00227 JackPortDisconnectRequest req(refnum, src, dst); 00228 JackResult res; 00229 ServerSyncCall(&req, &res, result); 00230 } 00231 00232 void JackWinNamedPipeClientChannel::PortRename(int refnum, jack_port_id_t port, const char* name, int* result) 00233 { 00234 JackPortRenameRequest req(refnum, port, name); 00235 JackResult res; 00236 ServerSyncCall(&req, &res, result); 00237 } 00238 00239 void JackWinNamedPipeClientChannel::SetBufferSize(jack_nframes_t buffer_size, int* result) 00240 { 00241 JackSetBufferSizeRequest req(buffer_size); 00242 JackResult res; 00243 ServerSyncCall(&req, &res, result); 00244 } 00245 00246 void JackWinNamedPipeClientChannel::SetFreewheel(int onoff, int* result) 00247 { 00248 JackSetFreeWheelRequest req(onoff); 00249 JackResult res; 00250 ServerSyncCall(&req, &res, result); 00251 } 00252 00253 void JackWinNamedPipeClientChannel::ComputeTotalLatencies(int* result) 00254 { 00255 JackComputeTotalLatenciesRequest req; 00256 JackResult res; 00257 ServerSyncCall(&req, &res, result); 00258 } 00259 00260 void JackWinNamedPipeClientChannel::SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t** result) 00261 { 00262 JackSessionNotifyRequest req(refnum, path, type, target); 00263 JackSessionNotifyResult res; 00264 int intresult; 00265 ServerSyncCall(&req, &res, &intresult); 00266 *result = res.GetCommands(); 00267 } 00268 00269 void JackWinNamedPipeClientChannel::SessionReply(int refnum, int* result) 00270 { 00271 JackSessionReplyRequest req(refnum); 00272 JackResult res; 00273 ServerSyncCall(&req, &res, result); 00274 } 00275 00276 void JackWinNamedPipeClientChannel::GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result) 00277 { 00278 JackGetUUIDRequest req(client_name); 00279 JackUUIDResult res; 00280 ServerSyncCall(&req, &res, result); 00281 strncpy(uuid_res, res.fUUID, JACK_UUID_SIZE); 00282 } 00283 00284 void JackWinNamedPipeClientChannel::GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result) 00285 { 00286 JackGetClientNameRequest req(uuid); 00287 JackClientNameResult res; 00288 ServerSyncCall(&req, &res, result); 00289 strncpy(name_res, res.fName, JACK_CLIENT_NAME_SIZE); 00290 } 00291 00292 void JackWinNamedPipeClientChannel::ClientHasSessionCallback(const char* client_name, int* result) 00293 { 00294 JackClientHasSessionCallbackRequest req(client_name); 00295 JackResult res; 00296 ServerSyncCall(&req, &res, result); 00297 } 00298 00299 void JackWinNamedPipeClientChannel::ReserveClientName(int refnum, const char* client_name, const char* uuid, int* result) 00300 { 00301 JackReserveNameRequest req(refnum, client_name, uuid); 00302 JackResult res; 00303 ServerSyncCall(&req, &res, result); 00304 } 00305 00306 void JackWinNamedPipeClientChannel::ReleaseTimebase(int refnum, int* result) 00307 { 00308 JackReleaseTimebaseRequest req(refnum); 00309 JackResult res; 00310 ServerSyncCall(&req, &res, result); 00311 } 00312 00313 void JackWinNamedPipeClientChannel::SetTimebaseCallback(int refnum, int conditional, int* result) 00314 { 00315 JackSetTimebaseCallbackRequest req(refnum, conditional); 00316 JackResult res; 00317 ServerSyncCall(&req, &res, result); 00318 } 00319 00320 void JackWinNamedPipeClientChannel::GetInternalClientName(int refnum, int int_ref, char* name_res, int* result) 00321 { 00322 JackGetInternalClientNameRequest req(refnum, int_ref); 00323 JackGetInternalClientNameResult res; 00324 ServerSyncCall(&req, &res, result); 00325 strcpy(name_res, res.fName); 00326 } 00327 00328 void JackWinNamedPipeClientChannel::InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result) 00329 { 00330 JackInternalClientHandleRequest req(refnum, client_name); 00331 JackInternalClientHandleResult res; 00332 ServerSyncCall(&req, &res, result); 00333 *int_ref = res.fIntRefNum; 00334 *status = res.fStatus; 00335 } 00336 00337 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 uuid, int* result) 00338 { 00339 JackInternalClientLoadRequest req(refnum, client_name, so_name, objet_data, options, uuid); 00340 JackInternalClientLoadResult res; 00341 ServerSyncCall(&req, &res, result); 00342 *int_ref = res.fIntRefNum; 00343 *status = res.fStatus; 00344 } 00345 00346 void JackWinNamedPipeClientChannel::InternalClientUnload(int refnum, int int_ref, int* status, int* result) 00347 { 00348 JackInternalClientUnloadRequest req(refnum, int_ref); 00349 JackInternalClientUnloadResult res; 00350 ServerSyncCall(&req, &res, result); 00351 *status = res.fStatus; 00352 } 00353 00354 bool JackWinNamedPipeClientChannel::Init() 00355 { 00356 jack_log("JackWinNamedPipeClientChannel::Init"); 00357 00358 if (!fNotificationListenPipe.Accept()) { 00359 jack_error("JackWinNamedPipeClientChannel: cannot establish notification pipe"); 00360 return false; 00361 } else { 00362 return true; 00363 } 00364 } 00365 00366 bool JackWinNamedPipeClientChannel::Execute() 00367 { 00368 JackClientNotification event; 00369 JackResult res; 00370 00371 if (event.Read(&fNotificationListenPipe) < 0) { 00372 jack_error("JackWinNamedPipeClientChannel read fail"); 00373 goto error; 00374 } 00375 00376 res.fResult = fClient->ClientNotify(event.fRefNum, event.fName, event.fNotify, event.fSync, event.fMessage, event.fValue1, event.fValue2); 00377 00378 if (event.fSync) { 00379 if (res.Write(&fNotificationListenPipe) < 0) { 00380 jack_error("JackWinNamedPipeClientChannel write fail"); 00381 goto error; 00382 } 00383 } 00384 return true; 00385 00386 error: 00387 // Close the pipes, server wont be able to create them otherwise. 00388 fNotificationListenPipe.Close(); 00389 fRequestPipe.Close(); 00390 fClient->ShutDown(); 00391 return false; 00392 } 00393 00394 } // end of namespace 00395 00396