From f2ea64414723b98fa68cad6151b7058658c9df48 Mon Sep 17 00:00:00 2001 From: kevin Date: Fri, 23 Oct 2020 16:47:00 -0400 Subject: [PATCH] Add tlCtl and libcmpp to this repo. --- .gitignore | 2 - Makefile.am | 4 +- src/libcmpp/.gitignore | 1 + src/libcmpp/Makefile.am | 18 + src/libcmpp/fltk/Fl_CbLinker.cpp | 82 ++ src/libcmpp/fltk/Fl_CbLinker.h | 72 ++ src/libcmpp/fltk/Fl_DevCfgGroup.cpp | 1135 ++++++++++++++++++ src/libcmpp/fltk/Fl_DevCfgGroup.h | 168 +++ src/libcmpp/fltk/Fl_File_Btn.cpp | 105 ++ src/libcmpp/fltk/Fl_File_Btn.h | 47 + src/libcmpp/fltk/Fl_Splitter.cpp | 273 +++++ src/libcmpp/fltk/Fl_Splitter.h | 70 ++ src/libcmpp/fltk/Fl_Vert_Progress.cpp | 66 ++ src/libcmpp/fltk/Fl_Vert_Progress.h | 14 + src/libcmpp/fltk/cmGrFltk.cpp | 1546 +++++++++++++++++++++++++ src/libcmpp/fltk/cmGrFltk.h | 242 ++++ src/libcmpp/fltk/cmUiDrvrFltk.cpp | 865 ++++++++++++++ src/libcmpp/fltk/cmUiDrvrFltk.h | 99 ++ src/tlCtl/Makefile.am | 11 + src/tlCtl/cmGr2dFltk.cpp | 148 +++ src/tlCtl/cmGr2dFltk.h | 44 + src/tlCtl/cmGrScFltk.cpp | 565 +++++++++ src/tlCtl/cmGrScFltk.h | 89 ++ src/tlCtl/cmGrTksbFltk.cpp | 695 +++++++++++ src/tlCtl/cmGrTksbFltk.h | 110 ++ src/tlCtl/cmGrTksrFltk.cpp | 461 ++++++++ src/tlCtl/cmGrTksrFltk.h | 91 ++ src/tlCtl/cmGrTlFltk.cpp | 835 +++++++++++++ src/tlCtl/cmGrTlFltk.h | 108 ++ src/tlCtl/cmdIf.cpp | 650 +++++++++++ src/tlCtl/cmdIf.h | 211 ++++ src/tlCtl/gvHashFunc.cpp | 62 + src/tlCtl/gvHashFunc.h | 18 + src/tlCtl/tlCtl.cpp | 388 +++++++ src/tlCtl/tlCtl.h | 99 ++ 35 files changed, 9390 insertions(+), 4 deletions(-) create mode 100644 src/libcmpp/.gitignore create mode 100644 src/libcmpp/Makefile.am create mode 100644 src/libcmpp/fltk/Fl_CbLinker.cpp create mode 100644 src/libcmpp/fltk/Fl_CbLinker.h create mode 100644 src/libcmpp/fltk/Fl_DevCfgGroup.cpp create mode 100644 src/libcmpp/fltk/Fl_DevCfgGroup.h create mode 100644 src/libcmpp/fltk/Fl_File_Btn.cpp create mode 100644 src/libcmpp/fltk/Fl_File_Btn.h create mode 100644 src/libcmpp/fltk/Fl_Splitter.cpp create mode 100644 src/libcmpp/fltk/Fl_Splitter.h create mode 100644 src/libcmpp/fltk/Fl_Vert_Progress.cpp create mode 100644 src/libcmpp/fltk/Fl_Vert_Progress.h create mode 100644 src/libcmpp/fltk/cmGrFltk.cpp create mode 100644 src/libcmpp/fltk/cmGrFltk.h create mode 100644 src/libcmpp/fltk/cmUiDrvrFltk.cpp create mode 100644 src/libcmpp/fltk/cmUiDrvrFltk.h create mode 100644 src/tlCtl/Makefile.am create mode 100644 src/tlCtl/cmGr2dFltk.cpp create mode 100644 src/tlCtl/cmGr2dFltk.h create mode 100644 src/tlCtl/cmGrScFltk.cpp create mode 100644 src/tlCtl/cmGrScFltk.h create mode 100644 src/tlCtl/cmGrTksbFltk.cpp create mode 100644 src/tlCtl/cmGrTksbFltk.h create mode 100644 src/tlCtl/cmGrTksrFltk.cpp create mode 100644 src/tlCtl/cmGrTksrFltk.h create mode 100644 src/tlCtl/cmGrTlFltk.cpp create mode 100644 src/tlCtl/cmGrTlFltk.h create mode 100644 src/tlCtl/cmdIf.cpp create mode 100644 src/tlCtl/cmdIf.h create mode 100644 src/tlCtl/gvHashFunc.cpp create mode 100644 src/tlCtl/gvHashFunc.h create mode 100644 src/tlCtl/tlCtl.cpp create mode 100644 src/tlCtl/tlCtl.h diff --git a/.gitignore b/.gitignore index 4a7f584..b56aadb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,5 @@ # directories to ignore libcm -libcmpp -tlCtl .deps autom4te.cache diff --git a/Makefile.am b/Makefile.am index 70beeea..4f34933 100644 --- a/Makefile.am +++ b/Makefile.am @@ -55,8 +55,8 @@ endif endif if OS_OSX - AM_CPPFLAGS += -I/opt/local/include - AM_LDFLAGS += -L/opt/local/lib + AM_CPPFLAGS += -I/opt/local/include # Search macports directory for fftw headers + AM_LDFLAGS += -L/opt/local/lib # and libraries. AM_LDFLAGS += -framework Cocoa -framework CoreAudio -framework CoreMIDI -framework Carbon -framework Accelerate endif diff --git a/src/libcmpp/.gitignore b/src/libcmpp/.gitignore new file mode 100644 index 0000000..70845e0 --- /dev/null +++ b/src/libcmpp/.gitignore @@ -0,0 +1 @@ +Makefile.in diff --git a/src/libcmpp/Makefile.am b/src/libcmpp/Makefile.am new file mode 100644 index 0000000..3ac5ed3 --- /dev/null +++ b/src/libcmpp/Makefile.am @@ -0,0 +1,18 @@ + + +cmppSRC = src/libcmpp/fltk/Fl_CbLinker.cpp src/libcmpp/fltk/Fl_Splitter.cpp +cmppHDR = src/libcmpp/fltk/Fl_CbLinker.h src/libcmpp/fltk/Fl_Splitter.h + +cmppSRC += src/libcmpp/fltk/cmGrFltk.cpp +cmppHDR += src/libcmpp/fltk/cmGrFltk.h + +cmppHDR += src/libcmpp/fltk/Fl_File_Btn.h src/libcmpp/fltk/Fl_Vert_Progress.h +cmppSRC += src/libcmpp/fltk/Fl_File_Btn.cpp src/libcmpp/fltk/Fl_Vert_Progress.cpp + +cmppHDR += src/libcmpp/fltk/Fl_DevCfgGroup.h +cmppSRC += src/libcmpp/fltk/Fl_DevCfgGroup.cpp + +cmppHDR += src/libcmpp/fltk/cmUiDrvrFltk.h +cmppSRC += src/libcmpp/fltk/cmUiDrvrFltk.cpp + + diff --git a/src/libcmpp/fltk/Fl_CbLinker.cpp b/src/libcmpp/fltk/Fl_CbLinker.cpp new file mode 100644 index 0000000..1987f09 --- /dev/null +++ b/src/libcmpp/fltk/Fl_CbLinker.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include "Fl_CbLinker.h" + + +Fl_CbLinker::Fl_CbLinker() +{} + +Fl_CbLinker::~Fl_CbLinker() +{ + unsigned i; + for(i=0; i<_ctlV.size(); ++i) + delete _ctlV[i]; +} + +void Fl_CbLinker::registerCtl( Fl_Button* c, unsigned id ) +{ + ctl_t* r; + _ctlV.push_back( r = new ctl_t(this,c,id) ); + c->callback(_s_callback,r); +} + +void Fl_CbLinker::registerCtl( Fl_Scrollbar* c, unsigned id ) +{ + ctl_t* r; + _ctlV.push_back( r = new ctl_t(this,c,id) ); + c->callback(_s_callback,r); +} + +void Fl_CbLinker::registerCtl( Fl_Menu_Button* c, unsigned id ) +{ + ctl_t* r; + _ctlV.push_back( r = new ctl_t(this,c,id) ); + c->callback(_s_callback,r); +} + +void Fl_CbLinker::registerCtl( Fl_Menu_Item* c, unsigned id ) +{ + ctl_t* r; + _ctlV.push_back( r = new ctl_t(this,c,id) ); + c->callback(_s_callback,r); +} + +void Fl_CbLinker::onButton( Fl_Button* c, unsigned id ) +{} + +void Fl_CbLinker::onScrollbar( Fl_Scrollbar* c, unsigned id ) +{} + +void Fl_CbLinker::onMenuBtn( Fl_Menu_Button* c, unsigned id ) +{} + +void Fl_CbLinker::onMenuItem( Fl_Menu_Item* c, unsigned id ) +{} + + +void Fl_CbLinker::_s_callback( Fl_Widget* w, void* arg ) +{ + ctl_t* r = static_cast(arg); + + unsigned i; + for(i=0; ithisPtr->_ctlV.size(); ++i) + if( r->thisPtr->_ctlV[i] == arg ) + { + switch( r->typeId ) + { + case kButtonTId: r->thisPtr->onButton( r->u.btn, r->ctlId); break; + case kScrollbarTId: r->thisPtr->onScrollbar( r->u.sb, r->ctlId); break; + case kMenuBtnTId: r->thisPtr->onMenuBtn( r->u.mbtn, r->ctlId); break; + case kMenuItemTId: r->thisPtr->onMenuItem( r->u.mitem, r->ctlId); break; + default: + { assert(0); } + } + } +} diff --git a/src/libcmpp/fltk/Fl_CbLinker.h b/src/libcmpp/fltk/Fl_CbLinker.h new file mode 100644 index 0000000..a2102a9 --- /dev/null +++ b/src/libcmpp/fltk/Fl_CbLinker.h @@ -0,0 +1,72 @@ +#ifndef Fl_CbLinker_h +#define Fl_CbLinker_h + +class Fl_Widget; +class Fl_Button; +class Fl_Scrollbar; +class Fl_Menu_Button; +struct Fl_Menu_Item; + +/* +This class solves the problem of linking static control callback functions +to an object instance. + +registerCtl() creates a record which links a control to an instance +of a Fl_CbLinker. The control is then given a static callback function: +_s_callback(). When _s_callback() is called from the control event +handler it links locates the controls link record an calls the +appropriate handler (e.g. onButton(), onScrollBar(), etc.) +*/ + +class Fl_CbLinker +{ + public: + Fl_CbLinker(); + virtual ~Fl_CbLinker(); + + void registerCtl( Fl_Button* c, unsigned id ); + void registerCtl( Fl_Scrollbar* c, unsigned id ); + void registerCtl( Fl_Menu_Button* c, unsigned id ); + void registerCtl( Fl_Menu_Item* c, unsigned id ); + + virtual void onButton( Fl_Button* c, unsigned id ); + virtual void onScrollbar( Fl_Scrollbar* c, unsigned id ); + virtual void onMenuBtn( Fl_Menu_Button* c, unsigned id ); + virtual void onMenuItem( Fl_Menu_Item* c, unsigned id ); + + private: + enum + { + kButtonTId, + kScrollbarTId, + kMenuBtnTId, + kMenuItemTId + }; + + typedef struct ctl_str + { + Fl_CbLinker* thisPtr; + unsigned typeId; + unsigned ctlId; + union + { + Fl_Button* btn; + Fl_Scrollbar* sb; + Fl_Menu_Button* mbtn; + Fl_Menu_Item* mitem; + Fl_Widget* w; + } u; + + ctl_str( Fl_CbLinker* t, Fl_Button* c, unsigned id) : thisPtr(t), typeId(kButtonTId), ctlId(id) { u.btn=c; } + ctl_str( Fl_CbLinker* t, Fl_Scrollbar* c, unsigned id ) : thisPtr(t), typeId(kScrollbarTId),ctlId(id) { u.sb=c; } + ctl_str( Fl_CbLinker* t, Fl_Menu_Button* c, unsigned id ) : thisPtr(t), typeId(kMenuBtnTId), ctlId(id) { u.mbtn=c; } + ctl_str( Fl_CbLinker* t, Fl_Menu_Item* c, unsigned id ) : thisPtr(t), typeId(kMenuItemTId), ctlId(id) { u.mitem=c; } + + } ctl_t; + + std::vector< ctl_t* > _ctlV; + + static void _s_callback( Fl_Widget* w, void* arg ); +}; + +#endif diff --git a/src/libcmpp/fltk/Fl_DevCfgGroup.cpp b/src/libcmpp/fltk/Fl_DevCfgGroup.cpp new file mode 100644 index 0000000..ce4b974 --- /dev/null +++ b/src/libcmpp/fltk/Fl_DevCfgGroup.cpp @@ -0,0 +1,1135 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cmGlobal.h" +#include "cmFloatTypes.h" +#include "cmRpt.h" +#include "cmErr.h" +#include "cmCtx.h" +#include "cmMem.h" +#include "cmMallocDebug.h" +#include "cmThread.h" +#include "cmJson.h" +#include "cmTime.h" +#include "cmAudioPort.h" +#include "cmMidi.h" +#include "cmMidiPort.h" +#include "cmUdpPort.h" +#include "cmRtSysMsg.h" +#include "cmRtNet.h" +#include "cmRtSys.h" +#include "cmDevCfg.h" + +#include "Fl_DevCfgGroup.h" + +#define DEVCFG_NONE_STR "None" + +Fl_DevCfgGroup::Fl_DevCfgGroup(cmDevCfgH_t dcH, + int xx, int yy, int ww, int hh, const char* label ) + : Fl_Group(xx,yy,ww,hh,label), + _dcH(dcH) +{ + + typedef enum + { + kInvalidTId, + kLabelTId, + kBtnTId, + kMenuBtnTId, + kChkBtnTId, + kInputTId, + kValueTId + } type_t; + + typedef struct + { + unsigned id; + type_t tid; + int x; + int y; + int w; + int h; + int flags; + const char* label; + } recd_t; + + const int r = -1; // current row + const int rn = -2; // next row + const int cn = -1; // next column + + + int r00 = 50; + + int c0 = 2; + int c3 = 400; + int c4 = 650; + + int lw = 250; // device/port/preset label widths + int vw = 75; // value widths + int iw = 125; + int dw = 400; + + int w = 100; + int h = 25; + + int fl = 0; + int fl1 = FL_WHEN_CHANGED; + + recd_t a[] = + { + + { kLocLabelCId, kLabelTId, c0,r00, w, h, fl, "Location:" }, + { kLocMenuCId, kMenuBtnTId, c0, rn, lw, h, fl, NULL }, + { kLocDeleteBtnCId, kBtnTId, cn, r, w, h, fl, "Delete" }, + { kLocStringCId, kInputTId, c0, rn, lw, h, fl1, NULL }, + { kLocStoreBtnCId, kBtnTId, cn, r, w, h, fl, "Create" }, + + { kMidiLabelCId, kLabelTId, c0, rn, w, h, fl, "MIDI:" }, + { kMidiCfgMenuCId, kMenuBtnTId, c0, rn, lw, h, fl, NULL }, + { kMidiDeleteBtnCId, kBtnTId, cn, r, w, h, fl, "Delete" }, + { kMidiCfgDescCId, kLabelTId, c0, rn, dw, h, fl, NULL }, + { kMidiCfgStringCId, kInputTId, c0, rn, lw, h, fl1, NULL }, + { kMidiApplyBtnCId, kBtnTId, cn, r, w, h, fl, "Store" }, + { kMidiDevMenuCId, kMenuBtnTId, c0, rn, lw, h, fl1, NULL }, + { kMidiDevLabelCId, kLabelTId, cn, r, w, h, fl, "MIDI Device"}, + { kMidiPortMenuCId, kMenuBtnTId, c0, rn, lw, h, fl1, NULL }, + { kMidiPortLabelCId, kLabelTId, cn, r, w, h, fl, "MIDI Port"}, + { kMidiInputCheckCId, kChkBtnTId, c0, rn, w, h, fl1, "Input"}, + + { kAudioLabelCId, kLabelTId, c3,r00, w, h, fl, "Audio:" }, + { kAudioCfgMenuCId, kMenuBtnTId, c3, rn, lw, h, fl, NULL }, + { kAudioDeleteBtnCId, kBtnTId, cn, r, w, h, fl, "Delete" }, + { kAudioCfgDescCId, kLabelTId, c3, rn, dw, h*2,fl, NULL }, + { kAudioCfgStringCId, kInputTId, c3, rn, lw, h, fl1, NULL }, + { kAudioApplyBtnCId, kBtnTId, cn, r, w, h, fl, "Store" }, + { kAudioInDevMenuCId, kMenuBtnTId, c3, rn, lw, h, fl1, NULL }, + { kAudioInDevLabelCId, kLabelTId, cn, r, w, h, fl, "Audio Input"}, + { kAudioOutDevMenuCId, kMenuBtnTId, c3, rn, lw, h, fl1, NULL }, + { kAudioOutDevLabelCId, kLabelTId, cn, r, w, h, fl1, "Audio Output"}, + { kAudioMsgQueSizeValCId,kValueTId, c3, rn, vw, h, fl1, "Msg Queue Bytes" }, + { kAudioDevFpCValCId, kValueTId, c4, r, vw, h, fl1, "Audio Frames" }, + { kAudioDspFpCValCId, kValueTId, c3, rn, vw, h, fl1, "DSP Frames" }, + { kAudioBufCntValCId, kValueTId, c4, r, vw, h, fl1, "Buffer Count" }, + { kAudioSrateMenuCId, kMenuBtnTId, c3, rn, w, h, fl1, "Rate" }, + { kAudioSyncInCheckCId, kChkBtnTId, c4, r, w, h, fl1, "Sync to Input"}, + { kAudioNetNodeStringCId,kInputTId, c3, rn, vw, h, fl1, "Net Node Label"}, + { kAudioBcastAddrStringCId,kInputTId, c4, r, iw, h, fl1, "Bcast Address"}, + { kAudioIpAddrStringCId, kInputTId, c3, rn, iw, h, fl1, "IP Address"}, + { kAudioIpPortValCId, kValueTId, c4, r, vw, h, fl1, "IP Port"}, + { kAudioActiveCheckCId, kChkBtnTId, c3, rn, w, h, fl1, "Active"}, + /* + { kNetLabelCId, kLabelTId, c3, rn, w, h, fl, "Remote Network Nodes:" }, + { kNetCfgMenuCId, kMenuBtnTId, c3, rn, lw, h, fl, NULL }, + { kNetDeleteBtnCId, kBtnTId, cn, r, w, h, fl, "Delete" }, + { kNetCfgDescCId, kLabelTId, c3, rn, dw, h, fl, NULL }, + { kNetCfgStringCId, kInputTId, c3, rn, lw, h, fl, NULL }, + { kNetApplyBtnCId, kBtnTId, cn, r, w, h, fl, "Store" }, + { kNetSockAddrStringCId, kInputTId, c3, rn, w, h, fl1, "IP Address" }, + { kNetPortNumbValCId, kValueTId, c4, r, vw, h, fl1, "IP Port" }, + { kNetLocalCheckCId, kChkBtnTId, c3, rn, w, h, fl1, "Local"}, + { kNetActiveCheckCId, kChkBtnTId, cn, r, vw, h, fl1, "Active"}, + */ + { kInvalidCId, kInvalidTId, 0, 0, 0, 0, 0, NULL } + }; + + const recd_t* d = a; + int y = r00; + int x = c0; + int ny = 0; + int nx = 0; + + for(; d->id != kInvalidCId; ++d) + { + Fl_Widget* wp = NULL; + ctl_t* c = new ctl_t; + + c->id = d->id; + c->p = this; + + switch( d->y ) + { + case r: break; + case rn: y = ny; break; + default: y = d->y; break; + } + + switch( d->x ) + { + case cn: x = nx; break; + default: x = d->x; break; + } + + switch( d->tid ) + { + case kLabelTId: + wp = c->u.box = new Fl_Box(x,y,d->w,d->h,d->label); + wp->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + break; + case kBtnTId: + wp = c->u.btn = new Fl_Button(x,y,d->w,d->h,d->label); + break; + case kMenuBtnTId: + wp = c->u.mbt = new Fl_Menu_Button(x,y,d->w,d->h,d->label); + break; + case kChkBtnTId: + wp = c->u.chk = new Fl_Check_Button(x,y,d->w,d->h,d->label); + break; + case kInputTId: + wp = c->u.inp = new Fl_Input(x,y,d->w,d->h,d->label); + wp->align(FL_ALIGN_RIGHT); + break; + case kValueTId: + wp = c->u.val = new Fl_Value_Input(x,y,d->w,d->h,d->label); + wp->align(FL_ALIGN_RIGHT); + break; + default: + break; + } + + if( wp != NULL ) + { + if( cmIsFlag(d->flags,FL_WHEN_CHANGED) ) + wp->when(FL_WHEN_CHANGED); + + ny = y + d->h + 2; + nx = x + d->w + 2; + + + wp->callback(Fl_DevCfgGroup::_s_ctl_cb,c); + + _ctlV.push_back(c); + } + } + + //_loadMenuButtons(); + _syncLoc(); +} + +Fl_DevCfgGroup::~Fl_DevCfgGroup() +{ + unsigned i; + for(i=0; i<_ctlV.size(); ++i) + delete _ctlV[i]; +} + +void Fl_DevCfgGroup::onEnableAudio( bool enableFl ) +{ + if( enableFl ) + { + deactivate(); + } + else + { + activate(); + parent()->redraw(); + } +} + +bool Fl_DevCfgGroup::_loadLocBtn() +{ + ctl_t* c; + if((c = _idToCtl(kLocMenuCId)) == NULL ) + return false; + + int val = c->u.mbt->value(); + + c->u.mbt->clear(); + + unsigned i; + for(i=0; iu.mbt->add(cmStringNullGuard(cmDevCfgLocLabel(_dcH,i)),0,_s_ctl_cb,c); + + _restoreMenuValue(kLocMenuCId, val ); + + if((c = _idToCtl(kLocStoreBtnCId)) != NULL) + c->u.btn->deactivate(); + + return true; +} + +void Fl_DevCfgGroup::_recallLoc() +{ + ctl_t* c; + const char* s; + + if((s = _getMenuCtl(kLocMenuCId)) == NULL ) + goto errLabel; + + if( cmDevCfgLocRecall(_dcH,s) != kOkDcRC ) + goto errLabel; + + if((c = _idToCtl(kLocStringCId)) == NULL ) + goto errLabel; + + c->u.inp->copy_label(s); + + errLabel: + _syncLoc(); +} + +void Fl_DevCfgGroup::_storeLoc() +{ + ctl_t* c; + const char* s; + + if((c = _idToCtl(kLocStringCId)) == NULL ) + goto errLabel; + + if((s = c->u.inp->value()) == NULL ) + goto errLabel; + + if( cmDevCfgLocStore(_dcH,s) != kOkDcRC ) + goto errLabel; + + errLabel: + + _syncLoc(); + +} + +void Fl_DevCfgGroup::_deleteLoc() +{ + const char* s; + + if((s = _getMenuCtl(kLocMenuCId)) == NULL ) + goto errLabel; + + if( cmDevCfgLocDelete(_dcH,s) != kOkDcRC ) + goto errLabel; + + errLabel: + _syncLoc(); + +} + +// load MIDI device menu from the MIDI driver +void Fl_DevCfgGroup::_loadMidiDevBtn() +{ + unsigned j; + ctl_t* c; + + if((c = _idToCtl(kMidiDevMenuCId)) == NULL ) + return; + + int val = c->u.mbt->value(); + + c->u.mbt->clear(); + + for(j=0; ju.mbt->add(cmStringNullGuard(cmMpDeviceName(j)),0,_s_ctl_cb,c); + + } + + _restoreMenuValue(kMidiDevMenuCId, val ); +} + +// Load the MIDI port menu from the MIDI driver accoring +// to the MIDI device seleted in the MIDI device menu +void Fl_DevCfgGroup::_loadMidiPortBtn() +{ + ctl_t* c; + + if((c = _idToCtl(kMidiDevMenuCId)) == NULL ) + return; + + int devIdx = c->u.mbt->value(); + + if((c = _idToCtl(kMidiInputCheckCId)) == NULL ) + return; + + unsigned flags = c->u.chk->value() ? kInMpFl : kOutMpFl; + + unsigned n = devIdx<0 ? 0 : cmMpDevicePortCount(devIdx,flags); + + if((c = _idToCtl(kMidiPortMenuCId)) == NULL ) + return; + + c->u.mbt->clear(); + + int val = c->u.mbt->value(); + + + for(unsigned j=0; ju.mbt->add(cmStringNullGuard(cmMpDevicePortName(devIdx,flags,j)),0,_s_ctl_cb,c); + + _restoreMenuValue(kMidiPortMenuCId, val ); + +} + +// Load the audio device menu from the audio port driver. +void Fl_DevCfgGroup::_loadAudioDevBtn( unsigned id, unsigned devIdx ) +{ + ctl_t* c; + unsigned i; + + if((c = _idToCtl(id)) == NULL ) + return; + + unsigned n = cmApDeviceCount(); + bool inputFl = id == kAudioInDevMenuCId; + int val = c->u.mbt->value(); + + c->u.mbt->clear(); + + for(i=0; i 0 ) + { + const cmChar_t* str; + + if((str = cmApDeviceLabel(i)) != NULL ) + { + bool activeFl = cmDevCfgAudioIsDeviceActive(_dcH, str, inputFl ); + + if( devIdx == i ) + activeFl = false; + + c->u.mbt->add(str,0,NULL,NULL, activeFl ? FL_MENU_INACTIVE : 0); + } + } + + + c->u.mbt->add(DEVCFG_NONE_STR,0,_s_ctl_cb,c); + + _restoreMenuValue(id, val ); + + if( devIdx == cmInvalidIdx ) + _setMenuBtnWithString(id,DEVCFG_NONE_STR); + +} + +// Load the sample rate menu with constant values. +void Fl_DevCfgGroup::_loadAudioSrateBtn() +{ + ctl_t* c; + + if((c = _idToCtl(kAudioSrateMenuCId)) == NULL ) + return; + + int val = c->u.mbt->value(); + + char* p = 0; + c->u.mbt->add("96000",0,NULL,p+96000); + c->u.mbt->add("48000",0,NULL,p+48000); + c->u.mbt->add("44100",0,NULL,p+44100); + c->u.mbt->add("22050",0,NULL,p+22050); + + + if( val < 0 || val >= c->u.mbt->size() ) + _setSrate(kAsDfltSrate); + else + if( c->u.mbt->size() > 0 ) + { + c->u.mbt->value(val); + c->u.mbt->copy_label( c->u.mbt->mvalue()->label() ); + } +} + +// Load a cfg menu with the labels of the cfg records from cmDevCfg. +// (but don't update the label yet). +void Fl_DevCfgGroup::_loadCfgMenu(cmTypeDcmId_t typeId, unsigned menuCtlId, unsigned deleteCtlId ) +{ + ctl_t* c; + + if((c = _idToCtl(menuCtlId)) == NULL ) + return; + + // get the current value of the menu + int val = c->u.mbt->value(); + + // empty the menu + c->u.mbt->clear(); + + // get the count of cfg recds + unsigned n = cmDevCfgCount(_dcH,typeId); + const cmChar_t* label; + + // reload the menu from cmDevCfg + for(unsigned i=0; iu.mbt->add(label,0,_s_ctl_cb,c); + + // get the count of menu items + int sz = c->u.mbt->size(); + + // if the original value is no longer valid then set the value to + // the most likely valid value - zero. + if( val < 0 || val >= sz ) + val = 0; + + // if the menu is not empty then set the value + if( sz > 0 ) + c->u.mbt->value(val); + + // update the 'delete' btn + if((c = _idToCtl(deleteCtlId)) != NULL ) + { + // if the menu is empty deactivate the delete btn + if( sz > 0 ) + c->u.btn->activate(); + else + c->u.btn->deactivate(); + } +} + + +// Load the cfg label edit string, description and type +// specific fields from the cmDevCfg based on the currently +// selected cfg menu item. +void Fl_DevCfgGroup::_recallCfg(cmTypeDcmId_t typeId, unsigned menuCtlId, unsigned strCtlId, unsigned descCtlId, unsigned storeCtlId ) +{ + const Fl_Menu_Item* mip; + ctl_t* c; + + // get the cfg menu + if((c = _idToCtl(menuCtlId)) == NULL ) + return; + + // get the current value of the cfg menu + int menuIdx = c->u.mbt->value(); + + if( menuIdx == -1 ) + return; + + // get the current menu item from the cfg menu + if((mip = c->u.mbt->mvalue()) == NULL) + return; + + // update the cfg menu label + c->u.mbt->copy_label( mip->label() ); + + + // set the cfg string text + if((c = _idToCtl(strCtlId)) != NULL ) + c->u.inp->value( mip->label() ); + + // set the desc string + if((c = _idToCtl(descCtlId)) != NULL ) + { + const cmChar_t* s = cmDevCfgDesc(_dcH, typeId, menuIdx ); + c->u.box->copy_label( s==NULL ? "" : s ); + } + + + // disable to store btn + if((c = _idToCtl(storeCtlId)) != NULL ) + c->u.btn->deactivate(); + + + switch( typeId ) + { + case kMidiDcmTId: + { + const cmDcmMidi_t* r = cmDevCfgMidiCfg(_dcH,menuIdx); + + // set the midi device from the cfg recd + _setMenuBtnWithString(kMidiDevMenuCId,r==NULL ? "" : r->devLabelStr); + _setCheckCtl( kMidiInputCheckCId, r==NULL ? 0 : r->inputFl ); + + // sync the midi port menu to the device + _loadMidiPortBtn(); + + } + break; + + case kAudioDcmTId: + { + const cmDcmAudio_t* r = cmDevCfgAudioCfg(_dcH,menuIdx); + + _setMenuBtnWithString(kAudioInDevMenuCId, r==NULL ? "" : (r->inDevLabelStr==NULL ? DEVCFG_NONE_STR : r->inDevLabelStr)); + _setMenuBtnWithString(kAudioOutDevMenuCId,r==NULL ? "" : (r->outDevLabelStr==NULL ? DEVCFG_NONE_STR : r->outDevLabelStr)); + _setValueCtl(kAudioMsgQueSizeValCId, r==NULL ? 0 : r->rtSysArgs.msgQueueByteCnt); + _setValueCtl(kAudioDevFpCValCId, r==NULL ? 0 : r->rtSysArgs.devFramesPerCycle); + _setValueCtl(kAudioDspFpCValCId, r==NULL ? 0 : r->rtSysArgs.dspFramesPerCycle); + _setValueCtl(kAudioBufCntValCId, r==NULL ? 0 : r->rtSysArgs.audioBufCnt); + _setCheckCtl(kAudioSyncInCheckCId, r==NULL ? 0 : r->rtSysArgs.syncInputFl); + _setInputCtl(kAudioNetNodeStringCId, r==NULL ? "" : r->netNodeLabel); + _setInputCtl(kAudioBcastAddrStringCId, r==NULL ? "" : r->bcastAddr); + _setInputCtl(kAudioIpAddrStringCId, r==NULL ? "" : r->ipAddr); + _setValueCtl(kAudioIpPortValCId, r==NULL ? 0 : r->ipPort); + _setCheckCtl(kAudioActiveCheckCId, r==NULL ? 0 : r->activeFl); + _setSrate( r==NULL ? kAsDfltSrate : r->rtSysArgs.srate); + + + //cmDevCfgAudioSetDefaultCfgIndex(_dcH,menuIdx); + + _loadAudioDevBtn(kAudioInDevMenuCId, r->rtSysArgs.inDevIdx ); + _loadAudioDevBtn(kAudioOutDevMenuCId, r->rtSysArgs.outDevIdx ); + + } + break; + /* + case kNetDcmTId: + { + const cmDcmNet_t* r = cmDevCfgNetCfg(_dcH,menuIdx); + _setInputCtl(kNetSockAddrStringCId, r==NULL ? "" : r->sockAddr); + _setValueCtl(kNetPortNumbValCId, r==NULL ? 0 : r->portNumber); + _setCheckCtl(kNetActiveCheckCId, r==NULL ? 0 : r->activeFl); + } + break; + */ + + default: + assert(0); + break; + } +} + +void Fl_DevCfgGroup::_syncLoc() +{ + ctl_t* c; + unsigned idx; + _loadLocBtn(); + + if((idx = cmDevCfgLocCurIndex(_dcH)) == cmInvalidIdx ) + return; + + if((c = _idToCtl(kLocMenuCId)) == NULL ) + return; + + assert((int)idx < c->u.mbt->size() ); + if( (int)idx >= c->u.mbt->size() ) + return; + + c->u.mbt->value(idx); + + _setMenuBtnLabel(kLocMenuCId,kLocStringCId); + + // Load the menu's based on the currently + // available hardware. + _loadMidiDevBtn(); + _loadMidiPortBtn(); + _loadAudioDevBtn(kAudioInDevMenuCId,cmInvalidId); + _loadAudioDevBtn(kAudioOutDevMenuCId,cmInvalidId); + _loadAudioSrateBtn(); + + // Set the default values for some fields. These values will only be + // used if there is no availabe cmDevCfg data. + _idToCtl(kAudioMsgQueSizeValCId)->u.val->value(kAsDfltMsgQueueByteCnt); + _idToCtl(kAudioDevFpCValCId)->u.val->value(kAsDfltDevFramesPerCycle); + _idToCtl(kAudioDspFpCValCId)->u.val->value(kAsDfltDspFramesPerCycle); + _idToCtl(kAudioBufCntValCId)->u.val->value(kAsDfltBufCnt); + _idToCtl(kAudioSyncInCheckCId)->u.chk->value(kAsDfltSyncToInputFl); + + // set the bounds for the IP port value + _idToCtl(kAudioIpPortValCId)->u.val->bounds(0,65535); + _idToCtl(kAudioIpPortValCId)->u.val->step(1); + + // Load the MIDI cfg information from cmDevCfg. + _loadCfgMenu(kMidiDcmTId, kMidiCfgMenuCId, kMidiDeleteBtnCId ); + _recallCfg(kMidiDcmTId, kMidiCfgMenuCId, kMidiCfgStringCId, kMidiCfgDescCId, kMidiApplyBtnCId ); + + // Load the Audio cfg information from cmDevCfg. + _loadCfgMenu(kAudioDcmTId, kAudioCfgMenuCId, kAudioDeleteBtnCId ); + + // Display the default audio configuration + // if((c = _idToCtl(kAudioCfgMenuCId)) != NULL ) + // if((idx = cmDevCfgAudioGetDefaultCfgIndex(_dcH)) != cmInvalidIdx ) + // if( c->u.mbt->size() < (int)idx ) + // c->u.mbt->value(idx); + + _recallCfg(kAudioDcmTId, kAudioCfgMenuCId, kAudioCfgStringCId, kAudioCfgDescCId, kAudioApplyBtnCId ); + + // Load the network cfg information from cmDevCfg. + //_loadCfgMenu(kNetDcmTId, kNetCfgMenuCId, kNetDeleteBtnCId ); + //_recallCfg(kNetDcmTId, kNetCfgMenuCId, kNetCfgStringCId, kNetCfgDescCId, kNetApplyBtnCId ); + +} + +// Called when the MIDI 'Store' cfg button is pressed. +// Creates or edits a MIDI cfg recd in cmDevCfg. +void Fl_DevCfgGroup::_createMidiCfg() +{ + const cmChar_t* cfgStr = _getInputCtl(kMidiCfgStringCId); + const cmChar_t* devStr = _getMenuCtl(kMidiDevMenuCId); + const cmChar_t* portStr = _getMenuCtl(kMidiPortMenuCId); + bool inputFl = _getCheckCtl(kMidiInputCheckCId); + + // create or edit a MIDI cfg recd + if( cmDevCfgNameMidiPort(_dcH,cfgStr,devStr,portStr,inputFl) == kOkDcRC ) + { + // a MIDI cfg recd may have been created so reload the MIDI cfg menu btn + _loadCfgMenu(kMidiDcmTId,kMidiCfgMenuCId,kMidiDeleteBtnCId); + + // set the MIDI cfg menu btn to display the label of the cfg just edited or creaed + _setMenuBtnWithString(kMidiCfgMenuCId,cfgStr); + + // update the other MIDI fields based on the current cfg menu value + _recallCfg(kMidiDcmTId, kMidiCfgMenuCId, kMidiCfgStringCId, kMidiCfgDescCId, kMidiApplyBtnCId ); + + } +} + +// Called when the Audio 'Store' button is pressed. +// Creates or edits an audio cfg recd in the cmDevCfg. +void Fl_DevCfgGroup::_createAudioCfg() +{ + const cmChar_t* cfgStr = _getInputCtl(kAudioCfgStringCId); + const cmChar_t* inDevStr = _getMenuCtl(kAudioInDevMenuCId); + const cmChar_t* outDevStr = _getMenuCtl(kAudioOutDevMenuCId); + bool syncInFl = _getCheckCtl(kAudioSyncInCheckCId); + unsigned msgQueCnt = _getValueCtl(kAudioMsgQueSizeValCId); + unsigned devFpC = _getValueCtl(kAudioDevFpCValCId); + unsigned dspFpC = _getValueCtl(kAudioDspFpCValCId); + unsigned bufCnt = _getValueCtl(kAudioBufCntValCId); + const cmChar_t* nodeStr = _getInputCtl(kAudioNetNodeStringCId); + const cmChar_t* bcastAddr = _getInputCtl(kAudioBcastAddrStringCId); + const cmChar_t* ipAddr = _getInputCtl(kAudioIpAddrStringCId); + cmUdpPort_t ipPort = _getValueCtl(kAudioIpPortValCId); + bool activeFl = _getCheckCtl(kAudioActiveCheckCId); + + double srate = _getSrate(); + + if( strcmp(inDevStr,DEVCFG_NONE_STR)==0 ) + inDevStr = NULL; + + if( strcmp(outDevStr,DEVCFG_NONE_STR)==0 ) + outDevStr = NULL; + + // create or edit a audio cfg recd + if( cmDevCfgNameAudioPort(_dcH,cfgStr,inDevStr,outDevStr,syncInFl,msgQueCnt,devFpC,dspFpC,bufCnt,srate,nodeStr,bcastAddr,ipAddr,ipPort,activeFl) == kOkDcRC ) + { + // a new cfg recd may have been created so reload audio cfg menu + _loadCfgMenu(kAudioDcmTId,kAudioCfgMenuCId,kAudioDeleteBtnCId); + + // set the cfg menu to display the label of the cfg just edited or created + _setMenuBtnWithString(kAudioCfgMenuCId,cfgStr); + + // update the other audio fields based on the current cfg menu value + _recallCfg(kAudioDcmTId, kAudioCfgMenuCId, kAudioCfgStringCId, kAudioCfgDescCId, kAudioApplyBtnCId ); + + } +} + +/* +// Called when the Net 'Store' button is pressed. +// Creates or edits a net cfg recd in the cmDevCfg. +void Fl_DevCfgGroup::_createNetCfg() +{ + const cmChar_t* cfgStr = _idToCtl(kNetCfgStringCId)->u.inp->value(); + const cmChar_t* addrStr = _idToCtl(kNetSockAddrStringCId)->u.inp->value(); + unsigned portNum = _idToCtl(kNetPortNumbValCId)->u.val->value(); + bool activeFl= _idToCtl(kNetActiveCheckCId)->u.chk->value(); + + // create or edit a NET cfg recd + if( cmDevCfgNameNetPort(_dcH,cfgStr,addrStr,portNum,activeFl) == kOkDcRC ) + { + // a NET cfg recd may have been created so reload the NET cfg menu btn + _loadCfgMenu(kNetDcmTId,kNetCfgMenuCId,kNetDeleteBtnCId); + + // set the NET cfg menu btn to display the label of the cfg just edited or creaed + _setMenuBtnWithString(kNetCfgMenuCId,cfgStr); + + // update the other net fields based on the current cfg menu value + _recallCfg(kNetDcmTId, kNetCfgMenuCId, kNetCfgStringCId, kNetCfgDescCId, kNetApplyBtnCId ); + + } +} +*/ + +void Fl_DevCfgGroup::_deleteCfg( cmTypeDcmId_t typeId, unsigned menuCtlId, unsigned inpCtlId, unsigned descCtlId, unsigned storeCtlId, unsigned deleteCtlId ) +{ + ctl_t* c; + const cmChar_t* s; + int idx; + + if((s = _getMenuCtl(menuCtlId)) == NULL ) + goto errLabel; + + if(cmDevCfgDeleteCfg(_dcH, typeId, s ) != kOkDcRC ) + goto errLabel; + + if(( c = _idToCtl(menuCtlId)) == NULL ) + goto errLabel; + + if((idx = c->u.mbt->find_index(s)) < 0 ) + goto errLabel; + + c->u.mbt->remove(idx); + + if( c->u.mbt->size() > 0 ) + c->u.mbt->value(0); + + _loadCfgMenu(typeId,menuCtlId,deleteCtlId); + + _recallCfg(typeId,menuCtlId,inpCtlId,descCtlId,storeCtlId); + + errLabel: + return; +} + +void Fl_DevCfgGroup::_restoreMenuValue( unsigned menuCtlId, int val, int dfltVal ) +{ + ctl_t* c; + if((c = _idToCtl(menuCtlId)) == NULL ) + return; + + if( val < 0 || val >= c->u.mbt->size() ) + val = dfltVal; + + if( c->u.mbt->size() > 0 ) + c->u.mbt->value(val); + else + c->u.mbt->value(-1); + + _setMenuBtnLabel(menuCtlId); +} + +void Fl_DevCfgGroup::_setMenuBtnLabel( unsigned menuCtlId, unsigned inpCtlId ) +{ + ctl_t* c; + const Fl_Menu_Item* mip; + const char* s; + + if((c = _idToCtl(menuCtlId)) == NULL ) + goto errLabel; + + int v; + if((v = c->u.mbt->value()) == -1 ) + goto errLabel; + + if((mip = c->u.mbt->mvalue()) == NULL ) + goto errLabel; + + if((s = mip->label()) == NULL || strlen(s)==0) + s = ""; // the menu is empty or the label is invalid + + c->u.mbt->copy_label(s); + + if( inpCtlId != cmInvalidId ) + { + if((c = _idToCtl(inpCtlId)) == NULL ) + goto errLabel; + + c->u.inp->copy_label(s); + } + + errLabel: + return; +} + +void Fl_DevCfgGroup::_setMenuBtnWithString( unsigned menuCtlId, const char* string ) +{ + ctl_t* c; + int idx; + + if((c = _idToCtl(menuCtlId)) == NULL ) + goto errLabel; + + if((idx = c->u.mbt->find_index(string)) < 0 ) + goto errLabel; + + c->u.mbt->value(idx); + + c->u.mbt->copy_label(string); + + errLabel: + return; +} + +void Fl_DevCfgGroup::_setCheckCtl( unsigned ctlId, int val ) +{ + ctl_t* c; + if((c = _idToCtl(ctlId)) == NULL ) + return; + + c->u.chk->value(val); +} + +void Fl_DevCfgGroup::_setValueCtl( unsigned ctlId, double val ) +{ + ctl_t* c; + if((c = _idToCtl(ctlId)) == NULL ) + return; + + c->u.val->value(val); +} + +void Fl_DevCfgGroup::_setInputCtl( unsigned ctlId, const cmChar_t* val ) +{ + ctl_t* c; + if((c = _idToCtl(ctlId)) == NULL ) + return; + + c->u.inp->value(val); +} + +const cmChar_t* Fl_DevCfgGroup::_getMenuCtl( unsigned ctlId ) +{ + ctl_t* c; + const Fl_Menu_Item* mip; + + if((c = _idToCtl(ctlId)) == NULL) + goto errLabel; + + if( c->u.mbt->value() == -1 ) + goto errLabel; + + if((mip = c->u.mbt->mvalue()) == NULL) + goto errLabel; + + if( mip->label() == NULL ) + goto errLabel; + + return mip->label(); + + errLabel: + return ""; +} + +const cmChar_t* Fl_DevCfgGroup::_getInputCtl( unsigned ctlId ) +{ + ctl_t* c; + + if((c = _idToCtl(ctlId)) == NULL) + goto errLabel; + + if( c->u.inp->value() == NULL ) + goto errLabel; + + return c->u.inp->value(); + + errLabel: + return ""; +} + +double Fl_DevCfgGroup::_getValueCtl( unsigned ctlId ) +{ + ctl_t* c; + + if((c = _idToCtl(ctlId)) == NULL) + return 0; + + return c->u.val->value(); +} + +bool Fl_DevCfgGroup::_getCheckCtl( unsigned ctlId ) +{ + ctl_t* c; + + if((c = _idToCtl(ctlId)) == NULL) + return 0; + + return c->u.chk->value(); +} + + +double Fl_DevCfgGroup::_getSrate() +{ + ctl_t* c; + const Fl_Menu_Item* mip; + + if((c = _idToCtl(kAudioSrateMenuCId)) == NULL ) + return kAsDfltSrate; + + assert( c->u.mbt->value() != -1); + + if((mip = c->u.mbt->mvalue()) == NULL ) + return kAsDfltSrate; + + return (char*)mip->user_data() - (char*)NULL; +} + +void Fl_DevCfgGroup::_setSrate( double srate ) +{ + ctl_t* c; + + if((c = _idToCtl(kAudioSrateMenuCId)) == NULL ) + return; + + int i; + for(i=0; iu.mbt->size(); ++i) + { + const Fl_Menu_Item* mip = &c->u.mbt->menu()[i]; + if( mip != NULL && ((char*)mip->user_data() - (char*)NULL) == srate) + { + c->u.mbt->value(i); + c->u.mbt->copy_label( mip->label() ); + return; + } + } +} + +void Fl_DevCfgGroup::_enableStoreBtn( unsigned ctlId ) +{ + ctl_t* c; + if((c = _idToCtl(ctlId)) == NULL ) + return; + + c->u.btn->activate(); +} + +Fl_DevCfgGroup::ctl_t* Fl_DevCfgGroup::_idToCtl( unsigned id ) +{ + unsigned i = 0; + for(i=0; i<_ctlV.size(); ++i) + if( _ctlV[i]->id == id ) + return _ctlV[i]; + + assert(0); + return NULL; +} + + +void Fl_DevCfgGroup::_s_ctl_cb( Fl_Widget* w, void* arg ) +{ + ctl_t* c = (ctl_t*)arg; + + switch( c->id ) + { + // ------------------------------------------------------------ + // Location + + case kLocLabelCId: + break; + + case kLocMenuCId: + c->p->_recallLoc(); + break; + + case kLocStoreBtnCId: + c->p->_storeLoc(); + break; + + case kLocStringCId: + c->p->_enableStoreBtn(kLocStoreBtnCId); + break; + + case kLocDeleteBtnCId: + c->p->_deleteLoc(); + break; + + + // ------------------------------------------------------------ + // MIDI + + case kMidiCfgMenuCId: + c->p->_recallCfg(kMidiDcmTId, kMidiCfgMenuCId, kMidiCfgStringCId, kMidiCfgDescCId, kMidiApplyBtnCId ); + break; + + case kMidiDeleteBtnCId: + c->p->_deleteCfg(kMidiDcmTId,kMidiCfgMenuCId,kMidiCfgStringCId,kMidiCfgDescCId,kMidiApplyBtnCId,kMidiDeleteBtnCId); + break; + + case kMidiCfgStringCId: + c->p->_enableStoreBtn(kMidiApplyBtnCId); + break; + + case kMidiApplyBtnCId: + c->p->_createMidiCfg(); + c->p->_recallCfg(kMidiDcmTId, kMidiCfgMenuCId, kMidiCfgStringCId, kMidiCfgDescCId, kMidiApplyBtnCId ); + break; + + case kMidiDevMenuCId: + c->p->_setMenuBtnLabel(c->id); + c->p->_loadMidiPortBtn(); + c->p->_enableStoreBtn(kMidiApplyBtnCId); + break; + + case kMidiPortMenuCId: + c->p->_setMenuBtnLabel(c->id); + c->p->_enableStoreBtn(kMidiApplyBtnCId); + break; + + case kMidiInputCheckCId: + c->p->_enableStoreBtn(kMidiApplyBtnCId); + break; + + // ------------------------------------------------------------ + // Audio + + case kAudioLabelCId: + break; + + case kAudioCfgMenuCId: + c->p->_recallCfg(kAudioDcmTId, kAudioCfgMenuCId, kAudioCfgStringCId, kAudioCfgDescCId, kAudioApplyBtnCId ); + break; + + case kAudioDeleteBtnCId: + c->p->_deleteCfg(kAudioDcmTId,kAudioCfgMenuCId,kAudioCfgStringCId,kAudioCfgDescCId, kAudioApplyBtnCId, kAudioDeleteBtnCId); + break; + + case kAudioCfgStringCId: + c->p->_enableStoreBtn(kAudioApplyBtnCId); + break; + + case kAudioApplyBtnCId: + c->p->_createAudioCfg(); + c->p->_recallCfg(kAudioDcmTId, kAudioCfgMenuCId, kAudioCfgStringCId, kAudioCfgDescCId, kAudioApplyBtnCId ); + break; + + case kAudioInDevMenuCId: + c->p->_setMenuBtnLabel(c->id); + c->p->_enableStoreBtn(kAudioApplyBtnCId); + break; + + case kAudioOutDevMenuCId: + c->p->_setMenuBtnLabel(c->id); + c->p->_enableStoreBtn(kAudioApplyBtnCId); + break; + + case kAudioSrateMenuCId: + c->p->_setMenuBtnLabel(c->id); + c->p->_enableStoreBtn(kAudioApplyBtnCId); + break; + + case kAudioActiveCheckCId: + case kAudioMsgQueSizeValCId: + case kAudioDevFpCValCId: + case kAudioDspFpCValCId: + case kAudioBufCntValCId: + case kAudioSyncInCheckCId: + case kAudioNetNodeStringCId: + case kAudioBcastAddrStringCId: + case kAudioIpAddrStringCId: + case kAudioIpPortValCId: + c->p->_enableStoreBtn(kAudioApplyBtnCId); + break; + + + + + // ------------------------------------------------------------ + // Network + /* + case kNetLabelCId: + break; + + case kNetCfgMenuCId: + c->p->_recallCfg(kNetDcmTId, kNetCfgMenuCId, kNetCfgStringCId, kNetCfgDescCId, kNetApplyBtnCId ); + break; + + case kNetDeleteBtnCId: + c->p->_deleteCfg(kNetDcmTId,kNetCfgMenuCId,kNetCfgStringCId,kNetCfgDescCId, kNetApplyBtnCId, kNetDeleteBtnCId); + break; + + case kNetCfgStringCId: + c->p->_enableStoreBtn(kNetApplyBtnCId); + break; + + case kNetApplyBtnCId: + c->p->_createNetCfg(); + c->p->_recallCfg(kNetDcmTId, kNetCfgMenuCId, kNetCfgStringCId, kNetCfgDescCId, kNetApplyBtnCId ); + c->p->_enableStoreBtn(kNetApplyBtnCId); + break; + + case kNetSockAddrStringCId: + case kNetPortNumbValCId: + case kNetActiveCheckCId: + c->p->_enableStoreBtn(kNetApplyBtnCId); + break; + */ + + default: + break; + } + +} diff --git a/src/libcmpp/fltk/Fl_DevCfgGroup.h b/src/libcmpp/fltk/Fl_DevCfgGroup.h new file mode 100644 index 0000000..d6110f5 --- /dev/null +++ b/src/libcmpp/fltk/Fl_DevCfgGroup.h @@ -0,0 +1,168 @@ +#ifndef Fl_DevCfgGroup_h +#define Fl_DevCfgGroup_h + +#include + +class Fl_DevCfgGroup : public Fl_Group +{ +public: + Fl_DevCfgGroup(cmDevCfgH_t dcH, int x, int y, int w, int h, const char* label ); + virtual ~Fl_DevCfgGroup(); + + void onEnableAudio(bool enableFl ); + +private: + enum + { + kInvalidCId, + kLocLabelCId, + kLocMenuCId, + kLocStringCId, + kLocStoreBtnCId, + kLocDeleteBtnCId, + + kMidiLabelCId, + kMidiCfgMenuCId, + kMidiDeleteBtnCId, + kMidiCfgStringCId, + kMidiApplyBtnCId, + kMidiCfgDescCId, + kMidiDevMenuCId, + kMidiDevLabelCId, + kMidiPortMenuCId, + kMidiPortLabelCId, + kMidiInputCheckCId, + + kAudioLabelCId, + kAudioCfgMenuCId, + kAudioDeleteBtnCId, + kAudioCfgDescCId, + kAudioCfgStringCId, + kAudioApplyBtnCId, + kAudioInDevMenuCId, + kAudioInDevLabelCId, + kAudioOutDevMenuCId, + kAudioOutDevLabelCId, + kAudioMsgQueSizeValCId, + kAudioDevFpCValCId, + kAudioDspFpCValCId, + kAudioBufCntValCId, + kAudioSrateMenuCId, + kAudioSyncInCheckCId, + kAudioNetNodeStringCId, + kAudioBcastAddrStringCId, + kAudioIpAddrStringCId, + kAudioIpPortValCId, + kAudioActiveCheckCId, + + /* + kNetLabelCId, + kNetCfgMenuCId, + kNetDeleteBtnCId, + kNetCfgDescCId, + kNetCfgStringCId, + kNetApplyBtnCId, + kNetSockAddrStringCId, + kNetPortNumbValCId, + kNetLocalCheckCId, + kNetActiveCheckCId + */ + + }; + + typedef struct + { + unsigned id; + Fl_DevCfgGroup* p; + union + { + Fl_Button* btn; + Fl_Check_Button* chk; + Fl_Box* box; + Fl_Menu_Button* mbt; + Fl_Input* inp; + Fl_Value_Input* val; + } u; + + } ctl_t; + + cmDevCfgH_t _dcH; + std::vector< ctl_t* > _ctlV; + + bool _loadLocBtn(); + void _recallLoc(); + void _storeLoc(); + void _deleteLoc(); + + void _loadMidiDevBtn(); + void _loadMidiPortBtn(); + void _loadAudioDevBtn( unsigned id, unsigned devIdx ); + void _loadAudioSrateBtn(); + void _loadCfgMenu(cmTypeDcmId_t typeId, unsigned menuCtlId, unsigned deleteCtlId ); + void _syncLoc(); + void _createMidiCfg(); + void _createAudioCfg(); + //void _createNetCfg(); + void _deleteCfg( cmTypeDcmId_t typeId, unsigned menuCtlId, unsigned inpCtlCId, unsigned descCtlId, unsigned storeCtlId, unsigned deleteCtlId ); + void _recallCfg( cmTypeDcmId_t typeId, unsigned menuCtlId, unsigned strCtlId, unsigned descCtlId, unsigned storeCtlId ); + + // Attempt to set the menu to index 'val' otherwise attempt to set it to 'dfltVal' + // Finish by updating the label. + void _restoreMenuValue( unsigned menuCtlId, int val, int dfltVal=0 ); + + // Get the current string value of the menu btn. + const char* _menuBtnValueStr( unsigned menuCtlId ); + + // Copy the menu btn's current string value to the label (and the input control) + void _setMenuBtnLabel( unsigned menuCtlId, unsigned inpCtlId = cmInvalidId ); + + // Set the menu buttons value to 'string' and update the menu btn's label + void _setMenuBtnWithString( unsigned menuCtlId, const char* string ); + void _setCheckCtl( unsigned ctlId, int val ); + void _setValueCtl( unsigned ctlId, double val ); + void _setInputCtl( unsigned ctlId, const cmChar_t* val ); + + const cmChar_t* _getMenuCtl( unsigned ctlId ); + const cmChar_t* _getInputCtl( unsigned ctlId ); + double _getValueCtl( unsigned ctlId ); + bool _getCheckCtl( unsigned ctlId ); + + double _getSrate(); + void _setSrate( double srate ); + + void _enableStoreBtn( unsigned ctlId ); + + ctl_t* _idToCtl(unsigned id); + + + static void _s_ctl_cb( Fl_Widget* w, void* arg ); + +}; + +// Init: +// 1) Load all menu X btns and set to first entry. +// 2) set cfg string X to string value of cfg menu +// 3) update desc and X fields. +// +// Cfg: +// Store: +// 1) call cmDevCfgNameX( cfg_label ) successfully +// 2) reload cfg menu +// 3) set cfg menu label to new cfg_label +// +// Recall: +// 1) set cfg menu X label +// 2) set cfg string X to string value of cfg menu +// 3) update desc and X fields +// +// Delete: +// 1) call cmDevDeleteX( cfg_label ) sucessfuly. +// 2) reload cfg menu and set to first entry +// 3) set cfg string X to string value of cfg menu +// 4) update desc and X fields +// +// + + + +#endif diff --git a/src/libcmpp/fltk/Fl_File_Btn.cpp b/src/libcmpp/fltk/Fl_File_Btn.cpp new file mode 100644 index 0000000..83e0071 --- /dev/null +++ b/src/libcmpp/fltk/Fl_File_Btn.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include "Fl_File_Btn.h" + +Fl_File_Btn::Fl_File_Btn( int xx, int yy, int ww, int hh, const char* l ) + : Fl_Group(xx,yy,ww,hh,l), + _patStr(NULL),_typeId(kFile_Type_Id),_btn(NULL),_out(NULL) +{ + _init(); + end(); +} + +Fl_File_Btn::Fl_File_Btn( unsigned typeId, const char* patStr, int xx, int yy, int ww, int hh, const char* l ) + : Fl_Group(xx,yy,ww,hh,l), + _patStr(NULL),_typeId(typeId),_btn(NULL),_out(NULL) +{ + _init(); + type(typeId); + pattern_string(patStr); + end(); +} + +Fl_File_Btn::~Fl_File_Btn() +{ delete[] _patStr; } + +unsigned Fl_File_Btn::type() +{ return _typeId; } + +void Fl_File_Btn::type( unsigned typeId ) +{ + switch(typeId) + { + case kFile_Type_Id: + _btn->label("File"); + _typeId = typeId; + break; + + case kDir_Type_Id: + _btn->label("Dir"); + _typeId = typeId; + break; + } + + +} + +const char* Fl_File_Btn::pattern_string() +{ return _patStr; } + +void Fl_File_Btn::pattern_string( const char* pat) +{ + delete[] _patStr; + if( pat != NULL ) + { + _patStr = new char[ strlen(pat) + 1]; + strcpy(_patStr,pat); + } +} + +void Fl_File_Btn::btn_width( int ww ) +{ + _btn->resize(_btn->x(),_btn->y(),ww,_btn->h()); + _out->resize(_btn->x() + _btn->w() + 2, _out->y(), w() - _btn->w() - 2, _out->h()); +} + +int Fl_File_Btn::btn_width() +{ return _btn->w(); } + +void Fl_File_Btn::filename( const char* fn ) +{ _out->value(fn); _out->redraw(); } + +const char* Fl_File_Btn::filename() const +{ return _out->value(); } + + +void Fl_File_Btn::_s_btn_cb(Fl_Widget* w, void* data) +{ ((Fl_File_Btn*)data)->_btn_cb(); } + +void Fl_File_Btn::_btn_cb() +{ + char* fn; + if( _typeId == kFile_Type_Id ) + fn = fl_file_chooser("Select a file",_patStr,_out->value(),0); + else + fn = fl_dir_chooser("Select a directory",_out->value(),0); + + if( fn != NULL ) + { + _out->value(fn); + do_callback(this,user_data()); + } + +} + +void Fl_File_Btn::_init() +{ + _btn = new Fl_Button(x(),y(),40,h(),_typeId==kFile_Type_Id ? "File" : "Dir"); + _btn->callback(_s_btn_cb,this); + + _out = new Fl_Output(x() + _btn->w() + 2, y(), w() - _btn->w(), h()); + +} diff --git a/src/libcmpp/fltk/Fl_File_Btn.h b/src/libcmpp/fltk/Fl_File_Btn.h new file mode 100644 index 0000000..d9d937d --- /dev/null +++ b/src/libcmpp/fltk/Fl_File_Btn.h @@ -0,0 +1,47 @@ +#ifndef Fl_File_Btn_h +#define Fl_File_Btn_h + +class Fl_Button; +class Fl_Output; + +class Fl_File_Btn : public Fl_Group +{ +public: + enum + { + kFile_Type_Id, + kDir_Type_Id + }; + + Fl_File_Btn( int x, int y, int w, int h, const char* l = 0 ); + + Fl_File_Btn( unsigned typeId, const char* patStr, int x, int y, int w, int h, const char* l = 0 ); + virtual ~Fl_File_Btn(); + + unsigned type(); + void type( unsigned typeId ); + + const char* pattern_string(); + void pattern_string( const char* pat); + + void btn_width( int w ); + int btn_width(); + + void filename( const char* fn ); + const char* filename() const; + +private: + char* _patStr; + unsigned _typeId; + Fl_Button* _btn; + Fl_Output* _out; + + static void _s_btn_cb(Fl_Widget* w, void* data); + void _btn_cb(); + + void _init(); + +}; + + +#endif diff --git a/src/libcmpp/fltk/Fl_Splitter.cpp b/src/libcmpp/fltk/Fl_Splitter.cpp new file mode 100644 index 0000000..3cbad0e --- /dev/null +++ b/src/libcmpp/fltk/Fl_Splitter.cpp @@ -0,0 +1,273 @@ +// Code based on: http://www.mail-archive.com/fltk@easysw.com/msg04573.html +// Lucas Sanner/Ian MacArthur + +#include "Fl_Splitter.h" + +void Fl_HSplitter::draw() +{ + Fl_Group::draw(); + Fl_Color c = fl_color(); + fl_color(FL_BLACK); + fl_line_style( FL_DOT, 1); + + if(splitFl && Fl::event_button1() != 0) + { + fl_push_clip(x(), y(), w(), h()); + + yPos = Fl::event_y(); + + if(Fl::event_y() > h() - (border * 2)) + yPos = h() - (border * 2); + + if(Fl::event_y() < y() + (border * 2)) + yPos = y() + (border * 2); + + fl_line( x() + border, yPos - 1, x() + w() - (border*2), yPos - 1 ); + fl_line( x() + border, yPos , x() + w() - (border*2), yPos ); + fl_line( x() + border, yPos + 1, x() + w() - (border*2), yPos + 1 ); + + /* + fl_line( + x() + border, + yPos, + x() + w() - (border*2), + yPos ); + + fl_line( + x() + border, + yPos + 1, + x() + w() - (border*2), + yPos + 1 ); + */ + + fl_pop_clip(); + } + else + { + fl_push_clip(x(), y(), w(), h()); + fl_pop_clip(); + } + + fl_color(c); + fl_line_style(0); +} + +int Fl_HSplitter::handle(int e) +{ + int ret = Fl_Group::handle(e); + + switch(e) + { + case FL_MOVE: + + if(hCtnl - border < Fl::event_y() && Fl::event_y() < hCtnl + border) + { + fl_cursor(FL_CURSOR_NS); + splitFl = true; + } + else + { + fl_cursor(FL_CURSOR_DEFAULT); + splitFl = false; + } + + return 1; + + case FL_PUSH: + + if(Fl::event_button() == FL_LEFT_MOUSE && splitFl) + { + redraw(); + } + + return 1; + + case FL_RELEASE: + + if(Fl::event_button() == FL_LEFT_MOUSE && splitFl) + { + c0->resize(x(), y(), w(), yPos - y()); + hCtnl = yPos; + c1->resize(x(),hCtnl, w(), h() - (yPos - y())); + + if( stretchTopFl ) + init_sizes(); + + splitFl = false; + redraw(); + } + + return 1; + + case FL_DRAG: + + if(splitFl && Fl::event_state(FL_BUTTON1) != 0) + redraw(); + + return 1; + } + + return(ret); +} + + +Fl_HSplitter::Fl_HSplitter(int x, int y, int w, int h, int h1, const char *l, bool stretchBotFl) + : Fl_Group(x, y, w, h, l) +{ + int h2 = h - h1; + + begin(); + c0 = new Splitter_Container(x, y, w, h1); + //c0->color((Fl_Color) FL_RED); + end(); + + begin(); + c1 = new Splitter_Container(x, y + h1, w, h2); + //c1->color((Fl_Color) FL_BLUE); + end(); + + hCtnl = y + h1; + splitFl = false; + stretchTopFl = !stretchBotFl; + border = Fl::box_dy(FL_DOWN_BOX); + + if( stretchTopFl ) + resizable(c0); +} + +void Fl_HSplitter::resize(int x, int y, int w, int h) +{ + Fl_Group::resize(x, y, w, h); + + if( stretchTopFl ) + { + hCtnl = c0->h() + y; + yPos = hCtnl; + //printf("hCtnl:%i\n",hCtnl); + } + else + { + c0->resize(x, y, w, hCtnl - y); + c1->resize(x, hCtnl, w, h - (hCtnl - y)); + } + +} + + + +void Fl_VSplitter::draw() +{ + Fl_Group::draw(); + Fl_Color c = fl_color(); + fl_color(FL_BLACK); + fl_line_style( FL_DOT, 1); + + if(splitFl && Fl::event_button1() != 0) + { + fl_push_clip(x(), y(), w(), h()); + + xPos = Fl::event_x(); + + if(Fl::event_x() > w() - (border * 2)) + xPos = w() - (border * 2); + + if(Fl::event_x() < x() + (border * 2)) + xPos = x() + (border * 2); + + fl_line(xPos - 1, y() + border, xPos - 1, y() + h() - (border * 2)); + fl_line(xPos, y() + border, xPos, y() + h() - (border * 2)); + fl_line(xPos + 1, y() + border, xPos + 1, y() + h() - (border * 2)); + + fl_pop_clip(); + } + else + { + fl_push_clip(x(), y(), w(), h()); + fl_pop_clip(); + } + + fl_color(c); + fl_line_style(0); // restore line style to defaults +} + +int Fl_VSplitter::handle(int e) +{ + int ret = Fl_Group::handle(e); + + switch(e) + { + case FL_MOVE: + + if(Fl::event_x() > wCtn1 - border && Fl::event_x() < wCtn1 + border) + { + fl_cursor(FL_CURSOR_WE); + splitFl = true; + } + else + { + fl_cursor(FL_CURSOR_DEFAULT); + splitFl = false; + } + + return 1; + + case FL_PUSH: + + if(Fl::event_button() == FL_LEFT_MOUSE && splitFl) + { + redraw(); + } + + return 1; + + case FL_RELEASE: + + if(Fl::event_button() == FL_LEFT_MOUSE && splitFl) + { + c0->resize(x(), y(), xPos, h()); + wCtn1 = xPos; + c1->resize(wCtn1, y(), w() - wCtn1, h()); + splitFl = false; + redraw(); + } + + return 1; + + case FL_DRAG: + + if(splitFl && Fl::event_state(FL_BUTTON1) != 0) + redraw(); + + return 1; + } + + return(ret); +} + +Fl_VSplitter::Fl_VSplitter(int x, int y, int w, int h, const char *l) + : Fl_Group(x, y, w, h, l) +{ + begin(); + c0 = new Splitter_Container(x, y, w / 2, h); + //c0->color((Fl_Color) FL_RED); + end(); + + begin(); + c1 = new Splitter_Container(x + (w / 2), y, w / 2, h); + //c1->color((Fl_Color) FL_BLUE); + end(); + + wCtn1 = w / 2; + splitFl = false; + + border = Fl::box_dx(FL_DOWN_BOX); + +} + +void Fl_VSplitter::resize_splitter(int x, int y, int w, int h) +{ + resize(x, y, w, h); + c0->resize(x, y, wCtn1, h); + c1->resize(wCtn1, y, w - wCtn1, h); +} + diff --git a/src/libcmpp/fltk/Fl_Splitter.h b/src/libcmpp/fltk/Fl_Splitter.h new file mode 100644 index 0000000..f93d8d1 --- /dev/null +++ b/src/libcmpp/fltk/Fl_Splitter.h @@ -0,0 +1,70 @@ +// Code based on: http://www.mail-archive.com/fltk@easysw.com/msg04573.html +// Lucas Sanner/Ian MacArthur + +#ifndef Fl_Splitter_h +#define Fl_Splitter_h + +#include +#include +#include +#include + + +class Splitter_Container : public Fl_Group +{ + + public: + + Splitter_Container(int x, int y, int w, int h, char *l = NULL) + : Fl_Group(x, y, w, h, l) + { + box(FL_NO_BOX); // do not draw the background + } +}; + +class Fl_HSplitter : public Fl_Group +{ + int hCtnl; // window coord's of the horzontal splitter + int border; // splitter divider height + int yPos; // window posn where divider was last draw + bool splitFl; // set if split cursor is enabled + bool stretchTopFl; // set to make top container stretch when splitter is resized + //int hh2; + + virtual void draw(); + + int handle(int e); + + public: + + Splitter_Container *c0, *c1; + + Fl_HSplitter(int x, int y, int w, int h, int h1, const char *l=NULL, bool stretchBotFl=false); + + virtual void resize(int x, int y, int w, int h); + +}; + + +class Fl_VSplitter : public Fl_Group +{ + + int wCtn1, border, xPos; + bool splitFl; + + void draw(); + int handle(int e); + + public: + + Splitter_Container *c0, *c1; + + Fl_VSplitter(int x, int y, int w, int h, const char *l = NULL); + + void resize_splitter(int x, int y, int w, int h); + + + +}; + +#endif diff --git a/src/libcmpp/fltk/Fl_Vert_Progress.cpp b/src/libcmpp/fltk/Fl_Vert_Progress.cpp new file mode 100644 index 0000000..8dfb243 --- /dev/null +++ b/src/libcmpp/fltk/Fl_Vert_Progress.cpp @@ -0,0 +1,66 @@ +#include +#include +#include +#include "Fl_Vert_Progress.h" + +Fl_Vert_Progress::Fl_Vert_Progress(int x, int y, int w, int h, const char* l) + : Fl_Progress(x,y,w,h) +{ +} + +// This member function is a slight variation on a verbatim +// copy of Fl_Progress.cxx from the FLTK source library. +void Fl_Vert_Progress::draw() +{ + int progress; // Size of progress bar... + int bx, by, bw, bh; // Box areas... + int tx, tw; // Temporary X + width + + // Get the box borders... + bx = Fl::box_dx(box()); + by = Fl::box_dy(box()); + bw = Fl::box_dw(box()); + bh = Fl::box_dh(box()); + + tx = x() + bx; + tw = w() - bw; + + // Draw the progress bar... + if (maximum() > minimum()) + progress = (int)(h() * (value() - minimum()) / (maximum() - minimum()) + 0.5f); + else + progress = 0; + + // Draw the box and label... + if (progress > 0) + { + Fl_Color c = labelcolor(); + labelcolor(fl_contrast(labelcolor(), selection_color())); + + fl_push_clip(x(), y() + h() - (progress + by), w(), progress + by); + + draw_box(box(), x(), y(), w(), h(), active_r() ? selection_color() : fl_inactive(selection_color())); + + draw_label(tx, y() + by, tw, h() - bh); + + fl_pop_clip(); + + labelcolor(c); + + if (progress +#include +#include +#include +#include +#include +#include + + +#include "cmPrefix.h" +#include "cmGlobal.h" +#include "cmFloatTypes.h" +#include "cmRpt.h" +#include "cmErr.h" +#include "cmCtx.h" +#include "cmMem.h" +#include "cmMallocDebug.h" +#include "cmGr.h" +#include "cmGrDevCtx.h" +#include "cmGrPage.h" +#include "cmGrPlot.h" + +#include "cmGrFltk.h" + +//-------------------------------------------------------------------------------------- +cmGrDevDrvFltk::cmGrDevDrvFltk() + : _fltk_pen_width(0), _fltk_pen_style(0), _fltk_font_size(0), + _w(0), _h(0) +{ + d.create = create; + d.destroy = destroy; + + d.begin_draw = begin_draw; + d.end_draw = end_draw; + d.draw = draw; + + d.set_color = set_color; + d.get_color = get_color; + + d.set_font_family = set_font_family; + d.get_font_family = get_font_family; + + d.set_font_style = set_font_style; + d.get_font_style = get_font_style; + + d.set_font_size = set_font_size; + d.get_font_size = get_font_size; + + d.set_pen_style = set_pen_style; + d.get_pen_style = get_pen_style; + + d.set_pen_width = set_pen_width; + d.get_pen_width = get_pen_width; + + d.draw_line = draw_line; + d.draw_rect = draw_rect; + d.fill_rect = fill_rect; + d.draw_ellipse = draw_ellipse; + d.fill_ellipse = fill_ellipse; + d.draw_diamond = draw_diamond; + d.fill_diamond = fill_diamond; + d.draw_triangle = draw_triangle; + d.fill_triangle = fill_triangle; + d.draw_text = draw_text; + d.draw_text_rot = draw_text_rot; + d.measure_text = measure_text; + d.read_image = read_image; + d.draw_image = draw_image; +} + +bool cmGrDevDrvFltk::create( void* user, unsigned ww, unsigned hh ) +{ + cmGrDevDrvFltk* p = (cmGrDevDrvFltk*)user; + + if( ww && hh && p->_w != ww && p->_h != hh ) + { + destroy(user); + + p->_w = ww; + p->_h = hh; + + //printf("creat: 0x%x w:%i h:%i\n",(unsigned)p->fl_os,p->w,p->h); + } + return true; +} + +void cmGrDevDrvFltk::destroy( void* user ) +{ + cmGrDevDrvFltk* p = (cmGrDevDrvFltk*)user; + + p->_w = 0; + p->_h = 0; +} + +void cmGrDevDrvFltk::begin_draw( void* arg ) +{ +} + +void cmGrDevDrvFltk::end_draw( void* arg ) +{ +} + +void cmGrDevDrvFltk::draw( void* arg, int x, int y ) +{ +} + + +void cmGrDevDrvFltk::set_color( void* user, const cmGrColor_t c ) +{ + Fl_Color color = fl_rgb_color(cmGrColorToR(c),cmGrColorToG(c),cmGrColorToB(c)); + fl_color(color); +} + +void cmGrDevDrvFltk::get_color( void* user, cmGrColor_t* c ) +{ + Fl_Color color = fl_color(); + *c = cmGrRgbToColor( ((color>>24)&0x000000ff),((color>>16)&0x000000ff),((color>>8)&0x000000ff)); +} + + +void cmGrDevDrvFltk::_get_font_family_style( unsigned* fontId, unsigned* style) +{ + switch( fl_font() ) + { + case FL_HELVETICA: *fontId = kHelveticaFfGrId; *style = kNormalFsGrFl; break; + case FL_HELVETICA_BOLD: *fontId = kHelveticaFfGrId; *style = kBoldFsGrFl; break; + case FL_HELVETICA_ITALIC: *fontId = kHelveticaFfGrId; *style = kItalicFsGrFl; break; + case FL_HELVETICA_BOLD_ITALIC: *fontId = kHelveticaFfGrId; *style = kBoldFsGrFl | kItalicFsGrFl; break; + + case FL_TIMES: *fontId = kTimesFfGrId; *style = kNormalFsGrFl; break; + case FL_TIMES_BOLD: *fontId = kTimesFfGrId; *style = kBoldFsGrFl; break; + case FL_TIMES_ITALIC: *fontId = kTimesFfGrId; *style = kItalicFsGrFl; break; + case FL_TIMES_BOLD_ITALIC: *fontId = kTimesFfGrId; *style = kBoldFsGrFl | kItalicFsGrFl; break; + + case FL_COURIER: *fontId = kCourierFfGrId; *style = kNormalFsGrFl; break; + case FL_COURIER_BOLD: *fontId = kCourierFfGrId; *style = kBoldFsGrFl; break; + case FL_COURIER_ITALIC: *fontId = kCourierFfGrId; *style = kItalicFsGrFl; break; + case FL_COURIER_BOLD_ITALIC: *fontId = kCourierFfGrId; *style = kBoldFsGrFl | kItalicFsGrFl; break; + + default: + { assert(0); } + } +} + +void cmGrDevDrvFltk::_set_font_family_style( void* user, unsigned fontId, unsigned style) +{ + switch( fontId ) + { + case kHelveticaFfGrId: + switch( style ) + { + case kNormalFsGrFl: fontId = FL_HELVETICA; break; + case kBoldFsGrFl: fontId = FL_HELVETICA_BOLD; break; + case kItalicFsGrFl: fontId = FL_HELVETICA_ITALIC; break; + case kItalicFsGrFl + kBoldFsGrFl: fontId = FL_HELVETICA_BOLD_ITALIC; break; + default: + { assert(0); } + } + break; + + case kTimesFfGrId: + switch( style ) + { + case kNormalFsGrFl: fontId = FL_TIMES; break; + case kBoldFsGrFl: fontId = FL_TIMES_BOLD; break; + case kItalicFsGrFl: fontId = FL_TIMES_ITALIC; break; + case kItalicFsGrFl + kBoldFsGrFl: fontId = FL_TIMES_BOLD_ITALIC; break; + default: + { assert(0); } + } + break; + + case kCourierFfGrId: + switch( style ) + { + case kNormalFsGrFl: fontId = FL_COURIER; break; + case kBoldFsGrFl: fontId = FL_COURIER_BOLD; break; + case kItalicFsGrFl: fontId = FL_COURIER_ITALIC; break; + case kItalicFsGrFl + kBoldFsGrFl: fontId = FL_COURIER_BOLD_ITALIC; break; + default: + { assert(0); } + } + break; + + default: + { assert(0); } + } + + cmGrDevDrvFltk* p = (cmGrDevDrvFltk*)user; + + fl_font( fontId, p->_fltk_font_size ); +} + +void cmGrDevDrvFltk::set_font_family( void* user, unsigned fontId ) +{ _set_font_family_style( user, fontId, get_font_style(user) ); } + +unsigned cmGrDevDrvFltk::get_font_family( void* user ) +{ + unsigned fontId=0, style=0; + _get_font_family_style(&fontId,&style); + return fontId; +} + +void cmGrDevDrvFltk::set_font_style( void* user, unsigned style ) +{ _set_font_family_style( user, get_font_family(user), style); } + +unsigned cmGrDevDrvFltk::get_font_style( void* user ) +{ + unsigned fontId=0, style=0; + _get_font_family_style(&fontId,&style); + return style; +} + +void cmGrDevDrvFltk::set_font_size( void* user, unsigned size ) +{ + unsigned fontId=0, style=0; + cmGrDevDrvFltk* p = (cmGrDevDrvFltk*)user; + _get_font_family_style(&fontId,&style); + p->_fltk_font_size = size; + _set_font_family_style(user,fontId,style); +} + +unsigned cmGrDevDrvFltk::get_font_size( void* user ) +{ return fl_size(); } + +void cmGrDevDrvFltk::set_pen_style( void* user, unsigned style ) +{ + cmGrDevDrvFltk* p = (cmGrDevDrvFltk*)user; + + switch( style ) + { + case kSolidLsGrFl: style = FL_SOLID; break; + case kDashLsGrFl: style = FL_DASH; break; + case kDotLsGrFl: style = FL_DOT; break; + default: + { assert(0); } + } + + p->_fltk_pen_style = style; + + fl_line_style( p->_fltk_pen_style, p->_fltk_pen_width ); +} + +unsigned cmGrDevDrvFltk::get_pen_style( void* user ) +{ + cmGrDevDrvFltk* p = (cmGrDevDrvFltk*)user; + unsigned style = kSolidLsGrFl; + + switch( p->_fltk_pen_style ) + { + case FL_SOLID: style = kSolidLsGrFl; break; + case FL_DASH: style = kDashLsGrFl; break; + case FL_DOT: style = kDotLsGrFl; break; + default: + { assert(0); } + } + return style; +} + +void cmGrDevDrvFltk::set_pen_width( void* user, unsigned w ) +{ + cmGrDevDrvFltk* p = (cmGrDevDrvFltk*)user; + + p->_fltk_pen_width = w; + fl_line_style( p->_fltk_pen_style, p->_fltk_pen_width ); +} + +unsigned cmGrDevDrvFltk::get_pen_width( void* user ) +{ + cmGrDevDrvFltk* p = (cmGrDevDrvFltk*)user; + return p->_fltk_pen_width; +} + +void cmGrDevDrvFltk::draw_line( void* user, int x0, int y0, int x1, int y1 ) +{ fl_line(x0,y0,x1,y1); } + +void cmGrDevDrvFltk::draw_rect( void* user, int x0, int y0, unsigned w, unsigned h ) +{ fl_rect(x0,y0,w,h); } + +void cmGrDevDrvFltk::fill_rect( void* user, int x0, int y0, unsigned w, unsigned h ) +{ fl_rectf(x0,y0,w,h); } + +void cmGrDevDrvFltk::draw_ellipse( void* user, int x0, int y0, unsigned w, unsigned h ) +{ + fl_arc(x0,y0,w,h,0,360); +} + +void cmGrDevDrvFltk::fill_ellipse( void* user, int x0, int y0, unsigned w, unsigned h ) +{ + fl_pie(x0,y0,w,h,0,360); +} + +void cmGrDevDrvFltk::draw_diamond( void* user, int x0, int y0, unsigned w, unsigned h ) +{ +} + +void cmGrDevDrvFltk::fill_diamond( void* user, int x0, int y0, unsigned w, unsigned h ) +{ +} + +void cmGrDevDrvFltk::draw_triangle( void* user, int x0, int y0, unsigned w, unsigned h, unsigned dirFlag ) +{ +} + +void cmGrDevDrvFltk::fill_triangle( void* user, int x0, int y0, unsigned w, unsigned h, unsigned dirFlag ) +{ +} + + + +void cmGrDevDrvFltk::draw_text( void* user, const char* text, int x, int y ) +{ + int y0 = y - fl_descent(); + fl_draw(text,x,y0); + + /* + Fl_Color c = fl_color(); + fl_color(FL_RED); + fl_point(x,y); + fl_point(x,y0); + fl_point(x,y - fl_height()); + fl_color(c); + */ +} + +void cmGrDevDrvFltk::draw_text_rot( void* user, const char* text, int x, int y, int angle ) +{ + fl_draw(angle,text,strlen(text),x,y); + + Fl_Color c = fl_color(); + fl_color(FL_RED); + fl_point(x,y); + fl_color(c); +} + +void cmGrDevDrvFltk::measure_text( void* user, const char* text, unsigned* w, unsigned* h ) +{ + int ww; + int hh; + fl_measure(text,ww,hh); + *w = ww; + *h = hh; +} + + +void cmGrDevDrvFltk::read_image( void* user, unsigned char* p, int x, int y, unsigned w, unsigned h ) +{ + fl_read_image(p,x,y,w,h,false); +} + +void cmGrDevDrvFltk::draw_image( void* user, const unsigned char* p, int x, int y, unsigned w, unsigned h ) +{ + fl_draw_image(p,x,y,w,h,3,0); +} + +bool cmGrDevDrvFltk::is_initialized() const +{ return true; } + + +//-------------------------------------------------------------------------------------- +void testKey() +{ + int k = Fl::event_key(); + + printf("code:0x%x text:%s ",k,Fl::event_text()); + + bool fl = Fl::event_state() & FL_NUM_LOCK; + + if( fl ) + printf("KP "); + + // if this key has an ASCII printable symbol + if( kSpaceGrId <= k && k <= kTildeGrId ) + { + char ch = Fl::event_text()[0]; + + // correct for an apparent bug in FLTK + // which get's the case of the characters + // wrong. + if( ('A' <= ch && ch <= 'Z') ) + ch = tolower(ch); + else + if(('a' <= ch && ch <= 'z' ) ) + ch = toupper(ch); + + + printf("Known: ASCII '%c'.\n", ch); + return; + } + + const char* str = NULL; + + if( str == NULL ) + switch( k ) + { + case 0xffaa: str="KP_Mult"; break; + case 0xffab: str="KP_Plus"; break; + case 0xffad: str="KP_Minus"; break; + case 0xffae: str="KP_DecPt"; break; + case 0xffaf: str="KP_Div"; break; + case 0xffb1: str="KP_1"; break; + case 0xffb2: str="KP_2"; break; + case 0xffb3: str="KP_3"; break; + case 0xffb4: str="KP_4"; break; + case 0xffb5: str="KP_5"; break; + case 0xffb6: str="KP_6"; break; + case 0xffb7: str="KP_7"; break; + case 0xffb8: str="KP_8"; break; + case 0xffb9: str="KP_9"; break; + case 0xffbd: str="KP_Equal"; break; + + case 0xffbe: str="F1"; break; + case 0xffbf: str="F2"; break; + case 0xffc0: str="F3"; break; + case 0xffc1: str="F4"; break; + case 0xffc2: str="F5"; break; + case 0xffc3: str="F6"; break; + case 0xffc4: str="F7"; break; + case 0xffc5: str="F8"; break; + case 0xffc6: str="F9"; break; + case 0xffc7: str="F10"; break; + case 0xffc8: str="F11"; break; + case 0xffc9: str="F12"; break; + + case FL_Home: str="Home"; break; + case FL_Page_Up: str="PgUp"; break; + case FL_Delete: str="Del"; break; + case FL_End: str="End"; break; + case FL_Page_Down: str="PgDn"; break; + case FL_Left: str="Left"; break; + case FL_Up: str="Up"; break; + case FL_Right: str="Right"; break; + case FL_Down: str="Down"; break; + case FL_Insert: str="Insert"; break; + + case FL_Escape: str="Esc"; break; + case FL_BackSpace: str="BS"; break; + case FL_Tab: str="Tab"; break; + case FL_Enter: str="Enter"; break; + case FL_Print: str="Print"; break; + case FL_Scroll_Lock: str="ScrLck";break; + case FL_Pause: str="Pause"; break; + case FL_Shift_L: str="L-Shift"; break; + case FL_Shift_R: str="R-Shift"; break; + case FL_Control_L: str="L_Ctrl"; break; + case FL_Control_R: str="R_Ctrl"; break; + case FL_Caps_Lock: str="CapLck"; break; + case FL_Alt_L: str="L_Alt"; break; + case FL_Alt_R: str="R_Alt"; break; + case FL_Meta_L: str="L_Super"; break; + case FL_Meta_R: str="R_Super"; break; + case FL_Menu: str="Menu"; break; + case FL_Num_Lock: str="NumLock"; break; + case FL_KP_Enter: str="KP_Enter"; break; + } + + printf("%s\n", (str==NULL ? "" : str)); + +} + +cmGrViewFltk::keyMap_t cmGrViewFltk::_keymap[] = +{ + { 0, 0, 0, kInvalidKeyCodeGrId }, + { 1, 0, 0, kInvalidKeyCodeGrId }, + { 2, 0, 0, kInvalidKeyCodeGrId }, + { 3, 0, 0, kInvalidKeyCodeGrId }, + { 4, 0, 0, kInvalidKeyCodeGrId }, + { 5, FL_Home, 0, kHomeGrId}, + { 6, FL_Page_Up, 0, kPageUpGrId}, + { 7, FL_End, 0, kEndGrId}, + { 8, FL_BackSpace, 8, kBackSpaceGrId }, + { 9, FL_Tab, 9, kTabGrId }, + + { 10, FL_Page_Down, 0, kPageDownGrId}, + { 11, FL_Left, 0, kLeftGrId}, + { 12, FL_Up, 0, kUpGrId}, + { 13, FL_Enter, 13, kEnterGrId }, + { 14, FL_Right, 0, kRightGrId}, + { 15, FL_Down, 0, kDownGrId}, + { 16, FL_Insert, 0, kInsertGrId}, + { 17, FL_Print, 0, kPrintGrId}, + { 18, FL_Scroll_Lock, 0, kScrollLockGrId}, + { 19, FL_Pause, 0, kPauseGrId}, + { 20, FL_Menu, 0, kMenuGrId}, + + + { 21, FL_Shift_L, 0, kLShiftGrId}, + { 22, FL_Shift_R, 0, kRShiftGrId}, + { 23, FL_Control_L, 0, kLCtrlGrId}, + { 24, FL_Control_R, 0, kRCtrlGrId}, + { 25, FL_Alt_L, 0, kLAltGrId}, + { 26, FL_Alt_R, 0, kRAltGrId}, + { 27, FL_Escape, 27, kEscapeGrId }, + { 28, FL_Meta_L, 0, kLSuperGrId}, + { 29, FL_Meta_R, 0, kRSuperGrId}, + { 30, FL_Num_Lock, 0, kNumLockGrId}, + { 31, FL_Caps_Lock, 0, kCapsLockGrId}, + + + { 32, 32, 32, kSpaceGrId }, + { 33, 33, 33, kExclMarkGrId }, + { 34, 34, 34, kDQuoteGrId }, + { 35, 35, 35, kPoundGrId }, + { 36, 36, 36, kDollarGrId }, + { 37, 37, 37, kPercentGrId }, + { 38, 38, 38, kAmpersandGrId }, + { 39, 39, 39, kApostropheGrId }, + + { 40, 40, 40, kLParenGrId }, + { 41, 41, 41, kRParenGrId }, + { 42, 42, 42, kAsteriskGrId }, + { 43, 43, 43, kPlusGrId }, + { 44, 44, 44, kCommaGrId }, + { 45, 45, 45, kHyphenGrId }, + { 46, 46, 46, kPeriodGrId }, + { 47, 47, 47, kForwardSlashGrId }, + { 48, 48, 48, k0GrId }, + { 49, 49, 49, k1GrId }, + + { 50, 50, 50, k2GrId }, + { 51, 51, 51, k3GrId }, + { 52, 52, 52, k4GrId }, + { 53, 53, 53, k5GrId }, + { 54, 54, 54, k6GrId }, + { 55, 55, 55, k7GrId }, + { 56, 56, 56, k8GrId }, + { 57, 57, 57, k9GrId }, + { 58, 58, 58, kColonGrId }, + { 59, 59, 59, kSemiColonGrId }, + + { 60, 60, 60, kLesserGrId }, + { 61, 61, 61, kEqualGrId }, + { 62, 62, 62, kGreaterGrId }, + { 63, 63, 63, kQMarkGrId }, + { 64, 64, 64, kAtGrId }, + { 65, 65, 65, kA_GrId }, + { 66, 66, 66, kB_GrId }, + { 67, 67, 67, kC_GrId }, + { 68, 68, 68, kD_GrId }, + { 69, 69, 69, kE_GrId }, + + { 70, 70, 70, kF_GrId }, + { 71, 71, 71, kG_GrId }, + { 72, 72, 72, kH_GrId }, + { 73, 73, 73, kI_GrId }, + { 74, 74, 74, kJ_GrId }, + { 75, 75, 75, kK_GrId }, + { 76, 76, 76, kL_GrId }, + { 77, 77, 77, kM_GrId }, + { 78, 78, 78, kN_GrId }, + { 79, 79, 79, kO_GrId }, + + { 80, 80, 80, kP_GrId }, + { 81, 81, 81, kQ_GrId }, + { 82, 82, 82, kR_GrId }, + { 83, 83, 83, kS_GrId }, + { 84, 84, 84, kT_GrId }, + { 85, 85, 85, kU_GrId }, + { 86, 86, 86, kV_GrId }, + { 87, 87, 87, kW_GrId }, + { 88, 88, 88, kX_GrId }, + { 89, 89, 89, kY_GrId }, + + { 90, 90, 90, kZ_GrId }, + { 91, 91, 91, kLBracketGrId }, + { 92, 92, 92, kBackSlashGrId }, + { 93, 93, 93, kRBracketGrId }, + { 94, 94, 94, kCaretGrId }, + { 95, 95, 95, kUnderScoreGrId }, + { 96, 96, 96, kAccentGrId }, + { 97, 97, 97, ka_GrId }, + { 98, 98, 98, kb_GrId }, + { 99, 99, 99, kc_GrId }, + + { 100, 100, 100, kd_GrId }, + { 101, 101, 101, ke_GrId }, + { 102, 102, 102, kf_GrId }, + { 103, 103, 103, kg_GrId }, + { 104, 104, 104, kh_GrId }, + { 105, 105, 105, ki_GrId }, + { 106, 106, 106, kj_GrId }, + { 107, 107, 107, kk_GrId }, + { 108, 108, 108, kl_GrId }, + { 109, 109, 109, km_GrId }, + + { 110, 110, 110, kn_GrId }, + { 111, 111, 111, ko_GrId }, + { 112, 112, 112, kp_GrId }, + { 113, 113, 113, kq_GrId }, + { 114, 114, 114, kr_GrId }, + { 115, 115, 115, ks_GrId }, + { 116, 116, 116, kt_GrId }, + { 117, 117, 117, ku_GrId }, + { 118, 118, 118, kv_GrId }, + { 119, 119, 119, kw_GrId }, + + { 120, 120, 120, kx_GrId }, + { 121, 121, 121, ky_GrId }, + { 122, 122, 122, kz_GrId }, + { 123, 123, 123, kLBraceGrId }, + { 124, 124, 124, kPipeGrId }, + { 125, 125, 125, kRBraceGrId }, + { 126, 126, 126, kTildeGrId }, + { 127, FL_Delete, 127, kDeleteGrId }, + + { 128, 0xffaa, 42, kNP_MultGrId }, + { 129, 0xffab, 43, kNP_PlusGrId }, + { 130, 0xffad, 45, kNP_MinusGrId }, + { 131, 0xffae, 46, kNP_DecPtGrId}, + { 132, 0xffaf, 47, kNP_DivGrId}, + { 133, 0xffb0, 48, kNP_0GrId}, + { 134, 0xffb1, 49, kNP_1GrId}, + { 135, 0xffb2, 50, kNP_2GrId}, + { 136, 0xffb3, 51, kNP_3GrId}, + { 137, 0xffb4, 52, kNP_4GrId}, + { 138, 0xffb5, 53, kNP_5GrId}, + { 139, 0xffb6, 54, kNP_6GrId}, + { 140, 0xffb7, 55, kNP_7GrId}, + { 141, 0xffb8, 56, kNP_8GrId}, + { 142, 0xffb9, 57, kNP_9GrId}, + { 143, 0xffbd, 61, kNP_EqualGrId}, + { 144, FL_KP_Enter, 13, kNP_EnterGrId}, + { 145, 0xffbe, 0, kFunc_1GrId}, + { 146, 0xffbf, 0, kFunc_2GrId}, + { 147, 0xffc0, 0, kFunc_3GrId}, + { 148, 0xffc1, 0, kFunc_4GrId}, + { 149, 0xffc2, 0, kFunc_5GrId}, + { 150, 0xffc3, 0, kFunc_6GrId}, + { 151, 0xffc4, 0, kFunc_7GrId}, + { 152, 0xffc5, 0, kFunc_8GrId}, + { 153, 0xffc6, 0, kFunc_9GrId}, + { 154, 0xffc7, 0, kFunc_10GrId}, + { 155, 0xffc8, 0, kFunc_11GrId}, + { 156, 0xffc9, 0, kFunc_12GrId}, + { 157, 0x1008ff03, 0, kBrightUpGrId}, + { 158, 0x1008ff02, 0, kBrightDnGrId}, + { 159, 0xef16, 0, kAudio_PrevGrId}, + { 160, 0xef14, 0, kAudio_PlayGrId}, + { 161, 0xef17, 0, kAudio_NextGrId}, + { 162, 0xef12, 0, kAudio_MuteGrId}, + { 163, 0xef11, 0, kAudio_DnGrId }, + { 164, 0xef13, 0, kAudio_UpGrId }, + { 165, 0x1008ff2c, 0, kEjectGrId }, + { cmInvalidIdx, cmInvalidId, 0, kInvalidKeyCodeGrId } +}; + + +const cmGrViewFltk::keyMap_t* cmGrViewFltk::_getGrKeyCode( unsigned fltk_code ) + { + if( 32 <= fltk_code && fltk_code <= 126 ) + return _keymap + fltk_code; + + unsigned i; + for(i=0; i<32; ++i) + if( _keymap[i].fltk_code == fltk_code ) + return _keymap + i; + + for(i=127; _keymap[i].idx != cmInvalidIdx; ++i) + if( _keymap[i].fltk_code == fltk_code ) + return _keymap + i; + + return NULL; + } + +cmGrViewFltk::cmGrViewFltk( cmCtx_t* ctx, cmGrH_t grH, int x, int y, int w, int h ) + : Fl_Widget(x,y,w,h),_grH(grH),_dcH(cmGrDcNullHandle) +{ + cmGrDevCtxCreate( ctx, &_dcH, &_dd.d, &_dd, x, y, w, h ); +} + +cmGrViewFltk::~cmGrViewFltk() +{ cmGrDevCtxDestroy(&_dcH); } + +unsigned eventModKeyFlags() +{ + unsigned flags = 0; + + if( Fl::event_alt() ) + flags |= kAltKeyGrFl; + + if( Fl::event_ctrl() ) + flags |= kCtlKeyGrFl; + + if( Fl::event_shift() ) + flags |= kShiftKeyGrFl; + + switch( Fl::event_button() ) + { + case FL_LEFT_MOUSE: flags |= kMsLBtnGrFl; break; + case FL_RIGHT_MOUSE: flags |= kMsRBtnGrFl; break; + case FL_MIDDLE_MOUSE: flags |= kMsCBtnGrFl; break; + } + + return flags; +} + +cmGrKeyCodeId_t cmGrViewFltk::_eventKeyCode() +{ + const keyMap_t* kmp; + if(( kmp = _getGrKeyCode(Fl::event_key())) != NULL ) + return kmp->gr_code; + + return kInvalidKeyCodeGrId; +} + + +int cmGrViewFltk::handle(int event) +{ + bool fl = false; + + switch(event) + { + case FL_ENTER: // req'd to receive FL_MOVE event + break; + + case FL_LEAVE: + break; + + case FL_PUSH: + fl = cmGrEvent(_grH, kMsDownGrFl | eventModKeyFlags(), _eventKeyCode(), Fl::event_x(),Fl::event_y()); + break; + + case FL_RELEASE: + fl = cmGrEvent(_grH, kMsUpGrFl | eventModKeyFlags(), _eventKeyCode(), Fl::event_x(),Fl::event_y()); + break; + + case FL_DRAG: + fl = cmGrEvent(_grH, kMsDragGrFl | eventModKeyFlags(), _eventKeyCode(), Fl::event_x(),Fl::event_y()); + break; + + case FL_MOVE: + fl = cmGrEvent(_grH, kMsMoveGrFl | eventModKeyFlags(), _eventKeyCode(), Fl::event_x(),Fl::event_y()); + break; + + case FL_FOCUS: + Fl::focus(this); + break; + + case FL_UNFOCUS: + break; + + case FL_KEYDOWN: + fl = cmGrEvent(_grH, kKeyDnGrFl | eventModKeyFlags(), _eventKeyCode(), Fl::event_x(),Fl::event_y()); + break; + + case FL_KEYUP: + fl = cmGrEvent(_grH, kKeyUpGrFl | eventModKeyFlags(), _eventKeyCode(), Fl::event_x(),Fl::event_y()); + break; + + default: + return Fl_Widget::handle(event); + } + + if( fl ) + redraw(); + + return 1; +} + +void cmGrViewFltk::resize(int x, int y, int w, int h ) +{ + cmGrPExt_t pext0,pext1; + + cmGrPExtSet(&pext0,this->x(),this->y(),this->w(),this->h()); + cmGrPExtSet(&pext1,x,y,w,h); + + if( cmGrPExtIsEqual(&pext0,&pext1)==false ) + { + // must call base to make size change + Fl_Widget::resize(x,y,w,h); + + //printf("resize: %i %i %i %i : %i %i %i %i\n",x,y,w,h,this->x(),this->y(),this->w(),this->h()); + + if( cmGrIsValid( _grH ) ) + { + //cmGrDevCtxResize( _dcH, x, y, w, h ); + cmGrSetPhysExtents( _grH, x, y, w, h); + } + } + +} + + +void cmGrViewFltk::setGrH( cmGrH_t grH ) +{ _grH=grH;} + +void cmGrViewFltk::draw() +{ + /* + fl_line_style(FL_SOLID,1,NULL); + fl_color(FL_RED); + + cmGrPExt_t pext; + cmGrPhysExtents(_grH, &pext ); + + fl_rect(pext.loc.x,pext.loc.y,pext.sz.w,pext.sz.h); + + fl_line(x(),y(),x()+w()-1,y()+h()-1); + fl_line(x()+w()-1,y(),x(),y()+h()-1); + */ + + fl_push_clip(x(),y(),w(),h()); + + fl_color(FL_BACKGROUND_COLOR); + fl_rectf(x(),y(),w(),h()); + + + if( cmGrIsValid(_grH) ) + { + cmGrPExt_t pext0,pext1; + + //cmGrPExtSet(&pext0,this->x(),this->y(),this->w(),this->h()); + cmGrPhysExtents(_grH, &pext0 ); + cmGrDevCtxSize( _dcH, &pext1 ); + + if( cmGrPExtIsEqual(&pext0,&pext1)==false ) + //cmGrDevCtxResize(_dcH, this->x(), this->y(), this->w(),this->h() ); + cmGrDevCtxResize(_dcH, cmGrPExtL(&pext0), cmGrPExtT(&pext0), cmGrPExtW(&pext0), cmGrPExtH(&pext0) ); + + cmGrDevCtxBeginDraw(_dcH); + cmGrDraw(_grH,_dcH); + cmGrDevCtxEndDraw(_dcH); + cmGrDevCtxDraw(_dcH); + } + + fl_pop_clip(); + +} + +//-------------------------------------------------------------------------------------- +cmGrPageFltk::cmGrPageFltk( cmCtx_t* ctx, cmGrPgH_t pgH, int x, int y, int w, int h ) + : Fl_Group(x,y,w,h),_ctx(ctx),_pgH(pgH),_dcH(cmGrDcNullHandle), + _vwV(NULL),_vwN(0) +{ + end(); + resizable(NULL); + cmGrDevCtxCreate( ctx, &_dcH, &_dd.d, &_dd, x, y, w, h ); +} + +cmGrPageFltk::~cmGrPageFltk() +{ + if( _vwV != NULL ) + { + int i, n = _vwN; + for(i=0; i= _vwN ) + { + assert( vwIdx == _vwN ); + _vwV = cmMemResizeP(cmGrViewFltk*,_vwV,++_vwN); + + _vwV[ vwIdx ] = new cmGrViewFltk( _ctx, grH, pext.loc.x, pext.loc.y, pext.sz.w, pext.sz.h ); + add(_vwV[vwIdx]); + + } + else + { + _vwV[vwIdx]->setGrH(grH); + cmGrSetPhysExtentsE(grH,&pext); + } + +} + +void cmGrPageFltk::destroyView( unsigned vwIdx ) +{ + assert( vwIdx < _vwN ); + delete _vwV[vwIdx]; + _vwV = NULL; +} + +cmGrDcH_t cmGrPageFltk::devCtxHandle() +{ return _dcH; } + +cmGrViewFltk* cmGrPageFltk::viewWidget( unsigned vwIdx ) +{ + assert( vwIdx < _vwN ); + + if( vwIdx < _vwN ) + return _vwV[vwIdx]; + + return NULL; +} + + +void cmGrPageFltk::resize(int x, int y, int w, int h ) +{ + cmGrPExt_t pext; + + x+=1; + y+=1; + w-=2; + h-=2; + + Fl_Group::resize(x,y,w,h); + + // We would like to call cmGrPageLayout() here but it is not + // possible because we cannot guarantee that we can get + // an offscreen FLTK drawing context which needed to measure the + // size of text strings given a paricular font. Instead we defer + // to the draw() routine where we know the drawing context is + // valid. + + cmGrPExtSet(&pext,x,y,w,h); + cmGrPageResize(_pgH,&pext,_dcH); +} + +void cmGrPageFltk::draw() +{ + fl_color(FL_BACKGROUND_COLOR); + fl_rectf(x(),y(),w(),h()); + + // if the dc is valid and the layout changed + if( cmGrDevCtxIsValid(_dcH)) + { + if( cmGrPageLayout(_pgH,_dcH) ) + { + cmGrDevCtxResize( _dcH, x(), y(), w(), h() ); + + unsigned vwIdx; + + for(vwIdx=0; vwIdx<_vwN; ++vwIdx) + { + cmGrVwH_t vwH = cmGrPageViewHandle( _pgH, vwIdx ); + cmGrViewFltk* vp = _vwV[vwIdx]; + cmGrPExt_t p0ext,p1ext; + + assert( cmGrViewIsValid(vwH) ); + + // get the size of the view + cmGrViewPExt( vwH, &p0ext ); + + // get the size of the FLTK widget containing the view + cmGrPExtSet(&p1ext,vp->x(),vp->y(),vp->w(),vp->h()); + + // if the views are different sizes then + if( !cmGrPExtIsEqual(&p0ext,&p1ext) ) + vp->resize(p0ext.loc.x,p0ext.loc.y,p0ext.sz.w,p0ext.sz.h); + } + } + + cmGrDevCtxBeginDraw(_dcH); + cmGrPageDraw(_pgH,_dcH); + cmGrDevCtxEndDraw(_dcH); + cmGrDevCtxDraw(_dcH); + } + + draw_children(); + +} + + +//-------------------------------------------------------------------------------------- + +cmGrPlotFltk::cmGrPlotFltk( cmCtx_t* ctx, int x, int y, int w, int h, int rn, int cn, int textSz ) + : Fl_Group(x,y,w,h,NULL), + _pgH(cmGrPgNullHandle),_plH(cmGrPlNullHandle), + _pg(NULL),_ctl_grp(NULL),_usr_grp(NULL),_status(NULL), + _hsb(NULL),_vsb(NULL), + _gx(NULL),_gy(NULL),_lx(NULL),_ly(NULL), + _s0x(NULL),_s0y(NULL),_s1x(NULL),_s1y(NULL),_sdx(NULL),_sdy(NULL), + _textSz(textSz) +{ + end(); + + // create the platform indendent page + cmGrPageCreate(ctx,&_pgH,_s_cmGrCallback,this); + + // create the ctl panel + add(_ctl_grp = _create_ctls()); + + // create the scroll bars + _create_scroll_bars(); + + // create the FLTK page + add(_pg = new cmGrPageFltk(ctx,_pgH,0,0,10,10)); + + // turn off automatic resizing - all resizing is done + // explicitly in _layout(). + resizable(NULL); + + // create the plot object manager + cmGrPlotCreate(ctx,&_plH); + cmGrPlotSetCb(_plH,_s_cmGrPlotObjCbFunc,this ); + + initViews(rn,cn); + + // layout the window + _layout(); + +} + +cmGrPlotFltk::~cmGrPlotFltk() +{ + cmGrPageDestroy(&_pgH); + cmGrPlotDestroy(&_plH); +} + +void cmGrPlotFltk::resize(int x, int y, int w, int h ) +{ + Fl_Group::resize(x,y,w,h); + _layout(); +} + +cmGrPgH_t cmGrPlotFltk::pageHandle() { return _pgH; } +cmGrPlH_t cmGrPlotFltk::plotHandle() { return _plH; } +cmGrDcH_t cmGrPlotFltk::dcHandle() { return _pg->devCtxHandle(); } + +void cmGrPlotFltk::initViews( int rn, int cn ) +{ + if( cmGrPageIsValid(_pgH) && _pg != NULL ) + { + cmGrPExt_t pext; + cmGrPExtSet(&pext,_pg->x(),_pg->y(),_pg->w(),_pg->h()); + + cmGrPageInit( _pgH, &pext, rn, cn, _pg->devCtxHandle() ); + } +} + +void cmGrPlotFltk::setStatusText( const cmChar_t* text ) +{ _status->value(text); } + + +void cmGrPlotFltk::on_button( unsigned id ) +{ + cmGrH_t grH; + + if( !cmGrIsValid(grH = _getFocusedView()) ) + return; + + switch( id ) + { + case kShowAllId: + cmGrZoom( grH, kShowAllGrFl | kXAxisGrFl | kYAxisGrFl ); + break; + + case kZoomInId: + cmGrZoom( grH, kZoomInGrFl | kXAxisGrFl | kYAxisGrFl | kSelectGrFl ); + break; + + case kZoomInXId: + cmGrZoom( grH, kZoomInGrFl | kXAxisGrFl | kSelectGrFl ); + break; + + case kZoomInYId: + cmGrZoom( grH, kZoomInGrFl | kYAxisGrFl | kSelectGrFl ); + break; + + case kZoomOutId: + cmGrZoom( grH, kXAxisGrFl | kYAxisGrFl | kSelectGrFl ); + break; + + case kZoomOutXId: + cmGrZoom( grH, kXAxisGrFl | kSelectGrFl ); + break; + + case kZoomOutYId: + cmGrZoom( grH, kYAxisGrFl | kSelectGrFl ); + break; + + case kReportId: + cmGrReport( grH, NULL ); + break; + } + +} + +void cmGrPlotFltk::on_scroll( Fl_Scrollbar* sb, unsigned id ) +{ + bool fl = false; + cmGrH_t grH = cmGrNullHandle; + + if( cmGrIsValid(grH = _getFocusedView()) ) + { + switch( id ) + { + case kHScrollId: + fl = cmGrSetScrollH( grH, sb->value() ); + break; + + case kVScrollId: + fl = cmGrSetScrollV( grH, (sb->maximum() - sb->slider_size()) + 1 - sb->value() ); + break; + } + } + + if( fl ) + { + _pg->redraw(); + } + +} + +void cmGrPlotFltk::on_view_create( unsigned viewIdx ) +{ + if( _pg != NULL ) + _pg->createView(viewIdx); +} + +void cmGrPlotFltk::on_view_destroy( unsigned viewIdx ) +{ + if( _pg != NULL ) + _pg->destroyView(viewIdx); +} + + +void cmGrPlotFltk::rpt_local_pt( cmGrH_t grH ) +{ + int bufCharCnt = 31; + cmChar_t buf[ bufCharCnt ]; + cmGrVwH_t vwH = cmGrPageViewHandle( _pgH, cmGrId(grH) ); + const cmChar_t* cp = NULL ; + + if( _lx != NULL ) + { + _lx->value( cp = cmGrViewValue( vwH, kLocalX_VwId, buf, bufCharCnt)); + _lx->redraw(); + } + if( _ly != NULL ) + { + _ly->value( cp = cmGrViewValue( vwH, kLocalY_VwId, buf, bufCharCnt)); + _ly->redraw(); + } +} + +void cmGrPlotFltk::rpt_global_pt( cmGrH_t grH ) +{ + int bufCharCnt = 31; + cmChar_t buf[ bufCharCnt ]; + cmGrVwH_t vwH = cmGrPageViewHandle( _pgH, cmGrId(grH) ); + + if( _gx != NULL ) + { + _gx->value( cmGrViewValue( vwH, kGlobalX_VwId, buf, bufCharCnt)); + _gx->redraw(); + } + if( _gy != NULL ) + { + _gy->value( cmGrViewValue( vwH, kGlobalY_VwId, buf, bufCharCnt)); + _gy->redraw(); + } +} + +void cmGrPlotFltk::on_phys_change( cmGrH_t grH ) +{ + cmGrViewFltk* vwp = _pg->viewWidget( cmGrId( grH ) ); + if( vwp != NULL ) + { + cmGrPExt_t pext; + cmGrPhysExtents(grH,&pext); + vwp->resize( pext.loc.x, pext.loc.y, pext.sz.w, pext.sz.h ); + } +} + +void cmGrPlotFltk::on_view_change(cmGrH_t grH) +{ + unsigned vwIdx = cmGrId(grH); + cmGrViewFltk* vwp; + + if( cmGrViewHasFocus( cmGrPageGrHandleToView(_pgH,grH) ) ) + { + cmGrPSz_t tot,vis,max; + cmGrPPt_t pos; + + _showHideScrollBars(); + + cmGrScrollExtents(grH,&tot,&vis,&max,&pos); + + _hsb->value(pos.x,vis.w,0,tot.w); + + pos.y = (tot.h - vis.h) + 1 - pos.y; // invert vert slider + _vsb->value(pos.y,vis.h,0,tot.h); + + } + + // update the hash labels + if((vwp = _pg->viewWidget( vwIdx )) != NULL ) + vwp->redraw(); +} + +void cmGrPlotFltk::on_select_change(cmGrH_t grH) +{ + cmGrViewFltk* vwp; + + unsigned vwIdx = cmGrId(grH); + + if( cmGrViewHasFocus( cmGrPageGrHandleToView(_pgH,grH) ) ) + { + int bufCharCnt = 31; + cmChar_t buf[ bufCharCnt ]; + cmGrVwH_t vwH = cmGrPageViewHandle( _pgH, vwIdx ); + + _s0x->value(cmGrViewValue( vwH, kSelX0_VwId, buf, bufCharCnt)); _s0x->redraw(); + _s0y->value(cmGrViewValue( vwH, kSelY0_VwId, buf, bufCharCnt)); _s0y->redraw(); + _s1x->value(cmGrViewValue( vwH, kSelX1_VwId, buf, bufCharCnt)); _s1x->redraw(); + _s1y->value(cmGrViewValue( vwH, kSelY1_VwId, buf, bufCharCnt)); _s1y->redraw(); + _sdx->value(cmGrViewValue( vwH, kSelW_VwId, buf, bufCharCnt)); _sdx->redraw(); + _sdy->value(cmGrViewValue( vwH, kSelH_VwId, buf, bufCharCnt)); _sdy->redraw(); + } + + if((vwp = _pg->viewWidget( vwIdx )) != NULL ) + vwp->redraw(); + +} + +void cmGrPlotFltk::on_focused_plot( cmGrH_t grH) +{ + on_view_change(grH); + redraw(); +} + +void cmGrPlotFltk::on_key_event( cmGrH_t grH, unsigned eventFlags, cmGrKeyCodeId_t keycode ) +{ + cmGrPlotKeyEvent( _plH, grH, eventFlags, keycode ); +} + +bool cmGrPlotFltk::on_plot_object( cmGrPlotCbArg_t* arg ) +{ return true; } + + + +void cmGrPlotFltk::_layout() +{ + // position the vertical scroll bar + _vsb->position(x()+w()-_vsb->w(),y()); + _vsb->size(_vsb->w(),h()-_hsb->h()); + + // position the horizontal scroll bar + _hsb->position(x(),y()+h()-_hsb->h()); + _hsb->size(w()-_vsb->w(),_hsb->h()); + + // position the ctl panel + _ctl_grp->position(x(),_hsb->y()-_ctl_grp->h()); + _ctl_grp->size(w()-_vsb->w(),_ctl_grp->h()); + + // position the user programmable group + _usr_grp->size(_ctl_grp->w()-_usr_grp->x()-1,_usr_grp->h()); + + // position the status ctl + _status->size(_ctl_grp->w()-_status->x()-1,_status->h()); + + // position the page + _pg->resize(x(),y(),w()-_vsb->w(),_ctl_grp->y()-y()); +} + + +Fl_Group* cmGrPlotFltk::_create_ctls() +{ + Fl_Boxtype outBoxFlags = FL_FLAT_BOX; + + Fl_Group* grp = new Fl_Group(0,0,10,10); + grp->user_data(this); + grp->box(FL_FLAT_BOX); + grp->end(); + + int x0 = kVBord; + int y0 = kHBord; + int x1 =0; + int x = x0; + int y = y0; + + Fl_Button* btn; + + btn = new Fl_Button(x,y,kBtnW,kBtnH,"All"); + btn->callback(_s_ctl_cb,kShowAllId); + btn->labelsize(_textSz); + grp->add(btn); + x += kBtnW+kVBord; + + btn = new Fl_Button(x,y,kBtnW,kBtnH,"In"); + btn->callback(_s_ctl_cb,kZoomInId); + btn->labelsize(_textSz); + grp->add(btn); + x += kBtnW+kVBord; + + btn = new Fl_Button(x,y,kBtnW,kBtnH,"In X"); + btn->callback(_s_ctl_cb,kZoomInXId); + btn->labelsize(_textSz); + grp->add(btn); + x += kBtnW+kVBord; + + btn = new Fl_Button(x,y,kBtnW,kBtnH,"Out X"); + btn->callback(_s_ctl_cb,kZoomOutXId); + btn->labelsize(_textSz); + grp->add(btn); + x += kBtnW+kLblW+kVBord; + + _gx = new Fl_Output(x,y+1,kOutW,kBtnH-2,"gx"); + _gx->box(outBoxFlags); + _gx->color(FL_LIGHT2); + _gx->labelsize(_textSz); + _gx->textsize(_textSz); + grp->add(_gx); + x += kOutW+kLblW+kVBord; + + _lx = new Fl_Output(x,y+1,kOutW,kBtnH-2,"lx"); + _lx->box(outBoxFlags); + _lx->color(FL_LIGHT2); + _lx->labelsize(_textSz); + _lx->textsize(_textSz); + grp->add(_lx); + x += kOutW+kLblW+kVBord; + + _s0x = new Fl_Output(x,y+1,kOutW,kBtnH-2,"sx"); + _s0x->box(outBoxFlags); + _s0x->color(FL_LIGHT2); + _s0x->labelsize(_textSz); + _s0x->textsize(_textSz); + grp->add(_s0x); + x += kOutW+kLblW+kVBord; + + _s1x = new Fl_Output(x,y+1,kOutW,kBtnH-2,"sx"); + _s1x->box(outBoxFlags); + _s1x->color(FL_LIGHT2); + _s1x->labelsize(_textSz); + _s1x->textsize(_textSz); + grp->add(_s1x); + x += kOutW+kLblW+kVBord; + + _sdx = new Fl_Output(x,y+1,kOutW,kBtnH-2,"dsx"); + _sdx->box(outBoxFlags); + _sdx->color(FL_LIGHT2); + _sdx->labelsize(_textSz); + _sdx->textsize(_textSz); + grp->add(_sdx); + x += kOutW+kVBord; + + x1 = x; + x = x0; + y += kBtnH+kHBord; + + btn = new Fl_Button(x,y,kBtnW,kBtnH,"Rpt"); + btn->callback(_s_ctl_cb,kReportId); + btn->labelsize(_textSz); + grp->add(btn); + x += kBtnW+kVBord; + + btn = new Fl_Button(x,y,kBtnW,kBtnH,"Out"); + btn->callback(_s_ctl_cb,kZoomOutId); + btn->labelsize(_textSz); + grp->add(btn); + x += kBtnW+kVBord; + + btn = new Fl_Button(x,y,kBtnW,kBtnH,"In Y"); + btn->callback(_s_ctl_cb,kZoomInYId); + btn->labelsize(_textSz); + grp->add(btn); + x += kBtnW+kVBord; + + btn = new Fl_Button(x,y,kBtnW,kBtnH,"Out Y"); + btn->callback(_s_ctl_cb,kZoomOutYId); + btn->labelsize(_textSz); + grp->add(btn); + x += kBtnW+kLblW+kVBord; + + + _gy = new Fl_Output(x,y+1,kOutW,kBtnH-2,"gy"); + _gy->box(outBoxFlags); + _gy->color(FL_LIGHT2); + _gy->labelsize(_textSz); + _gy->textsize(_textSz); + grp->add(_gy); + x += kOutW+kLblW+kVBord; + + _ly = new Fl_Output(x,y+1,kOutW,kBtnH-2,"ly"); + _ly->box(outBoxFlags); + _ly->color(FL_LIGHT2); + _ly->labelsize(_textSz); + _ly->textsize(_textSz); + grp->add(_ly); + x += kOutW+kLblW+kVBord; + + _s0y = new Fl_Output(x,y+1,kOutW,kBtnH-2,"sy"); + _s0y->box(outBoxFlags); + _s0y->color(FL_LIGHT2); + _s0y->labelsize(_textSz); + _s0y->textsize(_textSz); + grp->add(_s0y); + x += kOutW+kLblW+kVBord; + + _s1y = new Fl_Output(x,y+1,kOutW,kBtnH-2,"sy"); + _s1y->box(outBoxFlags); + _s1y->color(FL_LIGHT2); + _s1y->labelsize(_textSz); + _s1y->textsize(_textSz); + grp->add(_s1y); + x += kOutW+kLblW+kVBord; + + _sdy = new Fl_Output(x,y+1,kOutW,kBtnH-2,"dsy"); + _sdy->box(outBoxFlags); + _sdy->color(FL_LIGHT2); + _sdy->labelsize(_textSz); + _sdy->textsize(_textSz); + grp->add(_sdy); + x += kOutW+kVBord; + + + x1 = cmMax(x1,x); + x = x0; + y += kBtnH+kHBord; + + _status = new Fl_Output(x,y+1,x1-x0,kBtnH-2); + _status->box(FL_FLAT_BOX); + _status->color(FL_LIGHT2); + _status->textsize(_textSz); + grp->add(_status); + + _usr_grp = new Fl_Group(x1,y0,x1-x0,y-y0); + _usr_grp->end(); + _usr_grp->box(FL_FLAT_BOX); + grp->add(_usr_grp); + + x = x0; + y += kBtnH+kHBord; + + + grp->resizable(NULL); + grp->resize(grp->x(),grp->y(),x1-grp->x(),y-grp->y()); + + return grp; +} + +void cmGrPlotFltk::_create_scroll_bars() +{ + + // vert scroll bar + _vsb = new Fl_Scrollbar(x()+w()-kScrD, y(), kScrD, h()-kScrD, NULL); + _vsb->type(FL_VERTICAL); + _vsb->callback(_s_ctl_cb,kVScrollId); + add(_vsb); + + // horz scrollback + _hsb = new Fl_Scrollbar(x(),y()+h()-kScrD, w()-kScrD, kScrD, NULL); + _hsb->type(FL_HORIZONTAL); + _hsb->callback(_s_ctl_cb,kHScrollId); + add(_hsb); + + _showHideScrollBars(); +} + +void cmGrPlotFltk::_showHideScrollBars() +{ + bool hfl = true, vfl=true; + cmGrH_t grH; + + if( cmGrIsValid(grH = _getFocusedView()) == false ) + hfl = vfl = false; + else + { + cmGrPSz_t tot, vis; + cmGrScrollExtents(grH, &tot, &vis, NULL, NULL ); + vfl = tot.h != vis.h; + hfl = tot.w != vis.w; + } + + if( hfl != _hsb->visible() ) + hfl ? _hsb->show() : _hsb->hide(); + + if( vfl != _vsb->visible() ) + vfl ? _vsb->show() : _vsb->hide(); +} + +cmGrH_t cmGrPlotFltk::_getFocusedView() +{ + cmGrVwH_t vwH = cmGrPageFocusedView(_pgH); + + if( cmGrViewIsValid(vwH) == false ) + return cmGrNullHandle; + + return cmGrViewGrHandle( vwH ); +} + +void cmGrPlotFltk::_s_ctl_cb(Fl_Widget* wp, long id ) +{ + switch( id ) + { + case kHScrollId: + case kVScrollId: + { + cmGrPlotFltk* p = static_cast(wp->parent()); + p->on_scroll( (Fl_Scrollbar*)wp, id ); + } + break; + + case kShowAllId: + case kReportId: + case kZoomInId: + case kZoomOutId: + case kZoomInXId: + case kZoomInYId: + case kZoomOutXId: + case kZoomOutYId: + { + cmGrPlotFltk* p = (cmGrPlotFltk*)wp->parent()->user_data(); + p->on_button( id ); + } + break; + + } +} + +void cmGrPlotFltk::_s_cmGrCallback( void* arg, cmGrH_t grH, cmGrCbId_t id, unsigned eventFlags, cmGrKeyCodeId_t keycode ) +{ + cmGrPlotFltk* p = (cmGrPlotFltk*)arg; + + switch(id) + { + case kCreateCbGrId: p->on_view_create( cmGrId(grH)); break; + case kDestroyCbGrId: p->on_view_destroy(cmGrId(grH)); break; + case kLocalPtCbGrId: p->rpt_local_pt( grH ); break; + case kGlobalPtCbGrId: p->rpt_global_pt(grH ); break; + case kPhysExtCbGrId: p->on_phys_change( grH ); break; + case kViewExtCbGrId: p->on_view_change( grH ); break; + case kSelectExtCbGrId:p->on_select_change(grH); break; + case kFocusCbGrId: p->on_focused_plot(grH); break; + case kKeyUpCbGrId: p->on_key_event( grH, eventFlags, keycode ); break; + case kKeyDnCbGrId: p->on_key_event( grH, eventFlags, keycode ); break; + + default: + { assert(0); } + } + +} + +bool cmGrPlotFltk::_s_cmGrPlotObjCbFunc( cmGrPlotCbArg_t* arg ) +{ + cmGrPlotFltk* p = (cmGrPlotFltk*)arg->cbArg; + return p->on_plot_object(arg); +} diff --git a/src/libcmpp/fltk/cmGrFltk.h b/src/libcmpp/fltk/cmGrFltk.h new file mode 100644 index 0000000..689f37d --- /dev/null +++ b/src/libcmpp/fltk/cmGrFltk.h @@ -0,0 +1,242 @@ +#ifndef cmGrFltk_h +#define cmGrFltk_h + +class Fl_Group; +class Fl_Output; +class Fl_Scrollbar; + +class cmGrDevDrvFltk +{ + public: + + cmGrDevDrvFltk(); + virtual ~cmGrDevDrvFltk(){} + + + static bool create( void* user, unsigned w, unsigned h ); + static void destroy( void* user ); + + static void begin_draw( void* arg ); + static void end_draw( void* arg ); + static void draw( void* arg, int x, int y ); + + static void set_color( void* user, const cmGrColor_t c ); + static void get_color( void* user, cmGrColor_t* c ); + + static void set_font_family( void* user, unsigned fontId ); + static unsigned get_font_family( void* user ); + + static void set_font_style( void* user, unsigned style ); + static unsigned get_font_style( void* user ); + + static void set_font_size( void* user, unsigned size ); + static unsigned get_font_size( void* user ); + + static void set_pen_style( void* user, unsigned styleFlags ); + static unsigned get_pen_style( void* user ); + + static void set_pen_width( void* user, unsigned w ); + static unsigned get_pen_width( void* user ); + + static void draw_line( void* user, int x0, int y0, int x1, int y1 ); + static void draw_rect( void* user, int x0, int y0, unsigned w, unsigned h ); + static void fill_rect( void* user, int x0, int y0, unsigned w, unsigned h ); + static void draw_ellipse( void* user, int x0, int y0, unsigned w, unsigned h ); + static void fill_ellipse( void* user, int x0, int y0, unsigned w, unsigned h ); + static void draw_diamond( void* user, int x0, int y0, unsigned w, unsigned h ); + static void fill_diamond( void* user, int x0, int y0, unsigned w, unsigned h ); + static void draw_triangle( void* user, int x0, int y0, unsigned w, unsigned h, unsigned dirFlag ); + static void fill_triangle( void* user, int x0, int y0, unsigned w, unsigned h, unsigned dirFlag ); + + static void draw_text( void* user, const char* text, int x, int y ); + static void draw_text_rot( void* user, const char* text, int x, int y, int angle ); + static void measure_text( void* user, const char* text, unsigned* w, unsigned* h ); + + static void read_image( void* user, unsigned char* p, int x, int y, unsigned w, unsigned h ); + static void draw_image( void* user, const unsigned char* p, int x, int y, unsigned w, unsigned h ); + + bool is_initialized() const; + + cmGrDev_t d; + + private: + + unsigned _fltk_pen_width; + unsigned _fltk_pen_style; + unsigned _fltk_font_size; + unsigned _w; + unsigned _h; + + static void _get_font_family_style( unsigned* fontId, unsigned* style ); + static void _set_font_family_style( void* user, unsigned fontId, unsigned style ); +}; + +//-------------------------------------------------------------------------------------- +// Canvas Object + +class cmGrViewFltk : public Fl_Widget +{ + public: + cmGrViewFltk( cmCtx_t* ctx, cmGrH_t grH, int x, int y, int w, int h ); + virtual ~cmGrViewFltk(); + + virtual int handle(int event); + virtual void resize(int x, int y, int w, int h ); + void setGrH( cmGrH_t grH ); + + private: + virtual void draw(); + + typedef struct + { + unsigned idx; + unsigned fltk_code; + char ch; + cmGrKeyCodeId_t gr_code; + } keyMap_t; + + cmGrH_t _grH; + cmGrDevDrvFltk _dd; + cmGrDcH_t _dcH; + static keyMap_t _keymap[]; + + const keyMap_t* _getGrKeyCode( unsigned fltk_code ); + cmGrKeyCodeId_t _eventKeyCode( ); + +}; + + +//-------------------------------------------------------------------------------------- +// Container for multiple plots + +class cmGrPageFltk : public Fl_Group +{ + public: + cmGrPageFltk( cmCtx_t* ctx, cmGrPgH_t pgH, int x, int y, int w, int h ); + virtual ~cmGrPageFltk(); + + virtual void createView( unsigned vwIdx ); + + virtual void destroyView( unsigned vwIdx ); + + virtual cmGrDcH_t devCtxHandle(); + + virtual cmGrViewFltk* viewWidget( unsigned vwIdx ); + + virtual void resize(int x, int y, int w, int h ); + + private: + virtual void draw(); + + cmGrDevDrvFltk _dd; + cmCtx_t* _ctx; + cmGrPgH_t _pgH; + cmGrDcH_t _dcH; + cmGrViewFltk** _vwV; + unsigned _vwN; + +}; + +//-------------------------------------------------------------------------------------- +// Contains a single cmGrPageFltk and a control panel + +class cmGrPlotFltk : public Fl_Group +{ + public: + cmGrPlotFltk( cmCtx_t* ctx, int x, int y, int w, int h, int rn=1, int cn=1, int textSz=10 ); + virtual ~cmGrPlotFltk(); + + virtual void resize(int x, int y, int w, int h ); + + cmGrPgH_t pageHandle(); + cmGrPlH_t plotHandle(); + cmGrDcH_t dcHandle(); + + virtual void initViews( int rn, int cn ); + virtual void setStatusText( const cmChar_t* s ); + + virtual void on_button( unsigned id ); + virtual void on_scroll( Fl_Scrollbar* sb, unsigned id ); + virtual void on_view_create( unsigned viewIdx ); + virtual void on_view_destroy( unsigned viewIdx ); + virtual void rpt_local_pt( cmGrH_t grH ); + virtual void rpt_global_pt( cmGrH_t grH ); + virtual void on_phys_change( cmGrH_t grH ); + virtual void on_view_change( cmGrH_t grH ); + virtual void on_select_change( cmGrH_t grH ); + virtual void on_focused_plot( cmGrH_t grH ); + virtual void on_key_event( cmGrH_t grH, unsigned eventFlags, cmGrKeyCodeId_t keycode ); + virtual bool on_plot_object( cmGrPlotCbArg_t* arg ); + + private: + enum + { + kHBord = 0, // dist between vertical elements (cols) + kVBord = 0, // dist between horz elements (rows) + kBtnH = 20, // control height + kBtnW = 50, // button width + kOutW = 100, // output width + kLblW = 20, // output label width, + kScrD = 20 // scroll bar thickness + }; + + enum + { + kHScrollId, + kVScrollId, + kShowAllId, + kReportId, + kZoomInId, + kZoomOutId, + kZoomInXId, + kZoomInYId, + kZoomOutXId, + kZoomOutYId, + }; + + + cmGrPgH_t _pgH; + cmGrPlH_t _plH; + + cmGrPageFltk* _pg; + Fl_Group* _ctl_grp; + Fl_Group* _usr_grp; + Fl_Output* _status; // status text output + + Fl_Scrollbar* _hsb; // scroll bars + Fl_Scrollbar* _vsb; + + Fl_Output* _gx; // current global coord display + Fl_Output* _gy; + + Fl_Output* _lx; // current local coord display + Fl_Output* _ly; + + Fl_Output* _s0x; // seletion point + Fl_Output* _s0y; + Fl_Output* _s1x; + Fl_Output* _s1y; + Fl_Output* _sdx; + Fl_Output* _sdy; + + int _textSz; + + void _layout(); + Fl_Group* _create_ctls(); + void _create_scroll_bars(); + void _showHideScrollBars(); + cmGrH_t _getFocusedView(); + + // controls callback + static void _s_ctl_cb(Fl_Widget* w, long id ); + + // plot page callbacks + static void _s_cmGrCallback( void* arg, cmGrH_t grH, cmGrCbId_t id, unsigned eventFlags, cmGrKeyCodeId_t keycode ); + + // plot object callbacks + static bool _s_cmGrPlotObjCbFunc( cmGrPlotCbArg_t* arg ); + +}; + + +#endif diff --git a/src/libcmpp/fltk/cmUiDrvrFltk.cpp b/src/libcmpp/fltk/cmUiDrvrFltk.cpp new file mode 100644 index 0000000..421409e --- /dev/null +++ b/src/libcmpp/fltk/cmUiDrvrFltk.cpp @@ -0,0 +1,865 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Fl_File_Btn.h" +#include "Fl_Vert_Progress.h" + +#include "cmGlobal.h" +#include "cmRpt.h" +#include "cmErr.h" +#include "cmCtx.h" +#include "cmMem.h" +#include "cmMallocDebug.h" + +#include "cmRtSysMsg.h" +#include "cmUiDrvr.h" +#include "cmUiDrvrFltk.h" + + +cmUiDrvrFltk::cmUiDrvrFltk(cmCtx_t* ctx, Fl_Tabs* tabs, cmUiDriverFunc_t cbFunc, void* cbArg) + : _tabs(NULL),_cbFunc(NULL),_cbArgs(NULL),_panels(NULL) +{ + cmErrSetup(&_err,&ctx->rpt,"cmUiDrvrFltk"); + setBaseWindow(tabs); + setCallback(cbFunc,cbArg); +} + +void cmUiDrvrFltk::setBaseWindow( Fl_Tabs* tabs ) +{ + _tabs = tabs; + if( _tabs != NULL ) + _tabs->callback(_s_tab_cb,this); +} + +void cmUiDrvrFltk::setCallback( cmUiDriverFunc_t cbFunc, void* cbArg ) +{ + _cbFunc = cbFunc; + _cbArgs = cbArg; +} + +cmUiDrvrFltk::~cmUiDrvrFltk() +{ + _destroyAllPanels(false); +} + +cmUiRC_t cmUiDrvrFltk::cmUiDriverFunc( void* cbArg, const cmUiDriverArg_t* args ) +{ + cmUiDrvrFltk* p = (cmUiDrvrFltk*)cbArg; + cmUiRC_t rc = kOkUiRC; + switch(args->dId) + { + case kInvalidDId: + break; + + case kCreateCtlDId: + rc = p->_createCtl(args); + break; + + case kDestroyCtlDId: + rc = p->_destroyCtl(args->appId,args->panelId,args->usrId,true); + break; + + case kSetValDId: + rc = p->_setValueCtl(args); + break; + + case kEnableDId: + rc = p->_enableCtl(args); + break; + + //case kDestroyAllDId: + //rc = p->_destroyAllPanels(true); + //break; + + case kMaxDId: + assert(0); + break; + + } + return rc; +} + +void cmUiDrvrFltk::_insertNewCtl( panel_t* pp, ctl_t* ctl, Fl_Widget* wp, unsigned flags ) +{ + ctl->wdgt = wp; + + if( ctl->usrId != cmInvalidId ) + { + ctl->link = pp->ctls; + pp->ctls = ctl; + wp->callback( _s_ctl_cb, ctl ); + } + + pp->grp->add(wp); + + + int align_flags = 0; + if( cmIsFlag(flags,kLeftUiFl)) align_flags |= FL_ALIGN_LEFT; + if( cmIsFlag(flags,kTopUiFl)) align_flags |= FL_ALIGN_TOP; + if( cmIsFlag(flags,kRightUiFl)) align_flags |= FL_ALIGN_RIGHT; + if( cmIsFlag(flags,kBottomUiFl)) align_flags |= FL_ALIGN_BOTTOM; + if( cmIsFlag(flags,kHCtrUiFl)) align_flags |= FL_ALIGN_CENTER; + if( cmIsFlag(flags,kInsideUiFl)) align_flags |= FL_ALIGN_INSIDE; + if( cmIsFlag(flags,kVCtrUiFl)) align_flags = cmClrFlag(align_flags,FL_ALIGN_TOP | FL_ALIGN_BOTTOM); + + + wp->align(align_flags); + + + int when_flags = 0; + if( cmIsFlag(flags,kSendChangeFl)) when_flags |= FL_WHEN_CHANGED; + if( cmIsFlag(flags,kSendEnterFl)) when_flags |= FL_WHEN_ENTER_KEY; + if( cmIsFlag(flags,kSendFocusFl)) when_flags |= FL_WHEN_RELEASE; + if( cmIsFlag(flags,kSendNoChangeFl)) when_flags |= FL_WHEN_NOT_CHANGED; + + if( when_flags != 0 ) + wp->when(when_flags); +} + +bool cmUiDrvrFltk::_hasNoAlignFlags( unsigned flags ) const +{ + return !cmIsFlag(flags, kLeftUiFl | kTopUiFl | kRightUiFl | kBottomUiFl | kVCtrUiFl | kHCtrUiFl ); +} + +cmUiRC_t cmUiDrvrFltk::_createCtl( const cmUiDriverArg_t* a ) +{ + cmUiRC_t rc; + panel_t* pp; + panel_t* prvPnl; + + // if this is a panel create request + if( a->cId == kPanelUiCId ) + return _createPanel(a); + + // locate the new control's panel + if((rc = _findPanel(a->appId,a->panelId,pp,prvPnl)) != kOkUiRC ) + return rc; + + // allocate the control record + ctl_t* ctl ; + if( a->usrId == cmInvalidId ) + ctl = &_dummy; + else + ctl = cmMemAllocZ(ctl_t,1); + + ctl->cId = a->cId; + ctl->pnl = pp; + ctl->usrId = a->usrId; + ctl->flags = a->flags; + + int x = a->x + pp->x_offs; + int y = a->y + pp->y_offs; + + // cache the event callback arg record so that it + // does not have to be filled on every callback. + cmUiDriverArgSetup(&ctl->cbArg,a->hdr.rtSubIdx,kUiDrvrSelRtId,kInvalidDId,pp->appId,a->usrId,pp->usrId,a->cId,0,0,0,NULL,x,y,a->w,a->h); + + //printf("%i %i %i %i\n",x,y,a->w,a->h); + + switch(a->cId) + { + case kInvalidUiCId: + assert(0); + break; + + case kPanelUiCId: + break; + + case kBtnUiCId: + ctl->u.btn = new Fl_Button(x,y,a->w,a->h,a->sval); + _insertNewCtl(pp,ctl,ctl->u.btn,a->flags); + ctl->cbArg.flags |= kIvalUiFl; + break; + + case kCheckUiCId: + ctl->u.chk = new Fl_Check_Button(x,y,a->w,a->h,a->sval); + _insertNewCtl(pp,ctl,ctl->u.chk,a->flags); + ctl->cbArg.flags |= kIvalUiFl; + ctl->u.chk->value(a->ival); + break; + + case kMenuBtnUiCId: + ctl->u.mbt = new Fl_Menu_Button(x,y,a->w,a->h,a->sval!=NULL ? a->sval : NULL); + _insertNewCtl(pp,ctl,ctl->u.mbt,a->flags); + ctl->cbArg.flags |= kIvalUiFl; + ctl->u.mbt->value(0); + break; + + case kListUiCId: + ctl->u.lst = new Fl_Select_Browser(x,y,a->w,a->h); + _insertNewCtl(pp,ctl,ctl->u.lst,a->flags); + ctl->cbArg.flags |= kIvalUiFl; + break; + + case kLabelUiCId: + { + unsigned flags = a->flags; + ctl->u.lbl = new Fl_Box(x,y,a->w,a->h); + ctl->u.lbl->copy_label(a->sval); + if( _hasNoAlignFlags(flags) ) + flags |= kHCtrUiFl | kInsideUiFl; + _insertNewCtl(pp,ctl,ctl->u.lbl,flags); + } + break; + + case kStringUiCId: + { + unsigned flags = a->flags; + ctl->u.str = new Fl_Input(x,y,a->w/2,a->h); + ctl->u.str->copy_label(a->sval); + if( _hasNoAlignFlags(flags) ) + flags |= kRightUiFl; + _insertNewCtl(pp,ctl,ctl->u.str,flags); + ctl->cbArg.flags |= kSvalUiFl; + } + break; + + case kConsoleUiCId: + { + unsigned flags = a->flags; + ctl->u.con = new Fl_Text_Display(x,y,a->w,a->h); + ctl->u.con->buffer(new Fl_Text_Buffer()); + ctl->u.con->textsize(12); + ctl->u.con->textfont(FL_COURIER); + ctl->u.con->copy_label(a->sval); + if( _hasNoAlignFlags(flags) ) + flags |= kRightUiFl; + _insertNewCtl(pp,ctl,ctl->u.con,flags); + ctl->cbArg.flags |= kSvalUiFl; + } + break; + + case kSliderUiCId: + { + unsigned flags = a->flags; + int w = a->w; + int h = a->h; + + if( cmIsFlag(flags,kHorzUiFl) ) + { + if( _hasNoAlignFlags(flags) ) + flags |= kRightUiFl; + + w /= 2; + + } + + if( cmIsFlag(flags,kVertUiFl) ) + { + if( _hasNoAlignFlags(flags) ) + flags |= kTopUiFl | kHCtrUiFl; + + if( a->sval != NULL ) + { + int hh,ww; + fl_measure(a->sval,ww,hh); + + if( flags & kTopUiFl ) + { + y += hh; + h -= hh; + } + + if( flags & kBottomUiFl) + h -= hh; + + } + } + + ctl->u.sld = new Fl_Value_Slider(x,y,w,h); + ctl->u.sld->copy_label(a->sval); + + + if( cmIsFlag(flags,kHorzUiFl) ) + ctl->u.sld->type(FL_HOR_NICE_SLIDER); + + if( cmIsFlag(flags,kVertUiFl) ) + ctl->u.sld->type(FL_VERT_NICE_SLIDER); + + _insertNewCtl(pp,ctl,ctl->u.sld,flags); + + ctl->cbArg.flags |= kFvalUiFl; + + } + break; + + case kNumberUiCId: + { + unsigned flags = a->flags; + ctl->u.num = new Fl_Value_Input(x,y,a->w/2,a->h); + ctl->u.num->copy_label(a->sval); + if( _hasNoAlignFlags(flags) ) + flags |= kRightUiFl; + + _insertNewCtl(pp,ctl,ctl->u.num,flags); + ctl->cbArg.flags |= kFvalUiFl; + ctl->u.num->when(FL_WHEN_ENTER_KEY | FL_WHEN_NOT_CHANGED ); + } + break; + + case kProgressUiCId: + { + unsigned flags = a->flags; + ctl->u.prg = new Fl_Progress(x,y,a->w/2,a->h); + ctl->u.prg->copy_label(a->sval); + if( _hasNoAlignFlags(flags) ) + flags |= kRightUiFl; + _insertNewCtl(pp,ctl,ctl->u.prg,flags); + ctl->u.prg->color( fl_rgb_color((unsigned char)256),fl_rgb_color((unsigned char)128)); + } + break; + + case kMeterUiCId: + { + unsigned flags = a->flags; + if( cmIsFlag(flags,kVertUiFl) ) + { + ctl->u.mtr = new Fl_Vert_Progress(x,y,a->w/2,a->h); + ctl->u.mtr->color( fl_rgb_color((unsigned char)256),fl_rgb_color((unsigned char)128)); + } + else + { + ctl->u.mtr = new Fl_Progress(x,y,a->w,a->h); + ctl->u.mtr->color( fl_rgb_color((unsigned char)256),fl_rgb_color((unsigned char)128)); + } + + ctl->u.mtr->copy_label(a->sval); + + if( _hasNoAlignFlags(flags) ) + flags |= kRightUiFl; + _insertNewCtl(pp,ctl,ctl->u.mtr,flags); + } + break; + + case kFilenameUiCId: + case kDirUiCId: + { + unsigned flags = a->cId==kDirUiCId ? Fl_File_Btn::kDir_Type_Id : Fl_File_Btn::kFile_Type_Id; + ctl->u.fnb = new Fl_File_Btn(flags,"",x,y,a->w,a->h,a->sval); + flags = a->flags; + if( _hasNoAlignFlags(flags) ) + flags |= kRightUiFl; + _insertNewCtl(pp,ctl,ctl->u.fnb,flags); + ctl->cbArg.flags |= kSvalUiFl; + } + break; + + case kMaxUiCId: + assert(0); + break; + + } + + pp->grp->redraw(); + + return rc; +} + +cmUiRC_t cmUiDrvrFltk::_setValueCtl( const cmUiDriverArg_t* a ) +{ + cmUiRC_t rc; + panel_t* pp = NULL; + panel_t* prvPnl = NULL; + ctl_t* ctl = NULL; + ctl_t* prvCtl = NULL; + + if((rc = _findPanel(a->appId,a->panelId,pp,prvPnl)) != kOkUiRC ) + return rc; + + if((rc= _findCtl(pp, a->usrId, ctl, prvCtl )) != kOkUiRC ) + return rc; + + + switch( a->cId ) + { + case kInvalidUiCId: + break; + + case kPanelUiCId: + break; + + case kBtnUiCId: + if( cmIsFlag(a->flags,kLblUiFl) ) + ctl->u.btn->copy_label(a->sval); + break; + + case kCheckUiCId: + switch( a->flags & (kLblUiFl | kValUiFl) ) + { + case kValUiFl: ctl->u.chk->value(a->ival); break; + case kLblUiFl: ctl->u.chk->copy_label(a->sval); break; + } + break; + + case kMenuBtnUiCId: + switch( a->flags & (kAppendUiFl | kClearUiFl | kValUiFl) ) + { + case kValUiFl: + if( a->ival < ctl->u.mbt->size() ) + { + ctl->u.mbt->value(a->ival); + if( ctl->u.mbt->mvalue() != NULL) + ctl->u.mbt->copy_label( ctl->u.mbt->mvalue()->label()); + } + break; + + case kClearUiFl: + ctl->u.mbt->clear(); + ctl->u.mbt->copy_label(""); + break; + + case kAppendUiFl: + { + int n; + ctl->u.mbt->add( a->sval,0,ctl->u.mbt->callback(),ctl->u.mbt->user_data(),0); + n = ctl->u.mbt->size(); + if( (n) == 2 ) + { + + ctl->u.mbt->value(0); + if( ctl->u.mbt->mvalue() != NULL) + { + const char* s = ctl->u.mbt->mvalue()->label(); + ctl->u.mbt->copy_label( s); + } + } + } + break; + } + break; + + case kListUiCId: + switch( a->flags & (kAppendUiFl | kClearUiFl | kValUiFl) ) + { + case kValUiFl: ctl->u.lst->value(a->ival); break; + case kAppendUiFl: ctl->u.lst->add( a->sval ); break; + case kClearUiFl: ctl->u.lst->clear(); break; + } + break; + + case kLabelUiCId: + ctl->u.str->value(a->sval); + break; + + case kStringUiCId: + switch( a->flags & (kLblUiFl | kValUiFl) ) + { + case kValUiFl: ctl->u.str->value(a->sval); break; + case kLblUiFl: ctl->u.str->copy_label(a->sval); break; + } + break; + + case kConsoleUiCId: + switch( a->flags & (kLblUiFl | kValUiFl) ) + { + case kValUiFl: if(a->sval!=NULL) ctl->u.con->insert(a->sval); break; + case kLblUiFl: ctl->u.str->copy_label(a->sval); break; + } + break; + + case kSliderUiCId: + case kNumberUiCId: + { + Fl_Valuator* vp = static_cast(ctl->wdgt); + + // Correct for problem where the vertical slider values go up as the + // slider knob is dragged down. + bool invertFl = a->cId == kSliderUiCId && cmIsFlag(ctl->flags,kVertUiFl); + + switch(a->flags & (kNumMask | kLblUiFl | kMinUiFl | kMaxUiFl)) + { + case kLblUiFl: ctl->u.num->copy_label(a->sval); break; + case kValUiFl: vp->value(a->fval); break; + case kIncUiFl: vp->step(a->fval); break; + case kMinUiFl: invertFl ? vp->maximum(a->fval) : vp->minimum(a->fval); break; + case kMaxUiFl: invertFl ? vp->minimum(a->fval) : vp->maximum(a->fval); break; + } + } + break; + + case kProgressUiCId: + switch( a->flags & (kLblUiFl | kValUiFl | kMinUiFl | kMaxUiFl) ) + { + case kValUiFl: ctl->u.prg->value(a->ival); break; + case kLblUiFl: ctl->u.prg->copy_label(a->sval); break; + case kMinUiFl: ctl->u.prg->minimum(a->ival); break; + case kMaxUiFl: ctl->u.prg->maximum(a->ival); break; + } + break; + + case kMeterUiCId: + switch( a->flags & (kLblUiFl | kValUiFl | kMinUiFl | kMaxUiFl) ) + { + case kValUiFl: ctl->u.mtr->value(a->ival); ctl->u.mtr->redraw(); break; + case kLblUiFl: ctl->u.mtr->copy_label(a->sval); break; + case kMinUiFl: ctl->u.prg->minimum(a->ival); break; + case kMaxUiFl: ctl->u.prg->maximum(a->ival); break; + } + break; + + case kFilenameUiCId: + case kDirUiCId: + switch(a->flags & (kFnMask | kValUiFl | kFnPatUiFl | kFnDirUiFl) ) + { + case kValUiFl: + ctl->u.fnb->filename(a->sval); + break; + case kFnPatUiFl: ctl->u.fnb->pattern_string(a->sval); break; + case kFnDirUiFl: + ctl->u.fnb->type( ctl->u.fnb->type()==Fl_File_Btn::kFile_Type_Id ? Fl_File_Btn::kDir_Type_Id : Fl_File_Btn::kFile_Type_Id ); + break; + } + break; + + case kMaxUiCId: + assert(0); + break; + } + + // echo the result back to the UI + //if( cmIsFlag(a->flags,kValUiFl|kAppendUiFl) ) + // _cbFunc(_cbArgs,a); + + return rc; +} + +cmUiRC_t cmUiDrvrFltk::_enableCtl( const cmUiDriverArg_t* a ) +{ + cmUiRC_t rc; + panel_t* pp = NULL; + panel_t* prvPnl = NULL; + ctl_t* ctl = NULL; + ctl_t* prvCtl = NULL; + + if((rc = _findPanel(a->appId,a->panelId,pp,prvPnl)) != kOkUiRC ) + return rc; + + if((rc= _findCtl(pp, a->usrId, ctl, prvCtl )) != kOkUiRC ) + return rc; + + if( a->ival ) + ctl->wdgt->activate(); + else + ctl->wdgt->deactivate(); + + _doCb(ctl,kEnableDId,0); + + return rc; +} + +cmUiRC_t cmUiDrvrFltk::_destroyCtl( unsigned appId, unsigned panelId, unsigned usrId, bool deleteWindowEleFlag ) +{ + cmUiRC_t rc = kOkUiRC; + + panel_t* pp = NULL; + panel_t* prvPnl = NULL; + + // locate the panel assoc'd with the ctl + if((rc = _findPanel(appId,panelId,pp,prvPnl,true)) != kOkUiRC ) + return rc; + + // if the panel is the ctl to delete ... + if( usrId == pp->usrId ) + { + // ... unlink the panel + if( prvPnl!=NULL) + prvPnl->link = pp->link; + else + { + assert(_panels == pp ); + _panels = pp->link; + } + } + + return _destroyCtl(pp,usrId,deleteWindowEleFlag); +} + +cmUiRC_t cmUiDrvrFltk::_destroyCtl( panel_t* pp, unsigned usrId, bool deleteWindowEleFlag ) +{ + cmUiRC_t rc = kOkUiRC; + ctl_t* ctl = NULL; + ctl_t* prvCtl = NULL; + + // if the panel is the ctl to delete + if( usrId == pp->usrId ) + { + return _destroyPanel(pp,deleteWindowEleFlag); + } + + // locate the control on the panel + if((rc = _findCtl(pp,usrId,ctl,prvCtl,true)) != kOkUiRC ) + return rc; + + // unlink the control + if( prvCtl!=NULL) + prvCtl->link = ctl->link; + else + { + assert( pp->ctls == ctl ); + pp->ctls = ctl->link; + } + + // delete the window element + if( deleteWindowEleFlag) + delete ctl->wdgt; + + // release the control recd + cmMemFree(ctl); + + return rc; +} + +cmUiRC_t cmUiDrvrFltk::_createPanel( const cmUiDriverArg_t* a ) +{ + int tx,ty,tw,th; + _tabs->client_area(tx,ty,tw,th); + panel_t* pnl = cmMemAllocZ(panel_t,1); + + pnl->drvr = this; + pnl->grp = new Fl_Group(tx,ty,tw,th,a->sval); + pnl->grp->user_data(pnl); + pnl->appId = a->appId; + pnl->usrId = a->usrId; + pnl->x_offs = tx + 2; + pnl->y_offs = ty + 2; + pnl->link = _panels; + _panels = pnl; + + pnl->grp->end(); + + if( cmIsFlag(a->flags,kPrependUiFl) ) + _tabs->insert(*pnl->grp,0); + else + _tabs->add(pnl->grp); + + // cache the event callback arg record so that it + // does not have to be filled on every callback. + cmUiDriverArgSetup(&pnl->cbArg,a->hdr.rtSubIdx,kUiDrvrSelRtId,kSetValDId,a->appId,a->usrId,a->usrId,kPanelUiCId,kIvalUiFl,0,0,NULL,tx,ty,tw,th); + + + _tabs->redraw(); + + return kOkUiRC; +} + +cmUiRC_t cmUiDrvrFltk::_destroyAllPanels( bool deleteWindowEleFlag ) +{ + cmUiRC_t rc = kOkUiRC; + + while( _panels != NULL ) + { + cmUiRC_t rc0; + if((rc0 = _destroyCtl(_panels->appId,_panels->usrId,_panels->usrId,deleteWindowEleFlag)) != kOkUiRC ) + rc = rc0; + } + + return rc; +} + +cmUiRC_t cmUiDrvrFltk::_destroyPanel(panel_t* pp, bool deleteWindowEleFlag) +{ + cmUiRC_t rc = kOkUiRC; + + // delete the FLTK panel itself + if( deleteWindowEleFlag ) + { + delete pp->grp; + deleteWindowEleFlag = false; + } + + while( pp->ctls != NULL ) + { + cmUiRC_t rc0; + + if((rc0 = _destroyCtl(pp,pp->ctls->usrId,deleteWindowEleFlag)) != kOkUiRC ) + rc = rc0; + } + + cmMemFree(pp); + + return rc; +} + +cmUiRC_t cmUiDrvrFltk::_findPanel( unsigned appId, unsigned usrId, panel_t*& ppRef, panel_t*& prvPnl, bool errFl ) +{ + ppRef = NULL; + prvPnl = NULL; + + panel_t* pp = _panels; + for(; pp!=NULL; pp=pp->link) + { + if(pp->appId==appId && pp->usrId==usrId ) + { + ppRef = pp; + return kOkUiRC; + } + prvPnl = pp; + } + if( errFl ) + cmErrMsg(&_err,kPanelNotFoundUiRC,"Panel not found for id=%i.",usrId); + + return kPanelNotFoundUiRC; +} + +cmUiRC_t cmUiDrvrFltk::_findCtl( panel_t* pp, unsigned usrId, ctl_t*& ctlRef, ctl_t*& prvCtlRef, bool errFl ) +{ + ctlRef = NULL; + prvCtlRef = NULL; + ctl_t* cp = pp->ctls; + for(; cp!=NULL; cp=cp->link) + { + if( cp->usrId == usrId ) + { + ctlRef = cp; + return kOkUiRC; + } + + prvCtlRef = cp; + } + if( errFl ) + cmErrMsg(&_err,kCtlNotFoundUiRC,"Control %i not found in panel %i.",usrId,pp->usrId); + + return kCtlNotFoundUiRC; +} + +void cmUiDrvrFltk::_doCb( ctl_t* ctl, cmUiDId_t dId, unsigned flags ) +{ + cmUiDriverArg_t* a = &ctl->cbArg; + unsigned orgFlags = a->flags; + a->flags |= flags; + a->dId = dId; + + _cbFunc(_cbArgs,&ctl->cbArg); + + a->flags = orgFlags; + a->dId = kInvalidDId; +} + +void cmUiDrvrFltk::_s_ctl_cb(Fl_Widget* wp, void* arg ) +{ + ctl_t* ctl = (ctl_t*)arg; + cmUiDrvrFltk* p = ctl->pnl->drvr; + cmUiDriverArg_t* a = &ctl->cbArg; + bool callbackFl = true; + unsigned flags = kValUiFl; + + switch( ctl->cId ) + { + case kInvalidUiCId: + assert(0); + callbackFl = false; + break; + + case kPanelUiCId: + callbackFl = false; + break; + + case kBtnUiCId: + break; + + case kCheckUiCId: + a->ival = ctl->u.chk->value(); + flags |= kIvalUiFl; + break; + + case kMenuBtnUiCId: + if( ctl->u.mbt->mvalue() != NULL && ctl->u.mbt->mvalue()->label() != NULL ) + ctl->u.mbt->copy_label(ctl->u.mbt->mvalue()->label()); + a->ival = ctl->u.mbt->value(); + flags |= kIvalUiFl; + break; + + case kListUiCId: + a->ival = ctl->u.lst->value() - 1; + flags |= kIvalUiFl; + break; + + case kLabelUiCId: + callbackFl = false; + break; + + case kStringUiCId: + a->sval = ctl->u.str->value(); + flags |= kSvalUiFl; + break; + + case kConsoleUiCId: + callbackFl = false; + break; + + case kSliderUiCId: + a->fval = ctl->u.sld->value(); + flags |= kFvalUiFl; + break; + + case kNumberUiCId: + a->fval = ctl->u.num->value(); + flags |= kFvalUiFl; + break; + + case kProgressUiCId: + callbackFl = false; + break; + + case kMeterUiCId: + callbackFl = false; + break; + + case kFilenameUiCId: + a->sval = ctl->u.fnb->filename(); + flags |= kSvalUiFl; + break; + + case kDirUiCId: + a->sval = ctl->u.fnb->filename(); + flags |= kSvalUiFl; + break; + + case kMaxUiCId: + callbackFl = false; + assert(0); + break; + } + + if( callbackFl ) + p->_doCb(ctl,kSetValDId,flags); + +} + +void cmUiDrvrFltk::_s_tab_cb(Fl_Widget* wp, void* arg ) +{ + cmUiDrvrFltk* p = (cmUiDrvrFltk*)arg; + Fl_Widget* w = p->_tabs->value(); + + panel_t* pp = p->_panels; + for(; pp!=NULL; pp=pp->link) + { + // if this is the panel being selected then send a 1 otherwise send a 0. + pp->cbArg.flags = cmSetFlag(pp->cbArg.flags, kIvalUiFl ); + pp->cbArg.dId = kSetValDId; + pp->cbArg.ival = w->user_data() == pp->grp->user_data(); + + p->_cbFunc(p->_cbArgs,&pp->cbArg); + + pp->cbArg.flags = cmClrFlag(pp->cbArg.flags, kIvalUiFl ); + pp->cbArg.dId = kInvalidDId; + + } + +} + + + diff --git a/src/libcmpp/fltk/cmUiDrvrFltk.h b/src/libcmpp/fltk/cmUiDrvrFltk.h new file mode 100644 index 0000000..b136f1c --- /dev/null +++ b/src/libcmpp/fltk/cmUiDrvrFltk.h @@ -0,0 +1,99 @@ +#ifndef cmUiDrvrFltk_h +#define cmUiDrvrFltk_h + +class Fl_Tabs; +class Fl_Widget; +class Fl_Button; +class Fl_Check_Button; +class Fl_Menu_Button; +class Fl_Select_Browser; +class Fl_Box; +class Fl_Input; +class Fl_Value_Input; +class Fl_Value_Slider; +class Fl_Progress; +class Fl_Vert_Progress; +class Fl_File_Btn; +class Fl_Text_Display; + +class cmUiDrvrFltk +{ +public: + + cmUiDrvrFltk(cmCtx_t* ctx, Fl_Tabs* tabs, cmUiDriverFunc_t cbFunc, void* cbArg); + virtual ~cmUiDrvrFltk(); + + void setBaseWindow( Fl_Tabs* tabs ); + void setCallback( cmUiDriverFunc_t cbFunc, void* cbArg ); + + static cmUiRC_t cmUiDriverFunc( void* arg, const cmUiDriverArg_t* a ); + +private: + struct panel_str; + + typedef struct ctl_str + { + cmUiCId_t cId; // control type id + unsigned usrId; // user id + unsigned flags; // flags from this controls create call. + struct panel_str* pnl; // parent panel + Fl_Widget* wdgt; // this controls FLTK wdgt ptr + cmUiDriverArg_t cbArg; // cached callback arg. recd used by this ctl + struct ctl_str* link; // panel.ctls list link + + union + { + Fl_Button* btn; + Fl_Check_Button* chk; + Fl_Menu_Button* mbt; + Fl_Select_Browser* lst; + Fl_Box* lbl; + Fl_Input* str; + Fl_Text_Display* con; + Fl_Value_Input* num; + Fl_Value_Slider* sld; + Fl_Progress* prg; + Fl_Progress* mtr; + Fl_File_Btn* fnb; + } u; + } ctl_t; + + typedef struct panel_str + { + cmUiDrvrFltk* drvr; // parent driver object + Fl_Group* grp; // panel Widget + unsigned appId; // id of the app. this panel serves + unsigned usrId; // panels id + int x_offs; // left control border + int y_offs; // top control border + ctl_t* ctls; // this panels control list + cmUiDriverArg_t cbArg; // cached callback arg recd used by this ctl + struct panel_str* link; // links used by _panels + } panel_t; + + cmErr_t _err; // + Fl_Tabs* _tabs; // Fl_Tabs Widget containing the panels + cmUiDriverFunc_t _cbFunc; // application event callback function + void* _cbArgs; // + panel_t* _panels; // panel list + ctl_t _dummy; // + + void _insertNewCtl( panel_t* pp, ctl_t* ctl, Fl_Widget* wp, unsigned flags ); + bool _hasNoAlignFlags( unsigned flags ) const; + cmUiRC_t _createCtl( const cmUiDriverArg_t* a ); + cmUiRC_t _destroyCtl( unsigned appId, unsigned panelId, unsigned usrId, bool deleteWindowEleFlag ); + cmUiRC_t _destroyCtl( panel_t* pp, unsigned usrId, bool deleteWindowEleFlag ); + cmUiRC_t _createPanel( const cmUiDriverArg_t* a ); + cmUiRC_t _setValueCtl( const cmUiDriverArg_t* a ); + cmUiRC_t _enableCtl( const cmUiDriverArg_t* a ); + cmUiRC_t _destroyAllPanels( bool deleteWindowEleFl ); + cmUiRC_t _destroyPanel(panel_t* pp, bool deleteWindowEleFl ); + cmUiRC_t _findPanel( unsigned appId, unsigned usrId, panel_t*& ppRef, panel_t*& prvPnlRef, bool errFl=true ); + cmUiRC_t _findCtl( panel_t* pp, unsigned usrId, ctl_t*& ctlRef, ctl_t*& prvCtlRef, bool errFl=true ); + void _doCb( ctl_t* ctl, cmUiDId_t dId, unsigned flags ); + + static void _s_ctl_cb(Fl_Widget* wp, void* data ); + static void _s_tab_cb(Fl_Widget* wp, void* data ); +}; + +#endif diff --git a/src/tlCtl/Makefile.am b/src/tlCtl/Makefile.am new file mode 100644 index 0000000..402955e --- /dev/null +++ b/src/tlCtl/Makefile.am @@ -0,0 +1,11 @@ + + +tlCtlSRC = src/tlCtl/cmdIf.h src/tlCtl/cmdIf.cpp +tlCtlSRC += src/tlCtl/gvHashFunc.h src/tlCtl/gvHashFunc.cpp +tlCtlSRC += src/tlCtl/cmGrTlFltk.h src/tlCtl/cmGrTlFltk.cpp +tlCtlSRC += src/tlCtl/cmGrScFltk.h src/tlCtl/cmGrScFltk.cpp +tlCtlSRC += src/tlCtl/cmGrTksbFltk.h src/tlCtl/cmGrTksbFltk.cpp +tlCtlSRC += src/tlCtl/cmGrTksrFltk.h src/tlCtl/cmGrTksrFltk.cpp +tlCtlSRC += src/tlCtl/cmGr2dFltk.h src/tlCtl/cmGr2dFltk.cpp + +tlCtlSRC += src/tlCtl/tlCtl.h src/tlCtl/tlCtl.cpp diff --git a/src/tlCtl/cmGr2dFltk.cpp b/src/tlCtl/cmGr2dFltk.cpp new file mode 100644 index 0000000..61cecab --- /dev/null +++ b/src/tlCtl/cmGr2dFltk.cpp @@ -0,0 +1,148 @@ +#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 "cmGr.h" +#include "cmGrDevCtx.h" +#include "cmGrPlot.h" +#include "cmGrPage.h" +#include "cmGrFltk.h" +#include "cmGr2dFltk.h" + + +cmGr2dFltk::cmGr2dFltk(cmCtx_t* ctx, Fl_Menu_Bar* menuBar, int x, int y, int w, int h) + : cmGrPlotFltk(ctx,x,y,w,h), + _x(0),_y(0),_radius(0),_angle(0), + _objId(0) +{ + cmErrSetup(&_err,&ctx->rpt,"cmGr2dFltk"); + + if( cmGrPageIsValid(pageHandle()) == false ) + return; + + initViews(1,1); + + unsigned vwIdx = 0; + cmGrPgH_t pgH = pageHandle(); + cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx); + cmGrH_t cvH = cmGrViewGrHandle( vwH ); + cmGrVExt_t limExt; + + cmGrVExtSetD(&limExt,-kWidth,-kHeight,kWidth, kHeight); + + cmGrObjSetWorldExt( cvH, cmGrRootObjH(cvH), &limExt ); + cmGrObjSetWorldLimitExt(cvH, cmGrRootObjH(cvH), &limExt, kLeftGrFl | kRightGrFl | kTopGrFl | kBottomGrFl ); + + _createObj(); + + cmGrSetViewExtentsE( cvH, &limExt ); + +} + +cmGr2dFltk::~cmGr2dFltk() +{ +} + + +bool cmGr2dFltk::on_plot_object( cmGrPlotCbArg_t* arg ) +{ + if( arg->selId==kEventCbSelGrPlId && cmIsFlag(arg->eventFlags,kMsDragGrFl ) ) + { + cmGrVExt_t vext; + cmGrPlotObjVExt(arg->objH,&vext); + //cmGrVExtPrint("",&vext); + _x = cmGrVExtMinX(&vext); + _y = cmGrVExtMinY(&vext); + _radius = sqrtf(_x*_x + _y*_y)/kWidth; + _angle = -( atan2f(_y,_x) - M_PI/2.0); + + if( _angle < 0 ) + _angle += 2.0 * M_PI; + + _angle = 360.0f * _angle / (2.0*M_PI); + + setStatusText(cmTsPrintfS("r:%f angle:%f",_radius,_angle)); + + callback()(this,user_data()); + + } + + return true; +} + + +double cmGr2dFltk::x() const +{ return _x; } + +double cmGr2dFltk::y() const +{ return _y; } + +double cmGr2dFltk::radius() const +{ return _radius; } + +double cmGr2dFltk::angle() const +{ return _angle; } + +void cmGr2dFltk::_createObj() +{ + cmGrPlH_t plH = plotHandle(); + cmGrPgH_t pgH = pageHandle(); + unsigned vwIdx = 0; + cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx ); + cmGrH_t cvH = cmGrViewGrHandle( vwH ); + cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t objH = cmGrPlObjNullHandle; + cmGrPlObjTypeId_t objTypeId = kRectGrPlId; + cmReal_t x = 0; + cmReal_t y = 0; + cmReal_t w = 0; + cmReal_t h = 0; + unsigned flags = 0; //kNoDragGrPlFl; + cmGrVExt_t* wext = NULL; + + if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags | kNoDragGrPlFl, x, y, w, h, NULL, wext ) != kOkGrPlRC ) + { + cmErrMsg(&_err,kCreateObjRC,"Plot origin object create failed."); + } + else + { + cmGrPlotObjSetPhysExt(objH, -2, -2, 2, 2 ); + cmGrPlotObjSetFontSize(objH,8); + } + + objH = cmGrPlObjNullHandle; + + if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, NULL, wext ) != kOkGrPlRC ) + { + cmErrMsg(&_err,kCreateObjRC,"Plot object create failed."); + } + else + { + //unsigned f = 0 ? (kNorthJsGrFl | kTopJsGrFl) : (kSouthJsGrFl | kBottomJsGrFl); + //cmGrPlotObjSetLabelAttr( objH, f | kWestJsGrFl | kTopJsGrFl | kRightJsGrFl, 0, kBlackGrId ); + cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kGreenGrId ); + cmGrPlotObjSetPhysExt(objH, -4, -4, 4, 4 ); + cmGrPlotObjSetFontSize(objH,8); + } + +} + diff --git a/src/tlCtl/cmGr2dFltk.h b/src/tlCtl/cmGr2dFltk.h new file mode 100644 index 0000000..40e64d8 --- /dev/null +++ b/src/tlCtl/cmGr2dFltk.h @@ -0,0 +1,44 @@ +#ifndef cmGr2dFltk_h +#define cmGr2dFltk_h + +class Fl_Menu_Bar; + +class cmGr2dFltk : public cmGrPlotFltk +{ +public: + cmGr2dFltk(cmCtx_t* ctx, Fl_Menu_Bar* menuBar, int x, int y, int w, int h); + + virtual ~cmGr2dFltk(); + + virtual bool on_plot_object( cmGrPlotCbArg_t* arg ); + + double x() const; + double y() const; + double radius() const; + double angle() const; + +private: + enum + { + kWidth = 100, + kHeight = 100 + }; + + enum + { + kOkRC = 0, + kCreateObjRC + }; + + cmErr_t _err; + double _x; + double _y; + double _radius; + double _angle; + unsigned _objId; + + void _createObj(); + +}; + +#endif diff --git a/src/tlCtl/cmGrScFltk.cpp b/src/tlCtl/cmGrScFltk.cpp new file mode 100644 index 0000000..6f134cc --- /dev/null +++ b/src/tlCtl/cmGrScFltk.cpp @@ -0,0 +1,565 @@ +#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 "cmSymTbl.h" +#include "cmTime.h" +#include "cmMidi.h" +#include "cmMidiFile.h" +#include "cmAudioFile.h" +#include "cmAudioFileMgr.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 "cmGrScFltk.h" +#include "cmGrPlotAudio.h" +#include "cmdIf.h" + +cmGrScFltk::cmGrScFltk(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), + _samplesMetricId(cmInvalidId),_secondsMetricId(cmInvalidId), + _objSecs(0),_objId(0), + _togFl(true), + _lastBarPlotObjH(cmGrPlObjNullHandle) +{ + cmErrSetup(&_err,&ctx->rpt,"cmGrScFltk"); + + _createMenu(); + + if( cmGrPageIsValid(pageHandle()) == false ) + return; + + initViews(1,1); + + unsigned vwIdx = 0; + cmGrPgH_t pgH = pageHandle(); + cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx); + cmGrH_t cvH = cmGrViewGrHandle( vwH ); + cmGrAxH_t axH = cmGrAxNullHandle; + cmGrVExt_t limExt; + + _samplesMetricId = cmGrPageLabelFuncRegister( pgH, gvRoundHashValueFunc, this, "Round" ); + _secondsMetricId = cmGrPageLabelFuncRegister( pgH, gvMinSecMsHashValueFunc, this, "Min:Sec:Ms" ); + unsigned pitchLabelFuncId = cmGrPageLabelFuncRegister( pgH, gvMidiSciPitchValueFunc, this, "Pitch" ); + + cmGrVExtSetD(&limExt,0,0,0,127); + cmGrObjSetWorldExt( cvH, cmGrRootObjH(cvH), &limExt ); + + cmGrObjSetWorldLimitExt(cvH, cmGrRootObjH(cvH), &limExt, kTopGrFl | kBottomGrFl ); + + axH = cmGrViewAxisHandle(vwH, kTopGrIdx); + cmGrAxisSetCfg( axH, cmClrFlag(cmGrAxisCfg( axH ), kHashMarkGrFl | kHashLabelGrFl )); + + axH = cmGrViewAxisHandle(vwH, kLeftGrIdx ); + cmGrAxisSetLabelFunc( axH, pitchLabelFuncId ); + cmGrViewSetLabelFunc( vwH, kLeftGrIdx, pitchLabelFuncId ); + + axH = cmGrViewAxisHandle(vwH, kRightGrIdx); + cmGrAxisSetCfg( axH, cmClrFlag(cmGrAxisCfg( axH ), kHashLabelGrFl )); + + cmGrViewSetCfg( vwH, cmSetFlag(cmGrViewCfg(vwH),kSelectHorzGrFl) ); + +} + +cmGrScFltk::~cmGrScFltk() +{ +} + +cmScMsgTypeId_t cmGrScFltk::recvScoreMsg( const void* msg, unsigned msgByteCnt ) +{ + cmScMsg_t m; + + cmScoreDecode(msg,msgByteCnt,&m); + + switch( m.typeId ) + { + case kBeginMsgScId: + { + _objId = 0; + _objSecs = 0; + // remove all objects from all views + //cmGrPageClear(pageHandle()); + //_srate = m.srate; + //_updateSeqMenu(m.seqCnt,m.seqId); + } + break; + + case kEndMsgScId: + //size(w(),h()+1); + break; + + case kEventMsgScId: + _insertEvent(&m.u.evt); + break; + + case kSectionMsgScId: + _insertSection(&m.u.sect); + break; + + case kVarMsgScId: + break; + + default: + { assert(0); } + } + + return m.typeId; +} + +void cmGrScFltk::setSampleRate( double srate ) +{ _srate = srate; } + +double cmGrScFltk::sampleRate() const +{ return _srate; } + +bool cmGrScFltk::on_plot_object( cmGrPlotCbArg_t* arg ) +{ + if( arg->selId==kStateChangeGrPlId && cmIsFlag(arg->deltaFlags,kSelectGrPlFl) ) + { + scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(arg->objH); + + if( sop!=NULL && sop->id==kEventMsgScId && sop->u.ep != NULL /* && sep->type == kBarEvtScId */ ) + { + _lastBarPlotObjH = arg->objH; + + unsigned scoreIdx = scoreSelectedEleIndex(); + + // callback to: kcApp::_ctl_cb(ctl_t* cp) + callback()(this,user_data()); + + _cmdIf->onScoreBarSelected(scoreIdx); + + setStatusText(cmTsPrintfS("Score Index:%i",scoreIdx)); + } + } + return true; +} + +void cmGrScFltk::selectBar( unsigned barNumb ) +{ + cmGrPlH_t plH = plotHandle(); + unsigned n = cmGrPlotObjectCount(plH); + unsigned i; + for(i=0; iid==kEventMsgScId && sop->u.ep!=NULL && sop->u.ep->type==kBarEvtScId && sop->u.ep->barNumb==barNumb ) + { + unsigned flags = cmGrPlotObjStateFlags(poH); + + cmGrPlotObjSetStateFlags(poH,cmSetFlag(flags,kFocusGrPlFl | kSelectGrPlFl)); + redraw(); + + _lastBarPlotObjH = poH; + + _cmdIf->onScoreBarSelected(sop->u.ep->locIdx); + + setStatusText(cmTsPrintfS("Score Index:%i",sop->u.ep->locIdx)); + + break; + } + } + } + +} + +unsigned cmGrScFltk::scoreSelectedEleIndex() const +{ + + if( cmGrPlotObjIsValid(_lastBarPlotObjH) ) + { + scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(_lastBarPlotObjH); + + if( sop!=NULL && sop->id==kEventMsgScId && sop->u.ep != NULL /* && sop->u.ep->type == kBarEvtScId */ ) + return sop->u.ep->locIdx; + } + return cmInvalidIdx; +} + +void cmGrScFltk::setScoreLocation( unsigned locIdx, unsigned vel, unsigned smpIdx ) +{ + +} + +void cmGrScFltk::_insertSection( const cmScoreSection_t* m ) +{ + // The argument is a serialzed copy of a cmScoreSection_t record. + // Convert it to a pointer to an actual object in the local score mgr. + if( cmGrPageIsValid(pageHandle()) == false ) + return; + + m = _cmdIf->scoreSectionIdToPtr(m->index); + assert(m!=NULL); + + const cmScoreEvt_t* ep = _cmdIf->scoreEventIdToPtr(m->begEvtIndex); + assert( ep != NULL ); + + + cmGrPlH_t plH = plotHandle(); + cmGrPgH_t pgH = pageHandle(); + unsigned vwIdx = 0; + cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx ); + cmGrH_t cvH = cmGrViewGrHandle( vwH ); + cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t objH = cmGrPlObjNullHandle; + cmGrPlObjTypeId_t objTypeId = kLineGrPlId; + cmReal_t x = ep->secs; + cmReal_t y = 120; + cmReal_t w = 0; + cmReal_t h = 7; + const cmChar_t* label = m->label; + unsigned flags = kNoDragGrPlFl; + cmGrVExt_t wext; + scObj_t scObj(m); + + cmGrVExtSetNull(&wext); + + if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, label, cmGrVExtIsNull(&wext)?NULL:&wext ) != kOkGrPlRC ) + { + cmErrMsg(&_err,kInsertObjFailRC,"Insert failed on a score section.", cmStringNullGuard(label)); + return; + } + + cmGrPlotObjAllocUser(objH,&scObj,sizeof(scObj)); + + unsigned f = 0 ? (kNorthJsGrFl | kTopJsGrFl) : (kSouthJsGrFl | kBottomJsGrFl); + cmGrPlotObjSetLabelAttr( objH, f | kWestJsGrFl | kTopJsGrFl | kRightJsGrFl, 0, kBlackGrId ); + cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kGreenGrId ); + //cmGrPlotObjSetPhysExt(objH, 1, 0, 1, 0 ); + cmGrPlotObjSetFontSize(objH,8); + + +} + +void cmGrScFltk::_insertEvent( const cmScoreEvt_t* m ) +{ + // The argument is a serialzed copy of a cmScoreEvt record. + // Convert it to a pointer to an actual object in the local score mgr. + if( cmGrPageIsValid(pageHandle()) == false ) + return; + + m = _cmdIf->scoreEventIdToPtr(m->index); + assert(m!=NULL); + + cmGrPlH_t plH = plotHandle(); + cmGrPgH_t pgH = pageHandle(); + unsigned vwIdx = 0; + cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx ); + cmGrH_t cvH = cmGrViewGrHandle( vwH ); + cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t objH = cmGrPlObjNullHandle; + cmGrPlObjTypeId_t objTypeId = kVLineGrPlId; + cmReal_t x = m->secs; + cmReal_t y = 0; + cmReal_t w = 0; + cmReal_t h = 127; + const cmChar_t* label = NULL; + unsigned flags = kNoDragGrPlFl; + int bufN = 7; + cmChar_t buf[bufN+1]; + cmGrVExt_t wext; + scObj_t scObj(m); + + cmGrVExtSetNull(&wext); + + switch( m->type ) + { + case kNonEvtScId: + objTypeId = kRectGrPlId; + y = m->pitch; + h = 1; + w = m->durSecs; + label = cmMidiToSciPitch(m->pitch,NULL,0); + break; + + case kBarEvtScId: + { + buf[bufN] = 0; + snprintf(buf,bufN,"%i",m->barNumb); + objTypeId = kVLineGrPlId; + label = buf; + } + break; + + case kPedalEvtScId: + if( cmIsFlag(m->flags, kPedalDnScFl ) == false ) + return; + + objTypeId = kRectGrPlId; + y = m->pitch; // pedal type (damper=64, sostenuto=66) is held in pitch + h = 1; + w = m->durSecs; + flags += kNoFillGrPlFl; + break; + + default: + return; + } + + + if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, label, cmGrVExtIsNull(&wext)?NULL:&wext ) != kOkGrPlRC ) + { + cmErrMsg(&_err,kInsertObjFailRC,"Insert failed on a score event.", cmStringNullGuard(label)); + return; + } + + cmGrPlotObjAllocUser(objH,&scObj,sizeof(scObj)); + + + switch( m->type ) + { + case kBarEvtScId: + { + unsigned f = _togFl ? (kNorthJsGrFl | kTopJsGrFl) : (kSouthJsGrFl | kBottomJsGrFl); + cmGrPlotObjSetLabelAttr( objH, f | kWestJsGrFl | kTopJsGrFl | kRightJsGrFl, 0, kBlueGrId ); + cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kYellowGrId ); + cmGrPlotObjSetPhysExt(objH, 1, 0, 1, 0 ); + _togFl = !_togFl; + } + break; + + case kNonEvtScId: + cmGrPlotObjSetLineColor( objH, kEnablePlGrId, cmGrPlotObjFillColor(objH,kEnablePlGrId) ); + cmGrPlotObjSetFontSize(objH,8); + break; + + case kPedalEvtScId: + cmGrPlotObjSetLineColor( objH, kEnablePlGrId, y==64 ? kDarkGreenGrId : kLightGreenGrId ); + break; + + default: + break; + } + + if( cmIsFlag(m->flags,kInvalidScFl) ) + { + cmGrPlotObjSetFillColor(objH, kEnablePlGrId, kRedGrId ); + } + +} + +void cmGrScFltk::_createMenu( ) +{ + int idx = _menuBar->add("Score",0,NULL,0,FL_SUBMENU); + const char* titleArray[] = { "Pitch", "Attributes", "Dynamics", "Location", "Fraction", "Section Even", "Section Dyn", "Section Tempo" }; + bool onFl[] = { true, false, false, false, false, false, false, false }; + int i; + for(i=0; iinsert(idx+1+i,titleArray[i],0,_s_menuCallback, _menuArray + i, FL_MENU_TOGGLE ); + + if( onFl[i] ) + { + Fl_Menu_Item* mip = (Fl_Menu_Item*)_menuBar->menu() + idx + i + 1; + mip->set(); + } + } +} + +bool cmGrScFltk::_isMenuChecked( int id ) +{ + unsigned i; + // locate the menu item assoc'd with id + for(i=0; ifind_index("Score")) == -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; +} + +void cmGrScFltk::_setEventLabels() +{ + enum { kPitchFl=0x01, kAttrFl=0x02, kDynFl=0x04, kLocFl=0x08, kFracFl=0x10 }; + + cmGrPlH_t plH = plotHandle(); + unsigned flags = 0; + flags |= _isMenuChecked(kPitchMId) ? kPitchFl : 0; + flags |= _isMenuChecked(kAttrMId) ? kAttrFl : 0; + flags |= _isMenuChecked(kDynMId) ? kDynFl : 0; + flags |= _isMenuChecked(kLocIdxMId) ? kLocFl : 0; + flags |= _isMenuChecked(kFracMId) ? kFracFl : 0; + + unsigned n = cmGrPlotObjectCount(plH); + unsigned i; + for(i=0; iid==kEventMsgScId && sop->u.ep!=NULL && sop->u.ep->type==kNonEvtScId ) + { + const cmScoreEvt_t* ep = sop->u.ep; + int bufN = 255; + cmChar_t buf[ bufN+1 ]; + + buf[bufN] = 0; + buf[0] = 0; + + if( cmIsFlag(flags,kPitchFl) ) + snprintf(buf+strlen(buf),bufN-strlen(buf),"%s ",cmMidiToSciPitch(ep->pitch,NULL,0)); + + if( cmIsFlag(flags,kAttrFl) ) + { + cmChar_t s[4]; + int j=0; + if( cmIsFlag(ep->flags,kEvenScFl) ) + s[j++] = 'e'; + if( cmIsFlag(ep->flags,kDynScFl) ) + s[j++] = 'd'; + if( cmIsFlag(ep->flags,kTempoScFl) ) + s[j++] = 't'; + s[j] = 0; + snprintf(buf+strlen(buf),bufN-strlen(buf),"%s ",s); + } + + + if( cmIsFlag(flags,kDynFl) && cmIsFlag(ep->flags,kDynScFl) ) + { + snprintf(buf+strlen(buf),bufN-strlen(buf),"d:%i",ep->dynVal); + + if( ep->perfDynLvl != 0 ) + snprintf(buf+strlen(buf),bufN-strlen(buf),"|%i ",ep->perfDynLvl); + else + snprintf(buf+strlen(buf),bufN-strlen(buf)," "); + } + + if( cmIsFlag(flags,kLocFl) ) + snprintf(buf+strlen(buf),bufN-strlen(buf),"loc:%i ",ep->locIdx); + + if( cmIsFlag(flags,kFracFl) && ep->frac != 0) + snprintf(buf+strlen(buf),bufN-strlen(buf),"%5.3f ",ep->frac); + + cmGrPlotObjSetLabel(poH, buf ); + } + } + } +} + +void cmGrScFltk::_setSectionLabels() +{ + enum { kEvenFl=0x01, kDynFl=0x02, kTempoFl=0x04 }; + + cmGrPlH_t plH = plotHandle(); + unsigned flags = 0; + flags |= _isMenuChecked(kSectEvenMId) ? kEvenFl : 0; + flags |= _isMenuChecked(kSectDynMId) ? kDynFl : 0; + flags |= _isMenuChecked(kSectTempoMId) ? kTempoFl : 0; + + unsigned n = cmGrPlotObjectCount(plH); + unsigned i; + for(i=0; iid==kSectionMsgScId && sop->u.sp!=NULL ) + { + const cmScoreSection_t* sp = sop->u.sp; + int bufN = 255; + cmChar_t buf[ bufN+1 ]; + + buf[bufN] = 0; + buf[0] = 0; + + snprintf(buf,bufN,"%s ",sp->label); + + if( cmIsFlag(flags,kEvenFl) && sp->vars[kEvenVarScId] != DBL_MAX) + snprintf(buf+strlen(buf),bufN-strlen(buf),"e:%f ",sp->vars[kEvenVarScId]); + + if( cmIsFlag(flags,kDynFl) && sp->vars[kDynVarScId] != DBL_MAX) + snprintf(buf+strlen(buf),bufN-strlen(buf),"d:%f ",sp->vars[kDynVarScId]); + + if( cmIsFlag(flags,kTempoFl) && sp->vars[kTempoVarScId] != DBL_MAX) + snprintf(buf+strlen(buf),bufN-strlen(buf),"t:%f ",sp->vars[kTempoVarScId]); + + cmGrPlotObjSetLabel(poH, buf ); + } + } + } + +} + +void cmGrScFltk::_s_menuCallback(Fl_Widget* w, void* arg ) +{ + item_t* ip = (item_t*)arg; + cmGrScFltk* p = ip->p; + unsigned long id = ip->id; + + switch( id ) + { + case kPitchMId: + case kAttrMId: + case kDynMId: + case kLocIdxMId: + case kFracMId: + { + p->_setEventLabels(); + p->redraw(); + } + break; + + case kSectEvenMId: + case kSectDynMId: + case kSectTempoMId: + { + p->_setSectionLabels(); + p->redraw(); + } + break; + } +} + diff --git a/src/tlCtl/cmGrScFltk.h b/src/tlCtl/cmGrScFltk.h new file mode 100644 index 0000000..9c170e1 --- /dev/null +++ b/src/tlCtl/cmGrScFltk.h @@ -0,0 +1,89 @@ +#ifndef cmGrScFltk_h +#define cmGrScFltk_h + +class Fl_Menu_Bar; +class cmdIf; + +class cmGrScFltk : public cmGrPlotFltk, public gvHashFuncArg +{ + public: + cmGrScFltk(cmCtx_t* ctx, cmdIf* cp, Fl_Menu_Bar* menuBar, int x, int y, int w, int h); + virtual ~cmGrScFltk(); + + virtual cmScMsgTypeId_t recvScoreMsg( const void* msg, unsigned msgByteCnt ); + + void setSampleRate( double srate ); + virtual double sampleRate() const; + + virtual bool on_plot_object( cmGrPlotCbArg_t* arg ); + + virtual void selectBar( unsigned barNumb ); + + virtual unsigned scoreSelectedEleIndex() const; + + virtual void setScoreLocation( unsigned locIdx, unsigned vel, unsigned smpIdx ); + + private: + enum + { + kOkRC, + kInsertObjFailRC + }; + + enum + { + kPitchMId, + kAttrMId, + kDynMId, + kLocIdxMId, + kFracMId, + kSectEvenMId, + kSectDynMId, + kSectTempoMId, + kMenuItemCnt + }; + + typedef struct + { + cmGrScFltk* p; + int id; + } item_t; + + typedef struct scObj_str + { + cmScMsgTypeId_t id; // kEventMsgScId | kSectionMsgScId + union + { + const cmScoreEvt_t* ep; + const cmScoreSection_t* sp; + } u; + + scObj_str( const cmScoreEvt_t* e) : id(kEventMsgScId) {u.ep=e;} + scObj_str( const cmScoreSection_t* s) : id(kSectionMsgScId) {u.sp=s;} + } scObj_t; + + double _srate; + cmErr_t _err; + cmdIf* _cmdIf; + Fl_Menu_Bar* _menuBar; + unsigned _samplesMetricId; + unsigned _secondsMetricId; + double _objSecs; + unsigned _objId; + bool _togFl; + cmGrPlObjH_t _lastBarPlotObjH; + item_t _menuArray[ kMenuItemCnt ]; + + void _insertSection( const cmScoreSection_t* s ); + void _insertEvent( const cmScoreEvt_t* m ); + void _createMenu(); + bool _isMenuChecked( int id ); + void _setEventLabels(); + void _setSectionLabels(); + + static void _s_menuCallback(Fl_Widget* w, void* arg); + +}; + + +#endif diff --git a/src/tlCtl/cmGrTksbFltk.cpp b/src/tlCtl/cmGrTksbFltk.cpp new file mode 100644 index 0000000..c37120f --- /dev/null +++ b/src/tlCtl/cmGrTksbFltk.cpp @@ -0,0 +1,695 @@ +#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 "cmSymTbl.h" +#include "cmTime.h" +#include "cmMidi.h" +#include "cmMidiFile.h" +#include "cmAudioFile.h" +#include "cmAudioFileMgr.h" +#include "cmTimeLine.h" +#include "cmScore.h" +#include "cmTakeSeqBldr.h" + +#include "cmGr.h" +#include "cmGrDevCtx.h" +#include "cmGrPlot.h" +#include "cmGrPage.h" +#include "cmGrFltk.h" +#include "gvHashFunc.h" +#include "cmGrTksbFltk.h" +#include "cmGrPlotAudio.h" +#include "cmdIf.h" + +cmGrTksbFltk::cmGrTksbFltk(cmCtx_t* ctx, cmdIf* cp, Fl_Menu_Bar* menu, int x, int y, int w, int h) + : cmGrPlotFltk(ctx,x,y,w,h), + //_cmdIf(cp), + _tksbH(cmTakeSeqBldrNullHandle), + _menuBar(menu), + _samplesMetricId(cmInvalidId),_secondsMetricId(cmInvalidId), + //_objSecs(0), + _objId(0), + //_togFl(true), + _lastBarPlotObjH(cmGrPlObjNullHandle), + _nextTakeY(5), + _curCbTId(kInvalidTId) +{ + cmErrSetup(&_err,&ctx->rpt,"cmGrTksbFltk"); + + _createMenu(); + + if( cmGrPageIsValid(pageHandle()) == false ) + return; + + initViews(1,1); + + unsigned vwIdx = 0; + cmGrPgH_t pgH = pageHandle(); + cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx); + cmGrH_t cvH = cmGrViewGrHandle( vwH ); + cmGrAxH_t axH = cmGrAxNullHandle; + cmGrVExt_t limExt; + + _samplesMetricId = cmGrPageLabelFuncRegister( pgH, gvRoundHashValueFunc, this, "Round" ); + _secondsMetricId = cmGrPageLabelFuncRegister( pgH, gvMinSecMsHashValueFunc, this, "Min:Sec:Ms" ); + unsigned pitchLabelFuncId = cmGrPageLabelFuncRegister( pgH, gvMidiSciPitchValueFunc, this, "Pitch" ); + + cmGrVExtSetD(&limExt,0,0,0,127); + cmGrObjSetWorldExt( cvH, cmGrRootObjH(cvH), &limExt ); + + cmGrObjSetWorldLimitExt(cvH, cmGrRootObjH(cvH), &limExt, kTopGrFl | kBottomGrFl ); + + axH = cmGrViewAxisHandle(vwH, kTopGrIdx); + cmGrAxisSetCfg( axH, cmClrFlag(cmGrAxisCfg( axH ), kHashMarkGrFl | kHashLabelGrFl )); + + axH = cmGrViewAxisHandle(vwH, kLeftGrIdx ); + cmGrAxisSetLabelFunc( axH, pitchLabelFuncId ); + cmGrViewSetLabelFunc( vwH, kLeftGrIdx, pitchLabelFuncId ); + + axH = cmGrViewAxisHandle(vwH, kRightGrIdx); + cmGrAxisSetCfg( axH, cmClrFlag(cmGrAxisCfg( axH ), kHashLabelGrFl )); + + cmGrViewSetCfg( vwH, cmSetFlag(cmGrViewCfg(vwH),kSelectHorzGrFl) ); + +} + +cmGrTksbFltk::~cmGrTksbFltk() +{ +} + +void _cmGrTksbRecvScoreMsg( void* cbArg, const void* msg, unsigned msgByteCnt ) +{ + cmGrTksbFltk* thisPtr = (cmGrTksbFltk*)cbArg; + thisPtr->recvScoreMsg(msg,msgByteCnt); +} + +void cmGrTksbFltk::setTksbHandle( void* v ) +{ + _tksbH.h = v; + + + if( cmTakeSeqBldrIsValid(_tksbH) == false ) + return; + + // load the score plot objects + cmScoreSeqNotifyCb(cmTakeSeqBldrScoreHandle(_tksbH),_cmGrTksbRecvScoreMsg, this ); + + // get the count of score-track takes + unsigned n = cmTakeSeqBldrScTrkTakeCount(_tksbH); + + // for each score-track take + for(unsigned i=0; iselId!=kStateChangeGrPlId || cmIsNotFlag(arg->deltaFlags,kSelectGrPlFl) ) + return true; + + scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(arg->objH); + unsigned state = cmGrPlotObjStateFlags(arg->objH); + bool isSelectedFl = cmIsFlag( state, kSelectGrPlFl); + + if( sop == NULL ) + return true; + + //printf("SELECT:%i %i 0x%x\n",cmGrPlotObjId(arg->objH),isSelectedFl,state); + + if( sop->id==kTakeTksbId && sop->u.tlMarkerUid!=cmInvalidId ) + { + if( isSelectedFl ) + cmTakeSeqBldrLoadTake(_tksbH,sop->u.tlMarkerUid,true); + else + cmTakeSeqBldrUnloadTake(_tksbH,sop->u.tlMarkerUid); + + setStatusText(cmTsPrintfS("%s", cmStringNullGuard(cmTakeSeqBldrScTrkTakeText(_tksbH,sop->u.tlMarkerUid)))); + + _curCbTId = kRefreshTId; + + // callback to: kcApp::_ctl_cb(ctl_t* cp) + callback()(this,user_data()); + + } + + if( sop->id==kEventTksbId && sop->u.ep!=NULL && sop->u.ep->type==kBarEvtScId ) + { + _lastBarPlotObjH = arg->objH; + + _curCbTId = kSelectTId; + + // callback to: kcApp::_ctl_cb(ctl_t* cp) + callback()(this,user_data()); + } + + return true; +} + +cmGrTksbFltk::cbTId_t cmGrTksbFltk::cbTypeId() const +{ return _curCbTId; } + +unsigned cmGrTksbFltk::scoreSelectedEleIndex() const +{ + + if( cmGrPlotObjIsValid(_lastBarPlotObjH) ) + { + scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(_lastBarPlotObjH); + + if( sop!=NULL && sop->id==kEventTksbId && sop->u.ep != NULL && sop->u.ep->type == kBarEvtScId ) + { + return sop->u.ep->locIdx; + } + } + return cmInvalidIdx; +} + +void cmGrTksbFltk::setScoreLocation( unsigned locIdx, unsigned vel, unsigned smpIdx ) +{ + +} + +void cmGrTksbFltk::_insertSection( const cmScoreSection_t* m ) +{ + // The argument is a serialzed copy of a cmScoreSection_t record. + // Convert it to a pointer to an actual object in the local score mgr. + if( cmGrPageIsValid(pageHandle()) == false ) + return; + + m = cmScoreSection(cmTakeSeqBldrScoreHandle(_tksbH),m->index); + assert(m!=NULL); + + const cmScoreEvt_t* ep = cmScoreEvt( cmTakeSeqBldrScoreHandle(_tksbH), m->begEvtIndex); + assert( ep != NULL ); + + cmGrPlH_t plH = plotHandle(); + cmGrPgH_t pgH = pageHandle(); + unsigned vwIdx = 0; + cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx ); + cmGrH_t cvH = cmGrViewGrHandle( vwH ); + cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t objH = cmGrPlObjNullHandle; + cmGrPlObjTypeId_t objTypeId = kLineGrPlId; + cmReal_t x = ep->secs; + cmReal_t y = 120; + cmReal_t w = 0; + cmReal_t h = 7; + const cmChar_t* label = m->label; + unsigned flags = kNoDragGrPlFl; + cmGrVExt_t wext; + scObj_t scObj(m); + + cmGrVExtSetNull(&wext); + + if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, label, cmGrVExtIsNull(&wext)?NULL:&wext ) != kOkGrPlRC ) + { + cmErrMsg(&_err,kInsertObjFailRC,"Insert failed on a score section.", cmStringNullGuard(label)); + return; + } + + cmGrPlotObjAllocUser(objH,&scObj,sizeof(scObj)); + + unsigned f = 0 ? (kNorthJsGrFl | kTopJsGrFl) : (kSouthJsGrFl | kBottomJsGrFl); + cmGrPlotObjSetLabelAttr( objH, f | kWestJsGrFl | kTopJsGrFl | kRightJsGrFl, 0, kBlackGrId ); + cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kGreenGrId ); + //cmGrPlotObjSetPhysExt(objH, 1, 0, 1, 0 ); + cmGrPlotObjSetFontSize(objH,8); + + +} + +void cmGrTksbFltk::_insertEvent( const cmScoreEvt_t* m ) +{ + // The argument is a serialzed copy of a cmScoreEvt record. + // Convert it to a pointer to an actual object in the local score mgr. + if( cmGrPageIsValid(pageHandle()) == false ) + return; + + // Get a pointer to the score event + m = cmScoreEvt( cmTakeSeqBldrScoreHandle(_tksbH), m->index ); + assert(m!=NULL); + + cmGrPlH_t plH = plotHandle(); + cmGrPgH_t pgH = pageHandle(); + unsigned vwIdx = 0; + cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx ); + cmGrH_t cvH = cmGrViewGrHandle( vwH ); + cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t objH = cmGrPlObjNullHandle; + cmGrPlObjTypeId_t objTypeId = kVLineGrPlId; + cmReal_t x = m->secs; + cmReal_t y = 0; + cmReal_t w = 0; + cmReal_t h = 127; + const cmChar_t* label = NULL; + unsigned flags = kNoDragGrPlFl; + int bufN = 7; + cmChar_t buf[bufN+1]; + cmGrVExt_t wext; + scObj_t scObj(m); + + cmGrVExtSetNull(&wext); + + switch( m->type ) + { + case kNonEvtScId: + objTypeId = kRectGrPlId; + y = m->pitch; + h = 1; + w = m->durSecs; + label = cmMidiToSciPitch(m->pitch,NULL,0); + break; + + case kPedalEvtScId: + objTypeId = kRectGrPlId; + y = 108; + h = 2; + w = m->durSecs; + label = "pedal"; + break; + + case kBarEvtScId: + { + buf[bufN] = 0; + snprintf(buf,bufN,"%i",m->barNumb); + objTypeId = kVLineGrPlId; + label = buf; + } + break; + + default: + return; + } + + + // create the plot object to represent this event + if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, label, cmGrVExtIsNull(&wext)?NULL:&wext ) != kOkGrPlRC ) + { + cmErrMsg(&_err,kInsertObjFailRC,"Insert failed on a score event.", cmStringNullGuard(label)); + return; + } + + // store the score event reference as custom data inside the plot object + cmGrPlotObjAllocUser(objH,&scObj,sizeof(scObj)); + + + switch( m->type ) + { + case kBarEvtScId: + { + unsigned f = _togFl ? (kNorthJsGrFl | kTopJsGrFl) : (kSouthJsGrFl | kBottomJsGrFl); + cmGrPlotObjSetLabelAttr( objH, f | kWestJsGrFl | kTopJsGrFl | kRightJsGrFl, 0, kBlueGrId ); + cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kYellowGrId ); + cmGrPlotObjSetPhysExt(objH, 1, 0, 1, 0 ); + _togFl = !_togFl; + } + break; + + case kNonEvtScId: + cmGrPlotObjSetLineColor( objH, kEnablePlGrId, cmGrPlotObjFillColor(objH,kEnablePlGrId) ); + cmGrPlotObjSetFontSize(objH,8); + break; + + case kPedalEvtScId: + cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kDeepPinkGrId ); + cmGrPlotObjSetFillColor(objH, kEnablePlGrId, kDeepPinkGrId ); + cmGrPlotObjSetFontSize(objH,8); + break; + + default: + break; + } + + if( cmIsFlag(m->flags,kInvalidScFl) ) + { + cmGrPlotObjSetFillColor(objH, kEnablePlGrId, kRedGrId ); + } + +} + +void cmGrTksbFltk::_insertTake( const cmTksbScTrkTake_t* take ) +{ + + cmGrPlH_t plH = plotHandle(); + cmGrPgH_t pgH = pageHandle(); + unsigned vwIdx = 0; + cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx ); + cmGrH_t cvH = cmGrViewGrHandle( vwH ); + cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t objH = cmGrPlObjNullHandle; + cmGrPlObjTypeId_t objTypeId = kRectGrPlId; + cmReal_t x = 0; + cmReal_t y = 0; + cmReal_t w = 0; + cmReal_t h = 127; + const cmChar_t* label = NULL; + unsigned flags = kNoDragGrPlFl | kNoFillGrPlFl; + int bufN = 7; + cmChar_t buf[bufN+1]; + cmGrVExt_t wext; + cmGrVExt_t vext; + scObj_t scObj(take->tlMarkerUid); + + cmGrVExtSetNull(&wext); + + if( cmGrPlotObjIsValid(objH = _scEvtIdxToPlotObj( take->minScEvtIdx ))==false ) + return; + + cmGrPlotObjVExt( objH, &vext); + + x = cmGrVExtMinX(&vext); + + if( cmGrPlotObjIsValid(objH = _scEvtIdxToPlotObj( take->maxScEvtIdx )) == false ) + return; + + cmGrPlotObjVExt( objH, &vext); + + w = cmGrVExtMaxX(&vext) - x; + h = 1; + y = _nextTakeY; + + + buf[bufN] = 0; + snprintf(buf,bufN,"%i",(_nextTakeY-5)/2); + label = buf; + + _nextTakeY += 2; + if( _nextTakeY > 120 ) + _nextTakeY = 5; + + // create the plot object to represent this event + if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, label, cmGrVExtIsNull(&wext)?NULL:&wext ) != kOkGrPlRC ) + { + cmErrMsg(&_err,kInsertObjFailRC,"Insert failed on score-track take.", cmStringNullGuard(label)); + return; + } + + // store the score event reference as custom data inside the plot object + cmGrPlotObjAllocUser(objH,&scObj,sizeof(scObj)); + + + cmGrPlotObjSetLineColor( objH, kFocusPlGrId, kRedGrId ); + cmGrPlotObjSetLineColor( objH, kSelectPlGrId, kDeepPinkGrId ); + cmGrPlotObjSetFontSize(objH,8); + +} + +#define cmMENU_TITLE "Bldr" +void cmGrTksbFltk::_createMenu( ) +{ + int idx = _menuBar->add(cmMENU_TITLE,0,NULL,0,FL_SUBMENU); + const char* titleArray[] = { "Pitch", "Attributes", "Dynamics", "Location", "Fraction", "Section Even", "Section Dyn", "Section Tempo" }; + bool onFl[] = { true, false, false, false, false, false, false, false }; + int i; + for(i=0; iinsert(idx+1+i,titleArray[i],0,_s_menuCallback, _menuArray + i, FL_MENU_TOGGLE ); + + if( onFl[i] ) + { + Fl_Menu_Item* mip = (Fl_Menu_Item*)_menuBar->menu() + idx + i + 1; + mip->set(); + } + } + + _menuBar->redraw(); + +} + +bool cmGrTksbFltk::_isMenuChecked( int id ) +{ + unsigned i; + // locate the menu item assoc'd with id + for(i=0; ifind_index(cmMENU_TITLE)) == -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; +} + +void cmGrTksbFltk::_setEventLabels() +{ + enum { kPitchFl=0x01, kAttrFl=0x02, kDynFl=0x04, kLocFl=0x08, kFracFl }; + + cmGrPlH_t plH = plotHandle(); + unsigned flags = 0; + flags |= _isMenuChecked(kPitchMId) ? kPitchFl : 0; + flags |= _isMenuChecked(kAttrMId) ? kAttrFl : 0; + flags |= _isMenuChecked(kDynMId) ? kDynFl : 0; + flags |= _isMenuChecked(kLocIdxMId) ? kLocFl : 0; + flags |= _isMenuChecked(kFracMId) ? kFracFl : 0; + + unsigned n = cmGrPlotObjectCount(plH); + unsigned i; + for(i=0; iid==kEventTksbId && sop->u.ep!=NULL && sop->u.ep->type==kNonEvtScId ) + { + const cmScoreEvt_t* ep = sop->u.ep; + int bufN = 255; + cmChar_t buf[ bufN+1 ]; + + buf[bufN] = 0; + buf[0] = 0; + + if( cmIsFlag(flags,kPitchFl) ) + snprintf(buf+strlen(buf),bufN-strlen(buf),"%s ",cmMidiToSciPitch(ep->pitch,NULL,0)); + + if( cmIsFlag(flags,kAttrFl) ) + { + cmChar_t s[4]; + int j=0; + if( cmIsFlag(ep->flags,kEvenScFl) ) + s[j++] = 'e'; + if( cmIsFlag(ep->flags,kDynScFl) ) + s[j++] = 'd'; + if( cmIsFlag(ep->flags,kTempoScFl) ) + s[j++] = 't'; + s[j] = 0; + snprintf(buf+strlen(buf),bufN-strlen(buf),"%s ",s); + } + + + if( cmIsFlag(flags,kDynFl) && cmIsFlag(ep->flags,kDynScFl) ) + { + snprintf(buf+strlen(buf),bufN-strlen(buf),"d:%i",ep->dynVal); + + if( ep->perfDynLvl != 0 ) + snprintf(buf+strlen(buf),bufN-strlen(buf),"|%i ",ep->perfDynLvl); + else + snprintf(buf+strlen(buf),bufN-strlen(buf)," "); + } + + if( cmIsFlag(flags,kLocFl) ) + snprintf(buf+strlen(buf),bufN-strlen(buf),"loc:%i ",ep->locIdx); + + if( cmIsFlag(flags,kFracFl) && ep->frac != 0) + snprintf(buf+strlen(buf),bufN-strlen(buf),"%5.3f ",ep->frac); + + cmGrPlotObjSetLabel(poH, buf ); + } + } + } +} + +void cmGrTksbFltk::_setSectionLabels() +{ + enum { kEvenFl=0x01, kDynFl=0x02, kTempoFl=0x04 }; + + cmGrPlH_t plH = plotHandle(); + unsigned flags = 0; + flags |= _isMenuChecked(kSectEvenMId) ? kEvenFl : 0; + flags |= _isMenuChecked(kSectDynMId) ? kDynFl : 0; + flags |= _isMenuChecked(kSectTempoMId) ? kTempoFl : 0; + + unsigned n = cmGrPlotObjectCount(plH); + unsigned i; + for(i=0; iid==kSectionTksbId && sop->u.sp!=NULL ) + { + const cmScoreSection_t* sp = sop->u.sp; + int bufN = 255; + cmChar_t buf[ bufN+1 ]; + + buf[bufN] = 0; + buf[0] = 0; + + snprintf(buf,bufN,"%s ",sp->label); + + if( cmIsFlag(flags,kEvenFl) && sp->vars[kEvenVarScId] != DBL_MAX) + snprintf(buf+strlen(buf),bufN-strlen(buf),"e:%f ",sp->vars[kEvenVarScId]); + + if( cmIsFlag(flags,kDynFl) && sp->vars[kDynVarScId] != DBL_MAX) + snprintf(buf+strlen(buf),bufN-strlen(buf),"d:%f ",sp->vars[kDynVarScId]); + + if( cmIsFlag(flags,kTempoFl) && sp->vars[kTempoVarScId] != DBL_MAX) + snprintf(buf+strlen(buf),bufN-strlen(buf),"t:%f ",sp->vars[kTempoVarScId]); + + cmGrPlotObjSetLabel(poH, buf ); + } + } + } + +} + +void cmGrTksbFltk::_s_menuCallback(Fl_Widget* w, void* arg ) +{ + item_t* ip = (item_t*)arg; + cmGrTksbFltk* p = ip->p; + unsigned long id = ip->id; + + switch( id ) + { + case kPitchMId: + case kAttrMId: + case kDynMId: + case kLocIdxMId: + case kFracMId: + { + p->_setEventLabels(); + p->redraw(); + } + break; + + case kSectEvenMId: + case kSectDynMId: + case kSectTempoMId: + { + p->_setSectionLabels(); + p->redraw(); + } + break; + } +} + +cmGrPlObjH_t cmGrTksbFltk::_scEvtIdxToPlotObj( unsigned scEvtIdx ) +{ + cmGrPlH_t plH = plotHandle(); + unsigned n = cmGrPlotObjectCount(plH); + unsigned i; + cmGrPlObjH_t poH; + scObj_t* sop; + + for(i=0; iid == kEventTksbId + && sop->u.ep->index == scEvtIdx ) + { + return poH; + } + + + return cmGrPlObjNullHandle; +} + diff --git a/src/tlCtl/cmGrTksbFltk.h b/src/tlCtl/cmGrTksbFltk.h new file mode 100644 index 0000000..ed63632 --- /dev/null +++ b/src/tlCtl/cmGrTksbFltk.h @@ -0,0 +1,110 @@ +#ifndef cmGrTksbFltk_h +#define cmGrTksbFltk_h + +class Fl_Menu_Bar; +class cmdIf; + +class cmGrTksbFltk : public cmGrPlotFltk, public gvHashFuncArg +{ + public: + cmGrTksbFltk(cmCtx_t* ctx, cmdIf* cp, Fl_Menu_Bar* menuBar, int x, int y, int w, int h); + virtual ~cmGrTksbFltk(); + + void setTksbHandle( void* vp ); + + virtual cmScMsgTypeId_t recvScoreMsg( const void* msg, unsigned msgByteCnt ); + + virtual double sampleRate() const; + + virtual bool on_plot_object( cmGrPlotCbArg_t* arg ); + + typedef enum + { + kInvalidTId, + kSelectTId, + kRefreshTId, + } cbTId_t; + + cbTId_t cbTypeId() const; + + virtual unsigned scoreSelectedEleIndex() const; + + virtual void setScoreLocation( unsigned locIdx, unsigned vel, unsigned smpIdx ); + + private: + enum + { + kOkRC, + kInsertObjFailRC + }; + + enum + { + kPitchMId, + kAttrMId, + kDynMId, + kLocIdxMId, + kFracMId, + kSectEvenMId, + kSectDynMId, + kSectTempoMId, + kMenuItemCnt + }; + + typedef struct + { + cmGrTksbFltk* p; + int id; + } item_t; + + typedef enum + { + kEventTksbId, + kSectionTksbId, + kTakeTksbId + } tksbId_t; + + typedef struct scObj_str + { + tksbId_t id; + union + { + const cmScoreEvt_t* ep; + const cmScoreSection_t* sp; + unsigned tlMarkerUid; + } u; + + scObj_str( const cmScoreEvt_t* e) : id(kEventTksbId) { u.ep=e;} + scObj_str( const cmScoreSection_t* s) : id(kSectionTksbId) { u.sp=s;} + scObj_str( unsigned i ) : id(kTakeTksbId) { u.tlMarkerUid=i;} + } scObj_t; + + cmErr_t _err; + //cmdIf* _cmdIf; + cmTakeSeqBldrH_t _tksbH; + Fl_Menu_Bar* _menuBar; + unsigned _samplesMetricId; + unsigned _secondsMetricId; + double _objSecs; + unsigned _objId; + bool _togFl; + cmGrPlObjH_t _lastBarPlotObjH; + item_t _menuArray[ kMenuItemCnt ]; + unsigned _nextTakeY; + cbTId_t _curCbTId; + + void _insertSection( const cmScoreSection_t* s ); + void _insertEvent( const cmScoreEvt_t* m ); + void _insertTake( const cmTksbScTrkTake_t* take ); + void _createMenu(); + bool _isMenuChecked( int id ); + void _setEventLabels(); + void _setSectionLabels(); + cmGrPlObjH_t _scEvtIdxToPlotObj( unsigned scEvtIdx ); + + static void _s_menuCallback(Fl_Widget* w, void* arg); + +}; + + +#endif diff --git a/src/tlCtl/cmGrTksrFltk.cpp b/src/tlCtl/cmGrTksrFltk.cpp new file mode 100644 index 0000000..45adcf4 --- /dev/null +++ b/src/tlCtl/cmGrTksrFltk.cpp @@ -0,0 +1,461 @@ +#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 "cmSymTbl.h" +#include "cmTime.h" +#include "cmMidi.h" +#include "cmMidiFile.h" +#include "cmAudioFile.h" +#include "cmAudioFileMgr.h" +#include "cmTimeLine.h" +#include "cmScore.h" +#include "cmTakeSeqBldr.h" + +#include "cmGr.h" +#include "cmGrDevCtx.h" +#include "cmGrPlot.h" +#include "cmGrPage.h" +#include "cmGrFltk.h" +#include "gvHashFunc.h" +#include "cmGrTksrFltk.h" +#include "cmGrPlotAudio.h" +#include "cmdIf.h" + +cmGrTksrFltk::cmGrTksrFltk(cmCtx_t* ctx, cmdIf* cp, Fl_Menu_Bar* menu, int x, int y, int w, int h) + : cmGrPlotFltk(ctx,x,y,w,h), + //_cmdIf(cp), + _tksbH(cmTakeSeqBldrNullHandle), + _menuBar(menu), + _samplesMetricId(cmInvalidId),_secondsMetricId(cmInvalidId), + //_objSecs(0), + _objId(0) + //_togFl(true) +{ + cmErrSetup(&_err,&ctx->rpt,"cmGrTksrFltk"); + + _createMenu(); + + if( cmGrPageIsValid(pageHandle()) == false ) + return; + + initViews(1,1); + + unsigned vwIdx = 0; + cmGrPgH_t pgH = pageHandle(); + cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx); + cmGrH_t cvH = cmGrViewGrHandle( vwH ); + cmGrAxH_t axH = cmGrAxNullHandle; + cmGrVExt_t limExt; + + _samplesMetricId = cmGrPageLabelFuncRegister( pgH, gvRoundHashValueFunc, this, "Round" ); + _secondsMetricId = cmGrPageLabelFuncRegister( pgH, gvMinSecMsHashValueFunc, this, "Min:Sec:Ms" ); + unsigned pitchLabelFuncId = cmGrPageLabelFuncRegister( pgH, gvMidiSciPitchValueFunc, this, "Pitch" ); + + cmGrVExtSetD(&limExt,0,0,0,127); + cmGrObjSetWorldExt( cvH, cmGrRootObjH(cvH), &limExt ); + + cmGrObjSetWorldLimitExt(cvH, cmGrRootObjH(cvH), &limExt, kTopGrFl | kBottomGrFl ); + + axH = cmGrViewAxisHandle(vwH, kTopGrIdx); + cmGrAxisSetCfg( axH, cmClrFlag(cmGrAxisCfg( axH ), kHashMarkGrFl | kHashLabelGrFl )); + + axH = cmGrViewAxisHandle(vwH, kLeftGrIdx ); + cmGrAxisSetLabelFunc( axH, pitchLabelFuncId ); + cmGrViewSetLabelFunc( vwH, kLeftGrIdx, pitchLabelFuncId ); + + axH = cmGrViewAxisHandle(vwH, kRightGrIdx); + cmGrAxisSetCfg( axH, cmClrFlag(cmGrAxisCfg( axH ), kHashLabelGrFl )); + + cmGrViewSetCfg( vwH, cmSetFlag(cmGrViewCfg(vwH),kSelectHorzGrFl) ); + +} + +cmGrTksrFltk::~cmGrTksrFltk() +{} + + +void cmGrTksrFltk::setTksbHandle( void* v ) +{ + _tksbH.h = v; +} + +void cmGrTksrFltk::refresh() +{ + if( cmGrPlotClear( plotHandle() ) != kOkGrPlRC ) + { + cmErrMsg(&_err,kClearPlotFailRC,"Plot clear failed."); + return; + } + + if( cmTakeSeqBldrIsValid(_tksbH) == false ) + return; + + // insert tksb events here + cmTakeSeqBldrRendReset(_tksbH); + + cmTksbRend_t m; + unsigned absSmpIdx = 0; + double srate = cmTakeSeqBldrSampleRate(_tksbH); + while( cmTakeSeqBldrRendNext(_tksbH,&m) ) + { + m.evt.smpIdx = absSmpIdx; + _insertEvent(&m,srate); + absSmpIdx += m.offsetSmp; + } +} + +double cmGrTksrFltk::sampleRate() const +{ + if( cmTakeSeqBldrIsValid(_tksbH) ) + return cmTakeSeqBldrSampleRate(_tksbH); + return 0; +} + +bool cmGrTksrFltk::on_plot_object( cmGrPlotCbArg_t* arg ) +{ + /* + if( arg->selId==kStateChangeGrPlId && cmIsFlag(arg->deltaFlags,kSelectGrPlFl) ) + { + scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(arg->objH); + unsigned state = cmGrPlotObjStateFlags(arg->objH); + bool isSelectedFl = cmIsFlag( state, kSelectGrPlFl); + + if( sop != NULL ) + { + + //printf("SELECT:%i %i 0x%x\n",cmGrPlotObjId(arg->objH),isSelectedFl,state); + + if( sop->id==kTakeTksrId && sop->u.tlMarkerUid!=cmInvalidId ) + { + if( isSelectedFl ) + cmTakeSeqBldrLoadTake(_tksbH,sop->u.tlMarkerUid,true); + else + cmTakeSeqBldrUnloadTake(_tksbH,sop->u.tlMarkerUid); + + setStatusText(cmTsPrintfS("%s", cmStringNullGuard(cmTakeSeqBldrScTrkTakeText(_tksbH,sop->u.tlMarkerUid)))); + } + + if( sop->id==kEventTksrId && sop->u.ep!=NULL && sop->u.ep->type==kBarEvtScId ) + { + _lastBarPlotObjH = arg->objH; + + // callback to: kcApp::_ctl_cb(ctl_t* cp) + callback()(this,user_data()); + } + } + + + } + */ + return true; +} + + +void cmGrTksrFltk::_insertEvent( const cmTksbRend_t* m, double srate ) +{ + if( cmGrPageIsValid(pageHandle()) == false ) + return; + + cmGrPlH_t plH = plotHandle(); + cmGrPgH_t pgH = pageHandle(); + unsigned vwIdx = 0; + cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx ); + cmGrH_t cvH = cmGrViewGrHandle( vwH ); + cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle; + cmGrPlObjH_t objH = cmGrPlObjNullHandle; + cmGrPlObjTypeId_t objTypeId = kRectGrPlId; + cmReal_t x = m->evt.smpIdx / srate; + cmReal_t y = 0; + cmReal_t h = 1; + cmReal_t w = m->durSmp / srate; + const cmChar_t* label = NULL; + unsigned flags = kNoDragGrPlFl; + tksrId_t tid = kInvalidTksrId; + + + if( cmMidiIsNoteOn(m->evt.status) ) + { + tid = kNoteTksrId; + y = m->evt.d0; + label = cmMidiToSciPitch(m->evt.d0,NULL,0); + } + else + { + if( cmMidiIsPedalDown(m->evt.status,m->evt.d0,m->evt.d1) ) + { + tid = kPedalTksrId; + y = 120; + label = cmMidiPedalLabel(m->evt.d0); + flags |= kNoFillGrPlFl; + } + } + + if( tid == kInvalidTksrId ) + return; + + //printf("absSmpIdx:%f %f\n",x,w); + + + // create the plot object to represent this event + if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, label, NULL ) != kOkGrPlRC ) + { + cmErrMsg(&_err,kInsertObjFailRC,"Insert failed on a score event.", cmStringNullGuard(label)); + return; + } + + // store the score event reference as custom data inside the plot object + scObj_t scObj(tid,m->rid); + cmGrPlotObjAllocUser(objH,&scObj,sizeof(scObj)); + + + switch( tid ) + { + case kNoteTksrId: + cmGrPlotObjSetLineColor( objH, kEnablePlGrId, cmGrPlotObjFillColor(objH,kEnablePlGrId) ); + cmGrPlotObjSetFontSize(objH,8); + break; + + case kPedalTksrId: + cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kDeepPinkGrId ); + cmGrPlotObjSetFontSize(objH,8); + break; + + default: + break; + } + + +} + +#define cmMENU_TITLE "Rndr" +void cmGrTksrFltk::_createMenu( ) +{ + int idx = _menuBar->add(cmMENU_TITLE,0,NULL,0,FL_SUBMENU); + const char* titleArray[] = { "Pitch", "ScEvtIdx", "Delete", "Sustain", "Sostenuto", "Write", "Read" }; + bool onFl[] = { true, false, false, false, false, false, false }; + bool checkFl[] = { true, true, false, false, false, false, false }; + int i; + for(i=0; iinsert(idx+1+i,titleArray[i],0,_s_menuCallback, _menuArray + i, checkFl[i] ? FL_MENU_TOGGLE : 0 ); + + if( onFl[i] ) + { + Fl_Menu_Item* mip = (Fl_Menu_Item*)_menuBar->menu() + idx + i + 1; + mip->set(); + } + } + + _menuBar->redraw(); + +} + +bool cmGrTksrFltk::_isMenuChecked( int id ) +{ + unsigned i; + // locate the menu item assoc'd with id + for(i=0; ifind_index(cmMENU_TITLE)) == -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; +} + +void cmGrTksrFltk::_setEventLabels() +{ + enum { kPitchFl=0x01, kScEvtFl=0x02 }; + + if( cmTakeSeqBldrIsValid( _tksbH ) == false ) + return; + + cmGrPlH_t plH = plotHandle(); + unsigned flags = 0; + flags |= _isMenuChecked(kPitchMId) ? kPitchFl : 0; + flags |= _isMenuChecked(kScEvtMId) ? kScEvtFl : 0; + + unsigned n = cmGrPlotObjectCount(plH); + unsigned i; + for(i=0; iid==kNoteTksrId && sop->u.rid!=cmInvalidId ) + { + cmTksbRend_t r; + + if( cmTakeSeqBldrRendInfo( _tksbH, sop->u.rid, &r ) == kOkTsbRC ) + { + + int bufN = 255; + cmChar_t buf[ bufN+1 ]; + + buf[bufN] = 0; + buf[0] = 0; + + if( cmIsFlag(flags,kPitchFl) && r.evt.status == kNoteOnMdId ) + snprintf(buf+strlen(buf),bufN-strlen(buf),"%s ",cmMidiToSciPitch(r.evt.d0,NULL,0)); + + if( cmIsFlag(flags,kScEvtFl) && r.scEvtIdx != cmInvalidIdx ) + snprintf(buf+strlen(buf),bufN-strlen(buf),"sei:%i ",r.scEvtIdx); + + cmGrPlotObjSetLabel(poH, buf ); + } + } + } + } +} + + +void cmGrTksrFltk::_s_deleteSelectedEle( void* arg, cmGrPlObjH_t oh ) +{ + if( cmIsFlag(cmGrPlotObjStateFlags(oh), kSelectGrPlFl) ) + { + cmGrTksrFltk* p = (cmGrTksrFltk*)arg; + scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(oh); + cmTakeSeqBldrRendDelete( p->_tksbH, sop->u.rid ); + } +} + +void cmGrTksrFltk::_write() +{ + const cmChar_t* fn = "/home/kevin/temp/kr/tksb/tksb0.js"; + + if( cmTakeSeqBldrIsValid(_tksbH) == false ) + return; + + if( cmTakeSeqBldrWrite( _tksbH, fn ) != kOkTsbRC ) + cmErrMsg(&_err,kTksbFailRC,"Render write failed for '%s'.",cmStringNullGuard(fn)); + +} + +void cmGrTksrFltk::_read() +{ + const cmChar_t* fn = "/home/kevin/temp/kr/tksb/tksb0.js"; + + if( cmTakeSeqBldrIsValid(_tksbH) == false ) + return; + + if( cmTakeSeqBldrRead( _tksbH, fn ) != kOkTsbRC ) + cmErrMsg(&_err,kTksbFailRC,"Render write failed for '%s'.",cmStringNullGuard(fn)); +} + +void cmGrTksrFltk::_insertPedal( unsigned long pedalMId ) +{ + if( cmTakeSeqBldrIsValid(_tksbH) == false ) + return; + + unsigned vwIdx = 0; + cmGrPgH_t pgH = pageHandle(); + cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx); + cmGrH_t cvH = cmGrViewGrHandle( vwH ); + double srate = cmTakeSeqBldrSampleRate(_tksbH); + cmGrVPt_t pt0,pt1; + unsigned rid; + cmTksbEvent_t e; + memset(&e,0,sizeof(e)); + + cmGrSelectPoints( cvH, &pt0, &pt1 ); + + unsigned durSmp = (pt1.x - pt0.x) * srate; + + e.status = kCtlMdId; + switch( pedalMId ) + { + case kSustainMId: + e.d0 = kSustainCtlMdId; + break; + + case kSostenutoMId: + e.d0 = kSostenutoCtlMdId; + break; + } + + //printf("x0:%f x1:%f %i\n",pt0.x,pt1.x,durSmp); + + e.smpIdx = pt0.x * srate; + e.d1 = 127; + cmTakeSeqBldrRendInsert( _tksbH, &e, durSmp, &rid ); + + e.smpIdx = pt1.x * srate; + e.d1 = 0; + cmTakeSeqBldrRendInsert( _tksbH, &e, 0, &rid ); + + refresh(); +} + +void cmGrTksrFltk::_s_menuCallback(Fl_Widget* w, void* arg ) +{ + item_t* ip = (item_t*)arg; + cmGrTksrFltk* p = ip->p; + unsigned long id = ip->id; + + switch( id ) + { + case kPitchMId: + case kScEvtMId: + p->_setEventLabels(); + p->redraw(); + break; + + case kDeleteMId: + cmGrPlotObjCb(p->plotHandle(),_s_deleteSelectedEle,p); + p->refresh(); + p->redraw(); + break; + + case kSustainMId: + case kSostenutoMId: + p->_insertPedal(id); + p->refresh(); + p->redraw(); + break; + + case kWriteMId: + p->_write(); + break; + + case kReadMId: + p->_read(); + break; + } +} + diff --git a/src/tlCtl/cmGrTksrFltk.h b/src/tlCtl/cmGrTksrFltk.h new file mode 100644 index 0000000..5c3cf50 --- /dev/null +++ b/src/tlCtl/cmGrTksrFltk.h @@ -0,0 +1,91 @@ +#ifndef cmGrTksrFltk_h +#define cmGrTksrFltk_h + +class Fl_Menu_Bar; +class cmdIf; + +class cmGrTksrFltk : public cmGrPlotFltk, public gvHashFuncArg +{ + public: + cmGrTksrFltk(cmCtx_t* ctx, cmdIf* cp, Fl_Menu_Bar* menuBar, int x, int y, int w, int h); + virtual ~cmGrTksrFltk(); + + void setTksbHandle( void* vp ); + + void refresh(); + + virtual double sampleRate() const; + + virtual bool on_plot_object( cmGrPlotCbArg_t* arg ); + + private: + enum + { + kOkRC, + kInsertObjFailRC, + kClearPlotFailRC, + kTksbFailRC + }; + + enum + { + kPitchMId, + kScEvtMId, + kDeleteMId, + kSustainMId, + kSostenutoMId, + kWriteMId, + kReadMId, + kMenuItemCnt + }; + + typedef struct + { + cmGrTksrFltk* p; + int id; + } item_t; + + typedef enum + { + kInvalidTksrId, + kNoteTksrId, + kPedalTksrId, + } tksrId_t; + + typedef struct scObj_str + { + tksrId_t id; + union + { + unsigned rid; + } u; + + scObj_str( tksrId_t i, unsigned rid ) : id(i) { u.rid=rid; } + } scObj_t; + + cmErr_t _err; + //cmdIf* _cmdIf; + cmTakeSeqBldrH_t _tksbH; + Fl_Menu_Bar* _menuBar; + unsigned _samplesMetricId; + unsigned _secondsMetricId; + //double _objSecs; + unsigned _objId; + //bool _togFl; + item_t _menuArray[ kMenuItemCnt ]; + + void _insertEvent( const cmTksbRend_t* m, double srate ); + void _createMenu(); + bool _isMenuChecked( int id ); + void _setEventLabels(); + void _write(); + void _read(); + void _insertPedal( unsigned long pedalMId ); + + static void _s_deleteSelectedEle( void* arg, cmGrPlObjH_t oh ); + static void _s_menuCallback(Fl_Widget* w, void* arg); + +}; + + +#endif diff --git a/src/tlCtl/cmGrTlFltk.cpp b/src/tlCtl/cmGrTlFltk.cpp new file mode 100644 index 0000000..a7d98eb --- /dev/null +++ b/src/tlCtl/cmGrTlFltk.cpp @@ -0,0 +1,835 @@ +#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; + } +} diff --git a/src/tlCtl/cmGrTlFltk.h b/src/tlCtl/cmGrTlFltk.h new file mode 100644 index 0000000..b509e14 --- /dev/null +++ b/src/tlCtl/cmGrTlFltk.h @@ -0,0 +1,108 @@ +#ifndef cmGrTlFltk_h +#define cmGrTlFltk_h + +class Fl_Menu_Bar; +class cmdIf; + + +class cmGrTlFltk : public cmGrPlotFltk, public gvHashFuncArg +{ + public: + cmGrTlFltk(cmCtx_t* ctx, cmdIf* cp, Fl_Menu_Bar* menuBar, int x, int y, int w, int h); + virtual ~cmGrTlFltk(); + + virtual cmTlUiMsgTypeId_t recvTimeLineMsg( const void* msg, unsigned msgByteCnt ); + virtual void recvAudioFileLoad( unsigned fileId ); + + virtual double sampleRate() const { return _srate; } + + // Call these functions to notify the UI of changes of state that + // occurred programmatically. These notifications are bubbling up + // from the engine. + typedef enum { kSamplesMetricId, kSecondsMetricId } timeAxisMetricId_t; + virtual void setTimeAxisMetric( timeAxisMetricId_t metricId ); + virtual void toggleMarkerText(); + virtual unsigned timeLineSelectedMarkerId() const; + virtual void setAudioFileCursor( unsigned smpIdx ); + virtual void selectBar( unsigned barNumb ); + + // This function is called to notify the timeline UI that that state of one of it's + // UI elements has been changed/manipulated by the user. This is the first + // point of contact with a requested change from the user which is being + // directed down to the engine. + virtual bool on_plot_object( cmGrPlotCbArg_t* arg ); + + private: + enum + { + kOkRC, + kParentObjNotFoundRC, + kInsertObjFailRC, + kAudioObjFailRC, + }; + + enum + { + kAudioVwIdx, + kMidiVwIdx, + kViewCnt + }; + + enum + { + kViewSamplesMId, + kViewSecondsMId, + kViewMarkTextMId, + kViewPitchMId, + kViewVelocityMId, + kViewIdMId, + kGenOnsetMarksMId, + kDelOnsetMarksMId, + kMenuItemCnt + }; + + // Flags returned by _getMenuCheckFlags(); + enum { kPitchChkFl=0x01, kVelChkFl=0x02, kIdChkFl=0x04 }; + + + typedef struct item_str + { + cmGrTlFltk* p; + int id; + } item_t; + + + cmErr_t _err; + double _srate; + cmdIf* _cmdIf; + Fl_Menu_Bar* _menuBar; + int _seqMenuIdx; + int _seqCnt; + item_t* _seqItemArray; + int _markCnt; + unsigned _samplesMetricId; + unsigned _secondsMetricId; + cmGrPlObjH_t _selMarkPlotObjH; + unsigned _curSeqId; + item_t _menuArray[ kMenuItemCnt ]; + + + void _insertTimeLineObj( const cmTlUiMsg_t* m ); + void _updateSeqMenu(int newSeqCnt, unsigned seqId); + void _createMenu(); + bool _isMenuChecked(int id); + unsigned _getMenuCheckFlags(); + void _setLabels(); + void _setMidiEventLabels( cmGrPlObjH_t poH, unsigned flags); + + static void _s_seqMenuCallback( Fl_Widget* w, void* vp ); + + static void _s_midiSciPitchValueFunc( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value ); + static void _s_roundHashValueFunc( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value ); + static void _s_minSecMsHashValueFunc( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value ); + static void _s_menuCallback( Fl_Widget* w, void* arg ); +}; + + + +#endif diff --git a/src/tlCtl/cmdIf.cpp b/src/tlCtl/cmdIf.cpp new file mode 100644 index 0000000..c7506af --- /dev/null +++ b/src/tlCtl/cmdIf.cpp @@ -0,0 +1,650 @@ +#include +#include +#include +#include +#include + +#include "cmPrefix.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 "cmThread.h" +#include "cmText.h" +#include "cmFileSys.h" +#include "cmJson.h" +#include "cmPrefs.h" +#include "cmSymTbl.h" +#include "cmTime.h" +#include "cmMidi.h" +#include "cmMidiFile.h" +#include "cmAudioFile.h" +#include "cmTimeLine.h" + +#include "cmScore.h" + +#include "cmProcObj.h" +#include "cmProc4.h" + +#include "cmAudioFileMgr.h" +#include "cmdIf.h" + +#include + + +//------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------- + +cmdIf::cmdIf( cmCtx_t* ctx, cmdIfRspdr* rspdr, const cmChar_t* audioPath ) + : _ctx(ctx),_thH(cmThreadNullHandle), + _cmdQueH(cmTs1p1cNullHandle),_outQueH(cmTs1p1cNullHandle), + _tlH(cmTimeLineNullHandle),_afmH(cmAfmNullHandle),_scH(cmScNullHandle), + _afPath(NULL),_rspdr(rspdr),_curSeqId(cmInvalidId) +{ + cmErrSetup(&_err,&ctx->rpt,"cmdIf"); + + cmAfmCreate(ctx,&_afmH); + + cmThreadCreate( &_thH, _thFunc, this, &ctx->rpt ); + cmTs1p1cCreate( &_cmdQueH, 4*64536, NULL, NULL, &_ctx->rpt ); + cmTs1p1cCreate( &_outQueH, 4*64536, NULL, NULL, &_ctx->rpt ); + + if( audioPath != NULL ) + setAudioFilePath(audioPath); +} + +cmdIf::~cmdIf() +{ + cmThreadDestroy( &_thH ); // stop the thread to prevent interfering with que release + _releaseQue(&_cmdQueH); + _releaseQue(&_outQueH); + cmTimeLineFinalize(&_tlH); + cmAfmDestroy(&_afmH); + cmScoreFinalize(&_scH); + cmMemFree(_afPath); +} + +cmdIf::rc_t cmdIf::open( const cmChar_t* fn ) +{ return _sendCmd(kOpenCmdId,0,fn); } + +cmdIf::rc_t cmdIf::close( ) +{ return _sendCmd(kCloseCmdId); } + +const cmChar_t* cmdIf::tlFileName() const +{ + if( cmTimeLineIsValid(_tlH) == false ) + return NULL; + + return cmTimeLineFileName(_tlH); +} + +const cmTlMidiFile_t* cmdIf::tlMidiFileObjPtr( const cmTlObj_t* op ) const +{ return cmTimeLineMidiFileObjPtr(_tlH,const_cast(op)); } + +const cmTlAudioFile_t* cmdIf::tlAudioFileObjPtr( const cmTlObj_t* op ) const +{ return cmTimeLineAudioFileObjPtr(_tlH,const_cast(op)); } + +const cmTlMidiEvt_t* cmdIf::tlMidiEvtObjPtr( const cmTlObj_t* op ) const + +{ return cmTimeLineMidiEvtObjPtr(_tlH,const_cast(op)); } + +const cmTlAudioEvt_t* cmdIf::tlAudioEvtObjPtr( const cmTlObj_t* op ) const +{ return cmTimeLineAudioEvtObjPtr(_tlH,const_cast(op)); } + +const cmTlMarker_t* cmdIf::tlMarkerObjPtr( const cmTlObj_t* op ) const +{ return cmTimeLineMarkerObjPtr(_tlH,const_cast(op)); } + + +const cmChar_t* cmdIf::scoreFileName() const +{ + if( cmScoreIsValid(_scH) == false ) + return NULL; + return cmScoreFileName(_scH); +} + +const cmScoreEvt_t* cmdIf::scoreEventIdToPtr( unsigned scEvtId ) const +{ + if( cmScoreIsValid(_scH)==false ) + return NULL; + return cmScoreEvt(_scH,scEvtId); +} + +const cmScoreSection_t* cmdIf::scoreSectionIdToPtr( unsigned scSectId ) const +{ + if( cmScoreIsValid(_scH)==false) + return NULL; + return cmScoreSection(_scH,scSectId); +} + + + +const cmTlObj_t* cmdIf::tlObjIdToPtr( unsigned tlObjId ) const +{ return cmTlIdToObjPtr( _tlH, tlObjId ); } + + +cmdIf::rc_t cmdIf::selectSequence( unsigned id ) +{ return _sendCmd(kSelectSeqCmdId,id); } + + +cmdIf::rc_t cmdIf::audioFileLoad( const cmChar_t* fn, unsigned appFileId ) +{ + const cmChar_t* afFn = fn; + //cmFileSysPathPart_t* pp = NULL ; + + /* + if( _afPath != NULL ) + { + pp = cmFsPathParts(fn); + afFn = cmFsMakeFn(_afPath,pp->fnStr,pp->extStr,NULL); + } + */ + + rc_t rc = _sendCmd(kAfLoadCmdId,appFileId,afFn); + + /* + if( _afPath != NULL ) + { + cmFsFreeFn(afFn); + cmFsFreePathParts(pp); + } + */ + + return rc; +} + +cmAfmFileH_t cmdIf::audioFileHandle( unsigned appFileId ) +{ return cmAfmIdToHandle(_afmH,appFileId); } + +void cmdIf::setAudioFilePath( const cmChar_t* path ) +{ _afPath = cmMemResizeStr(_afPath,path); } + +cmdIf::rc_t cmdIf::setScore( const cmChar_t* scoreFn ) +{ return _sendCmd(kScoreCmdId,0,scoreFn); } + +void cmdIf::setScoreLocation( unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel ) +{ + cmScoreSetPerfEvent(_scH,locIdx,smpIdx,pitch,vel); +} + +void cmdIf::setScoreVarValue( unsigned locIdx, unsigned varId, double value ) +{ + cmScoreSetPerfValue(_scH,locIdx,varId,value); +} + +void cmdIf::setScoreDynLevel( unsigned evtIdx, unsigned dynLvl ) +{ + cmScoreSetPerfDynLevel(_scH,evtIdx,dynLvl); +} + + +void cmdIf::onTimeLineMarkerSelected( unsigned markerTlId ) +{ + if( _rspdr != NULL ) + _rspdr->cmdIfOnTimeLineMarkerSelect(markerTlId); + + _onTimeLineObjSelected(markerTlId); + +} + +void cmdIf::onTimeLineMidiEvtSelected( unsigned midiEvtTlId ) +{ + if( _rspdr != NULL ) + _rspdr->cmdIfOnTimeLineMidiEvtSelect(midiEvtTlId); + + _onTimeLineObjSelected(midiEvtTlId); +} + +void cmdIf::onScoreBarSelected( unsigned scoreIdx ) +{ + if( cmScoreIsValid(_scH) ) + cmScoreClearPerfInfo(_scH); + + if( _rspdr != NULL ) + _rspdr->cmdIfOnScoreBarSelect(scoreIdx); + +} + +cmdIf::rc_t cmdIf::generateOnsetMarks() +{ return _sendCmd( kGenOnsetMarksCmdId); } + +cmdIf::rc_t cmdIf::deleteOnsetMarks() +{ return _sendCmd( kDelOnsetMarksCmdId); } + + +bool cmdIf::isBusy() const +{ return cmThreadIsValid(_thH) && cmThreadState(_thH)==kRunningThId; } + +void cmdIf::onIdle() +{ + if( !cmTs1p1cIsValid(_outQueH) ) + return; + + // pick up msg's sent from the worker thread + while( cmTs1p1cMsgWaiting(_outQueH) ) + { + cmd_t c; + cmThRC_t thRC; + + if((thRC = cmTs1p1cDequeueMsg(_outQueH,&c,sizeof(c))) != kOkThRC ) + { + _thErrorMsg("Deque response failed."); + continue; + } + + //printf("deq th->app id:%i val:%i n:%i msg:%p\n",c.id,c.value,c.byteCnt,c.u.msg); + + switch( c.id ) + { + // the worker thread is busy - show a modal progress window + case kShowStatusCmdId: + _rspdr->cmdIfShowStatusMsg(c.u.string); + break; + + // the worker thread is idle - remove the modal progress window + case kHideStatusCmdId: + _rspdr->cmdIfHideStatus(); + break; + + // report an error which occured during a worker thread operation + case kErrMsgCmdId: + _rspdr->cmdIfErrorMsg(c.u.string); + break; + + // send a msg to the time-line UI + case kTimeLineMsgCmdId: + _rspdr->cmdIfTimeLineMsg(c.u.msg,c.byteCnt); + break; + + case kAfLoadCmdId: + _rspdr->cmdIfAudioFileLoad(c.value); + break; + + case kScoreMsgCmdId: + _rspdr->cmdIfScoreMsg(c.u.msg,c.byteCnt); + break; + + default: + break; + } + + if( c.byteCnt ) + { + cmMemFree(c.u.msg); + } + } +} + +//---------------------------------------------------------------------------------------- +// App Thread Functions +//---------------------------------------------------------------------------------------- + +cmdIf::rc_t cmdIf::_sendCmd( cmdId_t id, unsigned value, const char* str ) +{ + rc_t rc; + if((rc = _enqueue( _cmdQueH, id, value, str, str==NULL ? 0 : strlen(str)+1 )) == kOkRC ) + cmThreadPause(_thH, 0 ); + else + { + cmErrMsg(&_err,kCmdEnqueueFailRC,"Command enque failed."); + } + + return rc; +} + +void cmdIf::_releaseQue( cmTs1p1cH_t* queHPtr ) +{ + + while( cmTs1p1cMsgWaiting(*queHPtr) ) + { + cmd_t c; + cmThRC_t thRC; + + if((thRC = cmTs1p1cDequeueMsg(*queHPtr,&c,sizeof(c))) != kOkThRC ) + { + // TODO: PRINT ERROR MSG HERE USING APP THREAD ERROR HANDLER + //_thErrorMsg("Deque command failed during queue draining."); + continue; + } + + + if( c.byteCnt ) + cmMemFree(c.u.msg); + + } + + cmTs1p1cDestroy(queHPtr); + +} + +//---------------------------------------------------------------------------------------- +// Worker Thread Functions +//---------------------------------------------------------------------------------------- +bool cmdIf::_thFunc( void* arg ) +{ + cmdIf* p = (cmdIf*)arg; + + while( cmTs1p1cMsgWaiting(p->_cmdQueH) ) + { + cmd_t c; + cmThRC_t thRC; + + if((thRC = cmTs1p1cDequeueMsg(p->_cmdQueH,&c,sizeof(c))) != kOkThRC ) + { + p->_thErrorMsg("Deque command failed."); + continue; + } + + switch(c.id ) + { + case kOpenCmdId: + p->_thDoOpen(&c); + break; + + case kCloseCmdId: + p->_thDoClose(&c); + break; + + case kSelectSeqCmdId: + p->_thDoSelectSeq(&c); + break; + + case kAfLoadCmdId: + p->_thDoAfLoad(&c); + break; + + case kScoreCmdId: + p->_thDoScore(&c); + break; + + case kGenOnsetMarksCmdId: + p->_thDoGenOnsetMarks(&c); + break; + + case kDelOnsetMarksCmdId: + p->_thDoDelOnsetMarks(&c); + break; + + default: + break; + } + + if( c.byteCnt ) + cmMemFree(c.u.msg); + + } + + + cmThreadPause( p->_thH, kPauseThFl ); + + return true; +} + +//void cmdIfRptFunc( void* user, const cmChar_t* text ) +//{ printf("%s",text); } + +void cmdIf::_thDoOpen( const cmd_t* cmd ) +{ + _thStatusMsg("Loading: '%s'",cmd->u.string); + + if( cmTimeLineInitializeFromFile(_ctx,&_tlH,_thSendTimeLineMsg,this,cmd->u.string,_afPath) != kOkTlRC ) + _thErrorMsg("Load failed on '%s'.",cmd->u.string); + else + { + _curSeqId = 0; + + // Make notification callbacks for all time line records to _thSendTimeLineMsg() + // _thSendTimeLineMsg() then enqueues msg's into _outQueH which are picked + // up by the idle handler + cmTimeLineSeqNotify(_tlH,_curSeqId); + } + _thSendResponse(kHideStatusCmdId); +} + +void cmdIf::_thDoClose( const cmd_t* cmd ) +{ + _thStatusMsg("Closing ... "); + + if( cmTimeLineFinalize(&_tlH) != kOkTlRC ) + { + _thErrorMsg("Time line finalize failed."); + } + + _thSendResponse(kHideStatusCmdId); +} + +void cmdIf::_thDoSelectSeq( const cmd_t* cmd ) +{ + _thStatusMsg("Selecting Sequence:%i ",cmd->value); + + _curSeqId = cmInvalidId; + if( cmTimeLineSeqNotify(_tlH,cmd->value) != kOkTlRC ) + _thErrorMsg("Sequence selection failed."); + else + _curSeqId = cmd->value; + + _thSendResponse(kHideStatusCmdId); +} + +void cmdIf::_thDoAfLoad( const cmd_t* cmd ) +{ + _thStatusMsg("Loading Audio File: '%s'",cmd->u.string); + + cmAfmFileH_t afH = cmAfmFileNullHandle; + + if( cmAfmFileOpen(_afmH,&afH,cmd->u.string, cmd->value, NULL ) != kOkAfmRC ) + _thErrorMsg("Audio file load failed on '%s'.",cmd->u.string); + else + { + double msPerSummaryPt = 50.0; + unsigned samplesPerSummaryPt = (unsigned)floor(cmAfmFileInfo(afH)->srate * msPerSummaryPt / 1000.0); + + if( cmAfmFileSummarize(afH,samplesPerSummaryPt) != kOkAfmRC ) + _thErrorMsg("Audio file summarization failed on '%s'.",cmd->u.string); + else + _thSendResponse(kAfLoadCmdId,cmd->u.string,cmd->value); + } + + _thSendResponse(kHideStatusCmdId); +} + +void cmdIf::_thDoScore( const cmd_t* cmd ) +{ + _thStatusMsg("Loading Score File: '%s'",cmd->u.string); + + if( cmScoreInitialize(_ctx,&_scH,cmd->u.string,0,NULL,0,_thSendScoreMsg,this,cmSymTblNullHandle) != kOkScRC ) + _thErrorMsg("Score open failed on '%s'.",cmStringNullGuard(cmd->u.string)); + else + { + // Make notification callbacks for all score records to _thSendScoreMsg() + // _thSendScoreMsg() then enqueues msg's into _outQueH which are picked + // up by the idle handler + cmScoreSeqNotify(_scH); + } + _thSendResponse(kHideStatusCmdId); +} + +void cmdIf::_thDoGenOnsetMarks( const cmd_t* cmd ) +{ + if( !cmTimeLineIsValid(_tlH) ) + return; + + _thStatusMsg("Generating Onset Markers."); + + // makes notification callbacks to _thSendTimeLineMsg() + if( cmTimeLineGenOnsetMarks(_tlH,_curSeqId) != kOkTlRC ) + _thErrorMsg("Onset marker generation failed."); + else + cmTimeLineSeqNotify(_tlH,_curSeqId); + + _thSendResponse(kHideStatusCmdId); +} + +void cmdIf::_thDoDelOnsetMarks( const cmd_t* cmd ) +{ + if( !cmTimeLineIsValid(_tlH) ) + return; + + _thStatusMsg("Deleting Onset Markers."); + + // makes notification callbacks to _thSendTimeLineMsg() + if( cmTimeLineDeleteOnsetMarks(_tlH,_curSeqId) != kOkTlRC ) + _thErrorMsg("Onset marker deletion failed."); + + _thSendResponse(kHideStatusCmdId); +} + +/* +void cmdIf::_thErrorMsg( const char* fmt, va_list vl ) +{ + const cmChar_t* s = cmTsVPrintf(fmt,vl); + _thSendResponse(kErrMsgCmdId,s); + cmTsFreeStr(s); +} +*/ +void cmdIf::_thErrorMsg( const char* fmt, ... ) +{ + va_list vl,vl1; + va_start(vl,fmt); + va_copy(vl1,vl); + + int n = vsnprintf(NULL,0,fmt,vl); + char b[n+1]; + vsnprintf(b,n+1,fmt,vl1); + _thSendResponse(kErrMsgCmdId,b); + + va_end(vl1); + va_end(vl); +} + +/* +void cmdIf::_thStatusMsg( const char* fmt, va_list vl ) +{ + const cmChar_t* s = cmTsVPrintf(fmt,vl); + _thSendResponse(kShowStatusCmdId,s); + cmTsFreeStr(s); +} +*/ + +void cmdIf::_thStatusMsg( const char* fmt, ... ) +{ + va_list vl,vl1; + va_start(vl,fmt); + va_copy(vl1,vl); + + int n = vsnprintf(NULL,0,fmt,vl); + char b[n+1]; + vsnprintf(b,n+1,fmt,vl1); + _thSendResponse(kShowStatusCmdId,b); + va_end(vl1); + va_end(vl); +} + + +void cmdIf::_thSendResponse( cmdId_t id, const char* str, unsigned value ) +{ + if( _enqueue( _outQueH, id, value, str, str==NULL ? 0 : strlen(str)+1 ) != kOkRC ) + { + _thErrorMsg("Response send failed."); + } +} + +void cmdIf::_thSendTimeLineMsg( void* arg, const void* msg, unsigned byteCnt ) +{ + cmdIf* p = (cmdIf*)arg; + if( cmTs1p1cIsValid( p->_outQueH ) ) + if( p->_enqueue( p->_outQueH, kTimeLineMsgCmdId, 0, msg, byteCnt ) != kOkRC ) + p->_thErrorMsg("Time Line enqueue failed on response queue."); +} + +void cmdIf::_thSendScoreMsg( void* arg, const void* msg, unsigned byteCnt ) +{ + cmdIf* p = (cmdIf*)arg; + if( cmTs1p1cIsValid( p->_outQueH ) ) + if( p->_enqueue( p->_outQueH, kScoreMsgCmdId, 0, msg, byteCnt ) != kOkRC ) + p->_thErrorMsg("Score msg enqueue failed on response queue."); +} + + +//---------------------------------------------------------------------------------------- +// Thread Independent Functions +//---------------------------------------------------------------------------------------- + + +cmdIf::rc_t cmdIf::_enqueue( cmTs1p1cH_t qH, cmdId_t id, unsigned value, const void* data, unsigned byteCnt ) +{ + cmThRC_t thRC; + rc_t rc = kOkRC; + cmd_t c; + + assert( (byteCnt==0 && data==NULL) || (byteCnt!=0 && data!=NULL) ); + + c.id = id; + c.byteCnt = byteCnt; + c.value = value; + c.u.msg = NULL; + + if( byteCnt ) + { + // memory allocated here must be deleted after the record is dequeued + c.u.string = cmMemAlloc(char,byteCnt); + memcpy(c.u.msg,data,byteCnt); + } + + //printf("enq %s id:%i n:%i msg:%p\n", cmHandlesAreEqual(qH,_outQueH) ? "thr->app" : "app->thr", c.id,c.byteCnt,c.u.string); + + if((thRC = cmTs1p1cEnqueueMsg(qH,&c,sizeof(c))) != kOkThRC ) + { + if( byteCnt ) + cmMemFree(c.u.string); + + rc = kCmdFailRC; + } + + return rc; +} + + +//---------------------------------------------------------------------------------------- +void cmdIf::_onTimeLineObjSelected( unsigned tlObjId ) +{ + const cmTlObj_t* mop; + if((mop = cmTimeLineIdToObj(_tlH,cmInvalidId,tlObjId)) == NULL ) + { + cmErrMsg(&_err,kCmdFailRC,"Unexpected invalid time line marker id '%i'.",tlObjId); + return; + } + + const cmTlAudioFile_t* afp = cmTimeLineAudioFileAtTime(_tlH, mop->seqId, mop->seqSmpIdx ); + const cmTlMidiFile_t* mfp = cmTimeLineMidiFileAtTime( _tlH, mop->seqId, mop->seqSmpIdx ); + const cmTlMidiEvt_t* mep = cmTimeLineMidiEvtAtTime( _tlH, mop->seqId, mop->seqSmpIdx ); + + if( afp != NULL ) + printf("%s\n",afp->fn); + + if( mfp != NULL ) + printf("%s : %i\n",mfp->fn,mop->seqSmpIdx); + + if( mep != NULL ) + { + if( mep->msg->status == kNoteOnMdId ) + printf("%s : %i\n",cmMidiToSciPitch(mep->msg->u.chMsgPtr->d0,NULL,0),mep->obj.seqSmpIdx); + else + printf("midi:%i\n",mep->msg->status); + } +} + +//---------------------------------------------------------------------------------------- +void cmdIf::testStub() +{ + //ed_main(); + //cmScAlignScanMarkers(_err.rpt, _tlH, _scH ); + //sc_main(_scH,_tlH); + cmScorePrintLoc(_scH); +} + + diff --git a/src/tlCtl/cmdIf.h b/src/tlCtl/cmdIf.h new file mode 100644 index 0000000..57d8880 --- /dev/null +++ b/src/tlCtl/cmdIf.h @@ -0,0 +1,211 @@ +#ifndef cmdIf_h +#define cmdIf_h + +class Fl_Output; + + +// This class allows the 'model' to run independently +// from the user interface. This eliminates problems with +// application unresponsiveness which would arise from +// executing compute intensive operations from UI control or +// menu callback functions. It also allows a progress +// or status bar to be shown while the model operation +// is in progress. + +// The class works by enqueueing all incoming commands +// into a thread-safe queue. An internal worker thread +// executes the commands in the order they are received +// and thereby changes the state of the model. + +// The results of model changes are posted to a second +// thread-safe queue. These responses are picked +// up by the onIdle() member and dispatched to an +// object with a cmIfRspdr interface. Note that because +// the onIdle() function is called from the applications +// idle handler the callbacks to the cmIfRspdr are +// always in the application thread and can therefore +// safely interact with any application data constructs. + +// All calls to this object and all callbacks from it, +// therefore occur in the application thread. + + +class cmdIfRspdr +{ + public: + virtual ~cmdIfRspdr(){} + virtual void cmdIfShowStatusMsg( const char* msg ) = 0; + virtual void cmdIfHideStatus() = 0; + virtual void cmdIfErrorMsg( const char* msg ) = 0; + virtual void cmdIfTimeLineMsg( const void* msg, unsigned msgByteCnt ) = 0; + virtual void cmdIfAudioFileLoad( unsigned fileId ) = 0; + virtual void cmdIfScoreMsg( const void* msg, unsigned msgByteCnt ) = 0; + + virtual void cmdIfOnTimeLineMarkerSelect( unsigned markerId ) = 0; + virtual void cmdIfOnTimeLineMidiEvtSelect(unsigned midiEvtId ) = 0; + virtual void cmdIfOnScoreBarSelect( unsigned scoreIndex ) = 0; + + +}; + +class cmdIf +{ + public: + + typedef enum + { + kOkRC, + kCmdFailRC, + kCmdEnqueueFailRC + } rc_t; + + cmdIf( cmCtx_t* ctx, cmdIfRspdr* rspdr, const cmChar_t* audioPath=NULL ); + virtual ~cmdIf(); + + // Open a time line. + rc_t open( const cmChar_t* fn ); + + // Close the time line. + rc_t close(); + + // Time line interface + const cmChar_t* tlFileName() const; + const cmTlObj_t* tlObjIdToPtr( unsigned tlObjId ) const; + const cmTlMidiFile_t* tlMidiFileObjPtr( const cmTlObj_t* op ) const; + const cmTlAudioFile_t* tlAudioFileObjPtr( const cmTlObj_t* op ) const; + const cmTlMidiEvt_t* tlMidiEvtObjPtr( const cmTlObj_t* op ) const; + const cmTlAudioEvt_t* tlAudioEvtObjPtr( const cmTlObj_t* op ) const; + const cmTlMarker_t* tlMarkerObjPtr( const cmTlObj_t* op ) const; + + const cmChar_t* scoreFileName() const; + const cmScoreEvt_t* scoreEventIdToPtr( unsigned scEvtId ) const; + const cmScoreSection_t* scoreSectionIdToPtr( unsigned scSectId ) const; + + // Make a time line sequence active. + rc_t selectSequence( unsigned id ); + + // Load an audio file into the audio file mgr. + // If an audio file path was set via setAudioFilePath() then + // the directories referenced by 'fn' will be replaced by + // the previously set audio file path. + rc_t audioFileLoad( const cmChar_t* fn, unsigned appFileId ); + + // Return the audio file handle assigned to appFileId. + cmAfmFileH_t audioFileHandle( unsigned appFileId ); + + // Set the audio file location. + void setAudioFilePath( const cmChar_t* path ); + + // Assign a score file + rc_t setScore( const cmChar_t* scoreFn ); + + // Set the current score location + void setScoreLocation( unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel ); + + // Set the value of a score variable + void setScoreVarValue( unsigned locIdx, unsigned varId, double value ); + + // Set the performed dynamic level of a score event. + void setScoreDynLevel( unsigned evtIdx, unsigned dynLvl ); + + void onTimeLineMarkerSelected( unsigned markerTlId ); + void onTimeLineMidiEvtSelected( unsigned midiEvtTlId ); + void onScoreBarSelected( unsigned scoreIndex ); + + // Generate or delete Audio/MIDI onset markers. + rc_t generateOnsetMarks(); + rc_t deleteOnsetMarks(); + + // True if the worker thread is running. + bool isBusy() const; + + // Called by the application to dequeue messages via callbacks to + // the cmdIfRspdr. + void onIdle(); + + void testStub(); + + private: + + // Id's used by cmd_t + typedef enum + { + kInvalidCmdId, // 0 + kOpenCmdId, // 1 app->thread + kCloseCmdId, // 2 app->thread + kSelectSeqCmdId, // 3 app->thread + kAfLoadCmdId, // 4 app->thread and thread->app + kScoreCmdId, // 5 app->thread + kShowStatusCmdId, // 6 thread->app + kHideStatusCmdId, // 7 thread->app + kErrMsgCmdId, // 8 thread->app + kTimeLineMsgCmdId, // 9 thread->app + kScoreMsgCmdId, //10 thread->app + kGenOnsetMarksCmdId, + kDelOnsetMarksCmdId + + } cmdId_t; + + // Messages are passed between the app and the worker thread + // and v.v. using this record format. Note that the u.msg + // field is always dynamically allocated by _enqueue() + // and must be released following the dequeue operation. + typedef struct cmd_str + { + cmdId_t id; // cmdId + unsigned byteCnt; // length of msg + unsigned value; // msg value + + union + { + void* msg; // msg[byteCnt] + char* string; // string[byteCnt] + } u; + } cmd_t; + + cmCtx_t* _ctx; // + cmErr_t _err; // + cmThreadH_t _thH; // worker thread + cmTs1p1cH_t _cmdQueH; // app->model + cmTs1p1cH_t _outQueH; // model->appl + cmTlH_t _tlH; // time line handle + cmAfmH_t _afmH; // audio file manager + cmScH_t _scH; // score handle + cmChar_t* _afPath; // + cmdIfRspdr* _rspdr; // + unsigned _curSeqId; // seqId of last selected sequence + + + // Functions called from the app thread. + rc_t _sendCmd( cmdId_t id, unsigned value=0, const char* str=NULL ); + void _releaseQue( cmTs1p1cH_t* queHPtr ); + + // Functions called from the worker thread + static bool _thFunc( void* arg ); + void _thDoOpen( const cmd_t* cmd ); + void _thDoClose( const cmd_t* cmd ); + void _thDoSelectSeq( const cmd_t* cmd ); + void _thDoAfLoad( const cmd_t* cmd ); + void _thDoScore( const cmd_t* cmd ); + void _thDoGenOnsetMarks( const cmd_t* cmd ); + void _thDoDelOnsetMarks( const cmd_t* cmd ); + + //void _thErrorMsg( const char* fmt, va_list vl ); + void _thErrorMsg( const char* fmt, ... ); + //void _thStatusMsg( const char* fmt, va_list vl ); + void _thStatusMsg( const char* fmt, ... ); + void _thSendResponse( cmdId_t id, const char* str = NULL, unsigned value=0 ); + static void _thSendTimeLineMsg( void* arg, const void* msg, unsigned byteCnt ); + static void _thSendScoreMsg( void* arg, const void* msg, unsigned byteCnt ); + + // Thread independent functions + rc_t _enqueue( cmTs1p1cH_t qH, cmdId_t id, unsigned value, const void* msg, unsigned msgByteCnt ); + + + // Print context information for selected time line objects + void _onTimeLineObjSelected( unsigned tlObjId ); + +}; + + +#endif diff --git a/src/tlCtl/gvHashFunc.cpp b/src/tlCtl/gvHashFunc.cpp new file mode 100644 index 0000000..bf368a6 --- /dev/null +++ b/src/tlCtl/gvHashFunc.cpp @@ -0,0 +1,62 @@ +#include "cmPrefix.h" +#include "cmGlobal.h" +#include "cmFloatTypes.h" +#include "cmRpt.h" +#include "cmErr.h" +#include "cmCtx.h" +#include "cmTime.h" +#include "cmMidi.h" +#include "cmGr.h" +#include "gvHashFunc.h" + +void gvRoundHashValueFunc( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value ) +{ + snprintf(label,labelCharCnt,"%i",(int)round(value)); +} + +void gvMidiSciPitchValueFunc( 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 gvMinSecMsHashValueFunc( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value ) +{ + gvHashFuncArg* p = (gvHashFuncArg*)arg; + + int min=0,sec=0,ms=0; + + double smpPerMin = p->sampleRate() * 60.0; + double smpPerMs = p->sampleRate() / 1000.0; + + if( value > smpPerMin ) + { + min = (int)floor( value / smpPerMin ); + value -= min * smpPerMin; + } + + if( value > p->sampleRate() ) + { + sec = (int)floor( value / p->sampleRate() ); + value -= sec * p->sampleRate(); + } + + + if( value > smpPerMs ) + { + ms = (int)floor( value / smpPerMs ); + value -= ms * smpPerMs; + } + + snprintf(label,labelCharCnt,"%i:%2i:%2i",min,sec,ms); +} + diff --git a/src/tlCtl/gvHashFunc.h b/src/tlCtl/gvHashFunc.h new file mode 100644 index 0000000..44dfd8c --- /dev/null +++ b/src/tlCtl/gvHashFunc.h @@ -0,0 +1,18 @@ +#ifndef gvHashFunc_h +#define gvHashFunc_h + +class gvHashFuncArg +{ + public: + virtual ~gvHashFuncArg(){} + virtual double sampleRate() const = 0; + +}; + +extern "C" { +void gvRoundHashValueFunc( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value ); +void gvMinSecMsHashValueFunc( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value ); +void gvMidiSciPitchValueFunc( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value ); +} + +#endif diff --git a/src/tlCtl/tlCtl.cpp b/src/tlCtl/tlCtl.cpp new file mode 100644 index 0000000..419275e --- /dev/null +++ b/src/tlCtl/tlCtl.cpp @@ -0,0 +1,388 @@ +#include +#include +#include +#include +#include +#include + +#include +#include "Fl_Splitter.h" +#include "Fl_CbLinker.h" + +#include "cmPrefix.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 "cmFileSys.h" +#include "cmThread.h" +#include "cmText.h" +#include "cmPrefs.h" +#include "cmSymTbl.h" +#include "cmTime.h" +#include "cmMidi.h" +#include "cmMidiFile.h" +#include "cmAudioFile.h" +#include "cmAudioFileMgr.h" +#include "cmTimeLine.h" +#include "cmScore.h" +#include "cmTakeSeqBldr.h" +#include "cmGr.h" +#include "cmGrDevCtx.h" +#include "cmGrPlot.h" +#include "cmGrPage.h" +#include "cmGrFltk.h" +#include "gvHashFunc.h" +#include "cmGrTlFltk.h" +#include "cmGrScFltk.h" +#include "cmGrTksbFltk.h" +#include "cmGrTksrFltk.h" +#include "cmGr2dFltk.h" +#include "cmdIf.h" +#include "tlCtl.h" + +//---------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------- + +class tlStatusWnd : public Fl_Window +{ + public: + tlStatusWnd(int w, int h, const char* label); + virtual ~tlStatusWnd(); + + void display( const char* msg ); + virtual void draw(); + + private: + char* _msg; + enum { kBorder = 10 }; + +}; + +tlStatusWnd::tlStatusWnd(int w, int h, const char* label) + : Fl_Window(w,h,label),_msg(NULL) +{ + end(); + clear_border(); +} + +tlStatusWnd:: ~tlStatusWnd() +{ + cmMemFree(_msg); +} + +void tlStatusWnd::display( const char* msg ) +{ + bool fl = false; + int border = 2*kBorder; + + // store the string + _msg = cmMemResizeStr(_msg,msg); + + // The offscreen drawing context is probably not necesary. + // However if a font change was applied then it would guarantee that + // fl_measure() used the correct font. + Fl_Offscreen os = fl_create_offscreen(w(),h()); + fl_begin_offscreen(os); + + // BEWARE: fl_measure uses 'ww' on input. + int ww=0,hh=0; + fl_measure(_msg,ww,hh,0); + fl_end_offscreen(); + fl_delete_offscreen(os); + + if( ww+border < w() ) + ww = w(); + else + { + ww += border; + fl = true; + } + + if( hh+border < h() ) + hh = h(); + else + { + hh = hh+border; + fl = true; + } + + + if(fl) + size(ww,hh); + + int xx = parent()->w()/2 - ww/2; + int yy = parent()->h()/2 - hh/2; + position(xx,yy); + + + set_modal(); + show(); +} + +void tlStatusWnd::draw() +{ + // BEWARE: fl_measure uses 'ww' on input. + int ww=0,hh=0; + fl_measure(_msg,ww,hh,0); + + int xx = w()/2 - ww/2; + int yy = h()/2; + + fl_rect(0,0,w(),h()); + fl_draw(_msg,xx,yy); + +} + + +//---------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------- + + +tlCtl::tlCtl( cmCtx_t* ctx, Fl_Window* app, Fl_Menu_Bar* menuBar, tlCtlRspdr* rspdr ) + : _ctx(ctx),_rspdr(rspdr), + _cmdIf(NULL),_tlCtlr(NULL),_scCtlr(NULL),_tksbCtlr(NULL),_tksrCtlr(NULL),_2dCtlr(NULL), + _statusWnd(NULL),_menu(menuBar) +{ + cmErrSetup(&_err,&ctx->rpt,"tlCtl"); + _cmdIf = new cmdIf( ctx,this ); + app->add(_statusWnd = new tlStatusWnd(app->w()/2,app->h()/2,"Status")); + +} + +tlCtl::~tlCtl() +{ + delete _cmdIf; + delete _tlCtlr; + delete _scCtlr; + delete _tksbCtlr; + delete _tksrCtlr; + delete _2dCtlr; + delete _statusWnd; +} + +Fl_Widget* tlCtl::initTimeLineCtlr( int x, int y, int w, int h ) +{ + delete _tlCtlr; + _tlCtlr = NULL; + return _tlCtlr = new cmGrTlFltk(_ctx,_cmdIf,_menu,x,y,w,h); +} + +Fl_Widget* tlCtl::initScoreCtlr( int x, int y, int w, int h ) +{ + delete _scCtlr; + _scCtlr = NULL; + return _scCtlr = new cmGrScFltk(_ctx,_cmdIf,_menu,x,y,w,h); +} + +Fl_Widget* tlCtl::initTakeSeqBldrCtlr( int x, int y, int w, int h ) +{ + delete _tksbCtlr; + _tksbCtlr = NULL; + return _tksbCtlr = new cmGrTksbFltk(_ctx,_cmdIf,_menu,x,y,w,h); +} + +Fl_Widget* tlCtl::initTakeSeqRendCtlr( int x, int y, int w, int h ) +{ + delete _tksrCtlr; + _tksrCtlr = NULL; + return _tksrCtlr = new cmGrTksrFltk(_ctx,_cmdIf,_menu,x,y,w,h); +} + +Fl_Widget* tlCtl::init2dCtlr( int x, int y, int w, int h ) +{ + delete _2dCtlr; + _2dCtlr = NULL; + return _2dCtlr = new cmGr2dFltk(_ctx,_menu,x,y,w,h); +} + + +void tlCtl::openTlFile( const cmChar_t* fn ) +{ + if( fn!=NULL && _tlCtlr != NULL ) + _cmdIf->open(fn); +} + +void tlCtl::openScoreFile( const cmChar_t* fn ) +{ + if( fn!=NULL && _scCtlr != NULL ) + _cmdIf->setScore(fn); +} + +void tlCtl::openTakeSeqBldr( void* v ) +{ + if( v!=NULL && _tksbCtlr != NULL ) + _tksbCtlr->setTksbHandle(v); +} + +void tlCtl::openTakeSeqRend( void* v ) +{ + if( v!=NULL && _tksrCtlr != NULL ) + _tksrCtlr->setTksbHandle(v); +} + +void tlCtl::setAudioFilePath( const cmChar_t* path ) +{ + if( path!=NULL ) + _cmdIf->setAudioFilePath(path); +} + +void tlCtl::setAudioFileCursor( unsigned smpIdx ) +{ + if( _tlCtlr != NULL ) + _tlCtlr->setAudioFileCursor(smpIdx); +} + +void tlCtl::setTimeLineSelectBar( unsigned barNumb ) +{ + if( _tlCtlr != NULL ) + _tlCtlr->selectBar(barNumb); +} + +void tlCtl::setScoreSelectBar( unsigned barNumb ) +{ + if( _scCtlr != NULL ) + _scCtlr->selectBar(barNumb); +} + +void tlCtl::setScoreLocation( unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel ) +{ + _cmdIf->setScoreLocation( locIdx, smpIdx, pitch, vel ); +} + +void tlCtl::setScoreVarValue( unsigned locIdx, unsigned varId, double value ) +{ + _cmdIf->setScoreVarValue( locIdx, varId, value ); +} + +void tlCtl::setScoreDynLevel( unsigned evtIdx, unsigned dynLvl ) +{ + _cmdIf->setScoreDynLevel(evtIdx,dynLvl); +} + +void tlCtl::refreshTakeSeqRend() +{ + if( _tksrCtlr != NULL ) + _tksrCtlr->refresh(); +} + +void tlCtl::onIdle() +{ _cmdIf->onIdle(); } + + +void tlCtl::cmdIfShowStatusMsg( const char* msg ) +{ + _statusWnd->display(msg); +} + +void tlCtl::cmdIfHideStatus() +{ + _statusWnd->hide(); + _statusWnd->set_non_modal(); +} + +void tlCtl::cmdIfErrorMsg( const char* msg ) +{ + cmErrMsg(&_err,1,"%s",msg); +} + +void tlCtl::cmdIfTimeLineMsg( const void* msg, unsigned msgByteCnt ) +{ + switch( _tlCtlr->recvTimeLineMsg(msg,msgByteCnt) ) + { + case kInitMsgTlId: + if( _rspdr!= NULL && _cmdIf->tlFileName() != NULL ) + _rspdr->tlCtlNewTimeLineFile(this,_cmdIf->tlFileName()); + break; + + case kDoneMsgTlId: + + if( _scCtlr != NULL && _tlCtlr != NULL ) + _scCtlr->setSampleRate( _tlCtlr->sampleRate() ); + + _menu->parent()->redraw(); + + break; + + default: + break; + } + +} + +void tlCtl::cmdIfAudioFileLoad( unsigned fileId ) +{ + _tlCtlr->recvAudioFileLoad(fileId); +} + +void tlCtl::cmdIfScoreMsg( const void* msg, unsigned msgByteCnt ) +{ + assert( _scCtlr != NULL ); + + + switch( _scCtlr->recvScoreMsg(msg,msgByteCnt) ) + { + case kBeginMsgScId: + if( _rspdr!= NULL && _cmdIf->scoreFileName() != NULL ) + _rspdr->tlCtlNewScoreFile(this,_cmdIf->scoreFileName()); + break; + + case kEndMsgScId: + _scCtlr->setSampleRate( _tlCtlr->sampleRate() ); + _scCtlr->redraw(); + break; + + _menu->parent()->redraw(); + + default: + break; + } + +} + +void tlCtl::cmdIfOnTimeLineMarkerSelect( unsigned markerId ) +{ + +} + +void tlCtl::cmdIfOnTimeLineMidiEvtSelect( unsigned midiEvtId ) +{ +} + +void tlCtl::cmdIfOnScoreBarSelect( unsigned scoreIndex ) +{ +} + + +unsigned tlCtl::timeLineSelectedMarkerId() const +{ + if( _tlCtlr==NULL) + return cmInvalidId; + return _tlCtlr->timeLineSelectedMarkerId(); +} + +unsigned tlCtl::scoreSelectedEleIndex() const +{ + if(_scCtlr==NULL) + return cmInvalidId; + return _scCtlr->scoreSelectedEleIndex(); +} + +unsigned tlCtl::tksbSelectedEleIndex() const +{ + if(_tksbCtlr==NULL) + return cmInvalidId; + return _tksbCtlr->scoreSelectedEleIndex(); +} + + +void tlCtl::testStub() +{ + _cmdIf->testStub(); +} diff --git a/src/tlCtl/tlCtl.h b/src/tlCtl/tlCtl.h new file mode 100644 index 0000000..4c48289 --- /dev/null +++ b/src/tlCtl/tlCtl.h @@ -0,0 +1,99 @@ +#ifndef tlCtl_h +#define tlCtl_h + +class Fl_Menu_Bar; +class cmGrTlFltk; +class cmGrScFltk; +class cmGrTksbFltk; +class cmGrTksrFltk; +class cmGr2dFltk; +class tlStatusWnd; +class tlCtl; + +class tlCtlRspdr +{ +public: + virtual ~tlCtlRspdr(){} + virtual void tlCtlNewTimeLineFile( tlCtl* tlCtl, const cmChar_t* fn ) = 0; + virtual void tlCtlNewScoreFile( tlCtl* tlCtl, const cmChar_t* fn ) = 0; + +}; + +class tlCtl : public cmdIfRspdr +{ +public: + tlCtl( cmCtx_t* ctx, Fl_Window* app, Fl_Menu_Bar* menuBar, tlCtlRspdr* rspdr ); + virtual ~tlCtl(); + + // + // This group of functions represent commands from the application (kcApp) to the + // time-line control. + // + + Fl_Widget* initTimeLineCtlr( int x, int y, int w, int h ); + Fl_Widget* initScoreCtlr( int x, int y, int w, int h ); + Fl_Widget* initTakeSeqBldrCtlr( int x, int y, int w, int h ); + Fl_Widget* initTakeSeqRendCtlr( int x, int y, int w, int h ); + Fl_Widget* init2dCtlr( int x, int y, int w, int h ); + + void openTlFile( const cmChar_t* fn ); + void openScoreFile( const cmChar_t* fn ); + void openTakeSeqBldr( void* v ); + void openTakeSeqRend( void* v ); + void setAudioFilePath( const cmChar_t* path ); + void setAudioFileCursor( unsigned smpIdx ); + void setTimeLineSelectBar( unsigned barNumb ); + void setScoreSelectBar( unsigned barNumb ); + + // Set the currrent score location + void setScoreLocation( unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel ); + + // Set the value of a score variable. + void setScoreVarValue( unsigned locIdx, unsigned varId, double value ); + + // Set the performed dynamic level of a score event. + void setScoreDynLevel( unsigned evtIdx, unsigned dynLvl ); + + void refreshTakeSeqRend(); + + void onIdle(); + + + // + // cmdIfRspdr Interface + // + // These functions are callbacks from cmdIf to communicate + // from cmdIf processes to the UI or back to the engine. + + virtual void cmdIfShowStatusMsg( const char* msg ); + virtual void cmdIfHideStatus(); + virtual void cmdIfErrorMsg( const char* msg ); + virtual void cmdIfTimeLineMsg( const void* msg, unsigned msgByteCnt ); + virtual void cmdIfAudioFileLoad( unsigned fileId ); + virtual void cmdIfScoreMsg( const void* msg, unsigned msgByteCnt ); + virtual void cmdIfOnTimeLineMarkerSelect( unsigned markerId ); + virtual void cmdIfOnTimeLineMidiEvtSelect(unsigned midiEvtId ); + virtual void cmdIfOnScoreBarSelect( unsigned scoreIndex ); + + unsigned timeLineSelectedMarkerId() const; + unsigned scoreSelectedEleIndex() const; + unsigned tksbSelectedEleIndex() const; + + void testStub(); + +private: + cmErr_t _err; + cmCtx_t* _ctx; + tlCtlRspdr* _rspdr; + cmdIf* _cmdIf; + cmGrTlFltk* _tlCtlr; + cmGrScFltk* _scCtlr; + cmGrTksbFltk* _tksbCtlr; + cmGrTksrFltk* _tksrCtlr; + cmGr2dFltk* _2dCtlr; + tlStatusWnd* _statusWnd; + Fl_Menu_Bar* _menu; +}; + + +#endif