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