JackFifo.cpp

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

Generated on Wed Jan 10 11:42:45 2007 for Jackdmp by  doxygen 1.4.5