Programmable real-time audio signal processing application
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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. }