//| Copyright: (C) 2019-2020 Kevin Larke //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file. #include #include #include #include #include #include #include #include "Fl_CbLinker.h" #include "cmGlobal.h" #include "cmFloatTypes.h" #include "cmRpt.h" #include "cmErr.h" #include "cmCtx.h" #include "cmMem.h" #include "cmMallocDebug.h" #include "cmLinkedHeap.h" #include "cmText.h" #include "cmThread.h" #include "cmPrefs.h" #include "cmTime.h" #include "cmMidi.h" #include "cmMidiFile.h" #include "cmAudioFile.h" #include "cmAudioFileMgr.h" #include "cmSymTbl.h" #include "cmTimeLine.h" #include "cmScore.h" #include "cmGr.h" #include "cmGrDevCtx.h" #include "cmGrPlot.h" #include "cmGrPage.h" #include "cmGrFltk.h" #include "gvHashFunc.h" #include "cmGrTlFltk.h" #include "cmGrPlotAudio.h" #include "cmdIf.h" cmGrTlFltk::cmGrTlFltk(cmCtx_t* ctx, cmdIf* cp, Fl_Menu_Bar* menu, int x, int y, int w, int h) : cmGrPlotFltk(ctx,x,y,w,h),_srate(0),_cmdIf(cp),_menuBar(menu), _seqMenuIdx(cmInvalidIdx),_seqCnt(0),_seqItemArray(NULL), _markCnt(0), _samplesMetricId(cmInvalidId),_secondsMetricId(cmInvalidId), _selMarkPlotObjH(cmGrPlObjNullHandle), _curSeqId(cmInvalidId) { _createMenu(); //_seqMenuIdx = _menuBar->find_index("&Seq"); cmErrSetup(&_err,&ctx->rpt,"cmGrTlFltk"); if( cmGrPageIsValid(pageHandle()) == false ) return; // set the arrangement of 'views' on the 'page' // (2 rows, 1 column) initViews(kViewCnt,1); unsigned vwIdx = kAudioVwIdx; cmGrPgH_t grPgH = pageHandle(); cmGrVwH_t grVwH = cmGrPageViewHandle( grPgH, vwIdx); cmGrH_t grH = cmGrViewGrHandle( grVwH ); cmGrAxH_t grAxH = cmGrAxNullHandle; cmGrVExt_t limExt; // register plot hash mark labelling functions _samplesMetricId = cmGrPageLabelFuncRegister( grPgH, _s_roundHashValueFunc, this, "Round" ); _secondsMetricId = cmGrPageLabelFuncRegister( grPgH, _s_minSecMsHashValueFunc, this, "Min:Sec:Ms" ); unsigned pitchLabelFuncId = cmGrPageLabelFuncRegister( grPgH, _s_midiSciPitchValueFunc, this, "Pitch" ); //unsigned timeLabelFuncId = _secondsMetricId; cmGrVExtSetD(&limExt,0,-1,0,1); cmGrObjSetWorldLimitExt(grH, cmGrRootObjH(grH), &limExt, kTopGrFl | kBottomGrFl ); grAxH = cmGrViewAxisHandle(grVwH, kBottomGrIdx); cmGrAxisSetCfg( grAxH, cmClrFlag(cmGrAxisCfg( grAxH ), kHashMarkGrFl | kHashLabelGrFl )); //grAxH = cmGrViewAxisHandle(grVwH, kTopGrIdx ); //cmGrAxisSetLabelFunc( grAxH, timeLabelFuncId ); grAxH = cmGrViewAxisHandle(grVwH, kRightGrIdx); cmGrAxisSetCfg( grAxH, cmClrFlag(cmGrAxisCfg( grAxH ), kHashLabelGrFl )); //cmGrViewSetLabelFunc( grVwH, kTopGrIdx, timeLabelFuncId ); cmGrViewSetCfg( grVwH, cmSetFlag(cmGrViewCfg(grVwH),kSelectHorzGrFl) ); vwIdx = kMidiVwIdx; grVwH = cmGrPageViewHandle( grPgH, vwIdx); grH = cmGrViewGrHandle( grVwH ); cmGrVExtSetD(&limExt,0,0,0,127); cmGrObjSetWorldLimitExt(grH, cmGrRootObjH(grH), &limExt, kTopGrFl | kBottomGrFl ); grAxH = cmGrViewAxisHandle(grVwH, kTopGrIdx); cmGrAxisSetCfg( grAxH, cmClrFlag(cmGrAxisCfg( grAxH ), kHashMarkGrFl | kHashLabelGrFl )); //grAxH = cmGrViewAxisHandle(grVwH, kBottomGrIdx ); //cmGrAxisSetLabelFunc( grAxH, timeLabelFuncId ); grAxH = cmGrViewAxisHandle(grVwH, kRightGrIdx); cmGrAxisSetCfg( grAxH, cmClrFlag(cmGrAxisCfg( grAxH ), kHashLabelGrFl )); grAxH = cmGrViewAxisHandle(grVwH, kLeftGrIdx ); cmGrAxisSetLabelFunc( grAxH, pitchLabelFuncId ); //cmGrViewSetLabelFunc( grVwH, kTopGrIdx, timeLabelFuncId ); cmGrViewSetLabelFunc( grVwH, kLeftGrIdx, pitchLabelFuncId ); cmGrViewSetCfg( grVwH, cmSetFlag(cmGrViewCfg(grVwH),kSelectHorzGrFl) ); cmGrSetSync( grH, cmGrViewGrHandle( cmGrPageViewHandle( grPgH, kAudioVwIdx ) ), kWorldSyncGrFl | kViewSyncGrFl | kSelectSyncGrFl | kHorzSyncGrFl ); cmGrSetSync( cmGrViewGrHandle( cmGrPageViewHandle( grPgH, kAudioVwIdx ) ), grH, kWorldSyncGrFl | kViewSyncGrFl | kSelectSyncGrFl | kHorzSyncGrFl ); setTimeAxisMetric(kSecondsMetricId); } cmGrTlFltk::~cmGrTlFltk() { cmMemFree(_seqItemArray); } void cmGrTlFltk::_insertTimeLineObj( const cmTlUiMsg_t* m ) { cmGrPlH_t plH = plotHandle(); cmGrPgH_t pgH = pageHandle(); cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle; cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle; cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle; cmGrPlObjH_t objH = cmGrPlObjNullHandle; const cmTlObj_t* top = _cmdIf->tlObjIdToPtr(m->objId); assert(top != NULL); if( top==NULL) return; unsigned parentObjId = (top!=NULL && top->ref!=NULL) ? top->ref->uid : cmInvalidId; const cmTlMidiEvt_t* mep = NULL; const cmTlAudioFile_t* afp = NULL; unsigned vwIdx = kAudioVwIdx; cmGrPlObjTypeId_t objTypeId = kRectGrPlId; cmReal_t x = top->begSmpIdx; cmReal_t y = -1.0; cmReal_t w = top->durSmpCnt; cmReal_t h = 2.0; const cmChar_t* label = top->name; unsigned flags = kNoDragGrPlFl; bool pedalFl = false; cmGrVExt_t wext; cmGrVExtSetNull(&wext); // convert cmTlUiMsg_t into parameters for a call to cmGrPlotObjCreate(). switch( top->typeId ) { case kMidiFileTlId: { vwIdx = kMidiVwIdx; y = 0; h = 127; flags |= kNoFillGrPlFl | kNoSelectGrPlFl; cmGrVExtSet(&wext,0,0,top->durSmpCnt,h); if( parentObjId != cmInvalidId ) xAnchorObjH = cmGrPlotObjectIdToHandle( plH, parentObjId ); //printf("midi file id:%i x:%f y:%f w:%f h:%f %s\n",m->objId,x,y,w,h,cmStringNullGuard(label)); } break; case kMidiEvtTlId: { mep = _cmdIf->tlMidiEvtObjPtr(top); vwIdx = kMidiVwIdx; y = 127; // all non-note-on msg's get put to the top of the display h = 1; w = 100; // arbitrary msg duration xAnchorObjH = cmGrPlotObjectIdToHandle( plH, parentObjId ); parentObjH = cmGrPlotObjectIdToHandle( plH, mep->midiFileObjId ); assert( cmHandlesAreNotEqual(xAnchorObjH,cmGrPlObjNullHandle) ); assert( cmHandlesAreNotEqual(parentObjH,cmGrPlObjNullHandle) ); const cmMidiTrackMsg_t* mtm = mep->msg; cmMidiByte_t status = mtm->status; if( cmMidiIsNoteOn(status) ) { y = mtm->u.chMsgPtr->d0; w = top->durSmpCnt; label = cmMidiToSciPitch(mtm->u.chMsgPtr->d0,NULL,0); } else { if( cmMidiIsSustainPedalDown(status,mtm->u.chMsgPtr->d0,mtm->u.chMsgPtr->d1) ) { y = 64; w = top->durSmpCnt; flags += kNoFillGrPlFl; label = "Pedal"; pedalFl= true; } else { if( status == kMetaStId ) label = cmMidiMetaStatusToLabel(mtm->metaId); else label = cmMidiStatusToLabel(status); } } } break; case kAudioFileTlId: afp = _cmdIf->tlAudioFileObjPtr(top); if( parentObjId != cmInvalidId ) xAnchorObjH = cmGrPlotObjectIdToHandle( plH, parentObjId ); cmGrVExtSet(&wext,0,-1,top->durSmpCnt,h); //printf("audio file id:%i x:%f y:%f w:%f h:%f %s\n",m->objId,x,y,w,h,cmStringNullGuard(label)); break; case kAudioEvtTlId: objTypeId = kVLineGrPlId; break; case kMarkerTlId: if( _cmdIf->tlMarkerObjPtr(top)->typeId == kMidiOnsetMarkTlId ) vwIdx = kMidiVwIdx; objTypeId = kVLineGrPlId; xAnchorObjH = cmGrPlotObjectIdToHandle( plH, parentObjId ); //flags |= kNoFillGrPlFl | kBorderSelGrPlFl | kNoFocusGrPlFl; w = 0; break; default: { assert(0); } } cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx ); cmGrH_t cvH = cmGrViewGrHandle( vwH ); //const cmChar_t* anchLabel = cmHandlesAreEqual(xAnchorObjH,cmGrPlObjNullHandle) ? NULL : cmGrPlotObjLabel(xAnchorObjH); //const cmChar_t* parentLabel = cmHandlesAreEqual(parentObjH,cmGrPlObjNullHandle) ? NULL : cmGrPlotObjLabel(parentObjH); //printf("type:%i id:%i x:%f y:%f w:%f h:%f %s parent:%s xachor:%s\n",m->typeId,m->objId,x,y,w,h,cmStringNullGuard(label),cmStringNullGuard(parentLabel),cmStringNullGuard(anchLabel)); // Create the object if( cmGrPlotObjCreate(plH, cvH, &objH, m->objId, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, label, cmGrVExtIsNull(&wext)?NULL:&wext ) != kOkGrPlRC ) { cmErrMsg(&_err,kInsertObjFailRC,"Insert failed on the object labelled '%s'.", cmStringNullGuard(top->name)); return; } // set the plot obj's user arg. to be the time line element pointer cmGrPlotObjSetUserPtr(objH,(void*)top); // if the sequence is changing then invalidate the currently selected marker object if( m->seqId != _curSeqId ) { _curSeqId = m->seqId; _selMarkPlotObjH = cmGrPlObjNullHandle; } // Modify the objects attributes if( cmGrPlotObjIsValid(objH) ) { switch( top->typeId ) { case kMidiEvtTlId: cmGrPlotObjSetFontSize(objH,9); if( pedalFl ) cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kGreenGrId ); else cmGrPlotObjSetLineColor( objH, kEnablePlGrId, cmGrPlotObjFillColor(objH,kEnablePlGrId) ); _setMidiEventLabels(objH,_getMenuCheckFlags()); break; case kAudioFileTlId: if( afp->fn != NULL ) _cmdIf->audioFileLoad(afp->fn,m->objId); break; case kMarkerTlId: { cmGrColor_t color = kBlackGrId; const cmTlMarker_t* mop = _cmdIf->tlMarkerObjPtr(top); switch( mop->typeId) { case kAudioMarkTlId: { unsigned n = cmGrColorMapEleCount( cvH, kGrDefaultColorMapId ); unsigned ci = _markCnt++ % n; color = cmGrColorMap(cvH,kGrDefaultColorMapId)[ci]; } break; case kAudioOnsetMarkTlId: color = kDarkRedGrId; break; case kMidiOnsetMarkTlId: color = kDarkBlueGrId; break; default: { assert(0); } } cmGrPlotObjSetLabelAttr( objH, kNorthJsGrFl | kWestJsGrFl | kTopJsGrFl | kRightJsGrFl, 0, color ); cmGrPlotObjSetLineColor( objH, kEnablePlGrId, color );; cmGrPlotObjSetPhysExt(objH, 1, 0, 1, 0 ); // create the marker end indicator objH = cmGrPlObjNullHandle; if( cmGrPlotObjCreate(plH, cvH, &objH, cmInvalidId, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags | kNoSelectGrPlFl, x+top->durSmpCnt, y, w, h, "", NULL ) != kOkGrPlRC ) cmErrMsg(&_err,kInsertObjFailRC,"Insert failed ending marker line labelled '%s'.", cmStringNullGuard(top->name)); else cmGrPlotObjSetLineColor( objH, kEnablePlGrId, color ); } break; default: break; } } } cmTlUiMsgTypeId_t cmGrTlFltk::recvTimeLineMsg( const void* msg, unsigned msgByteCnt ) { cmTlUiMsg_t m; cmTimeLineDecode(msg,msgByteCnt,&m); switch( m.msgId ) { case kInitMsgTlId: { // remove all objects from all views cmGrPageClear(pageHandle()); _srate = m.srate; _updateSeqMenu(m.seqCnt,m.seqId); } break; case kDoneMsgTlId: //size(w(),h()+1); break; case kFinalMsgTlId: break; case kInsertMsgTlId: _insertTimeLineObj(&m); break; default: { assert(0); } } return m.msgId; } void cmGrTlFltk::recvAudioFileLoad( unsigned fileId ) { cmGrPlH_t plH = plotHandle(); cmGrPlObjH_t grPlObjH = cmGrPlotObjectIdToHandle( plH, fileId ); cmAfmFileH_t afH = _cmdIf->audioFileHandle( fileId ); unsigned chIdx = 0; if( cmAfmFileIsValid(afH) == false ) { cmErrMsg(&_err,kAudioObjFailRC,"Unable to locate audio file plot graphic object for id:%i.", fileId); return; } if( cmGrPlotAudioFileObjCreate( grPlObjH, afH, chIdx ) != kOkGrPlRC ) { const cmChar_t* audioFn = cmAudioFileName(cmAfmFileHandle(afH)); cmErrMsg(&_err,kAudioObjFailRC,"Create audio file graphic object failed for '%s'.", cmStringNullGuard(audioFn)); return; } redraw(); } void cmGrTlFltk::setTimeAxisMetric( timeAxisMetricId_t metricId ) { unsigned timeLabelFuncId = cmInvalidId; switch( metricId ) { case kSamplesMetricId: timeLabelFuncId = _samplesMetricId; break; case kSecondsMetricId: timeLabelFuncId = _secondsMetricId; break; default: { assert(0); } } cmGrPgH_t pgH = pageHandle(); cmGrVwH_t vwH = cmGrPageViewHandle( pgH, kAudioVwIdx); cmGrAxH_t axH = cmGrViewAxisHandle( vwH, kTopGrIdx); cmGrViewSetLabelFunc( vwH, kTopGrIdx, timeLabelFuncId ); cmGrAxisSetLabelFunc( axH, timeLabelFuncId ); vwH = cmGrPageViewHandle( pgH, kMidiVwIdx); axH = cmGrViewAxisHandle( vwH, kBottomGrIdx); cmGrViewSetLabelFunc( vwH, kBottomGrIdx, timeLabelFuncId ); cmGrAxisSetLabelFunc( axH, timeLabelFuncId ); } void cmGrTlFltk::toggleMarkerText() { cmGrPlH_t plH = plotHandle(); unsigned n = cmGrPlotObjectCount(plH); unsigned i; for(i=0; itypeId==kMarkerTlId || top->typeId==kMidiEvtTlId) ) { return top->uid; } return cmInvalidId; } void cmGrTlFltk::setAudioFileCursor( unsigned smpIdx ) { if( cmGrPlotObjIsValid(_selMarkPlotObjH) ) { cmGrPlObjH_t poh; // get the audio file plot object handle if(cmGrPlotObjIsValid(poh = cmGrPlotObjXAnchor(_selMarkPlotObjH))) { cmGrVExt_t vext; cmGrVPt_t pt0,pt1; // get the canvas handle cmGrPgH_t pgH = pageHandle(); cmGrVwH_t vwH = cmGrPageViewHandle( pgH, kAudioVwIdx ); cmGrH_t cvH = cmGrViewGrHandle( vwH ); cmGrPlotObjVExt(poh,&vext); // get the extents of the audio file object smpIdx += vext.loc.x; // offset the current sample index to put the index in global time cmGrViewExtents(cvH, &vext ); // get the current view extents cmGrVPtSet(&pt0,smpIdx,cmGrVExtMinY(&vext)); // setup the selection points cmGrVPtSet(&pt1,smpIdx,cmGrVExtMaxY(&vext)); cmGrSetSelectPoints(cvH, &pt0, &pt1 ); // apply the selection points to form a cursor line } } } void cmGrTlFltk::selectBar( unsigned barNumb ) { cmGrPlH_t plH = plotHandle(); unsigned n = cmGrPlotObjectCount(plH); unsigned i; for(i=0; itypeId == kMarkerTlId && (mkp = _cmdIf->tlMarkerObjPtr(top)) != NULL && mkp->bar == barNumb ) // <-------- there is an apparent weakness in selecting a marker based { // only on the bar number - because the intention is to pick a // bar line marker but it may be (i have not actually checked) // that other objects might have a given bar number but not be // a bar line object. unsigned flags = cmGrPlotObjStateFlags(poH); cmGrPlotObjSetStateFlags(poH,cmSetFlag(flags,kFocusGrPlFl | kSelectGrPlFl)); redraw(); _selMarkPlotObjH = poH; _cmdIf->onTimeLineMarkerSelected(mkp->obj.uid); } } } bool cmGrTlFltk::on_plot_object( cmGrPlotCbArg_t* arg ) { if( arg->selId==kStateChangeGrPlId && cmIsFlag(arg->deltaFlags,kSelectGrPlFl) && cmIsFlag(cmGrPlotObjStateFlags(arg->objH),kSelectGrPlFl) ) { const cmTlObj_t* top; if((top = (const cmTlObj_t*)cmGrPlotObjUserPtr(arg->objH)) != NULL) { const cmChar_t* s = NULL; switch(top->typeId) { case kAudioFileTlId: { const cmTlAudioFile_t* afp; if((afp = _cmdIf->tlAudioFileObjPtr(top)) != NULL && afp->fn != NULL) s = afp->fn; } break; case kMidiFileTlId: { const cmTlMidiFile_t* mfp; if((mfp = _cmdIf->tlMidiFileObjPtr(top)) != NULL && mfp->fn != NULL) s = mfp->fn; } break; case kMidiEvtTlId: { const cmTlMidiEvt_t* mep; if((mep = _cmdIf->tlMidiEvtObjPtr(top)) != NULL ) { _selMarkPlotObjH = arg->objH; callback()(this,user_data()); _cmdIf->onTimeLineMidiEvtSelected(mep->obj.uid); } } break; case kMarkerTlId: { const cmTlMarker_t* mkp; if((mkp = _cmdIf->tlMarkerObjPtr(top)) != NULL) { if(mkp->text != NULL) s = mkp->text; _selMarkPlotObjH = arg->objH; callback()(this,user_data()); _cmdIf->onTimeLineMarkerSelected(mkp->obj.uid); } } break; default: break; } if( s == NULL ) s = cmGrPlotObjLabel(arg->objH); if( s == NULL ) s = ""; setStatusText(s); } } return true; } void cmGrTlFltk::_s_seqMenuCallback( Fl_Widget* w, void* vp ) { item_t* ip = (item_t*)vp; assert( ip->id < ip->p->_seqCnt ); ip->p->_cmdIf->selectSequence(ip->id); } void cmGrTlFltk::_s_roundHashValueFunc( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value ) { snprintf(label,labelCharCnt,"%i",(int)round(value)); } void cmGrTlFltk::_s_minSecMsHashValueFunc( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value ) { cmGrTlFltk* p = (cmGrTlFltk*)arg; int min=0,sec=0,ms=0; double smpPerMin = p->_srate * 60.0; double smpPerMs = p->_srate / 1000.0; if( value > smpPerMin ) { min = (int)floor( value / smpPerMin ); value -= min * smpPerMin; } if( value > p->_srate ) { sec = (int)floor( value / p->_srate ); value -= sec * p->_srate; } if( value > smpPerMs ) { ms = (int)floor( value / smpPerMs ); value -= ms * smpPerMs; } snprintf(label,labelCharCnt,"%i:%2i:%2i",min,sec,ms); } void cmGrTlFltk::_s_midiSciPitchValueFunc( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value ) { assert( label != NULL && labelCharCnt > 0 ); if( labelCharCnt > 0 ) label[0] = 0; if( 0 <= value && value <= 127 ) cmMidiToSciPitch((cmMidiByte_t)floor(value), label, labelCharCnt ); else { if( labelCharCnt > 3 ) strcpy(label,"?"); } } void cmGrTlFltk::_updateSeqMenu(int newSeqCnt, unsigned seqId) { if(_seqMenuIdx == -1 ) return; //const Fl_Menu_Item* seq_mip = _menuBar->menu() + _seqMenuIdx; //int sz = seq_mip->size(); // if the count of time-line sequences does not match the new count of sequences if( 1 /*sz != newSeqCnt*/ ) { int i; // erase the current sequence sub-menu _menuBar->clear_submenu(_seqMenuIdx); // create an array to link the menu items to the sequence control id's _seqItemArray = cmMemResizeZ(item_t,_seqItemArray,newSeqCnt); // create each menu items and item map record for(i=0; iinsert(_seqMenuIdx + i + 1,cmTsPrintf("%i",i),0,_s_seqMenuCallback,_seqItemArray+i,FL_MENU_TOGGLE); } } // set the menu check boxes to indicate the selected sequence int i; for(i=0; imenu() + _seqMenuIdx + i + 1; if( i == (int)seqId ) mip->set(); else mip->clear(); } // track the current sequence count _seqCnt = newSeqCnt; } void cmGrTlFltk::_createMenu( ) { _seqMenuIdx = _menuBar->add("Seq", 0,NULL,0,FL_SUBMENU); int idx = _menuBar->add("Time Line",0,NULL,0,FL_SUBMENU); const char* titleArray[] = { "Samples", "Seconds", "Marker Text", "Pitch", "Velocity","Id", "Gen Onset","Del Onset" }; bool checkFl[] = { false, false, false, true, true, true, false, false }; bool onFl[] = { false, false, false, true, false, false, false, false }; int i; for(i=0; iinsert(idx+1+i,titleArray[i],0,_s_menuCallback, _menuArray + i, flag ); if( onFl[i] ) { Fl_Menu_Item* mip = (Fl_Menu_Item*)_menuBar->menu() + idx + i + 1; mip->set(); } } } bool cmGrTlFltk::_isMenuChecked( int id ) { unsigned i; // locate the menu item assoc'd with id for(i=0; ifind_index("Time Line")) == -1 ) return false; // The menu items and _menuArray[] were initialized in the same order // therefore the offset from the base of both should be the same. Fl_Menu_Item* mip = (Fl_Menu_Item*)_menuBar->menu() + menuIdx + i + 1; assert( (item_t*)mip->user_data() == _menuArray + i ); return mip->value() != 0; } unsigned cmGrTlFltk::_getMenuCheckFlags() { unsigned flags = 0; flags |= _isMenuChecked(kViewPitchMId) ? kPitchChkFl : 0; flags |= _isMenuChecked(kViewVelocityMId) ? kVelChkFl : 0; flags |= _isMenuChecked(kViewIdMId) ? kIdChkFl : 0; return flags; } void cmGrTlFltk::_setLabels() { cmGrPlH_t plH = plotHandle(); unsigned flags = _getMenuCheckFlags(); unsigned n = cmGrPlotObjectCount(plH); unsigned i; for(i=0; itypeId==kMidiEvtTlId ) { const cmMidiTrackMsg_t* mep = ((const cmTlMidiEvt_t*)top)->msg; if( mep->status == kNoteOnMdId ) { int bufN = 255; cmChar_t buf[ bufN+1 ]; buf[bufN] = 0; buf[0] = 0; if( cmIsFlag(flags,kPitchChkFl) ) snprintf(buf+strlen(buf),bufN-strlen(buf),"%s ",cmMidiToSciPitch(mep->u.chMsgPtr->d0,NULL,0)); if( cmIsFlag(flags,kVelChkFl) ) snprintf(buf+strlen(buf),bufN-strlen(buf),"%i ",mep->u.chMsgPtr->d1); if( cmIsFlag(flags,kIdChkFl) ) snprintf(buf+strlen(buf),bufN-strlen(buf),"%i ",mep->uid); cmGrPlotObjSetLabel(poH, buf ); } } } void cmGrTlFltk::_s_menuCallback(Fl_Widget* w, void* arg ) { item_t* ip = (item_t*)arg; cmGrTlFltk* p = ip->p; unsigned long id = ip->id; switch( id ) { case kViewSamplesMId: case kViewSecondsMId: { cmGrTlFltk::timeAxisMetricId_t metricId = id==kViewSamplesMId ? cmGrTlFltk::kSamplesMetricId : cmGrTlFltk::kSecondsMetricId; p->setTimeAxisMetric( metricId ); p->redraw(); } break; case kViewMarkTextMId: p->toggleMarkerText(); break; case kViewVelocityMId: case kViewPitchMId: case kViewIdMId: p->_setLabels(); p->redraw(); break; case kGenOnsetMarksMId: p->_cmdIf->generateOnsetMarks(); break; case kDelOnsetMarksMId: p->_cmdIf->deleteOnsetMarks(); break; } }