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.

167 lines
5.7KB

  1. #ifndef STK_MESSAGER_H
  2. #define STK_MESSAGER_H
  3. #include "Stk.h"
  4. #include "Skini.h"
  5. #include <queue>
  6. #if defined(__STK_REALTIME__)
  7. #include "Mutex.h"
  8. #include "Thread.h"
  9. #include "TcpServer.h"
  10. #include "RtMidi.h"
  11. #endif // __STK_REALTIME__
  12. namespace stk {
  13. /***************************************************/
  14. /*! \class Messager
  15. \brief STK input control message parser.
  16. This class reads and parses control messages from a variety of
  17. sources, such as a scorefile, MIDI port, socket connection, or
  18. stdin. MIDI messages are retrieved using the RtMidi class. All
  19. other input sources (scorefile, socket, or stdin) are assumed to
  20. provide SKINI formatted messages. This class can be compiled with
  21. generic, non-realtime support, in which case only scorefile
  22. reading is possible.
  23. The various \e realtime message acquisition mechanisms (from MIDI,
  24. socket, or stdin) take place asynchronously, filling the message
  25. queue. A call to popMessage() will pop the next available control
  26. message from the queue and return it via the referenced Message
  27. structure. When a \e non-realtime scorefile is set, it is not
  28. possible to start reading realtime input messages (from MIDI,
  29. socket, or stdin). Likewise, it is not possible to read from a
  30. scorefile when a realtime input mechanism is running.
  31. When MIDI input is started, input is also automatically read from
  32. stdin. This allows for program termination via the terminal
  33. window. An __SK_Exit_ message is pushed onto the stack whenever
  34. an "exit" or "Exit" message is received from stdin or when all
  35. socket connections close and no stdin thread is running.
  36. This class is primarily for use in STK example programs but it is
  37. generic enough to work in many other contexts.
  38. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  39. */
  40. /***************************************************/
  41. const int DEFAULT_QUEUE_LIMIT = 200;
  42. class Messager : public Stk
  43. {
  44. public:
  45. // This structure is used to share data among the various realtime
  46. // messager threads. It must be public.
  47. struct MessagerData {
  48. Skini skini;
  49. std::queue<Skini::Message> queue;
  50. unsigned int queueLimit;
  51. int sources;
  52. #if defined(__STK_REALTIME__)
  53. Mutex mutex;
  54. RtMidiIn *midi;
  55. TcpServer *socket;
  56. std::vector<int> fd;
  57. fd_set mask;
  58. #endif
  59. // Default constructor.
  60. MessagerData()
  61. :queueLimit(0), sources(0) {}
  62. };
  63. //! Default constructor.
  64. Messager();
  65. //! Class destructor.
  66. ~Messager();
  67. //! Pop the next message from the queue and write it to the referenced message structure.
  68. /*!
  69. Invalid messages (or an empty queue) are indicated by type
  70. values of zero, in which case all other message structure values
  71. are undefined. The user MUST verify the returned message type is
  72. valid before reading other message values.
  73. */
  74. void popMessage( Skini::Message& message );
  75. //! Push the referenced message onto the message stack.
  76. void pushMessage( Skini::Message& message );
  77. //! Specify a SKINI formatted scorefile from which messages should be read.
  78. /*!
  79. A return value of \c true indicates the call was successful. A
  80. return value of \c false can occur if the file is not found,
  81. cannot be opened, another file is currently still open, or if a
  82. realtime input mechanism is running. Scorefile input is
  83. considered to be a non-realtime control mechanism that cannot run
  84. concurrently with realtime input.
  85. */
  86. bool setScoreFile( const char* filename );
  87. #if defined(__STK_REALTIME__)
  88. //! Initiate the "realtime" retreival from stdin of control messages into the queue.
  89. /*!
  90. This function initiates a thread for asynchronous retrieval of
  91. SKINI formatted messages from stdin. A return value of \c true
  92. indicates the call was successful. A return value of \c false can
  93. occur if a scorefile is being read, a stdin thread is already
  94. running, or a thread error occurs during startup. Stdin input is
  95. considered to be a realtime control mechanism that cannot run
  96. concurrently with non-realtime scorefile input.
  97. */
  98. bool startStdInput();
  99. //! Start a socket server, accept connections, and read "realtime" control messages into the message queue.
  100. /*!
  101. This function creates a socket server on the optional port
  102. (default = 2001) and starts a thread for asynchronous retrieval of
  103. SKINI formatted messages from socket connections. A return value
  104. of \c true indicates the call was successful. A return value of
  105. \c false can occur if a scorefile is being read, a socket thread
  106. is already running, or an error occurs during the socket server
  107. or thread initialization stages. Socket input is considered to be
  108. a realtime control mechanism that cannot run concurrently with
  109. non-realtime scorefile input.
  110. */
  111. bool startSocketInput( int port=2001 );
  112. //! Start MIDI input, with optional device and port identifiers.
  113. /*!
  114. This function creates an RtMidiIn instance for MIDI input. The
  115. RtMidiIn class invokes a local callback function to read incoming
  116. messages into the queue. If \c port = -1, RtMidiIn will open a
  117. virtual port to which other software applications can connect (OS
  118. X and Linux only). A return value of \c true indicates the call
  119. was successful. A return value of \c false can occur if a
  120. scorefile is being read, MIDI input is already running, or an
  121. error occurs during RtMidiIn construction. Midi input is
  122. considered to be a realtime control mechanism that cannot run
  123. concurrently with non-realtime scorefile input.
  124. */
  125. bool startMidiInput( int port=0 );
  126. #endif
  127. protected:
  128. MessagerData data_;
  129. #if defined(__STK_REALTIME__)
  130. Thread stdinThread_;
  131. Thread socketThread_;
  132. #endif
  133. };
  134. } // stk namespace
  135. #endif