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.cpp 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. #include <FL/Fl.H>
  2. #include <FL/fl_draw.h>
  3. #include <FL/Fl_Widget.H>
  4. #include <FL/Fl_Double_Window.H>
  5. #include <Fl/Fl_Output.H>
  6. #include "cmPrefix.h"
  7. #include "cmGlobal.h"
  8. #include "cmFloatTypes.h"
  9. #include "cmRpt.h"
  10. #include "cmErr.h"
  11. #include "cmCtx.h"
  12. #include "cmMem.h"
  13. #include "cmMallocDebug.h"
  14. #include "cmLinkedHeap.h"
  15. #include "cmThread.h"
  16. #include "cmText.h"
  17. #include "cmFileSys.h"
  18. #include "cmJson.h"
  19. #include "cmPrefs.h"
  20. #include "cmSymTbl.h"
  21. #include "cmTime.h"
  22. #include "cmMidi.h"
  23. #include "cmMidiFile.h"
  24. #include "cmAudioFile.h"
  25. #include "cmTimeLine.h"
  26. #include "cmScore.h"
  27. #include "cmProcObj.h"
  28. #include "cmProc4.h"
  29. #include "cmAudioFileMgr.h"
  30. #include "cmdIf.h"
  31. #include <sstream>
  32. //-------------------------------------------------------------------------------------
  33. //-------------------------------------------------------------------------------------
  34. //-------------------------------------------------------------------------------------
  35. cmdIf::cmdIf( cmCtx_t* ctx, cmdIfRspdr* rspdr, const cmChar_t* audioPath )
  36. : _ctx(ctx),_thH(cmThreadNullHandle),
  37. _cmdQueH(cmTs1p1cNullHandle),_outQueH(cmTs1p1cNullHandle),
  38. _tlH(cmTimeLineNullHandle),_afmH(cmAfmNullHandle),_scH(cmScNullHandle),
  39. _afPath(NULL),_rspdr(rspdr),_curSeqId(cmInvalidId)
  40. {
  41. cmErrSetup(&_err,&ctx->rpt,"cmdIf");
  42. cmAfmCreate(ctx,&_afmH);
  43. cmThreadCreate( &_thH, _thFunc, this, &ctx->rpt );
  44. cmTs1p1cCreate( &_cmdQueH, 4*64536, NULL, NULL, &_ctx->rpt );
  45. cmTs1p1cCreate( &_outQueH, 4*64536, NULL, NULL, &_ctx->rpt );
  46. if( audioPath != NULL )
  47. setAudioFilePath(audioPath);
  48. }
  49. cmdIf::~cmdIf()
  50. {
  51. cmThreadDestroy( &_thH ); // stop the thread to prevent interfering with que release
  52. _releaseQue(&_cmdQueH);
  53. _releaseQue(&_outQueH);
  54. cmTimeLineFinalize(&_tlH);
  55. cmAfmDestroy(&_afmH);
  56. cmScoreFinalize(&_scH);
  57. cmMemFree(_afPath);
  58. }
  59. cmdIf::rc_t cmdIf::open( const cmChar_t* fn )
  60. { return _sendCmd(kOpenCmdId,0,fn); }
  61. cmdIf::rc_t cmdIf::close( )
  62. { return _sendCmd(kCloseCmdId); }
  63. const cmChar_t* cmdIf::tlFileName() const
  64. {
  65. if( cmTimeLineIsValid(_tlH) == false )
  66. return NULL;
  67. return cmTimeLineFileName(_tlH);
  68. }
  69. const cmTlMidiFile_t* cmdIf::tlMidiFileObjPtr( const cmTlObj_t* op ) const
  70. { return cmTimeLineMidiFileObjPtr(_tlH,const_cast<cmTlObj_t*>(op)); }
  71. const cmTlAudioFile_t* cmdIf::tlAudioFileObjPtr( const cmTlObj_t* op ) const
  72. { return cmTimeLineAudioFileObjPtr(_tlH,const_cast<cmTlObj_t*>(op)); }
  73. const cmTlMidiEvt_t* cmdIf::tlMidiEvtObjPtr( const cmTlObj_t* op ) const
  74. { return cmTimeLineMidiEvtObjPtr(_tlH,const_cast<cmTlObj_t*>(op)); }
  75. const cmTlAudioEvt_t* cmdIf::tlAudioEvtObjPtr( const cmTlObj_t* op ) const
  76. { return cmTimeLineAudioEvtObjPtr(_tlH,const_cast<cmTlObj_t*>(op)); }
  77. const cmTlMarker_t* cmdIf::tlMarkerObjPtr( const cmTlObj_t* op ) const
  78. { return cmTimeLineMarkerObjPtr(_tlH,const_cast<cmTlObj_t*>(op)); }
  79. const cmChar_t* cmdIf::scoreFileName() const
  80. {
  81. if( cmScoreIsValid(_scH) == false )
  82. return NULL;
  83. return cmScoreFileName(_scH);
  84. }
  85. const cmScoreEvt_t* cmdIf::scoreEventIdToPtr( unsigned scEvtId ) const
  86. {
  87. if( cmScoreIsValid(_scH)==false )
  88. return NULL;
  89. return cmScoreEvt(_scH,scEvtId);
  90. }
  91. const cmScoreSection_t* cmdIf::scoreSectionIdToPtr( unsigned scSectId ) const
  92. {
  93. if( cmScoreIsValid(_scH)==false)
  94. return NULL;
  95. return cmScoreSection(_scH,scSectId);
  96. }
  97. const cmTlObj_t* cmdIf::tlObjIdToPtr( unsigned tlObjId ) const
  98. { return cmTlIdToObjPtr( _tlH, tlObjId ); }
  99. cmdIf::rc_t cmdIf::selectSequence( unsigned id )
  100. { return _sendCmd(kSelectSeqCmdId,id); }
  101. cmdIf::rc_t cmdIf::audioFileLoad( const cmChar_t* fn, unsigned appFileId )
  102. {
  103. const cmChar_t* afFn = fn;
  104. //cmFileSysPathPart_t* pp = NULL ;
  105. /*
  106. if( _afPath != NULL )
  107. {
  108. pp = cmFsPathParts(fn);
  109. afFn = cmFsMakeFn(_afPath,pp->fnStr,pp->extStr,NULL);
  110. }
  111. */
  112. rc_t rc = _sendCmd(kAfLoadCmdId,appFileId,afFn);
  113. /*
  114. if( _afPath != NULL )
  115. {
  116. cmFsFreeFn(afFn);
  117. cmFsFreePathParts(pp);
  118. }
  119. */
  120. return rc;
  121. }
  122. cmAfmFileH_t cmdIf::audioFileHandle( unsigned appFileId )
  123. { return cmAfmIdToHandle(_afmH,appFileId); }
  124. void cmdIf::setAudioFilePath( const cmChar_t* path )
  125. { _afPath = cmMemResizeStr(_afPath,path); }
  126. cmdIf::rc_t cmdIf::setScore( const cmChar_t* scoreFn )
  127. { return _sendCmd(kScoreCmdId,0,scoreFn); }
  128. void cmdIf::setScoreLocation( unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel )
  129. {
  130. cmScoreSetPerfEvent(_scH,locIdx,smpIdx,pitch,vel);
  131. }
  132. void cmdIf::setScoreVarValue( unsigned locIdx, unsigned varId, double value )
  133. {
  134. cmScoreSetPerfValue(_scH,locIdx,varId,value);
  135. }
  136. void cmdIf::setScoreDynLevel( unsigned evtIdx, unsigned dynLvl )
  137. {
  138. cmScoreSetPerfDynLevel(_scH,evtIdx,dynLvl);
  139. }
  140. void cmdIf::onTimeLineMarkerSelected( unsigned markerTlId )
  141. {
  142. if( _rspdr != NULL )
  143. _rspdr->cmdIfOnTimeLineMarkerSelect(markerTlId);
  144. _onTimeLineObjSelected(markerTlId);
  145. }
  146. void cmdIf::onTimeLineMidiEvtSelected( unsigned midiEvtTlId )
  147. {
  148. if( _rspdr != NULL )
  149. _rspdr->cmdIfOnTimeLineMidiEvtSelect(midiEvtTlId);
  150. _onTimeLineObjSelected(midiEvtTlId);
  151. }
  152. void cmdIf::onScoreBarSelected( unsigned scoreIdx )
  153. {
  154. if( cmScoreIsValid(_scH) )
  155. cmScoreClearPerfInfo(_scH);
  156. if( _rspdr != NULL )
  157. _rspdr->cmdIfOnScoreBarSelect(scoreIdx);
  158. }
  159. cmdIf::rc_t cmdIf::generateOnsetMarks()
  160. { return _sendCmd( kGenOnsetMarksCmdId); }
  161. cmdIf::rc_t cmdIf::deleteOnsetMarks()
  162. { return _sendCmd( kDelOnsetMarksCmdId); }
  163. bool cmdIf::isBusy() const
  164. { return cmThreadIsValid(_thH) && cmThreadState(_thH)==kRunningThId; }
  165. void cmdIf::onIdle()
  166. {
  167. if( !cmTs1p1cIsValid(_outQueH) )
  168. return;
  169. // pick up msg's sent from the worker thread
  170. while( cmTs1p1cMsgWaiting(_outQueH) )
  171. {
  172. cmd_t c;
  173. cmThRC_t thRC;
  174. if((thRC = cmTs1p1cDequeueMsg(_outQueH,&c,sizeof(c))) != kOkThRC )
  175. {
  176. _thErrorMsg("Deque response failed.");
  177. continue;
  178. }
  179. //printf("deq th->app id:%i val:%i n:%i msg:%p\n",c.id,c.value,c.byteCnt,c.u.msg);
  180. switch( c.id )
  181. {
  182. // the worker thread is busy - show a modal progress window
  183. case kShowStatusCmdId:
  184. _rspdr->cmdIfShowStatusMsg(c.u.string);
  185. break;
  186. // the worker thread is idle - remove the modal progress window
  187. case kHideStatusCmdId:
  188. _rspdr->cmdIfHideStatus();
  189. break;
  190. // report an error which occured during a worker thread operation
  191. case kErrMsgCmdId:
  192. _rspdr->cmdIfErrorMsg(c.u.string);
  193. break;
  194. // send a msg to the time-line UI
  195. case kTimeLineMsgCmdId:
  196. _rspdr->cmdIfTimeLineMsg(c.u.msg,c.byteCnt);
  197. break;
  198. case kAfLoadCmdId:
  199. _rspdr->cmdIfAudioFileLoad(c.value);
  200. break;
  201. case kScoreMsgCmdId:
  202. _rspdr->cmdIfScoreMsg(c.u.msg,c.byteCnt);
  203. break;
  204. default:
  205. break;
  206. }
  207. if( c.byteCnt )
  208. {
  209. cmMemFree(c.u.msg);
  210. }
  211. }
  212. }
  213. //----------------------------------------------------------------------------------------
  214. // App Thread Functions
  215. //----------------------------------------------------------------------------------------
  216. cmdIf::rc_t cmdIf::_sendCmd( cmdId_t id, unsigned value, const char* str )
  217. {
  218. rc_t rc;
  219. if((rc = _enqueue( _cmdQueH, id, value, str, str==NULL ? 0 : strlen(str)+1 )) == kOkRC )
  220. cmThreadPause(_thH, 0 );
  221. else
  222. {
  223. cmErrMsg(&_err,kCmdEnqueueFailRC,"Command enque failed.");
  224. }
  225. return rc;
  226. }
  227. void cmdIf::_releaseQue( cmTs1p1cH_t* queHPtr )
  228. {
  229. while( cmTs1p1cMsgWaiting(*queHPtr) )
  230. {
  231. cmd_t c;
  232. cmThRC_t thRC;
  233. if((thRC = cmTs1p1cDequeueMsg(*queHPtr,&c,sizeof(c))) != kOkThRC )
  234. {
  235. // TODO: PRINT ERROR MSG HERE USING APP THREAD ERROR HANDLER
  236. //_thErrorMsg("Deque command failed during queue draining.");
  237. continue;
  238. }
  239. if( c.byteCnt )
  240. cmMemFree(c.u.msg);
  241. }
  242. cmTs1p1cDestroy(queHPtr);
  243. }
  244. //----------------------------------------------------------------------------------------
  245. // Worker Thread Functions
  246. //----------------------------------------------------------------------------------------
  247. bool cmdIf::_thFunc( void* arg )
  248. {
  249. cmdIf* p = (cmdIf*)arg;
  250. while( cmTs1p1cMsgWaiting(p->_cmdQueH) )
  251. {
  252. cmd_t c;
  253. cmThRC_t thRC;
  254. if((thRC = cmTs1p1cDequeueMsg(p->_cmdQueH,&c,sizeof(c))) != kOkThRC )
  255. {
  256. p->_thErrorMsg("Deque command failed.");
  257. continue;
  258. }
  259. switch(c.id )
  260. {
  261. case kOpenCmdId:
  262. p->_thDoOpen(&c);
  263. break;
  264. case kCloseCmdId:
  265. p->_thDoClose(&c);
  266. break;
  267. case kSelectSeqCmdId:
  268. p->_thDoSelectSeq(&c);
  269. break;
  270. case kAfLoadCmdId:
  271. p->_thDoAfLoad(&c);
  272. break;
  273. case kScoreCmdId:
  274. p->_thDoScore(&c);
  275. break;
  276. case kGenOnsetMarksCmdId:
  277. p->_thDoGenOnsetMarks(&c);
  278. break;
  279. case kDelOnsetMarksCmdId:
  280. p->_thDoDelOnsetMarks(&c);
  281. break;
  282. default:
  283. break;
  284. }
  285. if( c.byteCnt )
  286. cmMemFree(c.u.msg);
  287. }
  288. cmThreadPause( p->_thH, kPauseThFl );
  289. return true;
  290. }
  291. //void cmdIfRptFunc( void* user, const cmChar_t* text )
  292. //{ printf("%s",text); }
  293. void cmdIf::_thDoOpen( const cmd_t* cmd )
  294. {
  295. _thStatusMsg("Loading: '%s'",cmd->u.string);
  296. if( cmTimeLineInitializeFromFile(_ctx,&_tlH,_thSendTimeLineMsg,this,cmd->u.string,_afPath) != kOkTlRC )
  297. _thErrorMsg("Load failed on '%s'.",cmd->u.string);
  298. else
  299. {
  300. _curSeqId = 0;
  301. // Make notification callbacks for all time line records to _thSendTimeLineMsg()
  302. // _thSendTimeLineMsg() then enqueues msg's into _outQueH which are picked
  303. // up by the idle handler
  304. cmTimeLineSeqNotify(_tlH,_curSeqId);
  305. }
  306. _thSendResponse(kHideStatusCmdId);
  307. }
  308. void cmdIf::_thDoClose( const cmd_t* cmd )
  309. {
  310. _thStatusMsg("Closing ... ");
  311. if( cmTimeLineFinalize(&_tlH) != kOkTlRC )
  312. {
  313. _thErrorMsg("Time line finalize failed.");
  314. }
  315. _thSendResponse(kHideStatusCmdId);
  316. }
  317. void cmdIf::_thDoSelectSeq( const cmd_t* cmd )
  318. {
  319. _thStatusMsg("Selecting Sequence:%i ",cmd->value);
  320. _curSeqId = cmInvalidId;
  321. if( cmTimeLineSeqNotify(_tlH,cmd->value) != kOkTlRC )
  322. _thErrorMsg("Sequence selection failed.");
  323. else
  324. _curSeqId = cmd->value;
  325. _thSendResponse(kHideStatusCmdId);
  326. }
  327. void cmdIf::_thDoAfLoad( const cmd_t* cmd )
  328. {
  329. _thStatusMsg("Loading Audio File: '%s'",cmd->u.string);
  330. cmAfmFileH_t afH = cmAfmFileNullHandle;
  331. if( cmAfmFileOpen(_afmH,&afH,cmd->u.string, cmd->value, NULL ) != kOkAfmRC )
  332. _thErrorMsg("Audio file load failed on '%s'.",cmd->u.string);
  333. else
  334. {
  335. double msPerSummaryPt = 50.0;
  336. unsigned samplesPerSummaryPt = (unsigned)floor(cmAfmFileInfo(afH)->srate * msPerSummaryPt / 1000.0);
  337. if( cmAfmFileSummarize(afH,samplesPerSummaryPt) != kOkAfmRC )
  338. _thErrorMsg("Audio file summarization failed on '%s'.",cmd->u.string);
  339. else
  340. _thSendResponse(kAfLoadCmdId,cmd->u.string,cmd->value);
  341. }
  342. _thSendResponse(kHideStatusCmdId);
  343. }
  344. void cmdIf::_thDoScore( const cmd_t* cmd )
  345. {
  346. _thStatusMsg("Loading Score File: '%s'",cmd->u.string);
  347. if( cmScoreInitialize(_ctx,&_scH,cmd->u.string,0,NULL,0,_thSendScoreMsg,this,cmSymTblNullHandle) != kOkScRC )
  348. _thErrorMsg("Score open failed on '%s'.",cmStringNullGuard(cmd->u.string));
  349. else
  350. {
  351. // Make notification callbacks for all score records to _thSendScoreMsg()
  352. // _thSendScoreMsg() then enqueues msg's into _outQueH which are picked
  353. // up by the idle handler
  354. cmScoreSeqNotify(_scH);
  355. }
  356. _thSendResponse(kHideStatusCmdId);
  357. }
  358. void cmdIf::_thDoGenOnsetMarks( const cmd_t* cmd )
  359. {
  360. if( !cmTimeLineIsValid(_tlH) )
  361. return;
  362. _thStatusMsg("Generating Onset Markers.");
  363. // makes notification callbacks to _thSendTimeLineMsg()
  364. if( cmTimeLineGenOnsetMarks(_tlH,_curSeqId) != kOkTlRC )
  365. _thErrorMsg("Onset marker generation failed.");
  366. else
  367. cmTimeLineSeqNotify(_tlH,_curSeqId);
  368. _thSendResponse(kHideStatusCmdId);
  369. }
  370. void cmdIf::_thDoDelOnsetMarks( const cmd_t* cmd )
  371. {
  372. if( !cmTimeLineIsValid(_tlH) )
  373. return;
  374. _thStatusMsg("Deleting Onset Markers.");
  375. // makes notification callbacks to _thSendTimeLineMsg()
  376. if( cmTimeLineDeleteOnsetMarks(_tlH,_curSeqId) != kOkTlRC )
  377. _thErrorMsg("Onset marker deletion failed.");
  378. _thSendResponse(kHideStatusCmdId);
  379. }
  380. /*
  381. void cmdIf::_thErrorMsg( const char* fmt, va_list vl )
  382. {
  383. const cmChar_t* s = cmTsVPrintf(fmt,vl);
  384. _thSendResponse(kErrMsgCmdId,s);
  385. cmTsFreeStr(s);
  386. }
  387. */
  388. void cmdIf::_thErrorMsg( const char* fmt, ... )
  389. {
  390. va_list vl,vl1;
  391. va_start(vl,fmt);
  392. va_copy(vl1,vl);
  393. int n = vsnprintf(NULL,0,fmt,vl);
  394. char b[n+1];
  395. vsnprintf(b,n+1,fmt,vl1);
  396. _thSendResponse(kErrMsgCmdId,b);
  397. va_end(vl1);
  398. va_end(vl);
  399. }
  400. /*
  401. void cmdIf::_thStatusMsg( const char* fmt, va_list vl )
  402. {
  403. const cmChar_t* s = cmTsVPrintf(fmt,vl);
  404. _thSendResponse(kShowStatusCmdId,s);
  405. cmTsFreeStr(s);
  406. }
  407. */
  408. void cmdIf::_thStatusMsg( const char* fmt, ... )
  409. {
  410. va_list vl,vl1;
  411. va_start(vl,fmt);
  412. va_copy(vl1,vl);
  413. int n = vsnprintf(NULL,0,fmt,vl);
  414. char b[n+1];
  415. vsnprintf(b,n+1,fmt,vl1);
  416. _thSendResponse(kShowStatusCmdId,b);
  417. va_end(vl1);
  418. va_end(vl);
  419. }
  420. void cmdIf::_thSendResponse( cmdId_t id, const char* str, unsigned value )
  421. {
  422. if( _enqueue( _outQueH, id, value, str, str==NULL ? 0 : strlen(str)+1 ) != kOkRC )
  423. {
  424. _thErrorMsg("Response send failed.");
  425. }
  426. }
  427. void cmdIf::_thSendTimeLineMsg( void* arg, const void* msg, unsigned byteCnt )
  428. {
  429. cmdIf* p = (cmdIf*)arg;
  430. if( cmTs1p1cIsValid( p->_outQueH ) )
  431. if( p->_enqueue( p->_outQueH, kTimeLineMsgCmdId, 0, msg, byteCnt ) != kOkRC )
  432. p->_thErrorMsg("Time Line enqueue failed on response queue.");
  433. }
  434. void cmdIf::_thSendScoreMsg( void* arg, const void* msg, unsigned byteCnt )
  435. {
  436. cmdIf* p = (cmdIf*)arg;
  437. if( cmTs1p1cIsValid( p->_outQueH ) )
  438. if( p->_enqueue( p->_outQueH, kScoreMsgCmdId, 0, msg, byteCnt ) != kOkRC )
  439. p->_thErrorMsg("Score msg enqueue failed on response queue.");
  440. }
  441. //----------------------------------------------------------------------------------------
  442. // Thread Independent Functions
  443. //----------------------------------------------------------------------------------------
  444. cmdIf::rc_t cmdIf::_enqueue( cmTs1p1cH_t qH, cmdId_t id, unsigned value, const void* data, unsigned byteCnt )
  445. {
  446. cmThRC_t thRC;
  447. rc_t rc = kOkRC;
  448. cmd_t c;
  449. assert( (byteCnt==0 && data==NULL) || (byteCnt!=0 && data!=NULL) );
  450. c.id = id;
  451. c.byteCnt = byteCnt;
  452. c.value = value;
  453. c.u.msg = NULL;
  454. if( byteCnt )
  455. {
  456. // memory allocated here must be deleted after the record is dequeued
  457. c.u.string = cmMemAlloc(char,byteCnt);
  458. memcpy(c.u.msg,data,byteCnt);
  459. }
  460. //printf("enq %s id:%i n:%i msg:%p\n", cmHandlesAreEqual(qH,_outQueH) ? "thr->app" : "app->thr", c.id,c.byteCnt,c.u.string);
  461. if((thRC = cmTs1p1cEnqueueMsg(qH,&c,sizeof(c))) != kOkThRC )
  462. {
  463. if( byteCnt )
  464. cmMemFree(c.u.string);
  465. rc = kCmdFailRC;
  466. }
  467. return rc;
  468. }
  469. //----------------------------------------------------------------------------------------
  470. void cmdIf::_onTimeLineObjSelected( unsigned tlObjId )
  471. {
  472. const cmTlObj_t* mop;
  473. if((mop = cmTimeLineIdToObj(_tlH,cmInvalidId,tlObjId)) == NULL )
  474. {
  475. cmErrMsg(&_err,kCmdFailRC,"Unexpected invalid time line marker id '%i'.",tlObjId);
  476. return;
  477. }
  478. const cmTlAudioFile_t* afp = cmTimeLineAudioFileAtTime(_tlH, mop->seqId, mop->seqSmpIdx );
  479. const cmTlMidiFile_t* mfp = cmTimeLineMidiFileAtTime( _tlH, mop->seqId, mop->seqSmpIdx );
  480. const cmTlMidiEvt_t* mep = cmTimeLineMidiEvtAtTime( _tlH, mop->seqId, mop->seqSmpIdx );
  481. if( afp != NULL )
  482. printf("%s\n",afp->fn);
  483. if( mfp != NULL )
  484. printf("%s : %i\n",mfp->fn,mop->seqSmpIdx);
  485. if( mep != NULL )
  486. {
  487. if( mep->msg->status == kNoteOnMdId )
  488. printf("%s : %i\n",cmMidiToSciPitch(mep->msg->u.chMsgPtr->d0,NULL,0),mep->obj.seqSmpIdx);
  489. else
  490. printf("midi:%i\n",mep->msg->status);
  491. }
  492. }
  493. //----------------------------------------------------------------------------------------
  494. void cmdIf::testStub()
  495. {
  496. //ed_main();
  497. //cmScAlignScanMarkers(_err.rpt, _tlH, _scH );
  498. //sc_main(_scH,_tlH);
  499. cmScorePrintLoc(_scH);
  500. }