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.

524 lines
15KB

  1. /* SpiralPlugin
  2. * Copyleft (C) 2000 David Griffiths <dave@pawfal.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "MatrixPluginGUI.h"
  19. #include <FL/fl_draw.h>
  20. #include <FL/fl_draw.H>
  21. #include <FL/fl_file_chooser.h>
  22. static const int GUI_COLOUR = 179;
  23. static const int GUIBG_COLOUR = 144;
  24. static const int GUIBG2_COLOUR = 145;
  25. static const char NoteText[12][3] = {"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};
  26. ////////////////////////////////////////////
  27. Fl_MatrixButton::Fl_MatrixButton(int x, int y, int w, int h, char* n) :
  28. Fl_Button(x,y,w,h,n),
  29. m_Volume(NULL),
  30. cb_VolChange(NULL),
  31. cb_context(NULL)
  32. {
  33. m_SliderHidden=true;
  34. m_VolVal=255;
  35. }
  36. int Fl_MatrixButton::handle(int event)
  37. {
  38. if (value()==true && event==FL_PUSH && Fl::event_button()==3)
  39. {
  40. if (m_SliderHidden)
  41. {
  42. m_Volume = new Fl_Slider(x(),y()+h(),w(),50,"");
  43. m_Volume->type(4);
  44. m_Volume->selection_color(GUI_COLOUR);
  45. m_Volume->maximum(255);
  46. m_Volume->step(1);
  47. m_Volume->value(255-m_VolVal);
  48. m_Volume->user_data((void*)this);
  49. m_Volume->callback((Fl_Callback*)cb_Vol);
  50. m_Volume->show();
  51. parent()->add(m_Volume);
  52. parent()->redraw();
  53. m_SliderHidden=false;
  54. }
  55. else
  56. {
  57. m_Volume->hide();
  58. m_VolVal=255-m_Volume->value();
  59. parent()->remove(m_Volume);
  60. parent()->redraw();
  61. m_Volume=NULL;
  62. m_SliderHidden=true;
  63. }
  64. return 1;
  65. }
  66. if (event==FL_PUSH && Fl::event_button()==1 && !m_SliderHidden)
  67. {
  68. m_Volume->hide();
  69. m_VolVal=255-m_Volume->value();
  70. parent()->remove(m_Volume);
  71. parent()->redraw();
  72. m_Volume=NULL;
  73. m_SliderHidden=true;
  74. }
  75. if (Fl::event_button()!=3) return Fl_Button::handle(event);
  76. return 1;
  77. }
  78. inline void Fl_MatrixButton::cb_Vol_i(Fl_Slider* o, void* v)
  79. {
  80. m_VolVal=255-m_Volume->value();
  81. fl_color((char)m_VolVal,(char)m_VolVal,255);
  82. selection_color(fl_color());
  83. if (cb_VolChange) cb_VolChange(this,cb_context);
  84. redraw();
  85. }
  86. void Fl_MatrixButton::cb_Vol(Fl_Slider* o, void* v)
  87. { ((Fl_MatrixButton*)(o->user_data()))->cb_Vol_i(o,v);}
  88. ////////////////////////////////////////////
  89. MatrixPluginGUI::MatrixPluginGUI(int w, int h,MatrixPlugin *o,ChannelHandler *ch,const HostInfo *Info) :
  90. SpiralPluginGUI(w,h,o,ch),
  91. m_LastLight(0),
  92. m_LastPatSeqLight(0)
  93. {
  94. //size_range(10,10);
  95. m_NoteCut = new Fl_Button (5, h-30, 85, 20,"NoteCut");
  96. m_NoteCut->type(1);
  97. m_NoteCut->labelsize(10);
  98. m_NoteCut->value(0);
  99. m_NoteCut->callback((Fl_Callback*)cb_NoteCut);
  100. add(m_NoteCut);
  101. m_Pattern = new Fl_Counter(5, 20, 40, 20, "View");
  102. m_Pattern->labelsize(10);
  103. m_Pattern->type(FL_SIMPLE_COUNTER);
  104. m_Pattern->step(1);
  105. m_Pattern->value(0);
  106. m_Pattern->callback((Fl_Callback*)cb_Pattern);
  107. add(m_Pattern);
  108. m_PlayPattern = new Fl_Counter(50, 20, 40, 20, "Play");
  109. m_PlayPattern->labelsize(10);
  110. m_PlayPattern->type(FL_SIMPLE_COUNTER);
  111. m_PlayPattern->step(1);
  112. m_PlayPattern->value(0);
  113. m_PlayPattern->callback((Fl_Callback*)cb_PlayPattern);
  114. add(m_PlayPattern);
  115. m_Length = new Fl_Counter(5, 55, 40, 20, "Length");
  116. m_Length->labelsize(10);
  117. m_Length->type(FL_SIMPLE_COUNTER);
  118. m_Length->step(1);
  119. m_Length->value(64);
  120. m_Length->callback((Fl_Callback*)cb_Length);
  121. add(m_Length);
  122. m_Speed = new Fl_Knob (50, 60, 40, 40, "Speed");
  123. m_Speed->color(GUI_COLOUR);
  124. m_Speed->type(Fl_Knob::DOTLIN);
  125. m_Speed->labelsize(10);
  126. m_Speed->maximum(200);
  127. m_Speed->step(0.01);
  128. m_Speed->value(1.0);
  129. m_Speed->callback((Fl_Callback*)cb_Speed);
  130. add(m_Speed);
  131. m_SpeedVal = new Fl_Counter (5, 125, 85, 20, "");
  132. m_SpeedVal->labelsize(10);
  133. m_SpeedVal->value(10);
  134. m_SpeedVal->type(FL_SIMPLE_COUNTER);
  135. m_SpeedVal->step(1);
  136. m_SpeedVal->callback((Fl_Callback*)cb_Speed);
  137. add(m_SpeedVal);
  138. m_Octave = new Fl_Counter(5, 90, 40, 20, "Octave");
  139. m_Octave->labelsize(10);
  140. m_Octave->type(FL_SIMPLE_COUNTER);
  141. m_Octave->step(1);
  142. m_Octave->value(0);
  143. m_Octave->callback((Fl_Callback*)cb_Octave);
  144. add(m_Octave);
  145. m_CopyBtn = new Fl_Button (5, 150, 40, 20, "Copy");
  146. m_CopyBtn->labelsize (10);
  147. m_CopyBtn->callback ((Fl_Callback*)cb_CopyBtn);
  148. add (m_CopyBtn);
  149. m_PasteBtn = new Fl_Button (50, 150, 40, 20, "Paste");
  150. m_PasteBtn->labelsize (10);
  151. m_PasteBtn->deactivate();
  152. m_PasteBtn->callback ((Fl_Callback*)cb_PasteBtn);
  153. add (m_PasteBtn);
  154. m_ClearBtn = new Fl_Button (5, 175, 85, 20, "Clear");
  155. m_ClearBtn->labelsize (10);
  156. m_ClearBtn->callback ((Fl_Callback*)cb_ClearBtn);
  157. add (m_ClearBtn);
  158. m_TransUpBtn = new Fl_Button (5, 200, 40, 20, "Up");
  159. m_TransUpBtn->labelsize (10);
  160. m_TransUpBtn->callback ((Fl_Callback*)cb_TransUpBtn);
  161. add (m_TransUpBtn);
  162. m_TransDnBtn = new Fl_Button (50, 200, 40, 20, "Down");
  163. m_TransDnBtn->labelsize (10);
  164. m_TransDnBtn->callback ((Fl_Callback*)cb_TransDnBtn);
  165. add (m_TransDnBtn);
  166. m_TransLbl = new Fl_Box (5, 216, 85, 20, "Transpose");
  167. m_TransLbl->labelsize(10);
  168. add (m_TransLbl);
  169. int xoff=105;
  170. int yoff=40;
  171. int butsize=7;
  172. int n=0;
  173. fl_color(150,150,150);
  174. int markercol=fl_color();
  175. fl_color(170,170,170);
  176. int blcolour=fl_color();
  177. for(int x=0; x<MATX; x++)
  178. for(int y=0; y<MATY; y++)
  179. {
  180. Numbers[n]=n;
  181. m_Matrix[x][y] = new Fl_MatrixButton(xoff+x*butsize,yoff+((MATY-1)*butsize)-(y*butsize),butsize+1,butsize+1,"");
  182. m_Matrix[x][y]->type(1);
  183. m_Matrix[x][y]->box(FL_BORDER_BOX);
  184. if ((x%8)==0) m_Matrix[x][y]->color(markercol);
  185. else if ((y%12)==1 || (y%12)==3 || (y%12)==6 || (y%12)==8 || (y%12)==10) m_Matrix[x][y]->color(blcolour);
  186. else m_Matrix[x][y]->color(FL_GRAY);
  187. m_Matrix[x][y]->selection_color(FL_WHITE);
  188. m_Matrix[x][y]->callback((Fl_Callback*)cb_Matrix,(void*)&Numbers[n]);
  189. m_Matrix[x][y]->SetVolCallback((Fl_Callback*)cb_MatVol,(void*)&Numbers[n]);
  190. add(m_Matrix[x][y]);
  191. n++;
  192. }
  193. yoff=37;
  194. for(int y=0; y<MATY; y++)
  195. {
  196. Fl_Box *box = new Fl_Box(90,yoff+((MATY-1)*butsize)-(y*butsize),15,15,NoteText[y%12]);
  197. box->align(FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
  198. box->labelsize(8);
  199. }
  200. xoff=103;
  201. for(int x=0; x<MATX; x++)
  202. {
  203. m_Flash[x] = new Fl_LED_Button(xoff+x*butsize,20,15,15,"");
  204. m_Flash[x]->selection_color(FL_WHITE);
  205. add(m_Flash[x]);
  206. }
  207. xoff=560;
  208. yoff=40;
  209. int height=12,gap=2;
  210. Fl_Box *patseqlabel = new Fl_Box(xoff,yoff-15,30,10,"Pat Seq");
  211. patseqlabel->labelsize(10);
  212. add(patseqlabel);
  213. for(int y=0; y<NUM_PATSEQ; y++)
  214. {
  215. m_PatSeq[y]= new Fl_Counter(xoff,yoff+y*(height+gap),25,height);
  216. m_PatSeq[y]->type(FL_SIMPLE_COUNTER);
  217. m_PatSeq[y]->step(1);
  218. m_PatSeq[y]->textsize(8);
  219. m_PatSeq[y]->callback((Fl_Callback*)cb_PatSeq,(void*)&Numbers[y]);
  220. add(m_PatSeq[y]);
  221. m_PatSeqFlash[y] = new Fl_LED_Button(xoff+25,yoff+y*(height+gap),15,15,"");
  222. m_PatSeqFlash[y]->selection_color(FL_WHITE);
  223. add(m_PatSeqFlash[y]);
  224. }
  225. end();
  226. }
  227. void MatrixPluginGUI::Update()
  228. {
  229. int Light=m_GUICH->GetInt("Step");
  230. if (Light!=m_LastLight)
  231. {
  232. m_Flash[Light]->value(1);
  233. m_Flash[m_LastLight]->value(0);
  234. m_LastLight=Light;
  235. m_PlayPattern->value (m_GUICH->GetInt("EchoCur"));
  236. int PatSeqLight=m_GUICH->GetInt("PatSeqStep");
  237. if (PatSeqLight!=m_LastPatSeqLight)
  238. {
  239. m_PatSeqFlash[PatSeqLight]->value(1);
  240. m_PatSeqFlash[m_LastPatSeqLight]->value(0);
  241. m_LastPatSeqLight=PatSeqLight;
  242. }
  243. }
  244. }
  245. void MatrixPluginGUI::UpdateValues(SpiralPlugin *o)
  246. {
  247. MatrixPlugin *Plugin = (MatrixPlugin*)o;
  248. m_Pattern->value(Plugin->GetCurrent());
  249. m_Length->value(Plugin->GetPattern()->Length);
  250. m_Speed->value(Plugin->GetPattern()->Speed*8);
  251. m_SpeedVal->value((int)m_Speed->value());
  252. m_Octave->value(Plugin->GetPattern()->Octave);
  253. for(int x=0; x<MATX; x++)
  254. for(int y=0; y<MATY; y++)
  255. {
  256. m_Matrix[x][y]->value(Plugin->GetPattern()->Matrix[x][y]);
  257. m_Matrix[x][y]->SetVolume(Plugin->GetPattern()->Volume[x][y]);
  258. }
  259. for(int n=0; n<NUM_PATSEQ; n++)
  260. {
  261. m_PatSeq[n]->value(Plugin->GetPatSeq(n));
  262. }
  263. }
  264. void MatrixPluginGUI::UpdateMatrix()
  265. {
  266. m_GUICH->Wait();
  267. m_GUICH->RequestChannelAndWait("Matrix");
  268. m_GUICH->GetData("Matrix",(void*)m_GUIMatrix);
  269. Pattern *p=&m_GUIMatrix[(int)m_Pattern->value()];
  270. m_Length->value(p->Length);
  271. m_Speed->value(p->Speed*8);
  272. m_SpeedVal->value((int)m_Speed->value());
  273. m_Octave->value(p->Octave);
  274. for(int x=0; x<MATX; x++)
  275. for(int y=0; y<MATY; y++)
  276. {
  277. m_Matrix[x][y]->value(p->Matrix[x][y]);
  278. m_Matrix[x][y]->SetVolume(p->Volume[x][y]);
  279. }
  280. }
  281. inline void MatrixPluginGUI::cb_NoteCut_i(Fl_Button* o, void* v)
  282. {
  283. m_GUICH->Set("NoteCut",o->value());
  284. }
  285. void MatrixPluginGUI::cb_NoteCut(Fl_Button* o, void* v)
  286. { ((MatrixPluginGUI*)(o->parent()))->cb_NoteCut_i(o,v);}
  287. inline void MatrixPluginGUI::cb_Matrix_i(Fl_Button* o, void* v)
  288. {
  289. m_GUICH->Set("X",*(int*)v/MATY);
  290. m_GUICH->Set("Y",*(int*)v%MATY);
  291. if (o->value()) m_GUICH->SetCommand(MatrixPlugin::MAT_ACTIVATE);
  292. else m_GUICH->SetCommand(MatrixPlugin::MAT_DEACTIVATE);
  293. m_GUICH->Wait();
  294. }
  295. void MatrixPluginGUI::cb_Matrix(Fl_Button* o, void* v)
  296. { ((MatrixPluginGUI*)(o->parent()))->cb_Matrix_i(o,v);}
  297. inline void MatrixPluginGUI::cb_MatVol_i(Fl_Button* o, void* v)
  298. {
  299. m_GUICH->Set("X",*(int*)v/MATY);
  300. m_GUICH->Set("Y",*(int*)v%MATY);
  301. m_GUICH->Set("Volume",((Fl_MatrixButton*)o)->GetVolume());
  302. m_GUICH->SetCommand(MatrixPlugin::MAT_VOLUME);
  303. }
  304. void MatrixPluginGUI::cb_MatVol(Fl_Button* o, void* v)
  305. { ((MatrixPluginGUI*)(o->parent()))->cb_MatVol_i(o,v);}
  306. inline void MatrixPluginGUI::cb_Pattern_i(Fl_Counter* o, void* v)
  307. {
  308. if (o->value()<0) o->value(0);
  309. if (o->value()>NUM_PATTERNS-1) o->value(NUM_PATTERNS-1);
  310. m_GUICH->Set("Current",(int)o->value());
  311. UpdateMatrix();
  312. }
  313. void MatrixPluginGUI::cb_Pattern(Fl_Counter* o, void* v)
  314. { ((MatrixPluginGUI*)(o->parent()))->cb_Pattern_i(o,v);}
  315. inline void MatrixPluginGUI::cb_PlayPattern_i(Fl_Counter* o, void* v)
  316. {
  317. if (o->value()<0) o->value(0);
  318. if (o->value()>NUM_PATTERNS-1) o->value(NUM_PATTERNS-1);
  319. m_GUICH->Set("Num",(int)o->value());
  320. m_GUICH->SetCommand(MatrixPlugin::SET_CURRENT);
  321. }
  322. void MatrixPluginGUI::cb_PlayPattern(Fl_Counter* o, void* v)
  323. { ((MatrixPluginGUI*)(o->parent()))->cb_PlayPattern_i(o,v);}
  324. inline void MatrixPluginGUI::cb_Length_i(Fl_Counter* o, void* v)
  325. {
  326. if (o->value()<1) o->value(1);
  327. if (o->value()>64) o->value(64);
  328. m_GUICH->Set("Length",(int)o->value());
  329. m_GUICH->SetCommand(MatrixPlugin::MAT_LENGTH);
  330. }
  331. void MatrixPluginGUI::cb_Length(Fl_Counter* o, void* v)
  332. { ((MatrixPluginGUI*)(o->parent()))->cb_Length_i(o,v);}
  333. inline void MatrixPluginGUI::cb_Speed_i(Fl_Knob* o, void* v)
  334. {
  335. // Round off value, but it should be a float for tweaking
  336. float value=o->value()+((int)o->value()-o->value());
  337. m_SpeedVal->value(value);
  338. m_GUICH->Set("Speed",(float)value/8.0f);
  339. m_GUICH->SetCommand(MatrixPlugin::MAT_SPEED);
  340. }
  341. void MatrixPluginGUI::cb_Speed(Fl_Knob* o, void* v)
  342. { ((MatrixPluginGUI*)(o->parent()))->cb_Speed_i(o,v);}
  343. inline void MatrixPluginGUI::cb_Octave_i(Fl_Counter* o, void* v)
  344. {
  345. if (o->value()<0) o->value(0);
  346. if (o->value()>6) o->value(6);
  347. m_GUICH->Set("Octave",(int)o->value());
  348. m_GUICH->SetCommand(MatrixPlugin::MAT_OCTAVE);
  349. }
  350. void MatrixPluginGUI::cb_Octave(Fl_Counter* o, void* v)
  351. { ((MatrixPluginGUI*)(o->parent()))->cb_Octave_i(o,v);}
  352. inline void MatrixPluginGUI::cb_SpeedVal_i (Fl_Counter* o, void* v)
  353. {
  354. m_Speed->value(o->value());
  355. }
  356. void MatrixPluginGUI::cb_SpeedVal (Fl_Counter* o, void* v)
  357. {
  358. ((MatrixPluginGUI*)(o->parent())) -> cb_SpeedVal_i (o, v);
  359. }
  360. inline void MatrixPluginGUI::cb_CopyBtn_i (Fl_Button* o, void* v)
  361. {
  362. m_PasteBtn->activate();
  363. m_GUICH->SetCommand(MatrixPlugin::COPY);
  364. UpdateMatrix();
  365. }
  366. void MatrixPluginGUI::cb_CopyBtn (Fl_Button* o, void* v)
  367. {
  368. ((MatrixPluginGUI*)(o->parent())) -> cb_CopyBtn_i (o, v);
  369. }
  370. inline void MatrixPluginGUI::cb_PasteBtn_i (Fl_Button* o, void* v)
  371. {
  372. m_GUICH->SetCommand(MatrixPlugin::PASTE);
  373. UpdateMatrix();
  374. }
  375. void MatrixPluginGUI::cb_PasteBtn (Fl_Button* o, void* v)
  376. {
  377. ((MatrixPluginGUI*)(o->parent())) -> cb_PasteBtn_i (o, v);
  378. }
  379. inline void MatrixPluginGUI::cb_ClearBtn_i (Fl_Button* o, void* v)
  380. {
  381. m_GUICH->SetCommand(MatrixPlugin::CLEAR);
  382. UpdateMatrix();
  383. }
  384. void MatrixPluginGUI::cb_ClearBtn (Fl_Button* o, void* v)
  385. {
  386. ((MatrixPluginGUI*)(o->parent())) -> cb_ClearBtn_i (o, v);
  387. }
  388. inline void MatrixPluginGUI::cb_TransUpBtn_i (Fl_Button* o, void* v)
  389. {
  390. m_GUICH->SetCommand(MatrixPlugin::TUP);
  391. UpdateMatrix();
  392. }
  393. void MatrixPluginGUI::cb_TransUpBtn (Fl_Button* o, void* v)
  394. {
  395. ((MatrixPluginGUI*)(o->parent())) -> cb_TransUpBtn_i (o, v);
  396. }
  397. inline void MatrixPluginGUI::cb_TransDnBtn_i (Fl_Button* o, void* v)
  398. {
  399. m_GUICH->SetCommand(MatrixPlugin::TDOWN);
  400. UpdateMatrix();
  401. }
  402. void MatrixPluginGUI::cb_TransDnBtn (Fl_Button* o, void* v)
  403. {
  404. ((MatrixPluginGUI*)(o->parent())) -> cb_TransDnBtn_i (o, v);
  405. }
  406. inline void MatrixPluginGUI::cb_PatSeq_i(Fl_Counter* o, void* v)
  407. {
  408. if (o->value()<-1) o->value(-1);
  409. if (o->value()>NUM_PATTERNS-1) o->value(NUM_PATTERNS-1);
  410. m_GUICH->Set("Num",(int)o->value());
  411. m_GUICH->Set("Y",*(int*)v);
  412. m_GUICH->SetCommand(MatrixPlugin::SET_PATSEQ);
  413. }
  414. void MatrixPluginGUI::cb_PatSeq(Fl_Counter* o, void* v)
  415. { ((MatrixPluginGUI*)(o->parent()))->cb_PatSeq_i(o,v);}
  416. const string MatrixPluginGUI::GetHelpText(const string &loc){
  417. return string("")
  418. + "This is a matrix style step sequencer for techno purists. Great for\n"
  419. + "drum programming, but also capable of robotic bass and melodies.\n\n"
  420. + "Note events are turned on and off by activating the 64*32 grid of\n"
  421. + "toggle buttons on the GUI. The speed and octave of the notes can be\n"
  422. + "set. The length of the pattern in notes and note cut are also\n"
  423. + "present. The current play position is indicated by the row of LED's\n"
  424. + "along the top of the plugin window. You can copy and paste between\n"
  425. + "different patterns and transpose the notes\n\n"
  426. + "16 triggers are supplied for simultaneous triggering of samples in the\n"
  427. + "sampler plugin (for instance).\n\n"
  428. + "Each Matrix plugin can contain up to 16 different patterns, these are\n"
  429. + "selectable on the plugin GUI, and triggerable by the play trigger CV.\n"
  430. + "This CV input takes a note frequency CV rather than just a trigger,\n"
  431. + "and the bottom 16 notes on the midi scale trigger the 16 patterns.\n"
  432. + "This means that a matrix can trigger another matrix, if set to a much\n"
  433. + "lower speed, and (set to octave 0) the notes trigger the differnt\n"
  434. + "patterns in the slave matrix.\n\n"
  435. + "The external clock input is an important alternative to the matrixes\n"
  436. + "internal clock, it allows you to have multiple matrixes powered from one\n"
  437. + "oscillator clock. To allow you to sync these matrixes, the matrix is\n"
  438. + "provided with a Reset Trigger, which when plugged into the Play Trigger\n"
  439. + "of another matrix, will synch the two so they start at the same clock\n"
  440. + "pulse.\n\n"
  441. + "On the right hand side of the matrix you will find the pattern sequencer\n"
  442. + "this will advance each time a full pattern is played, and you can use it\n"
  443. + "to select which pattern will be played next. There are a maximum of 16\n"
  444. + "patterns to the sequence, but you can use less by setting a slot to -1\n"
  445. + "this will cause the sequence to loop back to zero";
  446. }