Jack2 1.9.6

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 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