Programmable real-time audio signal processing application
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.

cmdIf.h 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. //| Copyright: (C) 2019-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #ifndef cmdIf_h
  4. #define cmdIf_h
  5. class Fl_Output;
  6. // This class allows the 'model' to run independently
  7. // from the user interface. This eliminates problems with
  8. // application unresponsiveness which would arise from
  9. // executing compute intensive operations from UI control or
  10. // menu callback functions. It also allows a progress
  11. // or status bar to be shown while the model operation
  12. // is in progress.
  13. // The class works by enqueueing all incoming commands
  14. // into a thread-safe queue. An internal worker thread
  15. // executes the commands in the order they are received
  16. // and thereby changes the state of the model.
  17. // The results of model changes are posted to a second
  18. // thread-safe queue. These responses are picked
  19. // up by the onIdle() member and dispatched to an
  20. // object with a cmIfRspdr interface. Note that because
  21. // the onIdle() function is called from the applications
  22. // idle handler the callbacks to the cmIfRspdr are
  23. // always in the application thread and can therefore
  24. // safely interact with any application data constructs.
  25. // All calls to this object and all callbacks from it,
  26. // therefore occur in the application thread.
  27. class cmdIfRspdr
  28. {
  29. public:
  30. virtual ~cmdIfRspdr(){}
  31. virtual void cmdIfShowStatusMsg( const char* msg ) = 0;
  32. virtual void cmdIfHideStatus() = 0;
  33. virtual void cmdIfErrorMsg( const char* msg ) = 0;
  34. virtual void cmdIfTimeLineMsg( const void* msg, unsigned msgByteCnt ) = 0;
  35. virtual void cmdIfAudioFileLoad( unsigned fileId ) = 0;
  36. virtual void cmdIfScoreMsg( const void* msg, unsigned msgByteCnt ) = 0;
  37. virtual void cmdIfOnTimeLineMarkerSelect( unsigned markerId ) = 0;
  38. virtual void cmdIfOnTimeLineMidiEvtSelect(unsigned midiEvtId ) = 0;
  39. virtual void cmdIfOnScoreBarSelect( unsigned scoreIndex ) = 0;
  40. };
  41. class cmdIf
  42. {
  43. public:
  44. typedef enum
  45. {
  46. kOkRC,
  47. kCmdFailRC,
  48. kCmdEnqueueFailRC
  49. } rc_t;
  50. cmdIf( cmCtx_t* ctx, cmdIfRspdr* rspdr, const cmChar_t* audioPath=NULL );
  51. virtual ~cmdIf();
  52. // Open a time line.
  53. rc_t open( const cmChar_t* fn );
  54. // Close the time line.
  55. rc_t close();
  56. // Time line interface
  57. const cmChar_t* tlFileName() const;
  58. const cmTlObj_t* tlObjIdToPtr( unsigned tlObjId ) const;
  59. const cmTlMidiFile_t* tlMidiFileObjPtr( const cmTlObj_t* op ) const;
  60. const cmTlAudioFile_t* tlAudioFileObjPtr( const cmTlObj_t* op ) const;
  61. const cmTlMidiEvt_t* tlMidiEvtObjPtr( const cmTlObj_t* op ) const;
  62. const cmTlAudioEvt_t* tlAudioEvtObjPtr( const cmTlObj_t* op ) const;
  63. const cmTlMarker_t* tlMarkerObjPtr( const cmTlObj_t* op ) const;
  64. const cmChar_t* scoreFileName() const;
  65. const cmScoreEvt_t* scoreEventIdToPtr( unsigned scEvtId ) const;
  66. const cmScoreSection_t* scoreSectionIdToPtr( unsigned scSectId ) const;
  67. // Make a time line sequence active.
  68. rc_t selectSequence( unsigned id );
  69. // Load an audio file into the audio file mgr.
  70. // If an audio file path was set via setAudioFilePath() then
  71. // the directories referenced by 'fn' will be replaced by
  72. // the previously set audio file path.
  73. rc_t audioFileLoad( const cmChar_t* fn, unsigned appFileId );
  74. // Return the audio file handle assigned to appFileId.
  75. cmAfmFileH_t audioFileHandle( unsigned appFileId );
  76. // Set the audio file location.
  77. void setAudioFilePath( const cmChar_t* path );
  78. // Assign a score file
  79. rc_t setScore( const cmChar_t* scoreFn );
  80. // Set the current score location
  81. void setScoreLocation( unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel );
  82. // Set the value of a score variable
  83. void setScoreVarValue( unsigned locIdx, unsigned varId, double value );
  84. // Set the performed dynamic level of a score event.
  85. void setScoreDynLevel( unsigned evtIdx, unsigned dynLvl );
  86. void onTimeLineMarkerSelected( unsigned markerTlId );
  87. void onTimeLineMidiEvtSelected( unsigned midiEvtTlId );
  88. void onScoreBarSelected( unsigned scoreIndex );
  89. // Generate or delete Audio/MIDI onset markers.
  90. rc_t generateOnsetMarks();
  91. rc_t deleteOnsetMarks();
  92. // True if the worker thread is running.
  93. bool isBusy() const;
  94. // Called by the application to dequeue messages via callbacks to
  95. // the cmdIfRspdr.
  96. void onIdle();
  97. void testStub();
  98. private:
  99. // Id's used by cmd_t
  100. typedef enum
  101. {
  102. kInvalidCmdId, // 0
  103. kOpenCmdId, // 1 app->thread
  104. kCloseCmdId, // 2 app->thread
  105. kSelectSeqCmdId, // 3 app->thread
  106. kAfLoadCmdId, // 4 app->thread and thread->app
  107. kScoreCmdId, // 5 app->thread
  108. kShowStatusCmdId, // 6 thread->app
  109. kHideStatusCmdId, // 7 thread->app
  110. kErrMsgCmdId, // 8 thread->app
  111. kTimeLineMsgCmdId, // 9 thread->app
  112. kScoreMsgCmdId, //10 thread->app
  113. kGenOnsetMarksCmdId,
  114. kDelOnsetMarksCmdId
  115. } cmdId_t;
  116. // Messages are passed between the app and the worker thread
  117. // and v.v. using this record format. Note that the u.msg
  118. // field is always dynamically allocated by _enqueue()
  119. // and must be released following the dequeue operation.
  120. typedef struct cmd_str
  121. {
  122. cmdId_t id; // cmdId
  123. unsigned byteCnt; // length of msg
  124. unsigned value; // msg value
  125. union
  126. {
  127. void* msg; // msg[byteCnt]
  128. char* string; // string[byteCnt]
  129. } u;
  130. } cmd_t;
  131. cmCtx_t* _ctx; //
  132. cmErr_t _err; //
  133. cmThreadH_t _thH; // worker thread
  134. cmTs1p1cH_t _cmdQueH; // app->model
  135. cmTs1p1cH_t _outQueH; // model->appl
  136. cmTlH_t _tlH; // time line handle
  137. cmAfmH_t _afmH; // audio file manager
  138. cmScH_t _scH; // score handle
  139. cmChar_t* _afPath; //
  140. cmdIfRspdr* _rspdr; //
  141. unsigned _curSeqId; // seqId of last selected sequence
  142. // Functions called from the app thread.
  143. rc_t _sendCmd( cmdId_t id, unsigned value=0, const char* str=NULL );
  144. void _releaseQue( cmTs1p1cH_t* queHPtr );
  145. // Functions called from the worker thread
  146. static bool _thFunc( void* arg );
  147. void _thDoOpen( const cmd_t* cmd );
  148. void _thDoClose( const cmd_t* cmd );
  149. void _thDoSelectSeq( const cmd_t* cmd );
  150. void _thDoAfLoad( const cmd_t* cmd );
  151. void _thDoScore( const cmd_t* cmd );
  152. void _thDoGenOnsetMarks( const cmd_t* cmd );
  153. void _thDoDelOnsetMarks( const cmd_t* cmd );
  154. //void _thErrorMsg( const char* fmt, va_list vl );
  155. void _thErrorMsg( const char* fmt, ... );
  156. //void _thStatusMsg( const char* fmt, va_list vl );
  157. void _thStatusMsg( const char* fmt, ... );
  158. void _thSendResponse( cmdId_t id, const char* str = NULL, unsigned value=0 );
  159. static void _thSendTimeLineMsg( void* arg, const void* msg, unsigned byteCnt );
  160. static void _thSendScoreMsg( void* arg, const void* msg, unsigned byteCnt );
  161. // Thread independent functions
  162. rc_t _enqueue( cmTs1p1cH_t qH, cmdId_t id, unsigned value, const void* msg, unsigned msgByteCnt );
  163. // Print context information for selected time line objects
  164. void _onTimeLineObjSelected( unsigned tlObjId );
  165. };
  166. #endif