Jack2  1.9.10
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()
00031     :JackGenericClientChannel(),fThread(this)
00032 {
00033      fRequest = new JackWinNamedPipeClient();
00034 }
00035 
00036 JackWinNamedPipeClientChannel::~JackWinNamedPipeClientChannel()
00037 {
00038     delete fRequest;
00039 }
00040 
00041 int JackWinNamedPipeClientChannel::Open(const char* server_name, const char* name, int uuid, char* name_res, JackClient* client, jack_options_t options, jack_status_t* status)
00042 {
00043     int result = 0;
00044     jack_log("JackWinNamedPipeClientChannel::Open name = %s", name);
00045 
00046     /*
00047     16/08/07: was called before doing "fRequest->Connect" .... still necessary?
00048     if (fNotificationListenPipe.Bind(jack_client_dir, name, 0) < 0) {
00049         jack_error("Cannot bind pipe");
00050         goto error;
00051     }
00052     */
00053     
00054     // Before any server/client call
00055     fClient = client;
00056 
00057     if (fRequest->Connect(jack_server_dir, server_name, 0) < 0) {
00058         jack_error("Cannot connect to server pipe");
00059         goto error;
00060     }
00061     
00062     // OK so server is there...
00063     JackGlobals::fServerRunning = true;
00064 
00065     // Check name in server
00066     ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, true);
00067     if (result < 0) {
00068         int status1 = *status;
00069         if (status1 & JackVersionError) {
00070             jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION);
00071         } else {
00072             jack_error("Client name = %s conflits with another running client", name);
00073         }
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     return 0;
00082 
00083 error:
00084     fRequest->Close();
00085     fNotificationListenPipe.Close();
00086     return -1;
00087 }
00088 
00089 void JackWinNamedPipeClientChannel::Close()
00090 {
00091     fRequest->Close();
00092     fNotificationListenPipe.Close();
00093     // Here the thread will correctly stop when the pipe are closed
00094     fThread.Stop();
00095 }
00096 
00097 int JackWinNamedPipeClientChannel::Start()
00098 {
00099     jack_log("JackWinNamedPipeClientChannel::Start");
00100     /*
00101      To be sure notification thread is started before ClientOpen is called.
00102     */
00103     if (fThread.StartSync() != 0) {
00104         jack_error("Cannot start Jack client listener");
00105         return -1;
00106     } else {
00107         return 0;
00108     }
00109 }
00110 
00111 void JackWinNamedPipeClientChannel::Stop()
00112 {
00113     jack_log("JackWinNamedPipeClientChannel::Stop");
00114     fThread.Kill();  // Unsafe on WIN32... TODO : solve WIN32 thread Kill issue
00115 }
00116 
00117 bool JackWinNamedPipeClientChannel::Init()
00118 {
00119     jack_log("JackWinNamedPipeClientChannel::Init");
00120     
00121     // Setup context
00122     if (!jack_tls_set(JackGlobals::fNotificationThread, this)) {
00123         jack_error("Failed to set thread notification key");
00124     }
00125 
00126     if (!fNotificationListenPipe.Accept()) {
00127         jack_error("JackWinNamedPipeClientChannel: cannot establish notification pipe");
00128         return false;
00129     } else {
00130         return true;
00131     }
00132 }
00133 
00134 bool JackWinNamedPipeClientChannel::Execute()
00135 {
00136     JackClientNotification event;
00137     JackResult res;
00138 
00139     if (event.Read(&fNotificationListenPipe) < 0) {
00140         jack_error("JackWinNamedPipeClientChannel read fail");
00141         goto error;
00142     }
00143 
00144     res.fResult = fClient->ClientNotify(event.fRefNum, event.fName, event.fNotify, event.fSync, event.fMessage, event.fValue1, event.fValue2);
00145 
00146     if (event.fSync) {
00147         if (res.Write(&fNotificationListenPipe) < 0) {
00148             jack_error("JackWinNamedPipeClientChannel write fail");
00149             goto error;
00150         }
00151     }
00152     return true;
00153 
00154 error:
00155     // Close the pipes, server wont be able to create them otherwise.
00156     fNotificationListenPipe.Close();
00157     fRequest->Close();
00158     fClient->ShutDown(jack_status_t(JackFailure | JackServerError), JACK_SERVER_FAILURE);
00159     return false;
00160 }
00161 
00162 } // end of namespace
00163 
00164