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.

214 lines
5.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. // (This file gets included by juce_mac_NativeCode.mm, rather than being
  19. // compiled on its own).
  20. #if JUCE_INCLUDED_FILE
  21. //==============================================================================
  22. struct NamedPipeInternal
  23. {
  24. String pipeInName, pipeOutName;
  25. int pipeIn, pipeOut;
  26. bool volatile createdPipe, blocked, stopReadOperation;
  27. static void signalHandler (int) {}
  28. };
  29. void NamedPipe::cancelPendingReads()
  30. {
  31. while (internal != 0 && ((NamedPipeInternal*) internal)->blocked)
  32. {
  33. NamedPipeInternal* const intern = (NamedPipeInternal*) internal;
  34. intern->stopReadOperation = true;
  35. char buffer [1] = { 0 };
  36. int bytesWritten = ::write (intern->pipeIn, buffer, 1);
  37. (void) bytesWritten;
  38. int timeout = 2000;
  39. while (intern->blocked && --timeout >= 0)
  40. Thread::sleep (2);
  41. intern->stopReadOperation = false;
  42. }
  43. }
  44. void NamedPipe::close()
  45. {
  46. NamedPipeInternal* const intern = (NamedPipeInternal*) internal;
  47. if (intern != 0)
  48. {
  49. internal = 0;
  50. if (intern->pipeIn != -1)
  51. ::close (intern->pipeIn);
  52. if (intern->pipeOut != -1)
  53. ::close (intern->pipeOut);
  54. if (intern->createdPipe)
  55. {
  56. unlink (intern->pipeInName);
  57. unlink (intern->pipeOutName);
  58. }
  59. delete intern;
  60. }
  61. }
  62. bool NamedPipe::openInternal (const String& pipeName, const bool createPipe)
  63. {
  64. close();
  65. NamedPipeInternal* const intern = new NamedPipeInternal();
  66. internal = intern;
  67. intern->createdPipe = createPipe;
  68. intern->blocked = false;
  69. intern->stopReadOperation = false;
  70. signal (SIGPIPE, NamedPipeInternal::signalHandler);
  71. siginterrupt (SIGPIPE, 1);
  72. const String pipePath (T("/tmp/") + File::createLegalFileName (pipeName));
  73. intern->pipeInName = pipePath + T("_in");
  74. intern->pipeOutName = pipePath + T("_out");
  75. intern->pipeIn = -1;
  76. intern->pipeOut = -1;
  77. if (createPipe)
  78. {
  79. if ((mkfifo (intern->pipeInName, 0666) && errno != EEXIST)
  80. || (mkfifo (intern->pipeOutName, 0666) && errno != EEXIST))
  81. {
  82. delete intern;
  83. internal = 0;
  84. return false;
  85. }
  86. }
  87. return true;
  88. }
  89. int NamedPipe::read (void* destBuffer, int maxBytesToRead, int /*timeOutMilliseconds*/)
  90. {
  91. int bytesRead = -1;
  92. NamedPipeInternal* const intern = (NamedPipeInternal*) internal;
  93. if (intern != 0)
  94. {
  95. intern->blocked = true;
  96. if (intern->pipeIn == -1)
  97. {
  98. if (intern->createdPipe)
  99. intern->pipeIn = ::open (intern->pipeInName, O_RDWR);
  100. else
  101. intern->pipeIn = ::open (intern->pipeOutName, O_RDWR);
  102. if (intern->pipeIn == -1)
  103. {
  104. intern->blocked = false;
  105. return -1;
  106. }
  107. }
  108. bytesRead = 0;
  109. char* p = (char*) destBuffer;
  110. while (bytesRead < maxBytesToRead)
  111. {
  112. const int bytesThisTime = maxBytesToRead - bytesRead;
  113. const int numRead = ::read (intern->pipeIn, p, bytesThisTime);
  114. if (numRead <= 0 || intern->stopReadOperation)
  115. {
  116. bytesRead = -1;
  117. break;
  118. }
  119. bytesRead += numRead;
  120. p += bytesRead;
  121. }
  122. intern->blocked = false;
  123. }
  124. return bytesRead;
  125. }
  126. int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
  127. {
  128. int bytesWritten = -1;
  129. NamedPipeInternal* const intern = (NamedPipeInternal*) internal;
  130. if (intern != 0)
  131. {
  132. if (intern->pipeOut == -1)
  133. {
  134. if (intern->createdPipe)
  135. intern->pipeOut = ::open (intern->pipeOutName, O_WRONLY);
  136. else
  137. intern->pipeOut = ::open (intern->pipeInName, O_WRONLY);
  138. if (intern->pipeOut == -1)
  139. {
  140. return -1;
  141. }
  142. }
  143. const char* p = (const char*) sourceBuffer;
  144. bytesWritten = 0;
  145. const uint32 timeOutTime = Time::getMillisecondCounter() + timeOutMilliseconds;
  146. while (bytesWritten < numBytesToWrite
  147. && (timeOutMilliseconds < 0 || Time::getMillisecondCounter() < timeOutTime))
  148. {
  149. const int bytesThisTime = numBytesToWrite - bytesWritten;
  150. const int numWritten = ::write (intern->pipeOut, p, bytesThisTime);
  151. if (numWritten <= 0)
  152. {
  153. bytesWritten = -1;
  154. break;
  155. }
  156. bytesWritten += numWritten;
  157. p += bytesWritten;
  158. }
  159. }
  160. return bytesWritten;
  161. }
  162. #endif