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.

cmGrScFltk.cpp 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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. #include <FL/Fl.H>
  4. #include <Fl/fl_draw.h>
  5. #include <FL/Fl_Widget.H>
  6. #include <FL/Fl_Double_Window.H>
  7. #include <Fl/Fl_Output.H>
  8. #include <Fl/Fl_Menu_Bar.H>
  9. #include <vector>
  10. #include "Fl_CbLinker.h"
  11. #include "cmGlobal.h"
  12. #include "cmFloatTypes.h"
  13. #include "cmRpt.h"
  14. #include "cmErr.h"
  15. #include "cmCtx.h"
  16. #include "cmMem.h"
  17. #include "cmMallocDebug.h"
  18. #include "cmLinkedHeap.h"
  19. #include "cmText.h"
  20. #include "cmThread.h"
  21. #include "cmPrefs.h"
  22. #include "cmSymTbl.h"
  23. #include "cmTime.h"
  24. #include "cmMidi.h"
  25. #include "cmMidiFile.h"
  26. #include "cmAudioFile.h"
  27. #include "cmAudioFileMgr.h"
  28. #include "cmTimeLine.h"
  29. #include "cmScore.h"
  30. #include "cmGr.h"
  31. #include "cmGrDevCtx.h"
  32. #include "cmGrPlot.h"
  33. #include "cmGrPage.h"
  34. #include "cmGrFltk.h"
  35. #include "gvHashFunc.h"
  36. #include "cmGrScFltk.h"
  37. #include "cmGrPlotAudio.h"
  38. #include "cmdIf.h"
  39. cmGrScFltk::cmGrScFltk(cmCtx_t* ctx, cmdIf* cp, Fl_Menu_Bar* menu, int x, int y, int w, int h)
  40. : cmGrPlotFltk(ctx,x,y,w,h),
  41. _srate(0),_cmdIf(cp),_menuBar(menu),
  42. _samplesMetricId(cmInvalidId),_secondsMetricId(cmInvalidId),
  43. _objSecs(0),_objId(0),
  44. _togFl(true),
  45. _lastBarPlotObjH(cmGrPlObjNullHandle)
  46. {
  47. cmErrSetup(&_err,&ctx->rpt,"cmGrScFltk");
  48. _createMenu();
  49. if( cmGrPageIsValid(pageHandle()) == false )
  50. return;
  51. initViews(1,1);
  52. unsigned vwIdx = 0;
  53. cmGrPgH_t pgH = pageHandle();
  54. cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx);
  55. cmGrH_t cvH = cmGrViewGrHandle( vwH );
  56. cmGrAxH_t axH = cmGrAxNullHandle;
  57. cmGrVExt_t limExt;
  58. _samplesMetricId = cmGrPageLabelFuncRegister( pgH, gvRoundHashValueFunc, this, "Round" );
  59. _secondsMetricId = cmGrPageLabelFuncRegister( pgH, gvMinSecMsHashValueFunc, this, "Min:Sec:Ms" );
  60. unsigned pitchLabelFuncId = cmGrPageLabelFuncRegister( pgH, gvMidiSciPitchValueFunc, this, "Pitch" );
  61. cmGrVExtSetD(&limExt,0,0,0,127);
  62. cmGrObjSetWorldExt( cvH, cmGrRootObjH(cvH), &limExt );
  63. cmGrObjSetWorldLimitExt(cvH, cmGrRootObjH(cvH), &limExt, kTopGrFl | kBottomGrFl );
  64. axH = cmGrViewAxisHandle(vwH, kTopGrIdx);
  65. cmGrAxisSetCfg( axH, cmClrFlag(cmGrAxisCfg( axH ), kHashMarkGrFl | kHashLabelGrFl ));
  66. axH = cmGrViewAxisHandle(vwH, kLeftGrIdx );
  67. cmGrAxisSetLabelFunc( axH, pitchLabelFuncId );
  68. cmGrViewSetLabelFunc( vwH, kLeftGrIdx, pitchLabelFuncId );
  69. axH = cmGrViewAxisHandle(vwH, kRightGrIdx);
  70. cmGrAxisSetCfg( axH, cmClrFlag(cmGrAxisCfg( axH ), kHashLabelGrFl ));
  71. cmGrViewSetCfg( vwH, cmSetFlag(cmGrViewCfg(vwH),kSelectHorzGrFl) );
  72. }
  73. cmGrScFltk::~cmGrScFltk()
  74. {
  75. }
  76. cmScMsgTypeId_t cmGrScFltk::recvScoreMsg( const void* msg, unsigned msgByteCnt )
  77. {
  78. cmScMsg_t m;
  79. cmScoreDecode(msg,msgByteCnt,&m);
  80. switch( m.typeId )
  81. {
  82. case kBeginMsgScId:
  83. {
  84. _objId = 0;
  85. _objSecs = 0;
  86. // remove all objects from all views
  87. //cmGrPageClear(pageHandle());
  88. //_srate = m.srate;
  89. //_updateSeqMenu(m.seqCnt,m.seqId);
  90. }
  91. break;
  92. case kEndMsgScId:
  93. //size(w(),h()+1);
  94. break;
  95. case kEventMsgScId:
  96. _insertEvent(&m.u.evt);
  97. break;
  98. case kSectionMsgScId:
  99. _insertSection(&m.u.sect);
  100. break;
  101. case kVarMsgScId:
  102. break;
  103. default:
  104. { assert(0); }
  105. }
  106. return m.typeId;
  107. }
  108. void cmGrScFltk::setSampleRate( double srate )
  109. { _srate = srate; }
  110. double cmGrScFltk::sampleRate() const
  111. { return _srate; }
  112. bool cmGrScFltk::on_plot_object( cmGrPlotCbArg_t* arg )
  113. {
  114. if( arg->selId==kStateChangeGrPlId && cmIsFlag(arg->deltaFlags,kSelectGrPlFl) )
  115. {
  116. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(arg->objH);
  117. if( sop!=NULL && sop->id==kEventMsgScId && sop->u.ep != NULL /* && sep->type == kBarEvtScId */ )
  118. {
  119. _lastBarPlotObjH = arg->objH;
  120. unsigned scoreIdx = scoreSelectedEleIndex();
  121. // callback to: kcApp::_ctl_cb(ctl_t* cp)
  122. callback()(this,user_data());
  123. _cmdIf->onScoreBarSelected(scoreIdx);
  124. setStatusText(cmTsPrintfS("Score Index:%i",scoreIdx));
  125. }
  126. }
  127. return true;
  128. }
  129. void cmGrScFltk::selectBar( unsigned barNumb )
  130. {
  131. cmGrPlH_t plH = plotHandle();
  132. unsigned n = cmGrPlotObjectCount(plH);
  133. unsigned i;
  134. for(i=0; i<n; ++i)
  135. {
  136. cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
  137. if( cmGrPlotObjIsValid(poH) )
  138. {
  139. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
  140. if( sop->id==kEventMsgScId && sop->u.ep!=NULL && sop->u.ep->type==kBarEvtScId && sop->u.ep->barNumb==barNumb )
  141. {
  142. unsigned flags = cmGrPlotObjStateFlags(poH);
  143. cmGrPlotObjSetStateFlags(poH,cmSetFlag(flags,kFocusGrPlFl | kSelectGrPlFl));
  144. redraw();
  145. _lastBarPlotObjH = poH;
  146. _cmdIf->onScoreBarSelected(sop->u.ep->locIdx);
  147. setStatusText(cmTsPrintfS("Score Index:%i",sop->u.ep->locIdx));
  148. break;
  149. }
  150. }
  151. }
  152. }
  153. unsigned cmGrScFltk::scoreSelectedEleIndex() const
  154. {
  155. if( cmGrPlotObjIsValid(_lastBarPlotObjH) )
  156. {
  157. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(_lastBarPlotObjH);
  158. if( sop!=NULL && sop->id==kEventMsgScId && sop->u.ep != NULL /* && sop->u.ep->type == kBarEvtScId */ )
  159. return sop->u.ep->locIdx;
  160. }
  161. return cmInvalidIdx;
  162. }
  163. void cmGrScFltk::setScoreLocation( unsigned locIdx, unsigned vel, unsigned smpIdx )
  164. {
  165. }
  166. void cmGrScFltk::_insertSection( const cmScoreSection_t* m )
  167. {
  168. // The argument is a serialzed copy of a cmScoreSection_t record.
  169. // Convert it to a pointer to an actual object in the local score mgr.
  170. if( cmGrPageIsValid(pageHandle()) == false )
  171. return;
  172. m = _cmdIf->scoreSectionIdToPtr(m->index);
  173. assert(m!=NULL);
  174. const cmScoreEvt_t* ep = _cmdIf->scoreEventIdToPtr(m->begEvtIndex);
  175. assert( ep != NULL );
  176. cmGrPlH_t plH = plotHandle();
  177. cmGrPgH_t pgH = pageHandle();
  178. unsigned vwIdx = 0;
  179. cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx );
  180. cmGrH_t cvH = cmGrViewGrHandle( vwH );
  181. cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle;
  182. cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle;
  183. cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle;
  184. cmGrPlObjH_t objH = cmGrPlObjNullHandle;
  185. cmGrPlObjTypeId_t objTypeId = kLineGrPlId;
  186. cmReal_t x = ep->secs;
  187. cmReal_t y = 120;
  188. cmReal_t w = 0;
  189. cmReal_t h = 7;
  190. const cmChar_t* label = m->label;
  191. unsigned flags = kNoDragGrPlFl;
  192. cmGrVExt_t wext;
  193. scObj_t scObj(m);
  194. cmGrVExtSetNull(&wext);
  195. if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, label, cmGrVExtIsNull(&wext)?NULL:&wext ) != kOkGrPlRC )
  196. {
  197. cmErrMsg(&_err,kInsertObjFailRC,"Insert failed on a score section.", cmStringNullGuard(label));
  198. return;
  199. }
  200. cmGrPlotObjAllocUser(objH,&scObj,sizeof(scObj));
  201. unsigned f = 0 ? (kNorthJsGrFl | kTopJsGrFl) : (kSouthJsGrFl | kBottomJsGrFl);
  202. cmGrPlotObjSetLabelAttr( objH, f | kWestJsGrFl | kTopJsGrFl | kRightJsGrFl, 0, kBlackGrId );
  203. cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kGreenGrId );
  204. //cmGrPlotObjSetPhysExt(objH, 1, 0, 1, 0 );
  205. cmGrPlotObjSetFontSize(objH,8);
  206. }
  207. void cmGrScFltk::_insertEvent( const cmScoreEvt_t* m )
  208. {
  209. // The argument is a serialzed copy of a cmScoreEvt record.
  210. // Convert it to a pointer to an actual object in the local score mgr.
  211. if( cmGrPageIsValid(pageHandle()) == false )
  212. return;
  213. m = _cmdIf->scoreEventIdToPtr(m->index);
  214. assert(m!=NULL);
  215. cmGrPlH_t plH = plotHandle();
  216. cmGrPgH_t pgH = pageHandle();
  217. unsigned vwIdx = 0;
  218. cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx );
  219. cmGrH_t cvH = cmGrViewGrHandle( vwH );
  220. cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle;
  221. cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle;
  222. cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle;
  223. cmGrPlObjH_t objH = cmGrPlObjNullHandle;
  224. cmGrPlObjTypeId_t objTypeId = kVLineGrPlId;
  225. cmReal_t x = m->secs;
  226. cmReal_t y = 0;
  227. cmReal_t w = 0;
  228. cmReal_t h = 127;
  229. const cmChar_t* label = NULL;
  230. unsigned flags = kNoDragGrPlFl;
  231. int bufN = 7;
  232. cmChar_t buf[bufN+1];
  233. cmGrVExt_t wext;
  234. scObj_t scObj(m);
  235. cmGrVExtSetNull(&wext);
  236. switch( m->type )
  237. {
  238. case kNonEvtScId:
  239. objTypeId = kRectGrPlId;
  240. y = m->pitch;
  241. h = 1;
  242. w = m->durSecs;
  243. label = cmMidiToSciPitch(m->pitch,NULL,0);
  244. break;
  245. case kBarEvtScId:
  246. {
  247. buf[bufN] = 0;
  248. snprintf(buf,bufN,"%i",m->barNumb);
  249. objTypeId = kVLineGrPlId;
  250. label = buf;
  251. }
  252. break;
  253. case kPedalEvtScId:
  254. if( cmIsFlag(m->flags, kPedalDnScFl ) == false )
  255. return;
  256. objTypeId = kRectGrPlId;
  257. y = m->pitch; // pedal type (damper=64, sostenuto=66) is held in pitch
  258. h = 1;
  259. w = m->durSecs;
  260. flags += kNoFillGrPlFl;
  261. break;
  262. default:
  263. return;
  264. }
  265. if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, label, cmGrVExtIsNull(&wext)?NULL:&wext ) != kOkGrPlRC )
  266. {
  267. cmErrMsg(&_err,kInsertObjFailRC,"Insert failed on a score event.", cmStringNullGuard(label));
  268. return;
  269. }
  270. cmGrPlotObjAllocUser(objH,&scObj,sizeof(scObj));
  271. switch( m->type )
  272. {
  273. case kBarEvtScId:
  274. {
  275. unsigned f = _togFl ? (kNorthJsGrFl | kTopJsGrFl) : (kSouthJsGrFl | kBottomJsGrFl);
  276. cmGrPlotObjSetLabelAttr( objH, f | kWestJsGrFl | kTopJsGrFl | kRightJsGrFl, 0, kBlueGrId );
  277. cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kYellowGrId );
  278. cmGrPlotObjSetPhysExt(objH, 1, 0, 1, 0 );
  279. _togFl = !_togFl;
  280. }
  281. break;
  282. case kNonEvtScId:
  283. cmGrPlotObjSetLineColor( objH, kEnablePlGrId, cmGrPlotObjFillColor(objH,kEnablePlGrId) );
  284. cmGrPlotObjSetFontSize(objH,8);
  285. break;
  286. case kPedalEvtScId:
  287. cmGrPlotObjSetLineColor( objH, kEnablePlGrId, y==64 ? kDarkGreenGrId : kLightGreenGrId );
  288. break;
  289. default:
  290. break;
  291. }
  292. if( cmIsFlag(m->flags,kInvalidScFl) )
  293. {
  294. cmGrPlotObjSetFillColor(objH, kEnablePlGrId, kRedGrId );
  295. }
  296. }
  297. void cmGrScFltk::_createMenu( )
  298. {
  299. int idx = _menuBar->add("Score",0,NULL,0,FL_SUBMENU);
  300. const char* titleArray[] = { "Pitch", "Attributes", "Dynamics", "Location", "Fraction", "Section Even", "Section Dyn", "Section Tempo" };
  301. bool onFl[] = { true, false, false, false, false, false, false, false };
  302. int i;
  303. for(i=0; i<kMenuItemCnt; ++i)
  304. {
  305. _menuArray[i].id = i;
  306. _menuArray[i].p = this;
  307. _menuBar->insert(idx+1+i,titleArray[i],0,_s_menuCallback, _menuArray + i, FL_MENU_TOGGLE );
  308. if( onFl[i] )
  309. {
  310. Fl_Menu_Item* mip = (Fl_Menu_Item*)_menuBar->menu() + idx + i + 1;
  311. mip->set();
  312. }
  313. }
  314. }
  315. bool cmGrScFltk::_isMenuChecked( int id )
  316. {
  317. unsigned i;
  318. // locate the menu item assoc'd with id
  319. for(i=0; i<kMenuItemCnt; ++i)
  320. if( _menuArray[i].id == id )
  321. break;
  322. assert( i < kMenuItemCnt );
  323. int menuIdx;
  324. if(( menuIdx = _menuBar->find_index("Score")) == -1 )
  325. return false;
  326. // The menu items and _menuArray[] were initialized in the same order
  327. // therefore the offset from the base of both should be the same.
  328. Fl_Menu_Item* mip = (Fl_Menu_Item*)_menuBar->menu() + menuIdx + i + 1;
  329. assert( (item_t*)mip->user_data() == _menuArray + i );
  330. return mip->value() != 0;
  331. }
  332. void cmGrScFltk::_setEventLabels()
  333. {
  334. enum { kPitchFl=0x01, kAttrFl=0x02, kDynFl=0x04, kLocFl=0x08, kFracFl=0x10 };
  335. cmGrPlH_t plH = plotHandle();
  336. unsigned flags = 0;
  337. flags |= _isMenuChecked(kPitchMId) ? kPitchFl : 0;
  338. flags |= _isMenuChecked(kAttrMId) ? kAttrFl : 0;
  339. flags |= _isMenuChecked(kDynMId) ? kDynFl : 0;
  340. flags |= _isMenuChecked(kLocIdxMId) ? kLocFl : 0;
  341. flags |= _isMenuChecked(kFracMId) ? kFracFl : 0;
  342. unsigned n = cmGrPlotObjectCount(plH);
  343. unsigned i;
  344. for(i=0; i<n; ++i)
  345. {
  346. cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
  347. if( cmGrPlotObjIsValid(poH) )
  348. {
  349. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
  350. if( sop!=NULL && sop->id==kEventMsgScId && sop->u.ep!=NULL && sop->u.ep->type==kNonEvtScId )
  351. {
  352. const cmScoreEvt_t* ep = sop->u.ep;
  353. int bufN = 255;
  354. cmChar_t buf[ bufN+1 ];
  355. buf[bufN] = 0;
  356. buf[0] = 0;
  357. if( cmIsFlag(flags,kPitchFl) )
  358. snprintf(buf+strlen(buf),bufN-strlen(buf),"%s ",cmMidiToSciPitch(ep->pitch,NULL,0));
  359. if( cmIsFlag(flags,kAttrFl) )
  360. {
  361. cmChar_t s[4];
  362. int j=0;
  363. if( cmIsFlag(ep->flags,kEvenScFl) )
  364. s[j++] = 'e';
  365. if( cmIsFlag(ep->flags,kDynScFl) )
  366. s[j++] = 'd';
  367. if( cmIsFlag(ep->flags,kTempoScFl) )
  368. s[j++] = 't';
  369. s[j] = 0;
  370. snprintf(buf+strlen(buf),bufN-strlen(buf),"%s ",s);
  371. }
  372. if( cmIsFlag(flags,kDynFl) && cmIsFlag(ep->flags,kDynScFl) )
  373. {
  374. snprintf(buf+strlen(buf),bufN-strlen(buf),"d:%i",ep->dynVal);
  375. if( ep->perfDynLvl != 0 )
  376. snprintf(buf+strlen(buf),bufN-strlen(buf),"|%i ",ep->perfDynLvl);
  377. else
  378. snprintf(buf+strlen(buf),bufN-strlen(buf)," ");
  379. }
  380. if( cmIsFlag(flags,kLocFl) )
  381. snprintf(buf+strlen(buf),bufN-strlen(buf),"loc:%i ",ep->locIdx);
  382. if( cmIsFlag(flags,kFracFl) && ep->frac != 0)
  383. snprintf(buf+strlen(buf),bufN-strlen(buf),"%5.3f ",ep->frac);
  384. cmGrPlotObjSetLabel(poH, buf );
  385. }
  386. }
  387. }
  388. }
  389. void cmGrScFltk::_setSectionLabels()
  390. {
  391. enum { kEvenFl=0x01, kDynFl=0x02, kTempoFl=0x04 };
  392. cmGrPlH_t plH = plotHandle();
  393. unsigned flags = 0;
  394. flags |= _isMenuChecked(kSectEvenMId) ? kEvenFl : 0;
  395. flags |= _isMenuChecked(kSectDynMId) ? kDynFl : 0;
  396. flags |= _isMenuChecked(kSectTempoMId) ? kTempoFl : 0;
  397. unsigned n = cmGrPlotObjectCount(plH);
  398. unsigned i;
  399. for(i=0; i<n; ++i)
  400. {
  401. cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
  402. if( cmGrPlotObjIsValid(poH) )
  403. {
  404. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
  405. if( sop!=NULL && sop->id==kSectionMsgScId && sop->u.sp!=NULL )
  406. {
  407. const cmScoreSection_t* sp = sop->u.sp;
  408. int bufN = 255;
  409. cmChar_t buf[ bufN+1 ];
  410. buf[bufN] = 0;
  411. buf[0] = 0;
  412. snprintf(buf,bufN,"%s ",sp->label);
  413. if( cmIsFlag(flags,kEvenFl) && sp->vars[kEvenVarScId] != DBL_MAX)
  414. snprintf(buf+strlen(buf),bufN-strlen(buf),"e:%f ",sp->vars[kEvenVarScId]);
  415. if( cmIsFlag(flags,kDynFl) && sp->vars[kDynVarScId] != DBL_MAX)
  416. snprintf(buf+strlen(buf),bufN-strlen(buf),"d:%f ",sp->vars[kDynVarScId]);
  417. if( cmIsFlag(flags,kTempoFl) && sp->vars[kTempoVarScId] != DBL_MAX)
  418. snprintf(buf+strlen(buf),bufN-strlen(buf),"t:%f ",sp->vars[kTempoVarScId]);
  419. cmGrPlotObjSetLabel(poH, buf );
  420. }
  421. }
  422. }
  423. }
  424. void cmGrScFltk::_s_menuCallback(Fl_Widget* w, void* arg )
  425. {
  426. item_t* ip = (item_t*)arg;
  427. cmGrScFltk* p = ip->p;
  428. unsigned long id = ip->id;
  429. switch( id )
  430. {
  431. case kPitchMId:
  432. case kAttrMId:
  433. case kDynMId:
  434. case kLocIdxMId:
  435. case kFracMId:
  436. {
  437. p->_setEventLabels();
  438. p->redraw();
  439. }
  440. break;
  441. case kSectEvenMId:
  442. case kSectDynMId:
  443. case kSectTempoMId:
  444. {
  445. p->_setSectionLabels();
  446. p->redraw();
  447. }
  448. break;
  449. }
  450. }