Merge pull request #23 from jackaudio/device_reservation_fixes
[jack2.git] / posix / JackFifo.cpp
blobbe13a5d71a18f9fb0eb335517a3b90abd680c6d2
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.
20 #include "JackFifo.h"
21 #include "JackTools.h"
22 #include "JackError.h"
23 #include "JackPlatformPlug.h"
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <stdio.h>
30 namespace Jack
33 void JackFifo::BuildName(const char* client_name, const char* server_name, char* res)
35 char ext_client_name[JACK_CLIENT_NAME_SIZE + 1];
36 JackTools::RewriteName(client_name, ext_client_name);
37 sprintf(res, "%s/jack_fifo.%d_%s_%s", jack_client_dir, JackTools::GetUID(), server_name, ext_client_name);
40 bool JackFifo::Signal()
42 bool res;
43 char c = 0;
45 if (fFifo < 0) {
46 jack_error("JackFifo::Signal name = %s already desallocated!!", fName);
47 return false;
50 if (fFlush)
51 return true;
53 if ((res = (write(fFifo, &c, sizeof(c)) != sizeof(c)))) {
54 jack_error("JackFifo::Signal name = %s err = %s", fName, strerror(errno));
56 return !res;
59 bool JackFifo::SignalAll()
61 bool res;
62 char c = 0;
64 if (fFifo < 0) {
65 jack_error("JackFifo::SignalAll name = %s already desallocated!!", fName);
66 return false;
69 if (fFlush)
70 return true;
72 if ((res = (write(fFifo, &c, sizeof(c)) != sizeof(c)))) {
73 jack_error("JackFifo::SignalAll name = %s err = %s", fName, strerror(errno));
75 return !res;
78 bool JackFifo::Wait()
80 bool res;
81 char c;
83 if (fFifo < 0) {
84 jack_error("JackFifo::Wait name = %s already desallocated!!", fName);
85 return false;
88 if ((res = (read(fFifo, &c, sizeof(c)) != sizeof(c)))) {
89 jack_error("JackFifo::Wait name = %s err = %s", fName, strerror(errno));
91 return !res;
94 #ifdef __APPLE__
95 #warning JackFifo::TimedWait not available : synchronous mode may not work correctly if FIFO are used
96 bool JackFifo::TimedWait(long usec)
98 return Wait();
100 #else
101 // Does not work on OSX ??
102 bool JackFifo::TimedWait(long usec)
104 int res;
106 if (fFifo < 0) {
107 jack_error("JackFifo::TimedWait name = %s already desallocated!!", fName);
108 return false;
111 do {
112 res = poll(&fPoll, 1, usec / 1000);
113 } while (res < 0 && errno == EINTR);
115 if (fPoll.revents & POLLIN) {
116 return Wait();
117 } else {
118 // Wait failure but we still continue...
119 jack_log("JackFifo::TimedWait name = %s usec = %ld err = %s", fName, usec, strerror(errno));
120 return true;
123 #endif
125 // Server side
126 bool JackFifo::Allocate(const char* name, const char* server_name, int value)
128 struct stat statbuf;
129 BuildName(name, server_name, fName);
130 jack_log("JackFifo::Allocate name = %s", fName);
132 if (stat(fName, &statbuf) < 0) {
133 if (errno == ENOENT || errno == EPERM) {
134 if (mkfifo(fName, 0666) < 0) {
135 jack_error("Cannot create inter-client FIFO name = %s err = %s", name, strerror(errno));
136 return false;
138 } else {
139 jack_error("Cannot check on FIFO %s", name);
140 return false;
142 } else {
143 if (!S_ISFIFO(statbuf.st_mode)) {
144 jack_error("FIFO name = %s already exists, but is not a FIFO", name);
145 return false;
149 if ((fFifo = open(fName, O_RDWR | O_CREAT, 0666)) < 0) {
150 jack_error("Cannot open FIFO name = %s err = %s", name, strerror(errno));
151 return false;
152 } else {
153 fPoll.fd = fFifo;
154 fPoll.events = POLLERR | POLLIN | POLLHUP | POLLNVAL;
155 return true;
159 // Client side
160 bool JackFifo::ConnectAux(const char* name, const char* server_name, int access)
162 BuildName(name, server_name, fName);
163 jack_log("JackFifo::ConnectAux name = %s", fName);
165 // Temporary...
166 if (fFifo >= 0) {
167 jack_log("Already connected name = %s", name);
168 return true;
171 if ((fFifo = open(fName, access)) < 0) {
172 jack_error("Connect: can't connect named fifo name = %s err = %s", fName, strerror(errno));
173 return false;
174 } else {
175 fPoll.fd = fFifo;
176 fPoll.events = POLLERR | POLLIN | POLLHUP | POLLNVAL;
177 return true;
181 bool JackFifo::Connect(const char* name, const char* server_name)
183 return ConnectAux(name, server_name, O_RDWR);
186 bool JackFifo::ConnectOutput(const char* name, const char* server_name)
188 return ConnectAux(name, server_name, O_WRONLY | O_NONBLOCK);
191 bool JackFifo::ConnectInput(const char* name, const char* server_name)
193 return ConnectAux(name, server_name, O_RDONLY);
196 bool JackFifo::Disconnect()
198 if (fFifo >= 0) {
199 jack_log("JackFifo::Disconnect %s", fName);
200 if (close(fFifo) != 0) {
201 jack_error("Disconnect: can't disconnect named fifo name = %s err = %s", fName, strerror(errno));
202 return false;
203 } else {
204 fFifo = -1;
205 return true;
207 } else {
208 return true;
212 // Server side : destroy the fifo
213 void JackFifo::Destroy()
215 if (fFifo > 0) {
216 jack_log("JackFifo::Destroy name = %s", fName);
217 unlink(fName);
218 if (close(fFifo) != 0) {
219 jack_error("Destroy: can't destroy fifo name = %s err = %s", fName, strerror(errno));
221 fFifo = -1;
222 } else {
223 jack_error("JackFifo::Destroy fifo < 0");
227 } // end of namespace