commit 52e4e56ea296069948449d53af5a31d3da761997
parent 1bbd8d0024b7fcfc75b33827d324ad4422bd69b4
Author: fundamental <mark.d.mccurry@gmail.com>
Date: Sat, 27 Jul 2013 15:23:41 -0400
Partial OSC Integration with BankUI
- Add BankView Set of widgets
- Remove some of the need of the bank pointer in BankUI.fl
- Introduce some bug inducing behavior
The bank will realistically only be able to load things at the moment
as safe saving has not been implemented yet.
As the bank has gotten more abstract some of the old hacks to get the
rest of the UI to safely refresh are gone.
This _enhancement_ will result in drawing out some old bugs.
In all likelyhood this will take a few commits to fix up, but it is a
needed step in killing off some more pointers.
Diffstat:
10 files changed, 470 insertions(+), 305 deletions(-)
diff --git a/src/Misc/Bank.cpp b/src/Misc/Bank.cpp
@@ -23,13 +23,12 @@
*/
#include "Bank.h"
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
#include <dirent.h>
#include <sys/stat.h>
#include <algorithm>
-#include <iostream>
#include <sys/types.h>
#include <fcntl.h>
@@ -121,10 +120,7 @@ bool Bank::emptyslot(unsigned int ninstrument)
if(ins[ninstrument].filename.empty())
return true;
- if(ins[ninstrument].used)
- return false;
- else
- return true;
+ return false;
}
/*
@@ -275,6 +271,7 @@ int Bank::newbank(string newbankdirname)
*/
int Bank::locked()
{
+ //XXX Fixme
return dirname.empty();
}
@@ -409,7 +406,7 @@ void Bank::clearbank()
int Bank::addtobank(int pos, string filename, string name)
{
if((pos >= 0) && (pos < BANK_SIZE)) {
- if(ins[pos].used)
+ if(!ins[pos].filename.empty())
pos = -1; //force it to find a new free position
}
else
@@ -419,7 +416,7 @@ int Bank::addtobank(int pos, string filename, string name)
if(pos < 0) //find a free position
for(int i = BANK_SIZE - 1; i >= 0; i--)
- if(!ins[i].used) {
+ if(ins[i].filename.empty()) {
pos = i;
break;
}
@@ -429,32 +426,11 @@ int Bank::addtobank(int pos, string filename, string name)
deletefrombank(pos);
- ins[pos].used = true;
ins[pos].name = name;
ins[pos].filename = dirname + '/' + filename;
-
- //see if PADsynth is used
- //if(config.cfg.CheckPADsynth) {
- // XMLwrapper xml;
- // xml.loadXMLfile(ins[pos].filename);
-
- // ins[pos].info.PADsynth_used = xml.hasPadSynth();
- //}
- //else
- ins[pos].info.PADsynth_used = false;
-
return 0;
}
-bool Bank::isPADsynth_used(unsigned int ninstrument)
-{
- if(config.cfg.CheckPADsynth == 0)
- return 0;
- else
- return ins[ninstrument].info.PADsynth_used;
-}
-
-
void Bank::deletefrombank(int pos)
{
if((pos < 0) || (pos >= (int) banks.size()))
@@ -463,7 +439,5 @@ void Bank::deletefrombank(int pos)
}
Bank::ins_t::ins_t()
- :used(false), name(""), filename("")
-{
- info.PADsynth_used = false;
-}
+ :name(""), filename("")
+{}
diff --git a/src/Misc/Bank.h b/src/Misc/Bank.h
@@ -42,7 +42,6 @@ class Bank
void setname(unsigned int ninstrument,
const std::string &newname,
int newslot);
- bool isPADsynth_used(unsigned int ninstrument);
/**returns true when slot is empty*/
bool emptyslot(unsigned int ninstrument);
@@ -72,6 +71,13 @@ class Bank
};
std::vector<bankstruct> banks;
+
+ struct ins_t {
+ ins_t(void);
+ std::string name;
+ //All valid instruments must have a non-empty filename
+ std::string filename;
+ } ins[BANK_SIZE];
private:
@@ -86,16 +92,6 @@ class Bank
std::string defaultinsname;
- public:
- struct ins_t {
- ins_t();
- bool used;
- std::string name;
- std::string filename;
- struct {
- bool PADsynth_used;
- } info;
- } ins[BANK_SIZE];
private:
std::string dirname;
diff --git a/src/Misc/MiddleWare.cpp b/src/Misc/MiddleWare.cpp
@@ -122,7 +122,7 @@ void deallocate(const char *str, void *v)
printf("deallocating a '%s' at '%p'\n", str, v);
if(!strcmp(str, "Part"))
delete (Part*)v;
- if(!strcmp(str, "fft_t"))
+ else if(!strcmp(str, "fft_t"))
delete[] (fft_t*)v;
else
fprintf(stderr, "Unknown type '%s', leaking pointer %p!!\n", str, v);
@@ -186,6 +186,24 @@ void preparePadSynth(string path, PADnoteParameters *p)
}
}
+void refreshBankView(const Bank &bank, unsigned loc, Fl_Osc_Interface *osc)
+{
+ puts("bank response...");
+
+ if(loc >= BANK_SIZE)
+ return;
+
+ char response[2048];
+ if(!rtosc_message(response, 1024, "/bankview", "iss",
+ loc, bank.ins[loc].name.c_str(),
+ bank.ins[loc].filename.c_str()))
+ errx(1, "Failure to handle bank update properly...");
+
+
+ osc->tryLink(response);
+ puts("response sent...");
+}
+
//
//static rtosc::Ports padPorts= {
// {"prepare:", "::Prepares the padnote instance", 0, }
@@ -310,6 +328,7 @@ struct MiddleWareImpl
//Load the part
Part *p = new Part(&master->microtonal, master->fft, &master->mutex);
unsigned npart = rtosc_argument(msg, 0).i;
+ fprintf(stderr, "Part is stored in '%s'\n", rtosc_argument(msg, 1).s);
p->loadXMLinstrument(rtosc_argument(msg, 1).s);
p->applyparameters();
@@ -404,10 +423,16 @@ struct MiddleWareImpl
if(!last_path)
return;
+
//printf("watching '%s' go by\n", msg);
//Get the object resource locator
string obj_rl(msg, last_path+1);
- if(objmap.find(obj_rl) != objmap.end()) {
+ //XXX Utilize object map for this as well
+ //This dereference will become unsafe when loading new master instances
+ //is supported
+ if(!strcmp(msg, "/refresh_bank") && !strcmp(rtosc_argument_string(msg), "i"))
+ refreshBankView(master->bank, rtosc_argument(msg,0).i, osc);
+ else if(objmap.find(obj_rl) != objmap.end()) {
//try some over simplified pattern matching
if(strstr(msg, "oscil/")) {
if(!handleOscil(obj_rl, last_path+1, objmap[obj_rl]))
@@ -550,7 +575,7 @@ class UI_Interface:public Fl_Osc_Interface
void tryLink(const char *msg) override
{
- //printf("trying the link for a '%s'\n", msg);
+ printf("trying the link for a '%s'\n", msg);
const char *handle = rindex(msg,'/');
if(handle)
++handle;
@@ -558,6 +583,10 @@ class UI_Interface:public Fl_Osc_Interface
for(auto pair:map) {
if(pair.first == msg) {
const char *arg_str = rtosc_argument_string(msg);
+
+ //Always provide the raw message
+ pair.second->OSC_raw(msg);
+
//printf("Possible location for application of '%s' is '%p'\n", msg, pair.second);
if(!strcmp(arg_str, "b")) {
//printf("'%s' matches '%s' ala blob\n", pair.first.c_str(), msg);
diff --git a/src/UI/BankUI.fl b/src/UI/BankUI.fl
@@ -1,5 +1,5 @@
# data file for the Fltk User Interface Designer (fluid)
-version 1.0300
+version 1.0302
header_name {.h}
code_name {.cc}
decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {private local
@@ -41,83 +41,15 @@ decl {\#include "../Misc/Config.h"} {public local
decl {\#include "../Misc/Util.h"} {public local
}
-class BankProcess_ {} {
- Function {process()} {open return_type {virtual void}
- } {
- code {;} {}
- }
- decl {Bank *bank;} {public local
- }
+decl {\#include "BankView.h"} {public local
}
-class BankSlot {open : {public Fl_Button,BankProcess_}
-} {
- Function {BankSlot(int x,int y, int w, int h, const char *label=0):Fl_Button(x,y,w,h,label)} {open
- } {
- code {what=NULL;
-whatslot=NULL;
-nslot=0;
-nselected=NULL;} {}
- }
- Function {handle(int event)} {open return_type int
- } {
- code {if (what==NULL) return(0);
-if (Fl::event_inside(this)){
- *what=0;*whatslot=nslot;
- if ((event==FL_RELEASE)&&(Fl::event_button()==1))*what=1;
- if ((event==FL_RELEASE)&&(Fl::event_button()==3))*what=2;
- if (event==FL_PUSH) highlight=1;
-}else highlight=0;
-
-int tmp=Fl_Button::handle(event);
-if ((*what!=0) && Fl::event_inside(this)) (bp->*fnc)();
-return(tmp);} {}
- }
- Function {init(int nslot_, int *what_, int *whatslot_,void (BankProcess_:: *fnc_)(void),BankProcess_ *bp_,Bank *bank_,int *nselected_)} {} {
- code {nslot=nslot_;
-what=what_;
-whatslot=whatslot_;
-fnc=fnc_;
-bp=bp_;
-bank=bank_;
-nselected=nselected_;
-box(FL_THIN_UP_BOX);
-labelfont(0);
-labelsize(13);
-align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
-
-highlight=0;
-refresh();} {}
- }
- Function {refresh()} {} {
- code {if (bank->emptyslot(nslot))
- color(46);
-else if (bank->isPADsynth_used(nslot))
- color(26);
-else
- color(51);
-
-
-if (*nselected==nslot)
- color(6);
-
-
-copy_label(bank->getnamenumbered(nslot).c_str());} {}
- }
- decl {int *what,*whatslot,nslot,highlight, *nselected;} {private local
- }
- decl {void (BankProcess_:: *fnc)(void);} {private local
- }
- decl {BankProcess_ *bp;} {private local
- }
-}
-
-class BankUI {open : {public BankProcess_}
+class BankUI {open
} {
Function {make_window()} {open
} {
Fl_Window bankuiwindow {
- label Bank
+ label Bank open
xywh {492 406 785 575} type Double
code0 {o->label(bank->bankfiletitle.c_str());}
code1 {if (bank->bankfiletitle.empty()) o->label ("Choose a bank from the bank list on the left (or go to settings if to configure the bank location) or choose 'New Bank...' to make a new bank.");} visible
@@ -127,67 +59,14 @@ class BankUI {open : {public BankProcess_}
callback {bankuiwindow->hide();}
xywh {705 546 70 24} box THIN_UP_BOX
}
- Fl_Group {} {
+ Fl_Group bankview {open
xywh {5 34 772 491} box ENGRAVED_FRAME
- } {
- Fl_Pack {} {
- xywh {10 39 150 481} box BORDER_FRAME
- code0 {o->box(FL_NO_BOX);}
- code1 {for (int i=0;i<32;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);};}
- } {}
- Fl_Pack {} {
- xywh {163 39 150 481} box BORDER_FRAME
- code0 {o->box(FL_NO_BOX);}
- code1 {for (int i=32;i<64;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);};}
- } {}
- Fl_Pack {} {
- xywh {316 39 150 481} box BORDER_FRAME
- code0 {o->box(FL_NO_BOX);}
- code1 {for (int i=64;i<96;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);};}
- } {}
- Fl_Pack {} {
- xywh {469 39 150 481} box BORDER_FRAME
- code0 {o->box(FL_NO_BOX);}
- code1 {for (int i=96;i<128;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);};}
- } {}
- Fl_Pack {} {
- xywh {622 39 150 481} box BORDER_FRAME
- code0 {o->box(FL_NO_BOX);}
- code1 {for (int i=128;i<160;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);};}
- } {}
- }
- Fl_Group modeselect {
+ class BankView
+ } {}
+ Fl_Group modeselect {open
xywh {5 528 425 42} box ENGRAVED_BOX
- } {
- Fl_Light_Button writebutton {
- label WRITE
- callback {if (o->value()>0.5) mode=2;
-removeselection();}
- xywh {116 534 99 30} type Radio down_box THIN_DOWN_BOX selection_color 1 labeltype ENGRAVED_LABEL labelfont 1 labelsize 13
- code0 {if (bank->locked()) o->deactivate();}
- }
- Fl_Light_Button readbutton {
- label READ
- callback {if (o->value()>0.5) mode=1;
-removeselection();}
- xywh {11 534 99 30} type Radio down_box THIN_DOWN_BOX selection_color 101 labeltype ENGRAVED_LABEL labelfont 1 labelsize 13
- code0 {o->value(1);}
- }
- Fl_Light_Button clearbutton {
- label CLEAR
- callback {if (o->value()>0.5) mode=3;
-removeselection();}
- xywh {221 534 99 30} type Radio down_box THIN_DOWN_BOX selection_color 0 labeltype ENGRAVED_LABEL labelfont 1 labelsize 13
- code0 {if (bank->locked()) o->deactivate();}
- }
- Fl_Light_Button swapbutton {
- label SWAP
- callback {if (o->value()>0.5) mode=4;
-removeselection();}
- xywh {325 534 99 30} type Radio down_box THIN_DOWN_BOX selection_color 227 labeltype ENGRAVED_LABEL labelfont 1 labelsize 13
- code0 {if (bank->locked()) o->deactivate();}
- }
- }
+ class BankViewControls
+ } {}
Fl_Button {} {
label {New Bank...}
callback {const char *dirname;
@@ -216,7 +95,6 @@ if (dirname.empty()) return;
if (bank->loadbank(dirname)==2)
fl_alert("Error: Could not load the bank from the directory\\n%s.",dirname.c_str());
-for (int i=0;i<BANK_SIZE;i++) bs[i]->refresh();
refreshmainwindow();}
xywh {5 8 220 20} down_box BORDER_BOX labelfont 1 align 0 textfont 1 textsize 11
} {}
@@ -226,137 +104,46 @@ refreshmainwindow();}
banklist->value(0);}
tooltip {Refresh the bank list (rescan)} xywh {230 8 105 20} box THIN_UP_BOX color 50 labelsize 11
}
- Fl_Check_Button {} {
- label {Show PADsynth status}
- callback {config.cfg.CheckPADsynth=(int) o->value();
-refreshmainwindow();}
- xywh {435 530 150 15} down_box DOWN_BOX labelsize 11
- code0 {o->value(config.cfg.CheckPADsynth);}
- }
}
}
- Function {BankUI(Master *master_,int *npart_, Fl_Osc_Interface *osc_)} {} {
- code {fnc=&BankProcess_::process;
-master=master_;
-npart=npart_;
+ Function {BankUI(Master *master_,int *npart_, Fl_Osc_Interface *osc_)} {open
+ } {
+ code {npart=*npart_;
osc =osc_;
bank=&master_->bank;
-what=0;
-nselected=-1;
make_window();
-mode=1;} {}
+bankview->init(osc, modeselect, *npart_);} {}
}
- Function {~BankUI()} {return_type virtual
+ Function {~BankUI()} {open return_type virtual
} {
code {bankuiwindow->hide();
-delete(bankuiwindow);} {}
+delete bankuiwindow;} {}
}
- Function {show()} {} {
+ Function {show()} {open
+ } {
code {bankuiwindow->show();
simplesetmode(config.cfg.UserInterfaceMode==2);} {}
}
- Function {hide()} {} {
+ Function {hide()} {open
+ } {
code {bankuiwindow->hide();} {}
}
- Function {init(Fl_Valuator *cbwig_)} {} {
+ Function {init(Fl_Valuator *cbwig_)} {open
+ } {
code {cbwig=cbwig_;
rescan_for_banks();} {}
}
Function {process()} {open return_type void
} {
- code {int slot=this->slot;
-
-if ((what==2)&&(bank->emptyslot(slot)==0)&&(mode!=4)) {//Rename slot
- const char *tmp=fl_input("Slot (instrument) name:",bank->getname(slot).c_str());
- if (tmp!=NULL) bank->setname(slot,tmp,-1);
- bs[slot]->refresh();
-};
-
-if ((what==1)&&(mode==1)&&(!bank->emptyslot(slot))){//Reads from slot
- //pthread_mutex_lock(&master->part[*npart]->load_mutex);
- // bank->loadfromslot(slot,master->part[*npart]);
- //pthread_mutex_unlock(&master->part[*npart]->load_mutex);
- //master->part[*npart]->applyparameters();
- //snprintf((char *)master->part[*npart]->Pname,PART_MAX_NAME_LEN,"%s",bank->getname(slot).c_str());
- printf("throwing load to middleware\\n");
- printf("osc is '%p'\\n", osc);
- osc->write("/load-part", "is", *npart, bank->ins[slot].filename.c_str());
- printf("something should be showing up...\\n");
- osc->writeValue("/part"+to_s(*npart)+"/name", bank->getname(slot));
- printf("fake load of part '%d' with name '%s' from slot '%d'\\n", *npart, bank->getname(slot).c_str(), slot);
- cbwig->do_callback();
-
- if (config.cfg.BankUIAutoClose!=0)
- bankuiwindow->hide();
-
-};
-
-if ((what==1)&&(mode==2)){//save(write) to slot
- if (!bank->emptyslot(slot)){
- if (!fl_choice("Overwrite the slot no. %d ?","No","Yes",NULL,slot+1)) goto nooverwriteslot;
- };
- pthread_mutex_lock(&master->part[*npart]->load_mutex);
- bank->savetoslot(slot,master->part[*npart]);
- pthread_mutex_unlock(&master->part[*npart]->load_mutex);
-
- bs[slot]->refresh();
- mode=1;readbutton->value(1);writebutton->value(0);
- nooverwriteslot:;
-};
-
-
-
-if ((what==1)&&(mode==3)&&(!bank->emptyslot(slot))){//Clears the slot
- if (fl_choice("Clear the slot no. %d ?","No","Yes",NULL,slot+1)){
- bank->clearslot(slot);
- bs[slot]->refresh();
- };
-};
-
-if (mode==4){//swap
- bool done=false;
- if ((what==1)&&(nselected>=0)){
- bank->swapslot(nselected,slot);
- int ns=nselected;
- nselected=-1;
- bs[slot]->refresh();
- bs[ns]->refresh();
- done=true;
- };
- if (((nselected<0)||(what==2))&&(!done)){
- int ns=nselected;
- nselected=slot;
- if (ns>0) bs[ns]->refresh();
- bs[slot]->refresh();
- };
-};
-if (mode!=4) refreshmainwindow();} {selected
- }
+ code {} {}
}
- Function {refreshmainwindow()} {} {
+ Function {refreshmainwindow()} {open
+ } {
code {bankuiwindow->label(bank->bankfiletitle.c_str());
-mode=1;readbutton->value(1);writebutton->value(0);clearbutton->value(0);swapbutton->value(0);
-nselected=-1;
-if (bank->locked()){
- writebutton->deactivate();
- clearbutton->deactivate();
- swapbutton->deactivate();
-} else {
- writebutton->activate();
- clearbutton->activate();
- swapbutton->activate();
-};
-for (int i=0;i<BANK_SIZE;i++)
- bs[i]->refresh();} {}
- }
- Function {removeselection()} {} {
- code {if (nselected>=0) {
- int ns=nselected;
- nselected=-1;
- bs[ns]->refresh();
-};} {}
+bankview->refresh();} {}
}
- Function {rescan_for_banks()} {} {
+ Function {rescan_for_banks()} {open
+ } {
code {banklist->clear();
bank->rescanforbanks();
@@ -366,25 +153,17 @@ for (unsigned int i=0;i<bank->banks.size();i++) {
if (banklist->size() == 0)
banklist->add(" ");} {}
}
- Function {simplesetmode(bool beginnerui)} {} {
- code {readbutton->value(1);
-mode=1;
-removeselection();
-if (beginnerui) modeselect->hide();
+ Function {simplesetmode(bool beginnerui)} {open
+ } {
+ code {if (beginnerui) modeselect->hide();
else modeselect->show();} {}
}
- decl {BankSlot *bs[BANK_SIZE];} {private local
- }
- decl {int slot,what;//"what"=what button is pressed} {private local
- }
- decl {int mode,*npart,nselected;} {private local
- }
- decl {Master *master;} {private local
- }
- decl {void (BankProcess_::* fnc)(void);} {private local
- }
decl {Fl_Osc_Interface *osc;} {private local
}
decl {Fl_Valuator *cbwig;} {public local
}
+ decl {int npart;} {private local
+ }
+ decl {Bank *bank;} {private local
+ }
}
diff --git a/src/UI/BankView.cpp b/src/UI/BankView.cpp
@@ -0,0 +1,294 @@
+#include "BankView.h"
+#include "../Misc/Util.h"
+#include <FL/Fl.H>
+#include <FL/Fl_Light_Button.H>
+#include <FL/fl_ask.H>
+#include <rtosc/rtosc.h>
+#include <cstdio>
+#include <cstring>
+#include <cassert>
+
+BankSlot::BankSlot(int x,int y, int w, int h, const char *label)
+:Fl_Button(x,y,w,h,label), nslot(-1)
+{
+ memset(labelstr, 0, sizeof(labelstr));
+ box(FL_THIN_UP_BOX);
+ labelfont(0);
+ labelsize(13);
+ align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
+}
+
+int BankSlot::handle(int event)
+{
+ int what = 0;
+ if (Fl::event_inside(this))
+ {
+ what=0;
+ if ((event==FL_RELEASE)&&(Fl::event_button()==1))
+ what=1;
+ if ((event==FL_RELEASE)&&(Fl::event_button()==3))
+ what=2;
+ }
+
+ int tmp=Fl_Button::handle(event);
+
+ if (what && Fl::event_inside(this))
+ bv->react(what, nslot);
+
+ return tmp;
+}
+
+void BankSlot::init(int nslot_, BankView *bv_)
+{
+ nslot = nslot_;
+ bv = bv_;
+
+ snprintf(labelstr, 127, "%d.", nslot_);
+ label(labelstr);
+}
+
+void BankSlot::update(const char *name__, const char *fname__)
+{
+ name_ = name__;
+ filename_ = fname__;
+ snprintf(labelstr, 127, "%d. %s", nslot, name_.c_str());
+ label(labelstr);
+
+ color(empty() ? 46 : 51);
+}
+
+bool BankSlot::empty(void) const
+{
+ return filename_.empty();
+}
+
+const char *BankSlot::name(void) const
+{
+ return name_.c_str();
+}
+
+const char *BankSlot::filename(void) const
+{
+ return filename_.c_str();
+}
+
+/*
+ void BankSlot::init(int nslot_, int *what_, int *whatslot_,void (BankProcess_:: *fnc_)(void),BankProcess_ *bp_,Bank *bank_,int *nselected_) {
+ nslot=nslot_;
+ what=what_;
+ whatslot=whatslot_;
+ fnc=fnc_;
+ bp=bp_;
+//bank=bank_;
+nselected=nselected_;
+box(FL_THIN_UP_BOX);
+labelfont(0);
+labelsize(13);
+align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
+
+highlight=0;
+//refresh();
+}
+*/
+
+/*
+ void BankSlot::refresh() {
+ if (bank->emptyslot(nslot))
+ color(46);
+ else if (bank->isPADsynth_used(nslot))
+ color(26);
+ else
+ color(51);
+
+
+ if (*nselected==nslot)
+ color(6);
+
+
+ copy_label(bank->getnamenumbered(nslot).c_str());
+ }
+ */
+static int modeCb(const char *label)
+{
+ if(!strcmp("Read", label))
+ return 1;
+ else if(!strcmp("Write", label))
+ return 2;
+ else if(!strcmp("Clear", label))
+ return 3;
+ else if(!strcmp("Swap", label))
+ return 4;
+ return -1;
+}
+
+static void control_widget_cb(Fl_Light_Button *button, void *bvc_)
+{
+ BankViewControls *bvc = (BankViewControls*)bvc_;
+ bvc->mode(modeCb(button->label()));
+ //TODO removeselection?
+}
+
+BankViewControls::BankViewControls(int x, int y, int w, int h, const char *label)
+ :Fl_Group(x,y,w,h,label)
+{
+ //Margin
+ const int m = 10;
+ //Width per elm
+ const float W = w/4;
+
+ read = new Fl_Light_Button(x+m+0*W, y+m, W-2*m, h-2*m, "Read");
+ write = new Fl_Light_Button(x+m+1*W, y+m, W-2*m, h-2*m, "Write");
+ clear = new Fl_Light_Button(x+m+2*W, y+m, W-2*m, h-2*m, "Clear");
+ swap = new Fl_Light_Button(x+m+3*W, y+m, W-2*m, h-2*m, "Swap");
+ mode(1);
+}
+
+int BankViewControls::mode(void) const
+{
+ return mode_;
+}
+
+void BankViewControls::mode(int m)
+{
+ mode_ = m;
+ int M = m-1;
+ assert(0 <= M && M <= 3);
+ Fl_Button *buttons[4]{read, write, clear, swap};
+
+ for(int i=0; i<3; ++i)
+ buttons[i]->value(i==M);
+}
+
+
+BankView::BankView(int x,int y, int w, int h, const char *label)
+ :Fl_Group(x,y,w,h,label)
+{}
+
+
+BankView::~BankView(void)
+{
+ if(osc)
+ osc->removeLink("/bankview", this);
+}
+
+void BankView::init(Fl_Osc_Interface *osc_, BankViewControls *bvc_, int npart_)
+{
+ assert(osc_);
+
+ osc = osc_;
+ bvc = bvc_;
+ npart = npart_;
+ printf("BankView initialization...\n");
+
+ osc->createLink("/bankview", this);
+
+ //Element Size
+ const float width = w()/5.0;
+ const float height = h()/32.0;
+
+ //Offsets
+ const int X = x();
+ const int Y = y();
+
+ begin();
+ //Place All Slots
+ for(int i=0; i<5; ++i)
+ for(int j=0; j<32; ++j)
+ slots[i*32 + j] =
+ new BankSlot(X + i*width, Y + j*height, width, height);
+
+ end();
+
+ //Initialize callbacks
+ for(int i=0; i<160; ++i)
+ slots[i]->init(i, this);
+
+ //Request Values
+ for(int i=0; i<160; ++i)
+ osc->write("/refresh_bank", "i", i);
+}
+
+/*
+ * React to user input.
+ * This consists of the events:
+ * - Rename Slot (right click)
+ * - Read From Slot
+ * - Write To Slot
+ * - Swap Slot First Selection
+ * - Swap Slot Second Selction
+ *
+ * TODO restore autoclose functionality
+ */
+void BankView::react(int event, int nslot)
+{
+ printf("reacting...\n");
+ BankSlot &slot = *slots[nslot];
+ const bool isempty = slot.empty();
+ const int mode = bvc->mode();
+ printf("mode = %d\n", mode);
+
+ //Rename slot
+ if (event==2 && !isempty && mode!=4)
+ if(const char *name=fl_input("Slot (instrument) name:", slot.name()))
+ osc->write("/bank-rename", "is", nslot, name);
+
+ //Reads from slot
+ if ((event==1)&&(mode==1)&&(!slot.empty())){
+ printf("Loading a part #%d with file '%s'\n", nslot, slot.filename());
+ osc->write("/load-part", "is", npart, slot.filename());
+ osc->writeValue("/part"+to_s(npart)+"/name", slot.name());
+ }
+
+ //save(write) to slot
+ if(event==1 && mode==2){
+ if(!isempty && !fl_choice("Overwrite the slot no. %d ?","No","Yes",NULL,nslot+1))
+ return;
+
+ osc->write("/save-bank-part", "i", npart);
+ //pthread_mutex_lock(&master->part[*npart]->load_mutex);
+ //bank->savetoslot(slot,master->part[*npart]);
+ //pthread_mutex_unlock(&master->part[*npart]->load_mutex);
+
+ bvc->mode(1);//readbutton->value(1);writebutton->value(0);
+ }
+
+
+ //Clears the slot
+ if(event==1 && mode==3 && !isempty)
+ if (fl_choice("Clear the slot no. %d ?","No","Yes",NULL, nslot+1))
+ osc->write("/clear-bank-slot", "i", nslot);
+
+ //Swap
+ if(mode==4) {
+ if(event==1 && nselected>=0){
+ osc->write("/swap-bank-slots", "ii", nselected, nslot);
+ //bank->swapslot(nselected,slot);
+ nselected=-1;
+ } else if(nselected<0 || event==2) {
+ nselected=nslot;
+ };
+ };
+}
+
+void BankView::OSC_raw(const char *msg)
+{
+ if(strcmp(rtosc_argument_string(msg), "iss"))
+ return;
+
+ int nslot = rtosc_argument(msg,0).i;
+ const char *name = rtosc_argument(msg,1).s;
+ const char *fname = rtosc_argument(msg,2).s;
+
+ if(0 <= nslot && nslot < 160)
+ slots[nslot]->update(name, fname);
+
+
+ puts("Got a BankView event...");
+}
+
+void BankView::refresh(void)
+{
+ for(int i=0; i<160; ++i)
+ osc->write("/refresh_bank", "i", i);
+}
+
diff --git a/src/UI/BankView.h b/src/UI/BankView.h
@@ -0,0 +1,87 @@
+#ifndef BANKVIEW_H
+#define BANKVIEW_H
+
+#include "Fl_Osc_Widget.H"
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Button.H>
+#include <string>
+
+#include "common.H"
+
+class Bank;
+class BankView;
+class Fl_Light_Button;
+
+class BankSlot : public Fl_Button
+{
+ public:
+ BankSlot(int x,int y, int w, int h, const char *label=0);
+ int handle(int event);
+ void init(int nslot_, BankView *bv_);
+
+ void update(const char *name__, const char *fname__);
+
+ bool empty(void) const;
+ const char *name(void) const;
+ const char *filename(void) const;
+ private:
+ std::string name_;
+ std::string filename_;
+ char labelstr[128];
+ int nslot;
+ BankView *bv;
+};
+
+class BankViewControls: public Fl_Group
+{
+ public:
+ BankViewControls(int x,int y, int w, int h, const char *label=0);
+ void init(BankView *bv_);
+
+
+ int mode(void) const;
+ void mode(int);
+
+ private:
+ Fl_Light_Button *read;
+ Fl_Light_Button *write;
+ Fl_Light_Button *clear;
+ Fl_Light_Button *swap;
+
+ //1 -> read
+ //2 -> write
+ //3 -> clear
+ //4 -> swap
+ int mode_;
+
+ static void cb_clearbutton(Fl_Light_Button*, void*);
+ static void cb_readbutton(Fl_Light_Button*, void*);
+ static void cb_writebutton(Fl_Light_Button*, void*);
+};
+
+class BankView: public Fl_Group, public Fl_Osc_Widget
+{
+ public:
+ BankView(int x,int y, int w, int h, const char *label=0);
+ ~BankView(void);
+ void init(Fl_Osc_Interface *osc_, BankViewControls *bvc_, int npart_);
+
+ void react(int event, int slot);
+
+ virtual void OSC_raw(const char *msg) override;
+
+ void refresh(void);
+ private:
+ BankViewControls *bvc;
+ BankSlot *slots[160];
+
+ Fl_Osc_Interface *osc;
+ std::string loc;
+
+ //XXX TODO locked banks...
+ int mode;
+ int nselected;
+ int npart;
+};
+
+#endif
diff --git a/src/UI/CMakeLists.txt b/src/UI/CMakeLists.txt
@@ -40,6 +40,7 @@ add_library(zynaddsubfx_gui STATIC
Fl_Osc_Button.cpp
Fl_Osc_Check.cpp
Fl_Osc_Choice.cpp
+ BankView.cpp
Connection.cpp
)
diff --git a/src/UI/Fl_Osc_Check.H b/src/UI/Fl_Osc_Check.H
@@ -15,6 +15,7 @@ class Fl_Osc_Check:public Fl_Check_Button, public Fl_Osc_Widget
virtual ~Fl_Osc_Check(void);
virtual void OSC_value(bool);
+ using Fl_Osc_Widget::OSC_value;
void init(Fl_Osc_Interface *osc, std::string loc);
void init(std::string loc);
diff --git a/src/UI/Fl_Osc_Dial.H b/src/UI/Fl_Osc_Dial.H
@@ -13,6 +13,7 @@ class Fl_Osc_Dial:public WidgetPDial, Fl_Osc_Widget
void init(const char *path);
//void OSC_value(float);
void OSC_value(char);
+ using Fl_Osc_Widget::OSC_value;
//Refetch parameter information
void update(void);
diff --git a/src/UI/Fl_Osc_Widget.H b/src/UI/Fl_Osc_Widget.H
@@ -23,6 +23,9 @@ class Fl_Osc_Widget
virtual void OSC_value(unsigned x, void *v, const char *)
{OSC_value(x,v);}
+ virtual void OSC_raw(const char *)
+ {}
+
Fl_Osc_Pane *fetch_osc_pane(Fl_Widget *w)
{
if(!w)