Fixes for alsa device reservation
[jack2.git] / windows / JackWinNamedPipe.cpp
blob8d2776734ec8bb66f7c07b1883b8fa6087801767
1 /*
2 Copyright (C) 2004-2008 Grame
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.
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.
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.
21 #include "JackWinNamedPipe.h"
22 #include "JackError.h"
23 #include <assert.h>
24 #include <stdio.h>
26 #define BUFSIZE 4096
28 namespace Jack
31 int JackWinNamedPipe::Read(void* data, int len)
33 DWORD read;
34 BOOL res = ReadFile(fNamedPipe, data, len, &read, NULL);
35 if (res && read == (DWORD)len) {
36 return 0;
37 } else {
38 jack_error("Cannot read named pipe name = %s err = %ld", fName, GetLastError());
39 return -1;
43 int JackWinNamedPipe::Write(void* data, int len)
45 DWORD written;
46 BOOL res = WriteFile(fNamedPipe, data, len, &written, NULL);
47 if (res && written == (DWORD)len) {
48 return 0;
49 } else {
50 jack_error("Cannot write named pipe name = %s err = %ld", fName, GetLastError());
51 return -1;
56 See :
57 http://answers.google.com/answers/threadview?id=430173
58 http://msdn.microsoft.com/en-us/library/windows/desktop/aa365800(v=vs.85).aspx
62 int JackWinNamedPipeClient::ConnectAux()
64 fNamedPipe = CreateFile(fName, // pipe name
65 GENERIC_READ | // read and write access
66 GENERIC_WRITE,
67 0, // no sharing
68 NULL, // default security attributes
69 OPEN_EXISTING, // opens existing pipe
70 0, // default attributes
71 NULL); // no template file
73 if (fNamedPipe == INVALID_HANDLE_VALUE) {
74 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
75 return -1;
76 } else {
77 return 0;
82 int JackWinNamedPipeClient::ConnectAux()
84 jack_log("Connect: fName %s", fName);
86 while (true) {
88 fNamedPipe = CreateFile(fName, // pipe name
89 GENERIC_READ | // read and write access
90 GENERIC_WRITE,
91 0, // no sharing
92 NULL, // default security attributes
93 OPEN_EXISTING, // opens existing pipe
94 0, // default attributes
95 NULL); // no template file
97 // Break if the pipe handle is valid.
98 if (fNamedPipe != INVALID_HANDLE_VALUE) {
99 return 0;
102 // Exit if an error other than ERROR_PIPE_BUSY occurs.
103 if (GetLastError() != ERROR_PIPE_BUSY) {
104 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
105 return -1;
108 // All pipe instances are busy, so wait for 2 seconds.
109 if (!WaitNamedPipe(fName, 2000)) {
110 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
111 return -1;
116 int JackWinNamedPipeClient::Connect(const char* dir, int which)
118 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
119 return ConnectAux();
122 int JackWinNamedPipeClient::Connect(const char* dir, const char* name, int which)
124 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
125 return ConnectAux();
128 int JackWinNamedPipeClient::Close()
130 if (fNamedPipe != INVALID_HANDLE_VALUE) {
131 CloseHandle(fNamedPipe);
132 fNamedPipe = INVALID_HANDLE_VALUE;
133 return 0;
134 } else {
135 return -1;
139 void JackWinNamedPipeClient::SetReadTimeOut(long sec)
142 void JackWinNamedPipeClient::SetWriteTimeOut(long sec)
145 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient()
146 : JackWinNamedPipeClient(), fPendingIO(false), fIOState(kIdle)
148 fIOState = kIdle;
149 fOverlap.hEvent = CreateEvent(NULL, // default security attribute
150 TRUE, // manual-reset event
151 TRUE, // initial state = signaled
152 NULL); // unnamed event object
155 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient(HANDLE pipe, const char* name, bool pending)
156 : JackWinNamedPipeClient(pipe, name), fPendingIO(pending), fIOState(kIdle)
158 fOverlap.hEvent = CreateEvent(NULL, // default security attribute
159 TRUE, // manual-reset event
160 TRUE, // initial state = signaled
161 NULL); // unnamed event object
163 if (!fPendingIO) {
164 SetEvent(fOverlap.hEvent);
167 fIOState = (fPendingIO) ? kConnecting : kReading;
170 JackWinAsyncNamedPipeClient::~JackWinAsyncNamedPipeClient()
172 CloseHandle(fOverlap.hEvent);
175 int JackWinAsyncNamedPipeClient::FinishIO()
177 DWORD success, ret;
178 success = GetOverlappedResult(fNamedPipe, // handle to pipe
179 &fOverlap, // OVERLAPPED structure
180 &ret, // bytes transferred
181 FALSE); // do not wait
183 switch (fIOState) {
185 case kConnecting:
186 if (!success) {
187 jack_error("Conection error");
188 return -1;
189 } else {
190 fIOState = kReading;
191 // Prepare connection for new client ??
193 break;
195 case kReading:
196 if (!success || ret == 0) {
197 return -1;
199 fIOState = kWriting;
200 break;
202 case kWriting:
203 if (!success || ret == 0) {
204 return -1;
206 fIOState = kReading;
207 break;
209 default:
210 break;
213 return 0;
216 int JackWinAsyncNamedPipeClient::Read(void* data, int len)
218 DWORD read;
219 jack_log("JackWinNamedPipeClient::Read len = %ld", len);
220 BOOL res = ReadFile(fNamedPipe, data, len, &read, &fOverlap);
222 if (res && read != 0) {
223 fPendingIO = false;
224 fIOState = kWriting;
225 return 0;
226 } else if (!res && GetLastError() == ERROR_IO_PENDING) {
227 fPendingIO = true;
228 return 0;
229 } else {
230 jack_error("Cannot read named pipe err = %ld", GetLastError());
231 return -1;
235 int JackWinAsyncNamedPipeClient::Write(void* data, int len)
237 DWORD written;
238 jack_log("JackWinNamedPipeClient::Write len = %ld", len);
239 BOOL res = WriteFile(fNamedPipe, data, len, &written, &fOverlap);
241 if (res && written != 0) {
242 fPendingIO = false;
243 fIOState = kWriting;
244 return 0;
245 } else if (!res && GetLastError() == ERROR_IO_PENDING) {
246 fPendingIO = true;
247 return 0;
248 } else {
249 jack_error("Cannot write named pipe err = %ld", GetLastError());
250 return -1;
254 // Server side
255 int JackWinNamedPipeServer::BindAux()
257 jack_log("Bind: fName %s", fName);
259 if ((fNamedPipe = CreateNamedPipe(fName,
260 PIPE_ACCESS_DUPLEX, // read/write access
261 PIPE_TYPE_MESSAGE | // message type pipe
262 PIPE_READMODE_MESSAGE | // message-read mode
263 PIPE_WAIT, // blocking mode
264 PIPE_UNLIMITED_INSTANCES, // max. instances
265 BUFSIZE, // output buffer size
266 BUFSIZE, // input buffer size
267 INFINITE, // client time-out
268 NULL)) == INVALID_HANDLE_VALUE) { // no security
269 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
270 return -1;
271 } else {
272 return 0;
276 int JackWinNamedPipeServer::Bind(const char* dir, int which)
278 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
279 return BindAux();
282 int JackWinNamedPipeServer::Bind(const char* dir, const char* name, int which)
284 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
285 return BindAux();
288 bool JackWinNamedPipeServer::Accept()
290 if (ConnectNamedPipe(fNamedPipe, NULL)) {
291 return true;
292 } else {
293 jack_error("Cannot bind server pipe name = %s err = %ld", fName, GetLastError());
294 if (GetLastError() == ERROR_PIPE_CONNECTED) {
295 jack_error("pipe already connnected = %s ", fName);
296 return true;
297 } else {
298 return false;
303 JackWinNamedPipeClient* JackWinNamedPipeServer::AcceptClient()
305 if (ConnectNamedPipe(fNamedPipe, NULL)) {
306 JackWinNamedPipeClient* client = new JackWinNamedPipeClient(fNamedPipe, fName);
307 // Init the pipe to the default value
308 fNamedPipe = INVALID_HANDLE_VALUE;
309 return client;
310 } else {
311 switch (GetLastError()) {
313 case ERROR_PIPE_CONNECTED:
314 return new JackWinNamedPipeClient(fNamedPipe, fName);
316 default:
317 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
318 return NULL;
319 break;
324 int JackWinNamedPipeServer::Close()
326 jack_log("JackWinNamedPipeServer::Close");
328 if (fNamedPipe != INVALID_HANDLE_VALUE) {
329 DisconnectNamedPipe(fNamedPipe);
330 CloseHandle(fNamedPipe);
331 fNamedPipe = INVALID_HANDLE_VALUE;
332 return 0;
333 } else {
334 return -1;
338 // Server side
340 int JackWinAsyncNamedPipeServer::BindAux()
342 jack_log("Bind: fName %s", fName);
344 if ((fNamedPipe = CreateNamedPipe(fName,
345 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
346 PIPE_TYPE_MESSAGE | // message type pipe
347 PIPE_READMODE_MESSAGE | // message-read mode
348 PIPE_WAIT, // blocking mode
349 PIPE_UNLIMITED_INSTANCES, // max. instances
350 BUFSIZE, // output buffer size
351 BUFSIZE, // input buffer size
352 INFINITE, // client time-out
353 NULL)) == INVALID_HANDLE_VALUE) { // no security a
354 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
355 return -1;
356 } else {
357 return 0;
361 int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which)
363 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
364 return BindAux();
367 int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which)
369 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
370 return BindAux();
373 bool JackWinAsyncNamedPipeServer::Accept()
375 return false;
378 JackWinNamedPipeClient* JackWinAsyncNamedPipeServer::AcceptClient()
380 if (ConnectNamedPipe(fNamedPipe, NULL)) {
381 return new JackWinAsyncNamedPipeClient(fNamedPipe, fName, false);
382 } else {
383 switch (GetLastError()) {
385 case ERROR_IO_PENDING:
386 return new JackWinAsyncNamedPipeClient(fNamedPipe, fName, true);
388 case ERROR_PIPE_CONNECTED:
389 return new JackWinAsyncNamedPipeClient(fNamedPipe, fName, false);
391 default:
392 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
393 return NULL;
394 break;
399 } // end of namespace