Jack2 1.9.6
|
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 #include "JackFifo.h" 00021 #include "JackTools.h" 00022 #include "JackError.h" 00023 #include "JackPlatformPlug.h" 00024 #include <sys/types.h> 00025 #include <sys/stat.h> 00026 #include <unistd.h> 00027 #include <fcntl.h> 00028 #include <stdio.h> 00029 00030 namespace Jack 00031 { 00032 00033 void JackFifo::BuildName(const char* client_name, const char* server_name, char* res) 00034 { 00035 char ext_client_name[JACK_CLIENT_NAME_SIZE + 1]; 00036 JackTools::RewriteName(client_name, ext_client_name); 00037 sprintf(res, "%s/jack_fifo.%d_%s_%s", jack_client_dir, JackTools::GetUID(), server_name, ext_client_name); 00038 } 00039 00040 bool JackFifo::Signal() 00041 { 00042 bool res; 00043 char c = 0; 00044 00045 if (fFifo < 0) { 00046 jack_error("JackFifo::Signal name = %s already desallocated!!", fName); 00047 return false; 00048 } 00049 00050 if (fFlush) 00051 return true; 00052 00053 if ((res = (write(fFifo, &c, sizeof(c)) != sizeof(c)))) { 00054 jack_error("JackFifo::Signal name = %s err = %s", fName, strerror(errno)); 00055 } 00056 return !res; 00057 } 00058 00059 bool JackFifo::SignalAll() 00060 { 00061 bool res; 00062 char c = 0; 00063 00064 if (fFifo < 0) { 00065 jack_error("JackFifo::SignalAll name = %s already desallocated!!", fName); 00066 return false; 00067 } 00068 00069 if (fFlush) 00070 return true; 00071 00072 if ((res = (write(fFifo, &c, sizeof(c)) != sizeof(c)))) { 00073 jack_error("JackFifo::SignalAll name = %s err = %s", fName, strerror(errno)); 00074 } 00075 return !res; 00076 } 00077 00078 bool JackFifo::Wait() 00079 { 00080 bool res; 00081 char c; 00082 00083 if (fFifo < 0) { 00084 jack_error("JackFifo::Wait name = %s already desallocated!!", fName); 00085 return false; 00086 } 00087 00088 if ((res = (read(fFifo, &c, sizeof(c)) != sizeof(c)))) { 00089 jack_error("JackFifo::Wait name = %s err = %s", fName, strerror(errno)); 00090 } 00091 return !res; 00092 } 00093 00094 #ifdef __APPLE__ 00095 #warning JackFifo::TimedWait not available : synchronous mode may not work correctly if FIFO are used 00096 bool JackFifo::TimedWait(long usec) 00097 { 00098 return Wait(); 00099 } 00100 #else 00101 // Does not work on OSX ?? 00102 bool JackFifo::TimedWait(long usec) 00103 { 00104 int res; 00105 00106 if (fFifo < 0) { 00107 jack_error("JackFifo::TimedWait name = %s already desallocated!!", fName); 00108 return false; 00109 } 00110 00111 do { 00112 res = poll(&fPoll, 1, usec / 1000); 00113 } while (res < 0 && errno == EINTR); 00114 00115 if (fPoll.revents & POLLIN) { 00116 return Wait(); 00117 } else { 00118 // Wait failure but we still continue... 00119 jack_log("JackFifo::TimedWait name = %s usec = %ld err = %s", fName, usec, strerror(errno)); 00120 return true; 00121 } 00122 } 00123 #endif 00124 00125 // Server side 00126 bool JackFifo::Allocate(const char* name, const char* server_name, int value) 00127 { 00128 struct stat statbuf; 00129 BuildName(name, server_name, fName); 00130 jack_log("JackFifo::Allocate name = %s", fName); 00131 00132 if (stat(fName, &statbuf) < 0) { 00133 if (errno == ENOENT || errno == EPERM) { 00134 if (mkfifo(fName, 0666) < 0) { 00135 jack_error("Cannot create inter-client FIFO name = %s err = %s", name, strerror(errno)); 00136 return false; 00137 } 00138 } else { 00139 jack_error("Cannot check on FIFO %s", name); 00140 return false; 00141 } 00142 } else { 00143 if (!S_ISFIFO(statbuf.st_mode)) { 00144 jack_error("FIFO name = %s already exists, but is not a FIFO", name); 00145 return false; 00146 } 00147 } 00148 00149 if ((fFifo = open(fName, O_RDWR | O_CREAT, 0666)) < 0) { 00150 jack_error("Cannot open FIFO name = %s err = %s", name, strerror(errno)); 00151 return false; 00152 } else { 00153 fPoll.fd = fFifo; 00154 fPoll.events = POLLERR | POLLIN | POLLHUP | POLLNVAL; 00155 return true; 00156 } 00157 } 00158 00159 // Client side 00160 bool JackFifo::ConnectAux(const char* name, const char* server_name, int access) 00161 { 00162 BuildName(name, server_name, fName); 00163 jack_log("JackFifo::ConnectAux name = %s", fName); 00164 00165 // Temporary... 00166 if (fFifo >= 0) { 00167 jack_log("Already connected name = %s", name); 00168 return true; 00169 } 00170 00171 if ((fFifo = open(fName, access)) < 0) { 00172 jack_error("Connect: can't connect named fifo name = %s err = %s", fName, strerror(errno)); 00173 return false; 00174 } else { 00175 fPoll.fd = fFifo; 00176 fPoll.events = POLLERR | POLLIN | POLLHUP | POLLNVAL; 00177 return true; 00178 } 00179 } 00180 00181 bool JackFifo::Connect(const char* name, const char* server_name) 00182 { 00183 return ConnectAux(name, server_name, O_RDWR); 00184 } 00185 00186 bool JackFifo::ConnectOutput(const char* name, const char* server_name) 00187 { 00188 return ConnectAux(name, server_name, O_WRONLY | O_NONBLOCK); 00189 } 00190 00191 bool JackFifo::ConnectInput(const char* name, const char* server_name) 00192 { 00193 return ConnectAux(name, server_name, O_RDONLY); 00194 } 00195 00196 bool JackFifo::Disconnect() 00197 { 00198 if (fFifo >= 0) { 00199 jack_log("JackFifo::Disconnect %s", fName); 00200 if (close(fFifo) != 0) { 00201 jack_error("Disconnect: can't disconnect named fifo name = %s err = %s", fName, strerror(errno)); 00202 return false; 00203 } else { 00204 fFifo = -1; 00205 return true; 00206 } 00207 } else { 00208 return true; 00209 } 00210 } 00211 00212 // Server side : destroy the fifo 00213 void JackFifo::Destroy() 00214 { 00215 if (fFifo > 0) { 00216 jack_log("JackFifo::Destroy name = %s", fName); 00217 unlink(fName); 00218 if (close(fFifo) != 0) { 00219 jack_error("Destroy: can't destroy fifo name = %s err = %s", fName, strerror(errno)); 00220 } 00221 fFifo = -1; 00222 } else { 00223 jack_error("JackFifo::Destroy fifo < 0"); 00224 } 00225 } 00226 00227 } // end of namespace 00228