Add tlCtl and libcmpp to this repo.

This commit is contained in:
kevin 2020-10-23 16:47:00 -04:00
parent 1a16a3d5d8
commit f2ea644147
35 changed files with 9390 additions and 4 deletions

2
.gitignore vendored
View File

@ -1,7 +1,5 @@
# directories to ignore
libcm
libcmpp
tlCtl
.deps
autom4te.cache

View File

@ -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

1
src/libcmpp/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
Makefile.in

18
src/libcmpp/Makefile.am Normal file
View File

@ -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

View File

@ -0,0 +1,82 @@
#include <FL/Fl.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Scrollbar.H>
#include <FL/Fl_Menu_Button.H>
#include <FL/Fl_Menu_Item.H>
#include <vector>
#include <assert.h>
#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<ctl_t*>(arg);
unsigned i;
for(i=0; i<r->thisPtr->_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); }
}
}
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,168 @@
#ifndef Fl_DevCfgGroup_h
#define Fl_DevCfgGroup_h
#include <vector>
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

View File

@ -0,0 +1,105 @@
#include <Fl/Fl.H>
#include <Fl/Fl_Button.H>
#include <Fl/Fl_File_Chooser.H>
#include <Fl/Fl_Output.H>
#include <Fl/Fl_Group.H>
#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());
}

View File

@ -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

View File

@ -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);
}

View File

@ -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 <FL/Fl.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>
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

View File

@ -0,0 +1,66 @@
#include <FL/Fl.H>
#include <FL/fl_draw.H>
#include <Fl/Fl_Progress.H>
#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<h())
{
fl_push_clip(x(), y(), w(), h()-progress);
draw_box(box(), x(), y(), w(), h(), active_r() ? color() : fl_inactive(color()));
draw_label(tx, y() + by, tw, h() - bh);
fl_pop_clip();
}
}
else
{
draw_box(box(), x(), y(), w(), h(), active_r() ? color() : fl_inactive(color()));
draw_label(tx, y() + by, tw, h() - bh);
}
}

View File

@ -0,0 +1,14 @@
#ifndef Fl_Vert_Progress_h
#define Fl_Vert_Progress_h
class Fl_Vert_Progress : public Fl_Progress
{
protected:
virtual void draw();
public:
Fl_Vert_Progress(int x, int y, int w, int h, const char* l=0);
};
#endif

File diff suppressed because it is too large Load Diff

242
src/libcmpp/fltk/cmGrFltk.h Normal file
View File

@ -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

View File

@ -0,0 +1,865 @@
#include <FL/Fl.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Tabs.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Check_Button.H>
#include <FL/Fl_Box.H>
#include <Fl/Fl_Input.H>
#include <Fl/Fl_Value_Input.H>
#include <Fl/Fl_Value_Slider.H>
#include <Fl/Fl_Progress.H>
#include <Fl/Fl_Menu_Button.H>
#include <Fl/Fl_Select_Browser.H>
#include <Fl/Fl_Text_Display.H>
#include <FL/fl_draw.H>
#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<Fl_Valuator*>(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;
}
}

View File

@ -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

11
src/tlCtl/Makefile.am Normal file
View File

@ -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

148
src/tlCtl/cmGr2dFltk.cpp Normal file
View File

@ -0,0 +1,148 @@
#include <FL/Fl.H>
#include <Fl/fl_draw.h>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Double_Window.H>
#include <Fl/Fl_Output.H>
#include <Fl/Fl_Menu_Bar.H>
#include <vector>
#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);
}
}

44
src/tlCtl/cmGr2dFltk.h Normal file
View File

@ -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

565
src/tlCtl/cmGrScFltk.cpp Normal file
View File

