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.

570 lines
18KB

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