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.

225 lines
5.7KB

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