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.

221 lines
5.6KB

  1. /*
  2. Copyright (C) 2004-2008 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 "JackConstants.h"
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <unistd.h>
  21. #include <fcntl.h>
  22. namespace Jack
  23. {
  24. void JackFifo::BuildName(const char* name, const char* server_name, char* res)
  25. {
  26. sprintf(res, "%s/jack_fifo.%s_%s", jack_client_dir, server_name, name);
  27. }
  28. bool JackFifo::Signal()
  29. {
  30. bool res;
  31. char c = 0;
  32. if (fFifo < 0) {
  33. jack_error("JackFifo::Signal name = %s already desallocated!!", fName);
  34. return false;
  35. }
  36. if (fFlush)
  37. return true;
  38. if ((res = (write(fFifo, &c, sizeof(c)) != sizeof(c)))) {
  39. jack_error("JackFifo::Signal name = %s err = %s", fName, strerror(errno));
  40. }
  41. return !res;
  42. }
  43. bool JackFifo::SignalAll()
  44. {
  45. bool res;
  46. char c = 0;
  47. if (fFifo < 0) {
  48. jack_error("JackFifo::SignalAll name = %s already desallocated!!", fName);
  49. return false;
  50. }
  51. if (fFlush)
  52. return true;
  53. if ((res = (write(fFifo, &c, sizeof(c)) != sizeof(c)))) {
  54. jack_error("JackFifo::SignalAll name = %s err = %s", fName, strerror(errno));
  55. }
  56. return !res;
  57. }
  58. bool JackFifo::Wait()
  59. {
  60. bool res;
  61. char c;
  62. if (fFifo < 0) {
  63. jack_error("JackFifo::Wait name = %s already desallocated!!", fName);
  64. return false;
  65. }
  66. if ((res = (read(fFifo, &c, sizeof(c)) != sizeof(c)))) {
  67. jack_error("JackFifo::Wait name = %s err = %s", fName, strerror(errno));
  68. }
  69. return !res;
  70. }
  71. #ifdef __APPLE__
  72. #warning JackFifo::TimedWait not available : synchronous mode may not work correctly if FIFO are used
  73. bool JackFifo::TimedWait(long usec)
  74. {
  75. return Wait();
  76. }
  77. #else
  78. // Does not work on OSX ??
  79. bool JackFifo::TimedWait(long usec)
  80. {
  81. assert(fFifo >= 0);
  82. if ((poll(&fPoll, 1, usec / 1000) < 0) && (errno != EINTR)) {
  83. jack_error("JackFifo::TimedWait name = %s err = %s", fName, strerror(errno));
  84. return false;
  85. }
  86. if (fPoll.revents & POLLIN) {
  87. return Wait();
  88. } else {
  89. jack_error("JackFifo::TimedWait name = %s usec = %ld revents %ld ", fName, usec, fPoll.revents);
  90. return false;
  91. }
  92. }
  93. #endif
  94. // Server side
  95. bool JackFifo::Allocate(const char* name, const char* server_name, int value)
  96. {
  97. struct stat statbuf;
  98. BuildName(name, server_name, fName);
  99. jack_log("JackFifo::Allocate name = %s", fName);
  100. if (stat(fName, &statbuf)) {
  101. if (errno == ENOENT) {
  102. if (mkfifo(fName, 0666) < 0) {
  103. jack_error("Cannot create inter-client FIFO [%s] (%s)\n", name, strerror(errno));
  104. return false;
  105. }
  106. } else {
  107. jack_error("Cannot check on FIFO %s\n", name);
  108. return false;
  109. }
  110. } else {
  111. if (!S_ISFIFO(statbuf.st_mode)) {
  112. jack_error("FIFO (%s) already exists, but is not a FIFO!\n", name);
  113. return false;
  114. }
  115. }
  116. if ((fFifo = open(fName, O_RDWR | O_CREAT, 0666)) < 0) {
  117. jack_error("Cannot open fifo [%s] (%s)", name, strerror(errno));
  118. return false;
  119. } else {
  120. fPoll.fd = fFifo;
  121. fPoll.events = POLLERR | POLLIN | POLLHUP | POLLNVAL;
  122. return true;
  123. }
  124. }
  125. // Client side
  126. bool JackFifo::ConnectAux(const char* name, const char* server_name, int access)
  127. {
  128. BuildName(name, server_name, fName);
  129. jack_log("JackFifo::ConnectAux name = %s", fName);
  130. // Temporary...
  131. if (fFifo >= 0) {
  132. jack_log("Already connected name = %s", name);
  133. return true;
  134. }
  135. if ((fFifo = open(fName, access)) < 0) {
  136. jack_error("Connect: can't connect named fifo name = %s err = %s", fName, strerror(errno));
  137. return false;
  138. } else {
  139. fPoll.fd = fFifo;
  140. fPoll.events = POLLERR | POLLIN | POLLHUP | POLLNVAL;
  141. return true;
  142. }
  143. }
  144. bool JackFifo::Connect(const char* name, const char* server_name)
  145. {
  146. return ConnectAux(name, server_name, O_RDWR);
  147. }
  148. bool JackFifo::ConnectOutput(const char* name, const char* server_name)
  149. {
  150. return ConnectAux(name, server_name, O_WRONLY | O_NONBLOCK);
  151. }
  152. bool JackFifo::ConnectInput(const char* name, const char* server_name)
  153. {
  154. return ConnectAux(name, server_name, O_RDONLY);
  155. }
  156. bool JackFifo::Disconnect()
  157. {
  158. if (fFifo >= 0) {
  159. jack_log("JackFifo::Disconnect %s", fName);
  160. if (close(fFifo) != 0) {
  161. jack_error("Disconnect: can't disconnect named fifo name = %s err = %s", fName, strerror(errno));
  162. return false;
  163. } else {
  164. fFifo = -1;
  165. return true;
  166. }
  167. } else {
  168. return true;
  169. }
  170. }
  171. // Server side : destroy the fifo
  172. void JackFifo::Destroy()
  173. {
  174. if (fFifo > 0) {
  175. jack_log("JackFifo::Destroy name = %s", fName);
  176. unlink(fName);
  177. if (close(fFifo) != 0) {
  178. jack_error("Destroy: can't destroy fifo name = %s err = %s", fName, strerror(errno));
  179. }
  180. fFifo = -1;
  181. } else {
  182. jack_error("JackFifo::Destroy fifo < 0");
  183. }
  184. }
  185. } // end of namespace