The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

237 lines
6.2KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. #include "../../../src/juce_core/basics/juce_StandardHeader.h"
  24. #include <sys/stat.h>
  25. #include <sys/dir.h>
  26. #include <fcntl.h>
  27. // As well as being for the mac, this file is included by the linux build.
  28. #if ! JUCE_MAC
  29. #include <sys/wait.h>
  30. #include <errno.h>
  31. #include <unistd.h>
  32. #endif
  33. BEGIN_JUCE_NAMESPACE
  34. #include "../../../src/juce_core/io/files/juce_File.h"
  35. #include "../../../src/juce_core/io/files/juce_NamedPipe.h"
  36. #include "../../../src/juce_core/threads/juce_Thread.h"
  37. //==============================================================================
  38. struct NamedPipeInternal
  39. {
  40. String pipeInName, pipeOutName;
  41. int pipeIn, pipeOut;
  42. bool volatile createdPipe, blocked, stopReadOperation;
  43. static void signalHandler (int) {}
  44. };
  45. void NamedPipe::cancelPendingReads()
  46. {
  47. while (internal != 0 && ((NamedPipeInternal*) internal)->blocked)
  48. {
  49. NamedPipeInternal* const intern = (NamedPipeInternal*) internal;
  50. intern->stopReadOperation = true;
  51. char buffer [1] = { 0 };
  52. ::write (intern->pipeIn, buffer, 1);
  53. int timeout = 2000;
  54. while (intern->blocked && --timeout >= 0)
  55. Thread::sleep (2);
  56. intern->stopReadOperation = false;
  57. }
  58. }
  59. void NamedPipe::close()
  60. {
  61. NamedPipeInternal* const intern = (NamedPipeInternal*) internal;
  62. if (intern != 0)
  63. {
  64. internal = 0;
  65. if (intern->pipeIn != -1)
  66. ::close (intern->pipeIn);
  67. if (intern->pipeOut != -1)
  68. ::close (intern->pipeOut);
  69. if (intern->createdPipe)
  70. {
  71. unlink (intern->pipeInName);
  72. unlink (intern->pipeOutName);
  73. }
  74. delete intern;
  75. }
  76. }
  77. bool NamedPipe::openInternal (const String& pipeName, const bool createPipe)
  78. {
  79. close();
  80. NamedPipeInternal* const intern = new NamedPipeInternal();
  81. internal = intern;
  82. intern->createdPipe = createPipe;
  83. intern->blocked = false;
  84. intern->stopReadOperation = false;
  85. signal (SIGPIPE, NamedPipeInternal::signalHandler);
  86. siginterrupt (SIGPIPE, 1);
  87. const String pipePath (T("/tmp/") + File::createLegalFileName (pipeName));
  88. intern->pipeInName = pipePath + T("_in");
  89. intern->pipeOutName = pipePath + T("_out");
  90. intern->pipeIn = -1;
  91. intern->pipeOut = -1;
  92. if (createPipe)
  93. {
  94. if ((mkfifo (intern->pipeInName, 0666) && errno != EEXIST)
  95. || (mkfifo (intern->pipeOutName, 0666) && errno != EEXIST))
  96. {
  97. delete intern;
  98. internal = 0;
  99. return false;
  100. }
  101. }
  102. return true;
  103. }
  104. int NamedPipe::read (void* destBuffer, int maxBytesToRead, int /*timeOutMilliseconds*/)
  105. {
  106. int bytesRead = -1;
  107. NamedPipeInternal* const intern = (NamedPipeInternal*) internal;
  108. if (intern != 0)
  109. {
  110. intern->blocked = true;
  111. if (intern->pipeIn == -1)
  112. {
  113. if (intern->createdPipe)
  114. intern->pipeIn = ::open (intern->pipeInName, O_RDWR);
  115. else
  116. intern->pipeIn = ::open (intern->pipeOutName, O_RDWR);
  117. if (intern->pipeIn == -1)
  118. {
  119. intern->blocked = false;
  120. return -1;
  121. }
  122. }
  123. bytesRead = 0;
  124. char* p = (char*) destBuffer;
  125. while (bytesRead < maxBytesToRead)
  126. {
  127. const int bytesThisTime = maxBytesToRead - bytesRead;
  128. const int numRead = ::read (intern->pipeIn, p, bytesThisTime);
  129. if (numRead <= 0 || intern->stopReadOperation)
  130. {
  131. bytesRead = -1;
  132. break;
  133. }
  134. bytesRead += numRead;
  135. p += bytesRead;
  136. }
  137. intern->blocked = false;
  138. }
  139. return bytesRead;
  140. }
  141. int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
  142. {
  143. int bytesWritten = -1;
  144. NamedPipeInternal* const intern = (NamedPipeInternal*) internal;
  145. if (intern != 0)
  146. {
  147. if (intern->pipeOut == -1)
  148. {
  149. if (intern->createdPipe)
  150. intern->pipeOut = ::open (intern->pipeOutName, O_WRONLY);
  151. else
  152. intern->pipeOut = ::open (intern->pipeInName, O_WRONLY);
  153. if (intern->pipeOut == -1)
  154. {
  155. return -1;
  156. }
  157. }
  158. const char* p = (const char*) sourceBuffer;
  159. bytesWritten = 0;
  160. const uint32 timeOutTime = Time::getMillisecondCounter() + timeOutMilliseconds;
  161. while (bytesWritten < numBytesToWrite
  162. && (timeOutMilliseconds < 0 || Time::getMillisecondCounter() < timeOutTime))
  163. {
  164. const int bytesThisTime = numBytesToWrite - bytesWritten;
  165. const int numWritten = ::write (intern->pipeOut, p, bytesThisTime);
  166. if (numWritten <= 0)
  167. {
  168. bytesWritten = -1;
  169. break;
  170. }
  171. bytesWritten += numWritten;
  172. p += bytesWritten;
  173. }
  174. }
  175. return bytesWritten;
  176. }
  177. END_JUCE_NAMESPACE