Jack2 1.9.7
|
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); 00071 if (result < 0) { 00072 jack_error("Client name = %s conflits with another running client", name); 00073 goto error; 00074 } 00075 00076 if (fNotificationListenPipe.Bind(jack_client_dir, name_res, 0) < 0) { 00077 jack_error("Cannot bind pipe"); 00078 goto error; 00079 } 00080 00081 fClient = obj; 00082 return 0; 00083 00084 error: 00085 fRequestPipe.Close(); 00086 fNotificationListenPipe.Close(); 00087 return -1; 00088 } 00089 00090 void JackWinNamedPipeClientChannel::Close() 00091 { 00092 fRequestPipe.Close(); 00093 fNotificationListenPipe.Close(); 00094 // Here the thread will correctly stop when the pipe are closed 00095 fThread.Stop(); 00096 } 00097 00098 int JackWinNamedPipeClientChannel::Start() 00099 { 00100 jack_log("JackWinNamedPipeClientChannel::Start"); 00101 /* 00102 To be sure notification thread is started before ClientOpen is called. 00103 */ 00104 if (fThread.StartSync() != 0) { 00105 jack_error("Cannot start Jack client listener"); 00106 return -1; 00107 } else { 00108 return 0; 00109 } 00110 } 00111 00112 void JackWinNamedPipeClientChannel::Stop() 00113 { 00114 jack_log("JackWinNamedPipeClientChannel::Stop"); 00115 fThread.Kill(); // Unsafe on WIN32... TODO : solve WIN32 thread Kill issue 00116 } 00117 00118 void JackWinNamedPipeClientChannel::ServerSyncCall(JackRequest* req, JackResult* res, int* result) 00119 { 00120 if (req->Write(&fRequestPipe) < 0) { 00121 jack_error("Could not write request type = %ld", req->fType); 00122 *result = -1; 00123 return ; 00124 } 00125 00126 if (res->Read(&fRequestPipe) < 0) { 00127 jack_error("Could not read result type = %ld", req->fType); 00128 *result = -1; 00129 return ; 00130 } 00131 00132 *result = res->fResult; 00133 } 00134 00135 void JackWinNamedPipeClientChannel::ServerAsyncCall(JackRequest* req, JackResult* res, int* result) 00136 { 00137 if (req->Write(&fRequestPipe) < 0) { 00138 jack_error("Could not write request type = %ld", req->fType); 00139 *result = -1; 00140 } else { 00141 *result = 0; 00142 } 00143 } 00144 00145 void JackWinNamedPipeClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result) 00146 { 00147 JackClientCheckRequest req(name, protocol, options, uuid); 00148 JackClientCheckResult res; 00149 ServerSyncCall(&req, &res, result); 00150 *status = res.fStatus; 00151 strcpy(name_res, res.fName); 00152 } 00153 00154 void JackWinNamedPipeClientChannel::ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result) 00155 { 00156 JackClientOpenRequest req(name, pid, uuid); 00157 JackClientOpenResult res; 00158 ServerSyncCall(&req, &res, result); 00159 *shared_engine = res.fSharedEngine; 00160 *shared_client = res.fSharedClient; 00161 *shared_graph = res.fSharedGraph; 00162 } 00163 00164 void JackWinNamedPipeClientChannel::ClientClose(int refnum, int* result) 00165 { 00166 JackClientCloseRequest req(refnum); 00167 JackResult res; 00168 ServerSyncCall(&req, &res, result); 00169 } 00170 00171 void JackWinNamedPipeClientChannel::ClientActivate(int refnum, int is_real_time, int* result) 00172 { 00173 JackActivateRequest req(refnum, is_real_time); 00174 JackResult res; 00175 ServerSyncCall(&req, &res, result); 00176 } 00177 00178 void JackWinNamedPipeClientChannel::ClientDeactivate(int refnum, int* result) 00179 { 00180 JackDeactivateRequest req(refnum); 00181 JackResult res; 00182 ServerSyncCall(&req, &res, result); 00183 } 00184 00185 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) 00186 { 00187 JackPortRegisterRequest req(refnum, name, type, flags, buffer_size); 00188 JackPortRegisterResult res; 00189 ServerSyncCall(&req, &res, result); 00190 *port_index = res.fPortIndex; 00191 } 00192 00193 void JackWinNamedPipeClientChannel::PortUnRegister(int refnum, jack_port_id_t port_index, int* result) 00194 { 00195 JackPortUnRegisterRequest req(refnum, port_index); 00196 JackResult res; 00197 ServerSyncCall(&req, &res, result); 00198 } 00199 00200 void JackWinNamedPipeClientChannel::PortConnect(int refnum, const char* src, const char* dst, int* result) 00201 { 00202 JackPortConnectNameRequest req(refnum, src, dst); 00203 JackResult res; 00204 ServerSyncCall(&req, &res, result); 00205 } 00206 00207 void JackWinNamedPipeClientChannel::PortDisconnect(int refnum, const char* src, const char* dst, int* result) 00208 { 00209 JackPortDisconnectNameRequest req(refnum, src, dst); 00210 JackResult res; 00211 ServerSyncCall(&req, &res, result); 00212 } 00213 00214 void JackWinNamedPipeClientChannel::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result) 00215 { 00216 JackPortConnectRequest req(refnum, src, dst); 00217 JackResult res; 00218 ServerSyncCall(&req, &res, result); 00219 } 00220 00221 void JackWinNamedPipeClientChannel::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result) 00222 { 00223 JackPortDisconnectRequest req(refnum, src, dst); 00224 JackResult res; 00225 ServerSyncCall(&req, &res, result); 00226 } 00227 00228 void JackWinNamedPipeClientChannel::PortRename(int refnum, jack_port_id_t port, const char* name, int* result) 00229 { 00230 JackPortRenameRequest req(refnum, port, name); 00231 JackResult res; 00232 ServerSyncCall(&req, &res, result); 00233 } 00234 00235 void JackWinNamedPipeClientChannel::SetBufferSize(jack_nframes_t buffer_size, int* result) 00236 { 00237 JackSetBufferSizeRequest req(buffer_size); 00238 JackResult res; 00239 ServerSyncCall(&req, &res, result); 00240 } 00241 00242 void JackWinNamedPipeClientChannel::SetFreewheel(int onoff, int* result) 00243 { 00244 JackSetFreeWheelRequest req(onoff); 00245 JackResult res; 00246 ServerSyncCall(&req, &res, result); 00247 } 00248 00249 void JackWinNamedPipeClientChannel::ComputeTotalLatencies(int* result) 00250 { 00251 JackComputeTotalLatenciesRequest req; 00252 JackResult res; 00253 ServerSyncCall(&req, &res, result); 00254 } 00255 00256 void JackWinNamedPipeClientChannel::SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t** result) 00257 { 00258 JackSessionNotifyRequest req(refnum, path, type, target); 00259 JackSessionNotifyResult res; 00260 int intresult; 00261 ServerSyncCall(&req, &res, &intresult); 00262 00263 jack_session_command_t* session_command = (jack_session_command_t *)malloc(sizeof(jack_session_command_t) * (res.fCommandList.size() + 1)); 00264 int i = 0; 00265 00266 for (std::list<JackSessionCommand>::iterator ci=res.fCommandList.begin(); ci!=res.fCommandList.end(); ci++) { 00267 session_command[i].uuid = strdup( ci->fUUID ); 00268 session_command[i].client_name = strdup( ci->fClientName ); 00269 session_command[i].command = strdup( ci->fCommand ); 00270 session_command[i].flags = ci->fFlags; 00271 i += 1; 00272 } 00273 00274 session_command[i].uuid = NULL; 00275 session_command[i].client_name = NULL; 00276 session_command[i].command = NULL; 00277 session_command[i].flags = (jack_session_flags_t)0; 00278 00279 *result = session_command; 00280 } 00281 00282 void JackWinNamedPipeClientChannel::SessionReply(int refnum, int* result) 00283 { 00284 JackSessionReplyRequest req(refnum); 00285 JackResult res; 00286 ServerSyncCall(&req, &res, result); 00287 } 00288 00289 void JackWinNamedPipeClientChannel::GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result) 00290 { 00291 JackGetUUIDRequest req(client_name); 00292 JackUUIDResult res; 00293 ServerSyncCall(&req, &res, result); 00294 strncpy(uuid_res, res.fUUID, JACK_UUID_SIZE); 00295 } 00296 00297 void JackWinNamedPipeClientChannel::GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result) 00298 { 00299 JackGetClientNameRequest req(uuid); 00300 JackClientNameResult res; 00301 ServerSyncCall(&req, &res, result); 00302 strncpy(name_res, res.fName, JACK_CLIENT_NAME_SIZE); 00303 } 00304 00305 void JackWinNamedPipeClientChannel::ClientHasSessionCallback(const char* client_name, int* result) 00306 { 00307 JackClientHasSessionCallbackRequest req(client_name); 00308 JackResult res; 00309 ServerSyncCall(&req, &res, result); 00310 } 00311 00312 void JackWinNamedPipeClientChannel::ReserveClientName(int refnum, const char* client_name, const char* uuid, int* result) 00313 { 00314 JackReserveNameRequest req(refnum, client_name, uuid); 00315 JackResult res; 00316 ServerSyncCall(&req, &res, result); 00317 } 00318 00319 void JackWinNamedPipeClientChannel::ReleaseTimebase(int refnum, int* result) 00320 { 00321 JackReleaseTimebaseRequest req(refnum); 00322 JackResult res; 00323 ServerSyncCall(&req, &res, result); 00324 } 00325 00326 void JackWinNamedPipeClientChannel::SetTimebaseCallback(int refnum, int conditional, int* result) 00327 { 00328 JackSetTimebaseCallbackRequest req(refnum, conditional); 00329 JackResult res; 00330 ServerSyncCall(&req, &res, result); 00331 } 00332 00333 void JackWinNamedPipeClientChannel::GetInternalClientName(int refnum, int int_ref, char* name_res, int* result) 00334 { 00335 JackGetInternalClientNameRequest req(refnum, int_ref); 00336 JackGetInternalClientNameResult res; 00337 ServerSyncCall(&req, &res, result); 00338 strcpy(name_res, res.fName); 00339 } 00340 00341 void JackWinNamedPipeClientChannel::InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result) 00342 { 00343 JackInternalClientHandleRequest req(refnum, client_name); 00344 JackInternalClientHandleResult res; 00345 ServerSyncCall(&req, &res, result); 00346 *int_ref = res.fIntRefNum; 00347 *status = res.fStatus; 00348 } 00349 00350 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) 00351 { 00352 JackInternalClientLoadRequest req(refnum, client_name, so_name, objet_data, options, uuid); 00353 JackInternalClientLoadResult res; 00354 ServerSyncCall(&req, &res, result); 00355 *int_ref = res.fIntRefNum; 00356 *status = res.fStatus; 00357 } 00358 00359 void JackWinNamedPipeClientChannel::InternalClientUnload(int refnum, int int_ref, int* status, int* result) 00360 { 00361 JackInternalClientUnloadRequest req(refnum, int_ref); 00362 JackInternalClientUnloadResult res; 00363 ServerSyncCall(&req, &res, result); 00364 *status = res.fStatus; 00365 } 00366 00367 bool JackWinNamedPipeClientChannel::Init() 00368 { 00369 jack_log("JackWinNamedPipeClientChannel::Init"); 00370 00371 if (!fNotificationListenPipe.Accept()) { 00372 jack_error("JackWinNamedPipeClientChannel: cannot establish notification pipe"); 00373 return false; 00374 } else { 00375 return true; 00376 } 00377 } 00378 00379 bool JackWinNamedPipeClientChannel::Execute() 00380 { 00381 JackClientNotification event; 00382 JackResult res; 00383 00384 if (event.Read(&fNotificationListenPipe) < 0) { 00385 jack_error("JackWinNamedPipeClientChannel read fail"); 00386 goto error; 00387 } 00388 00389 res.fResult = fClient->ClientNotify(event.fRefNum, event.fName, event.fNotify, event.fSync, event.fMessage, event.fValue1, event.fValue2); 00390 00391 if (event.fSync) { 00392 if (res.Write(&fNotificationListenPipe) < 0) { 00393 jack_error("JackWinNamedPipeClientChannel write fail"); 00394 goto error; 00395 } 00396 } 00397 return true; 00398 00399 error: 00400 // Close the pipes, server wont be able to create them otherwise. 00401 fNotificationListenPipe.Close(); 00402 fRequestPipe.Close(); 00403 fClient->ShutDown(); 00404 return false; 00405 } 00406 00407 } // end of namespace 00408 00409