Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

354 lines
7.9KB

  1. #include "BankView.h"
  2. #include "../Misc/Util.h"
  3. #include <FL/Fl.H>
  4. #include <FL/Fl_Check_Button.H>
  5. #include <FL/fl_ask.H>
  6. #include <rtosc/rtosc.h>
  7. #include <cstdio>
  8. #include <cstring>
  9. #include <cassert>
  10. BankList::BankList(int x,int y, int w, int h, const char *label)
  11. :Fl_Osc_Choice(x,y,w,h,label)
  12. {}
  13. void BankList::init(std::string path)
  14. {
  15. ext = path;
  16. oscRegister(path.c_str());
  17. osc->createLink("/bank-list", this);
  18. }
  19. void BankList::OSC_raw(const char *msg)
  20. {
  21. if(!strcmp(msg, "/bank-list")) {
  22. const int pos = rtosc_argument(msg, 0).i;
  23. const char *path = rtosc_argument(msg, 1).s;
  24. value(0);
  25. if(pos == 0)
  26. this->clear();
  27. this->add(path);
  28. osc->write("/loadbank");
  29. }
  30. if(!strcmp(msg, "/loadbank")) {
  31. value(rtosc_argument(msg, 0).i);
  32. }
  33. }
  34. BankSlot::BankSlot(int x,int y, int w, int h, const char *label)
  35. :Fl_Button(x,y,w,h,label), nslot(-1)
  36. {
  37. memset(labelstr, 0, sizeof(labelstr));
  38. box(FL_THIN_UP_BOX);
  39. labelfont(0);
  40. labelsize(13);
  41. align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
  42. }
  43. int BankSlot::handle(int event)
  44. {
  45. int what = 0;
  46. if (Fl::event_inside(this))
  47. {
  48. what=0;
  49. if ((event==FL_RELEASE)&&(Fl::event_button()==1))
  50. what=1;
  51. if ((event==FL_RELEASE)&&(Fl::event_button()==3))
  52. what=2;
  53. }
  54. int tmp=Fl_Button::handle(event);
  55. if (what && Fl::event_inside(this))
  56. bv->react(what, nslot);
  57. return tmp;
  58. }
  59. void BankSlot::init(int nslot_, BankView *bv_)
  60. {
  61. nslot = nslot_;
  62. bv = bv_;
  63. snprintf(labelstr, 127, "%d.", nslot_);
  64. label(labelstr);
  65. }
  66. void BankSlot::update(const char *name__, const char *fname__)
  67. {
  68. name_ = name__;
  69. filename_ = fname__;
  70. snprintf(labelstr, 127, "%d. %s", nslot, name_.c_str());
  71. label(labelstr);
  72. if(name_.empty())
  73. label("");
  74. color(empty() ? 46 : 51);
  75. #ifdef NTK_GUI
  76. redraw();
  77. #endif
  78. }
  79. bool BankSlot::empty(void) const
  80. {
  81. return filename_.empty();
  82. }
  83. const char *BankSlot::name(void) const
  84. {
  85. return name_.c_str();
  86. }
  87. const char *BankSlot::filename(void) const
  88. {
  89. return filename_.c_str();
  90. }
  91. /*
  92. void BankSlot::init(int nslot_, int *what_, int *whatslot_,void (BankProcess_:: *fnc_)(void),BankProcess_ *bp_,Bank *bank_,int *nselected_) {
  93. nslot=nslot_;
  94. what=what_;
  95. whatslot=whatslot_;
  96. fnc=fnc_;
  97. bp=bp_;
  98. //bank=bank_;
  99. nselected=nselected_;
  100. box(FL_THIN_UP_BOX);
  101. labelfont(0);
  102. labelsize(13);
  103. align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
  104. highlight=0;
  105. //refresh();
  106. }
  107. */
  108. /*
  109. void BankSlot::refresh() {
  110. if (bank->emptyslot(nslot))
  111. color(46);
  112. else if (bank->isPADsynth_used(nslot))
  113. color(26);
  114. else
  115. color(51);
  116. if (*nselected==nslot)
  117. color(6);
  118. copy_label(bank->getnamenumbered(nslot).c_str());
  119. }
  120. */
  121. static int modeCb(const char *label)
  122. {
  123. if(!strcmp("Read", label))
  124. return 1;
  125. else if(!strcmp("Write", label))
  126. return 2;
  127. else if(!strcmp("Clear", label))
  128. return 3;
  129. else if(!strcmp("Swap", label))
  130. return 4;
  131. return -1;
  132. }
  133. static void modeButtonCb(Fl_Widget *w, void *v)
  134. {
  135. BankViewControls *bvc = (BankViewControls*)v;
  136. bvc->mode(modeCb(w->label()));
  137. }
  138. BankViewControls::BankViewControls(int x, int y, int w, int h, const char *label)
  139. :Fl_Group(x,y,w,h,label)
  140. {
  141. //Margin
  142. const int m = 10;
  143. //Width per elm
  144. const float W = w/4;
  145. read = new Fl_Check_Button(x+m+0*W, y+m, W-2*m, h-2*m, "Read");
  146. write = new Fl_Check_Button(x+m+1*W, y+m, W-2*m, h-2*m, "Write");
  147. clear = new Fl_Check_Button(x+m+2*W, y+m, W-2*m, h-2*m, "Clear");
  148. swap = new Fl_Check_Button(x+m+3*W, y+m, W-2*m, h-2*m, "Swap");
  149. read->box(FL_BORDER_BOX);
  150. write->box(FL_BORDER_BOX);
  151. clear->box(FL_BORDER_BOX);
  152. swap->box(FL_BORDER_BOX);
  153. read->callback(modeButtonCb, this);
  154. write->callback(modeButtonCb, this);
  155. clear->callback(modeButtonCb, this);
  156. swap->callback(modeButtonCb, this);
  157. mode(1);
  158. }
  159. int BankViewControls::mode(void) const
  160. {
  161. return mode_;
  162. }
  163. void BankViewControls::mode(int m)
  164. {
  165. mode_ = m;
  166. int M = m-1;
  167. assert(0 <= M && M <= 3);
  168. Fl_Button *buttons[4]{read, write, clear, swap};
  169. for(int i=0; i<4; ++i)
  170. buttons[i]->value(i==M);
  171. }
  172. BankView::BankView(int x,int y, int w, int h, const char *label)
  173. :Fl_Group(x,y,w,h,label), bvc(NULL), slots{0}, osc(0),
  174. loc(""), nselected(-1), npart(0), cbwig_(0)
  175. {}
  176. BankView::~BankView(void)
  177. {
  178. if(osc)
  179. osc->removeLink("/bankview", this);
  180. }
  181. void BankView::init(Fl_Osc_Interface *osc_, BankViewControls *bvc_, int *npart_)
  182. {
  183. assert(osc_);
  184. osc = osc_;
  185. bvc = bvc_;
  186. npart = npart_;
  187. osc->createLink("/bankview", this);
  188. //Element Size
  189. const float width = w()/5.0;
  190. const float height = h()/32.0;
  191. //Offsets
  192. const int X = x();
  193. const int Y = y();
  194. begin();
  195. //Place All Slots
  196. for(int i=0; i<5; ++i)
  197. for(int j=0; j<32; ++j)
  198. slots[i*32 + j] =
  199. new BankSlot(X + i*width, Y + j*height, width, height);
  200. end();
  201. //Initialize callbacks
  202. for(int i=0; i<160; ++i)
  203. slots[i]->init(i, this);
  204. //Request Values
  205. for(int i=0; i<160; ++i)
  206. osc->write("/refresh_bank", "i", i);
  207. }
  208. /*
  209. * React to user input.
  210. * This consists of the events:
  211. * - Rename Slot (right click)
  212. * - Read From Slot
  213. * - Write To Slot
  214. * - Swap Slot First Selection
  215. * - Swap Slot Second Selction
  216. *
  217. * TODO restore autoclose functionality
  218. */
  219. void BankView::react(int event, int nslot)
  220. {
  221. BankSlot &slot = *slots[nslot];
  222. const bool isempty = slot.empty();
  223. const int mode = bvc->mode();
  224. //Rename slot
  225. if (event==2 && !isempty && mode!=4) {
  226. if(const char *name=fl_input("Slot (instrument) name:", slot.name())) {
  227. osc->write("/bank-rename", "is", nslot, name);
  228. osc->write("/refresh_bank", "i", nslot);
  229. }
  230. }
  231. //Reads from slot
  232. if ((event==1)&&(mode==1)&&(!slot.empty())){
  233. printf("Loading a part #%d with file '%s'\n", nslot, slot.filename());
  234. osc->write("/load-part", "is", *npart, slot.filename());
  235. osc->writeValue("/part"+to_s(*npart)+"/name", slot.name());
  236. if(cbwig_)
  237. cbwig_->do_callback();
  238. }
  239. //save(write) to slot
  240. if(event==1 && mode==2){
  241. if(!isempty && !fl_choice("Overwrite the slot no. %d ?","No","Yes",NULL,nslot+1))
  242. return;
  243. osc->write("/save-bank-part", "ii", *npart, nslot);
  244. osc->write("/refresh_bank", "i", nslot);
  245. //pthread_mutex_lock(&master->part[*npart]->load_mutex);
  246. //bank->savetoslot(slot,master->part[*npart]);
  247. //pthread_mutex_unlock(&master->part[*npart]->load_mutex);
  248. bvc->mode(1);
  249. }
  250. //Clears the slot
  251. if(event==1 && mode==3 && !isempty) {
  252. if (fl_choice("Clear the slot no. %d ?","No","Yes",NULL, nslot+1)) {
  253. osc->write("/clear-bank-slot", "i", nslot);
  254. osc->write("/refresh_bank", "i", nslot);
  255. }
  256. }
  257. //Swap
  258. if(mode==4) {
  259. if(event==1 && nselected>=0){
  260. osc->write("/swap-bank-slots", "ii", nselected, nslot);
  261. osc->write("/refresh_bank", "i", nslot);
  262. osc->write("/refresh_bank", "i", nselected);
  263. //bank->swapslot(nselected,slot);
  264. nselected=-1;
  265. } else if(nselected<0 || event==2) {
  266. nselected=nslot;
  267. };
  268. };
  269. }
  270. void BankView::OSC_raw(const char *msg)
  271. {
  272. if(strcmp(rtosc_argument_string(msg), "iss"))
  273. return;
  274. int nslot = rtosc_argument(msg,0).i;
  275. const char *name = rtosc_argument(msg,1).s;
  276. const char *fname = rtosc_argument(msg,2).s;
  277. if(0 <= nslot && nslot < 160)
  278. slots[nslot]->update(name, fname);
  279. }
  280. void BankView::cbwig(Fl_Widget *w)
  281. {
  282. cbwig_ = w;
  283. }
  284. void BankView::refresh(void)
  285. {
  286. assert(osc);
  287. //Odd case during initialization
  288. if(!osc)
  289. return;
  290. for(int i=0; i<160; ++i)
  291. osc->write("/refresh_bank", "i", i);
  292. }