@ -0,0 +1,565 @@
#include <FL/Fl.H>
#include <Fl/fl_draw.h>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Double_Window.H>
#include <Fl/Fl_Output.H>
#include <Fl/Fl_Menu_Bar.H>
#include <vector>
#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; i<n; ++i)
{
cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
if( cmGrPlotObjIsValid(poH) )
{
scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
if( sop->id==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; i<kMenuItemCnt; ++i)
{
_menuArray[i].id = i;
_menuArray[i].p = this;
_menuBar->insert(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; i<kMenuItemCnt; ++i)
if( _menuArray[i].id == id )
break;
assert( i < kMenuItemCnt );
int menuIdx;
if(( menuIdx = _menuBar->find_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; i<n; ++i)
{
cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
if( cmGrPlotObjIsValid(poH) )
{
scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
if( sop!=NULL && sop->id==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; i<n; ++i)
{
cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
if( cmGrPlotObjIsValid(poH) )
{
scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
if( sop!=NULL && sop->id==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;
}
}

89
src/tlCtl/cmGrScFltk.h Normal file
View File

@ -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

695
src/tlCtl/cmGrTksbFltk.cpp Normal file
View File

@ -0,0 +1,695 @@
#include <FL/Fl.H>
#include <Fl/fl_draw.h>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Double_Window.H>
#include <Fl/Fl_Output.H>
#include <Fl/Fl_Menu_Bar.H>
#include <vector>
#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; i<n; ++i)
{
cmTksbScTrkTake_t r;
// get the ith take
if( cmTakeSeqBldrScTrkTake(_tksbH,i,&r) != kOkTsbRC )
continue;
// create the take plot-object
_insertTake(&r);
}
}
cmScMsgTypeId_t cmGrTksbFltk::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;
}
double cmGrTksbFltk::sampleRate() const
{
if( cmTakeSeqBldrIsValid(_tksbH) )
return cmTakeSeqBldrSampleRate(_tksbH);
return 0;
}
bool cmGrTksbFltk::on_plot_object( cmGrPlotCbArg_t* arg )
{
if( arg->selId!=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; i<kMenuItemCnt; ++i)
{
_menuArray[i].id = i;
_menuArray[i].p = this;
_menuBar->insert(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; i<kMenuItemCnt; ++i)
if( _menuArray[i].id == id )
break;
assert( i < kMenuItemCnt );
int menuIdx;
if(( menuIdx = _menuBar->find_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; i<n; ++i)
{
cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
if( cmGrPlotObjIsValid(poH) )
{
scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
if( sop!=NULL && sop->id==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; i<n; ++i)
{
cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
if( cmGrPlotObjIsValid(poH) )
{
scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
if( sop!=NULL && sop->id==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; i<n; ++i)
if(cmGrPlotObjIsValid(poH = cmGrPlotObjectIndexToHandle(plH,i))
&& (sop = (scObj_t*)cmGrPlotObjUserPtr(poH)) != NULL
&& sop->id == kEventTksbId
&& sop->u.ep->index == scEvtIdx )
{
return poH;
}
return cmGrPlObjNullHandle;
}

110
src/tlCtl/cmGrTksbFltk.h Normal file
View File

@ -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

461
src/tlCtl/cmGrTksrFltk.cpp Normal file
View File

@ -0,0 +1,461 @@
#include <FL/Fl.H>
#include <Fl/fl_draw.h>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Double_Window.H>
#include <Fl/Fl_Output.H>
#include <Fl/Fl_Menu_Bar.H>
#include <vector>
#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; i<kMenuItemCnt; ++i)
{
_menuArray[i].id = i;
_menuArray[i].p = this;
_menuBar->insert(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; i<kMenuItemCnt; ++i)
if( _menuArray[i].id == id )
break;
assert( i < kMenuItemCnt );
int menuIdx;
if(( menuIdx = _menuBar->find_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; i<n; ++i)
{
cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
if( cmGrPlotObjIsValid(poH) )
{
scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
if( sop!=NULL && sop->id==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;
}
}

91
src/tlCtl/cmGrTksrFltk.h Normal file
View File

@ -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

835
src/tlCtl/cmGrTlFltk.cpp Normal file
View File

@ -0,0 +1,835 @@
#include <FL/Fl.H>
#include <Fl/fl_draw.h>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Double_Window.H>
#include <Fl/Fl_Output.H>
#include <Fl/Fl_Menu_Bar.H>
#include <vector>
#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; i<n; ++i)
{
cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
if( cmGrPlotObjIsValid(poH) )
cmGrPlotObjTogCfgFlags(poH,kNoLabelGrPlFl);
}
redraw();
}
unsigned cmGrTlFltk::timeLineSelectedMarkerId() const
{
const cmTlObj_t* top;
if( cmGrPlotObjIsValid(_selMarkPlotObjH)
&& cmIsFlag(cmGrPlotObjStateFlags(_selMarkPlotObjH),kSelectGrPlFl)
&& (top = (const cmTlObj_t*)cmGrPlotObjUserPtr(_selMarkPlotObjH)) != NULL
&& (top->typeId==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; i<n; ++i)
{
cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
const cmTlMarker_t* mkp;
const cmTlObj_t* top;
if( cmGrPlotObjIsValid(poH)
&& (top = (const cmTlObj_t*)cmGrPlotObjUserPtr(poH)) != NULL
&& top->typeId == 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; i<newSeqCnt; ++i)
{
_seqItemArray[i].id = i;
_seqItemArray[i].p = this;
_menuBar->insert(_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; i<newSeqCnt; ++i)
{
Fl_Menu_Item* mip = (Fl_Menu_Item*)_menuBar->menu() + _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; i<kMenuItemCnt; ++i)
{
int flag = checkFl[i] ? FL_MENU_TOGGLE : 0;
_menuArray[i].id = i;
_menuArray[i].p = this;
_menuBar->insert(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; i<kMenuItemCnt; ++i)
if( _menuArray[i].id == id )
break;
assert( i < kMenuItemCnt );
int menuIdx;
if(( menuIdx = _menuBar->find_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; i<n; ++i)
{
cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
_setMidiEventLabels(poH,flags);
}
}
void cmGrTlFltk::_setMidiEventLabels( cmGrPlObjH_t poH, unsigned flags)
{
cmTlObj_t* top;
if( cmGrPlotObjIsValid(poH) && (top = (cmTlObj_t*)cmGrPlotObjUserPtr(poH))!=NULL && top->typeId==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;
}
}

108
src/tlCtl/cmGrTlFltk.h Normal file
View File

@ -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

650
src/tlCtl/cmdIf.cpp Normal file
View File

@ -0,0 +1,650 @@
#include <FL/Fl.H>
#include <FL/fl_draw.h>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Double_Window.H>
#include <Fl/Fl_Output.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 "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 <sstream>
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
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<cmTlObj_t*>(op)); }
const cmTlAudioFile_t* cmdIf::tlAudioFileObjPtr( const cmTlObj_t* op ) const
{ return cmTimeLineAudioFileObjPtr(_tlH,const_cast<cmTlObj_t*>(op)); }
const cmTlMidiEvt_t* cmdIf::tlMidiEvtObjPtr( const cmTlObj_t* op ) const
{ return cmTimeLineMidiEvtObjPtr(_tlH,const_cast<cmTlObj_t*>(op)); }
const cmTlAudioEvt_t* cmdIf::tlAudioEvtObjPtr( const cmTlObj_t* op ) const
{ return cmTimeLineAudioEvtObjPtr(_tlH,const_cast<cmTlObj_t*>(op)); }
const cmTlMarker_t* cmdIf::tlMarkerObjPtr( const cmTlObj_t* op ) const
{ return cmTimeLineMarkerObjPtr(_tlH,const_cast<cmTlObj_t*>(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);
}

211
src/tlCtl/cmdIf.h Normal file
View File

@ -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

62
src/tlCtl/gvHashFunc.cpp Normal file
View File

@ -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);
}

18
src/tlCtl/gvHashFunc.h Normal file
View File

@ -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

388
src/tlCtl/tlCtl.cpp Normal file
View File

@ -0,0 +1,388 @@
#include <FL/Fl.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Group.H>
#include <FL/fl_draw.H>
#include <vector>
#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();
}

99
src/tlCtl/tlCtl.h Normal file
View File

@ -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