Jack2 1.9.8

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, 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