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.

cmGrScFltk.cpp 15KB

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