Jack2 1.9.6

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, 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, 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, char* name_res, int protocol, int options, int* status, int* result)
00146 {
00147     JackClientCheckRequest req(name, protocol, options);
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* shared_engine, int* shared_client, int* shared_graph, int* result)
00155 {
00156     JackClientOpenRequest req(name, pid);
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::ReleaseTimebase(int refnum, int* result)
00250 {
00251     JackReleaseTimebaseRequest req(refnum);
00252     JackResult res;
00253     ServerSyncCall(&req, &res, result);
00254 }
00255 
00256 void JackWinNamedPipeClientChannel::SetTimebaseCallback(int refnum, int conditional, int* result)
00257 {
00258     JackSetTimebaseCallbackRequest req(refnum, conditional);
00259     JackResult res;
00260     ServerSyncCall(&req, &res, result);
00261 }
00262 
00263 void JackWinNamedPipeClientChannel::GetInternalClientName(int refnum, int int_ref, char* name_res, int* result)
00264 {
00265     JackGetInternalClientNameRequest req(refnum, int_ref);
00266     JackGetInternalClientNameResult res;
00267     ServerSyncCall(&req, &res, result);
00268     strcpy(name_res, res.fName);
00269 }
00270 
00271 void JackWinNamedPipeClientChannel::InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result)
00272 {
00273     JackInternalClientHandleRequest req(refnum, client_name);
00274     JackInternalClientHandleResult res;
00275     ServerSyncCall(&req, &res, result);
00276     *int_ref = res.fIntRefNum;
00277     *status = res.fStatus;
00278 }
00279 
00280 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)
00281 {
00282     JackInternalClientLoadRequest req(refnum, client_name, so_name, objet_data, options);
00283     JackInternalClientLoadResult res;
00284     ServerSyncCall(&req, &res, result);
00285     *int_ref = res.fIntRefNum;
00286     *status = res.fStatus;
00287 }
00288 
00289 void JackWinNamedPipeClientChannel::InternalClientUnload(int refnum, int int_ref, int* status, int* result)
00290 {
00291     JackInternalClientUnloadRequest req(refnum, int_ref);
00292     JackInternalClientUnloadResult res;
00293     ServerSyncCall(&req, &res, result);
00294     *status = res.fStatus;
00295 }
00296 
00297 bool JackWinNamedPipeClientChannel::Init()
00298 {
00299     jack_log("JackWinNamedPipeClientChannel::Init");
00300 
00301     if (!fNotificationListenPipe.Accept()) {
00302         jack_error("JackWinNamedPipeClientChannel: cannot establish notification pipe");
00303         return false;
00304     } else {
00305         return fClient->Init();
00306     }
00307 }
00308 
00309 bool JackWinNamedPipeClientChannel::Execute()
00310 {
00311     JackClientNotification event;
00312     JackResult res;
00313 
00314     if (event.Read(&fNotificationListenPipe) < 0) {
00315         jack_error("JackWinNamedPipeClientChannel read fail");
00316         goto error;
00317     }
00318 
00319     res.fResult = fClient->ClientNotify(event.fRefNum, event.fName, event.fNotify, event.fSync, event.fMessage, event.fValue1, event.fValue2);
00320 
00321     if (event.fSync) {
00322         if (res.Write(&fNotificationListenPipe) < 0) {
00323             jack_error("JackWinNamedPipeClientChannel write fail");
00324             goto error;
00325         }
00326     }
00327     return true;
00328 
00329 error:
00330     // Close the pipes, server wont be able to create them otherwise.
00331     fNotificationListenPipe.Close();
00332     fRequestPipe.Close();
00333     fClient->ShutDown();
00334     return false;
00335 }
00336 
00337 } // end of namespace
00338 
00339