jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
5.1KB

  1. /*
  2. Copyright (C) 2004-2006 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackFifo.h"
  16. #include "JackError.h"
  17. #include "JackChannel.h"
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <unistd.h>
  21. #include <fcntl.h>
  22. #include <assert.h>
  23. namespace Jack
  24. {
  25. void JackFifo::BuildName(const char* name, char* res)
  26. {
  27. sprintf(res, "%s/jack_fifo.%s", jack_client_dir, name);
  28. }
  29. bool JackFifo::Signal()
  30. {
  31. bool res;
  32. char c = 0;
  33. assert(fFifo >= 0);
  34. if (fFlush)
  35. return true;
  36. if ((res = (write(fFifo, &c, sizeof(c)) != sizeof(c)))) {
  37. jack_error("JackFifo::Signal name = %s err = %s", fName, strerror(errno));
  38. }
  39. return !res;
  40. }
  41. bool JackFifo::SignalAll()
  42. {
  43. bool res;
  44. char c = 0;
  45. assert(fFifo >= 0);
  46. if (fFlush)
  47. return true;
  48. if ((res = (write(fFifo, &c, sizeof(c)) != sizeof(c)))) {
  49. jack_error("JackFifo::SignalAll name = %s err = %s", fName, strerror(errno));
  50. }
  51. return !res;
  52. }
  53. bool JackFifo::Wait()
  54. {
  55. bool res;
  56. char c;
  57. assert(fFifo >= 0);
  58. if ((res = (read(fFifo, &c, sizeof(c)) != sizeof(c)))) {
  59. jack_error("JackFifo::Wait name = %s err = %s", fName, strerror(errno));
  60. }
  61. return !res;
  62. }
  63. #ifdef __APPLE__
  64. #warning JackFifo::TimedWait not available : synchronous mode may not work correctly if FIFO are used
  65. bool JackFifo::TimedWait(long usec)
  66. {
  67. return Wait();
  68. }
  69. #else
  70. // Does not work on OSX ??
  71. bool JackFifo::TimedWait(long usec)
  72. {
  73. assert(fFifo >= 0);
  74. if ((poll(&fPoll, 1, usec / 1000) < 0) && (errno != EINTR)) {
  75. jack_error("JackFifo::TimedWait name = %s err = %s", fName, strerror(errno));
  76. return false;
  77. }
  78. if (fPoll.revents & POLLIN) {
  79. return Wait();
  80. } else {
  81. jack_error("JackFifo::TimedWait fails name = %s revents %ld ", fName, fPoll.revents);
  82. return false;
  83. }
  84. }
  85. #endif
  86. // Server side
  87. bool JackFifo::Allocate(const char* name, int value)
  88. {
  89. struct stat statbuf;
  90. BuildName(name, fName);
  91. JackLog("JackFifo::Allocate name = %s\n", fName);
  92. if (stat(fName, &statbuf)) {
  93. if (errno == ENOENT) {
  94. if (mkfifo(fName, 0666) < 0) {
  95. jack_error("Cannot create inter-client FIFO [%s] (%s)\n", name, strerror(errno));
  96. return false;
  97. }
  98. } else {
  99. jack_error("Cannot check on FIFO %s\n", name);
  100. return false;
  101. }
  102. } else {
  103. if (!S_ISFIFO(statbuf.st_mode)) {
  104. jack_error("FIFO (%s) already exists, but is not a FIFO!\n", name);
  105. return false;
  106. }
  107. }
  108. if ((fFifo = open(fName, O_RDWR | O_CREAT, 0666)) < 0) {
  109. jack_error("Cannot open fifo [%s] (%s)", name, strerror(errno));
  110. return false;
  111. } else {
  112. fPoll.fd = fFifo;
  113. fPoll.events = POLLERR | POLLIN | POLLHUP | POLLNVAL;
  114. return true;
  115. }
  116. }
  117. // Client side
  118. bool JackFifo::ConnectAux(const char* name, int access)
  119. {
  120. BuildName(name, fName);
  121. JackLog("JackFifo::ConnectAux name = %s\n", fName);
  122. // Temporary...
  123. if (fFifo >= 0) {
  124. JackLog("Already connected name = %s\n", name);
  125. return true;
  126. }
  127. if ((fFifo = open(fName, access)) < 0) {
  128. jack_error("Connect: can't connect named fifo name = %s err = %s", fName, strerror(errno));
  129. return false;
  130. } else {
  131. fPoll.fd = fFifo;
  132. fPoll.events = POLLERR | POLLIN | POLLHUP | POLLNVAL;
  133. return true;
  134. }
  135. }
  136. bool JackFifo::Connect(const char* name)
  137. {
  138. return ConnectAux(name, O_RDWR);
  139. }
  140. bool JackFifo::ConnectOutput(const char* name)
  141. {
  142. return ConnectAux(name, O_WRONLY | O_NONBLOCK);
  143. }
  144. bool JackFifo::ConnectInput(const char* name)
  145. {
  146. return ConnectAux(name, O_RDONLY);
  147. }
  148. bool JackFifo::Disconnect()
  149. {
  150. if (fFifo >= 0) {
  151. JackLog("JackFifo::Disconnect %s\n", fName);
  152. if (close(fFifo) != 0) {
  153. jack_error("Disconnect: can't disconnect named fifo name = %s err = %s", fName, strerror(errno));
  154. return false;
  155. } else {
  156. fFifo = -1;
  157. return true;
  158. }
  159. } else {
  160. return true;
  161. }
  162. }
  163. // Server side : destroy the fifo
  164. void JackFifo::Destroy()
  165. {
  166. if (fFifo > 0) {
  167. JackLog("JackFifo::Destroy name = %s\n", fName);
  168. unlink(fName);
  169. if (close(fFifo) != 0) {
  170. jack_error("Destroy: can't destroy fifo name = %s err = %s", fName, strerror(errno));
  171. }
  172. fFifo = -1;
  173. } else {
  174. jack_error("JackFifo::Destroy fifo < 0");
  175. }
  176. }
  177. } // end of namespace