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

Generated on Thu Feb 14 11:16:01 2008 for Jackdmp by  doxygen 1.5.1