Jack2  1.9.7
JackWinNamedPipeClientChannel.cpp
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