Jack2  1.9.12
JackWinNamedPipeClientChannel.cpp
1 /*
2  Copyright (C) 2004-2008 Grame
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU Lesser General Public License as published by
6  the Free Software Foundation; either version 2.1 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 
18  */
19 
20 
21 #include "JackWinNamedPipeClientChannel.h"
22 #include "JackRequest.h"
23 #include "JackClient.h"
24 #include "JackGlobals.h"
25 #include "JackError.h"
26 
27 namespace Jack
28 {
29 
30 JackWinNamedPipeClientChannel::JackWinNamedPipeClientChannel()
31  :JackGenericClientChannel(),fThread(this)
32 {
33  fRequest = new JackWinNamedPipeClient();
34 }
35 
36 JackWinNamedPipeClientChannel::~JackWinNamedPipeClientChannel()
37 {
38  delete fRequest;
39 }
40 
41 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)
42 {
43  int result = 0;
44  jack_log("JackWinNamedPipeClientChannel::Open name = %s", name);
45 
46  /*
47  16/08/07: was called before doing "fRequest->Connect" .... still necessary?
48  if (fNotificationListenPipe.Bind(jack_client_dir, name, 0) < 0) {
49  jack_error("Cannot bind pipe");
50  goto error;
51  }
52  */
53 
54  // Before any server/client call
55  fClient = client;
56 
57  if (fRequest->Connect(jack_server_dir, server_name, 0) < 0) {
58  jack_error("Cannot connect to server pipe");
59  goto error;
60  }
61 
62  // OK so server is there...
63  JackGlobals::fServerRunning = true;
64 
65  // Check name in server
66  ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, true);
67  if (result < 0) {
68  int status1 = *status;
69  if (status1 & JackVersionError) {
70  jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION);
71  } else {
72  jack_error("Client name = %s conflits with another running client", name);
73  }
74  }
75 
76  if (fNotificationListenPipe.Bind(jack_client_dir, name_res, 0) < 0) {
77  jack_error("Cannot bind pipe");
78  goto error;
79  }
80 
81  return 0;
82 
83 error:
84  fRequest->Close();
85  fNotificationListenPipe.Close();
86  return -1;
87 }
88 
89 void JackWinNamedPipeClientChannel::Close()
90 {
91  fRequest->Close();
92  fNotificationListenPipe.Close();
93  // Here the thread will correctly stop when the pipe are closed
94  fThread.Stop();
95 }
96 
97 int JackWinNamedPipeClientChannel::Start()
98 {
99  jack_log("JackWinNamedPipeClientChannel::Start");
100  /*
101  To be sure notification thread is started before ClientOpen is called.
102  */
103  if (fThread.StartSync() != 0) {
104  jack_error("Cannot start Jack client listener");
105  return -1;
106  } else {
107  return 0;
108  }
109 }
110 
111 void JackWinNamedPipeClientChannel::Stop()
112 {
113  jack_log("JackWinNamedPipeClientChannel::Stop");
114  fThread.Kill(); // Unsafe on WIN32... TODO : solve WIN32 thread Kill issue
115 }
116 
118 {
119  jack_log("JackWinNamedPipeClientChannel::Init");
120 
121  // Setup context
122  if (!jack_tls_set(JackGlobals::fNotificationThread, this)) {
123  jack_error("Failed to set thread notification key");
124  }
125 
126  if (!fNotificationListenPipe.Accept()) {
127  jack_error("JackWinNamedPipeClientChannel: cannot establish notification pipe");
128  return false;
129  } else {
130  return true;
131  }
132 }
133 
134 bool JackWinNamedPipeClientChannel::Execute()
135 {
137  JackResult res;
138 
139  if (event.Read(&fNotificationListenPipe) < 0) {
140  jack_error("JackWinNamedPipeClientChannel read fail");
141  goto error;
142  }
143 
144  res.fResult = fClient->ClientNotify(event.fRefNum, event.fName, event.fNotify, event.fSync, event.fMessage, event.fValue1, event.fValue2);
145 
146  if (event.fSync) {
147  if (res.Write(&fNotificationListenPipe) < 0) {
148  jack_error("JackWinNamedPipeClientChannel write fail");
149  goto error;
150  }
151  }
152  return true;
153 
154 error:
155  // Close the pipes, server wont be able to create them otherwise.
156  fNotificationListenPipe.Close();
157  fRequest->Close();
158  fClient->ShutDown(jack_status_t(JackFailure | JackServerError), JACK_SERVER_FAILURE);
159  return false;
160 }
161 
162 } // end of namespace
163 
164 
jack_log
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:108
Jack::JackClientNotification
ClientNotification.
Definition: JackRequest.h:1636
Jack::JackResult
Result from the server.
Definition: JackRequest.h:129
jack_error
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
Jack::JackWinNamedPipeClientChannel::Init
bool Init()
Definition: JackWinNamedPipeClientChannel.cpp:117