1 /*
2  * Copyright (C) 2017 Hermann Meyer, Andreas Degert
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  * --------------------------------------------------------------------------
18  */
19 
20 #include "guitarix.h"                    // NOLINT
21 
22 namespace gx_seq {
23 
24 #define DRUMS 6
25 
26 #define FOR_DRUMS(func) std::for_each(drums.begin(), drums.end(), [&](Drums d) { func });
27 
28 /****************************************************************
29  ** PluginPresetConnectWindow
30  */
31 
create_from_builder(BaseObjectType * cobject,Glib::RefPtr<gx_gui::GxBuilder> bld,gx_engine::GxMachineBase & _machine)32 PluginPresetConnectWindow *PluginPresetConnectWindow::create_from_builder(
33     BaseObjectType* cobject, Glib::RefPtr<gx_gui::GxBuilder> bld, gx_engine::GxMachineBase& _machine) {
34     return new PluginPresetConnectWindow(cobject, bld, _machine);
35 }
36 
~PluginPresetConnectWindow()37 PluginPresetConnectWindow::~PluginPresetConnectWindow() {
38 }
39 
create(gx_engine::GxMachineBase & machine)40 PluginPresetConnectWindow *PluginPresetConnectWindow::create(
41                           gx_engine::GxMachineBase& machine) {
42     Glib::RefPtr<gx_gui::GxBuilder> bld = gx_gui::GxBuilder::create_from_file(
43       machine.get_options().get_builder_filepath("pluginpreset_connectwindow.glade"));
44     PluginPresetConnectWindow *w;
45     bld->get_toplevel_derived("PluginPresetConnectWindow", w,
46       sigc::bind(sigc::ptr_fun(PluginPresetConnectWindow::create_from_builder), bld, sigc::ref(machine)));
47     return w;
48 }
49 
on_key_press_event(GdkEventKey * event)50 bool PluginPresetConnectWindow::on_key_press_event(GdkEventKey *event) {
51     if (event->keyval == GDK_KEY_Escape && (event->state & Gtk::AccelGroup::get_default_mod_mask()) == 0) {
52         hide();
53         return true;
54     }
55     return Gtk::Window::on_key_press_event(event);
56 }
57 
on_connect()58 void PluginPresetConnectWindow::on_connect() {
59     Gtk::TreeIter it = treeview->get_selection()->get_selected();
60     if (it && !machine.midi_get_config_mode()) {
61         Glib::ustring id = "seq." + it->get_value(upresetliststore->col.name);
62         if (machine.parameter_hasId(id))
63           new gx_main_midi::MidiConnect(0, machine.get_parameter(id), machine);
64     }
65 }
66 
PluginPresetConnectWindow(BaseObjectType * cobject,Glib::RefPtr<gx_gui::GxBuilder> bld,gx_engine::GxMachineBase & _machine)67 PluginPresetConnectWindow::PluginPresetConnectWindow(
68     BaseObjectType* cobject, Glib::RefPtr<gx_gui::GxBuilder> bld, gx_engine::GxMachineBase& _machine)
69     : Gtk::Window(cobject),
70       upresetliststore(UPresetListStore::create()),
71       machine(_machine) {
72     set_title("Connect Midi");
73     Gtk::Button *b;
74     bld->find_widget("closebutton", b);
75     b->signal_clicked().connect(
76       sigc::mem_fun(*this, &PluginPresetConnectWindow::hide));
77     bld->find_widget("connectbutton", connectbutton);
78     connectbutton->signal_clicked().connect(
79       sigc::mem_fun0(*this, &PluginPresetConnectWindow::on_connect));
80     bld->find_widget("treeview", treeview);
81     gx_preset::UnitPresetList presetnames;
82     machine.plugin_preset_list_load(machine.pluginlist_lookup_plugin("seq")->get_pdef(), presetnames);
83     for (gx_preset::UnitPresetList::const_iterator i = presetnames.begin(); i != presetnames.end(); ++i) {
84         if (i->name.empty()) {
85             break;
86         }
87         upresetliststore->append()->set_value(upresetliststore->col.name, i->name);
88     }
89     treeview->set_model(upresetliststore);
90     connectbutton->set_sensitive(false);
91     Glib::RefPtr<Gtk::TreeSelection> sel = treeview->get_selection();
92     sel->signal_changed().connect(
93       sigc::mem_fun(*this, &PluginPresetConnectWindow::on_selection_changed));
94 }
95 
on_selection_changed()96 void PluginPresetConnectWindow::on_selection_changed() {
97     connectbutton->set_sensitive(treeview->get_selection()->get_selected());
98 }
99 
run()100 void PluginPresetConnectWindow::run() {
101     Gtk::Main::run(*this);
102 }
103 
104 /****************************************************************
105  ** Sequencer Parameter Window
106  */
107 
create(const std::string & unit_id,gx_engine::GxMachineBase & machine)108 SEQWindow *SEQWindow::create(const std::string& unit_id, gx_engine::GxMachineBase& machine) {
109     Glib::RefPtr<gx_gui::GxBuilder> bld = gx_gui::GxBuilder::create_from_file(
110       machine.get_options().get_builder_filepath("Sequencer.glade"), &machine);
111     gx_engine::SeqParameter *tomp = dynamic_cast<gx_engine::SeqParameter*>(&machine.get_parameter("seq.sequencer.tom"));
112     gx_engine::SeqParameter *tomp1 = dynamic_cast<gx_engine::SeqParameter*>(&machine.get_parameter("seq.sequencer.tom1"));
113     gx_engine::SeqParameter *tomp2 = dynamic_cast<gx_engine::SeqParameter*>(&machine.get_parameter("seq.sequencer.tom2"));
114     gx_engine::SeqParameter *kickp = dynamic_cast<gx_engine::SeqParameter*>(&machine.get_parameter("seq.sequencer.kick"));
115     gx_engine::SeqParameter *snarep = dynamic_cast<gx_engine::SeqParameter*>(&machine.get_parameter("seq.sequencer.snare"));
116     gx_engine::SeqParameter *hatp = dynamic_cast<gx_engine::SeqParameter*>(&machine.get_parameter("seq.sequencer.hat"));
117     assert(tomp);
118     assert(tomp1);
119     assert(tomp2);
120     assert(kickp);
121     assert(snarep);
122     assert(hatp);
123     return new SEQWindow(bld, tomp, tomp1, tomp2, kickp, snarep, hatp, machine);
124 }
125 
126 /*
127  ** Constructor
128  */
129 
SEQWindow(const Glib::RefPtr<gx_gui::GxBuilder> & bld,gx_engine::SeqParameter * tomp_,gx_engine::SeqParameter * tomp1_,gx_engine::SeqParameter * tomp2_,gx_engine::SeqParameter * kickp_,gx_engine::SeqParameter * snarep_,gx_engine::SeqParameter * hatp_,gx_engine::GxMachineBase & machine_)130 SEQWindow::SEQWindow(const Glib::RefPtr<gx_gui::GxBuilder>& bld,gx_engine::SeqParameter *tomp_,
131          gx_engine::SeqParameter *tomp1_,gx_engine::SeqParameter *tomp2_,
132          gx_engine::SeqParameter *kickp_, gx_engine::SeqParameter *snarep_,
133          gx_engine::SeqParameter *hatp_, gx_engine::GxMachineBase& machine_)
134     : machine(machine_),
135       builder(bld),
136       tom(tomp_),
137       tom1(tomp1_),
138       tom2(tomp2_),
139       kick(kickp_),
140       snare(snarep_),
141       hat(hatp_),
142       is_active(false),
143       gtk_window(0) {
144     bld->get_toplevel("SequencerWindow", gtk_window);
145 
146     init_connect();
147 
148     // reset display
149 }
150 
init_connect()151 void SEQWindow::init_connect() {
152 
153     builder->find_widget("viewport1", vp);
154     builder->find_widget("hbox1", tom.box);
155     builder->find_widget("hbox1a", tom1.box);
156     builder->find_widget("hbox1b", tom2.box);
157     builder->find_widget("hbox2", kick.box);
158     builder->find_widget("hbox3", snare.box);
159     builder->find_widget("hbox4", hat.box);
160     builder->find_widget("gxplayhead1", seq_pos);
161     builder->find_widget("gxsmallknob6", seq_count);
162     builder->find_widget("gxselector1", seq_tact);
163     builder->find_widget("hbox12", preset_button);
164     builder->find_widget("gxswitch6", add_button);
165     builder->find_widget("gxswitch3", next_preset);
166     builder->find_widget("gxswitch7", previus_preset);
167     builder->find_widget("gxswitch4", set_step);
168     builder->find_widget("gxswitch5", set_fstep);
169     builder->find_widget("gxswitch8", set_sync);
170     builder->find_widget("gxswitch9", reset_step);
171     builder->find_widget("label9:rack_label_inverse", preset_label);
172     builder->find_widget("gxvaluedisplay1", step_value);
173     builder->find_widget("label8:rack_label_inverse", step_label);
174 
175     Pango::FontDescription font = preset_label->get_style_context()->get_font();
176     font.set_size(10*Pango::SCALE);
177     font.set_weight(Pango::WEIGHT_BOLD);
178     preset_label->override_font(font);
179 
180     make_preset_button(preset_button);
181 
182     drums.push_back(tom);
183     drums.push_back(tom1);
184     drums.push_back(tom2);
185     drums.push_back(kick);
186     drums.push_back(snare);
187     drums.push_back(hat);
188 
189     on_sec_length_changed(false);
190 
191     FOR_DRUMS(
192         d.p->signal_changed().connect(sigc::bind(
193           sigc::mem_fun(this, &SEQWindow::seq_changed), d.box));
194         init_sequences(d.p, d.box);
195     );
196 
197     seq_pos->cp_set_value(0.0);
198     std::string id;
199     seq_pos->get_property("var_id",id);
200 
201     int ti_o = 60;
202     if (!machine.get_jack()) ti_o = 250;
203     Glib::signal_timeout().connect(
204       sigc::bind<Gxw::Regler*>(sigc::bind<const std::string>(
205       sigc::mem_fun(*this, &SEQWindow::get_sequencer_pos),id), seq_pos), ti_o);
206 
207     seq_count->signal_value_changed().connect(
208       sigc::bind(sigc::mem_fun(*this, &SEQWindow::on_sec_length_changed), true));
209 
210     seq_tact->signal_value_changed().connect(
211       sigc::mem_fun(*this, &SEQWindow::on_sec_tact_changed));
212 
213     next_preset->signal_toggled().connect(
214       sigc::mem_fun(*this, &SEQWindow::on_next_preset));
215 
216     previus_preset->signal_toggled().connect(
217       sigc::mem_fun(*this, &SEQWindow::on_previus_preset));
218 
219     set_step->signal_toggled().connect(
220       sigc::mem_fun(*this, &SEQWindow::on_set_step));
221 
222     set_fstep->signal_toggled().connect(
223       sigc::mem_fun(*this, &SEQWindow::on_set_fstep));
224 
225     set_sync->signal_toggled().connect(
226       sigc::mem_fun(*this, &SEQWindow::on_sync_stepper));
227 
228     reset_step->signal_toggled().connect(
229       sigc::mem_fun(*this, &SEQWindow::on_reset_stepper));
230 
231     add_button->signal_clicked().connect(
232       sigc::mem_fun(*this, &SEQWindow::on_preset_add_clicked));
233     gx_gui::GxBuilder::set_tooltip_text_connect_handler(*add_button, _("add effect unit preset to the sequence"));
234 
235     gtk_window->signal_key_press_event().connect(
236       sigc::mem_fun(this, &SEQWindow::on_key_press_event));
237 
238     if (!machine.get_jack()) {
239         step_value->hide();
240         step_label->hide();
241     }
242 }
243 
init_sequences(gx_engine::SeqParameter * p,Gtk::Box * _box)244 void SEQWindow::init_sequences(gx_engine::SeqParameter *p, Gtk::Box* _box) {
245     Glib::ListHandle<Gtk::Widget*> List = _box->get_children();
246     for (Glib::ListHandle<Gtk::Widget*>::iterator itt = List.begin();itt != List.end(); ++itt) {
247         dynamic_cast<Gtk::ToggleButton*>((*itt))->signal_clicked().connect(
248           sigc::bind(sigc::bind(sigc::mem_fun(this, &SEQWindow::on_seq_button_clicked),p),_box));
249     }
250 }
251 
on_set_step()252 void SEQWindow::on_set_step() {
253     if (!set_step->get_active()) return;
254         float tactv = machine.get_parameter_value<float>("seq.tact");
255         float value = std::max(0,int(machine.get_parameter_value<float>("seq.step")-tactv));
256         reset_control("seq.step",value);
257         set_step->set_active(false);
258 }
259 
on_set_fstep()260 void SEQWindow::on_set_fstep() {
261     if (!set_fstep->get_active()) return;
262         float tactv = machine.get_parameter_value<float>("seq.tact");
263         float valuea = machine.get_parameter_value<float>("seq.asequences");
264         float value = std::min(int(valuea),int(machine.get_parameter_value<float>("seq.step")+tactv));
265         reset_control("seq.step",value);
266         set_fstep->set_active(false);
267 }
268 
on_sync_stepper()269 void SEQWindow::on_sync_stepper() {
270     if (!set_sync->get_active()) return;
271     reset_control("seq.step",machine.get_parameter_value<float>("seq.step_orig"));
272     set_sync->set_active(false);
273 }
274 
on_reset_stepper()275 void SEQWindow::on_reset_stepper() {
276     if (!reset_step->get_active()) return;
277     reset_control("seq.step",0.0);
278     reset_control("seq.step_orig",0.0);
279     reset_control("seq.pos",0.0);
280     reset_step->set_active(false);
281 }
282 
on_next_preset()283 void SEQWindow::on_next_preset() {
284     if (!next_preset->get_active()) return;
285     if (!is_active) {
286         is_active = true;
287         Glib::signal_idle().connect_once(sigc::mem_fun(this, &SEQWindow::on_next_preset_set));
288     }
289 }
290 
on_next_preset_set()291 void SEQWindow::on_next_preset_set() {
292     gx_preset::UnitPresetList presetnames;
293     machine.plugin_preset_list_load(machine.pluginlist_lookup_plugin("seq")->get_pdef(), presetnames);
294     for (gx_preset::UnitPresetList::iterator i = presetnames.begin(); i != presetnames.end(); ++i) {
295         if (!i->name.empty()) {
296             if (i->is_set) {
297                ++i;
298                if (i->name.empty()) i = presetnames.begin();
299                machine.plugin_preset_list_sync_set(machine.pluginlist_lookup_plugin("seq")->get_pdef(), false, i->name);
300                 break;
301             } else {
302                 machine.plugin_preset_list_sync_set(machine.pluginlist_lookup_plugin("seq")->get_pdef(), false, presetnames.begin()->name);
303             }
304         }
305     }
306     is_active = false;
307     reset_control("seq.npreset",0);
308 }
309 
on_previus_preset()310 void SEQWindow::on_previus_preset() {
311     if (!previus_preset->get_active()) return;
312     if (!is_active) {
313         is_active = true;
314         Glib::signal_idle().connect_once(sigc::mem_fun(this, &SEQWindow::on_previus_preset_set));
315     }
316 }
317 
on_previus_preset_set()318 void SEQWindow::on_previus_preset_set() {
319     gx_preset::UnitPresetList presetnames;
320     machine.plugin_preset_list_load(machine.pluginlist_lookup_plugin("seq")->get_pdef(), presetnames);
321     gx_preset::UnitPresetList::iterator i = presetnames.begin();
322     for ( i = presetnames.begin(); i != presetnames.end(); ++i) {
323         if (!i->name.empty()) {
324             if (i->is_set) break;
325         }
326     }
327     if (i == presetnames.begin()) {
328         i = presetnames.end();
329         --i;
330     } else if (i == presetnames.end()) {
331         i -=2;
332     }
333     --i;
334     machine.plugin_preset_list_sync_set(machine.pluginlist_lookup_plugin("seq")->get_pdef(), false, i->name);
335     is_active = false;
336     reset_control("seq.ppreset",0);
337 }
338 
on_preset_popup_clicked()339 void SEQWindow::on_preset_popup_clicked() {
340     Gtk::Menu *presetMenu = static_cast<Gtk::Menu*>(new PluginPresetPopup(machine.pluginlist_lookup_plugin("seq")->get_pdef(), machine));
341     Gtk::MenuItem* subitem = Gtk::manage(new Gtk::MenuItem("connect midi...", true));
342     presetMenu->append(*subitem);
343     subitem->signal_activate().connect(sigc::mem_fun(
344               *this, &SEQWindow::connect_midi));
345     presetMenu->show_all();
346 }
347 
connect_midi()348 void SEQWindow::connect_midi() {
349     PluginPresetConnectWindow *w = PluginPresetConnectWindow::create(machine);
350     w->run();
351     delete w;
352 }
353 
make_preset_button(Gtk::Box * box)354 void SEQWindow::make_preset_button(Gtk::Box * box) {
355     Gtk::Button *p = new Gtk::Button();
356     Gtk::Image *l = new Gtk::Image();
357     l->Gtk::Image::set_from_icon_name("rack_preset", Gtk::ICON_SIZE_BUTTON);
358     p->add(*Gtk::manage(l));
359     p->set_can_default(false);
360     p->set_can_focus(false);
361     gx_gui::GxBuilder::set_tooltip_text_connect_handler(*p, _("manage effect unit presets"));
362     p->set_name("effect_on_off");
363     box->pack_start(*Gtk::manage(p),Gtk::PACK_SHRINK);
364     p->signal_clicked().connect(
365       sigc::mem_fun(*this, &SEQWindow::on_preset_popup_clicked));
366     p->show_all();
367 }
368 
reset_control(Glib::ustring id,float value)369 void SEQWindow::reset_control(Glib::ustring id, float value) {
370     machine.set_parameter_value(id,value);
371     machine.signal_parameter_value<float>(id)(value);
372 }
373 
append_sequence(const gx_engine::GxSeqSettings * seqc,gx_engine::SeqParameter * p,std::vector<int> * sequence)374 int SEQWindow::append_sequence(const gx_engine::GxSeqSettings* seqc, gx_engine::SeqParameter *p, std::vector<int> *sequence) {
375     int s = 0;
376     std::vector<int> sequence_append = seqc->getseqline();
377     for(std::vector<int>::const_iterator i = sequence_append.begin(); i != sequence_append.end(); ++i) {
378         sequence->push_back(*i);
379        ++s;
380     }
381     return s;
382 }
383 
append_plugin_preset(Glib::ustring name)384 void SEQWindow::append_plugin_preset(Glib::ustring name) {
385     if (!is_active) {
386         is_active = true;
387         Glib::signal_timeout().connect_once(sigc::bind(sigc::mem_fun(this, &SEQWindow::append_plugin_preset_set),name),5);
388     }
389 }
390 
append_plugin_preset_set(Glib::ustring name)391 void SEQWindow::append_plugin_preset_set(Glib::ustring name) {
392     // get current sequences
393     std::vector<int> sequence[DRUMS];
394     int i = 0;
395     FOR_DRUMS(
396         sequence[i] = static_cast<const gx_engine::GxSeqSettings*>(&d.p->get_value())->getseqline();
397         ++i;
398     );
399 
400     // get current control values
401     float value = machine.get_parameter_value<float>("seq.asequences");
402     float bpmv = machine.get_parameter_value<float>("seq.bpm");
403     float tactv = machine.get_parameter_value<float>("seq.tact");
404     float gainv = machine.get_parameter_value<float>("seq.gain");
405     float tomg = machine.get_parameter_value<float>("seq.tom.dsp.Gain");
406     float tomg1 = machine.get_parameter_value<float>("seq.tom.dsp.Gain1");
407     float tomg2 = machine.get_parameter_value<float>("seq.tom.dsp.Gain2");
408     float kickg = machine.get_parameter_value<float>("seq.kick.dsp.Gain");
409     float snareg = machine.get_parameter_value<float>("seq.snare.dsp.Gain");
410     float hatg = machine.get_parameter_value<float>("seq.hat_closed.dsp.Gain");
411     // set preset values
412     machine.plugin_preset_list_set(machine.pluginlist_lookup_plugin("seq")->get_pdef(), false, name);
413 
414     // append preset sequence to current and get new step size
415     int s = 24;
416     i = 0;
417     FOR_DRUMS(
418         s = append_sequence(&d.p->get_value(), d.p, &sequence[i]);
419         ++i;
420     );
421 
422     // set new step size
423     value += float(s);
424     reset_control("seq.asequences",value);
425 
426     // set new sequences as parameter
427     gx_engine::GxSeqSettings seqc;
428     i = 0;
429     FOR_DRUMS(
430         seqc.setseqline(sequence[i]);
431         d.p->set(seqc);
432         ++i;
433     );
434 
435     // reset controls to previous values
436     reset_control("seq.bpm",bpmv);
437     reset_control("seq.tact",tactv);
438     reset_control("seq.gain",gainv);
439     reset_control("seq.tom.dsp.Gain",tomg);
440     reset_control("seq.tom.dsp.Gain1",tomg1);
441     reset_control("seq.tom.dsp.Gain2",tomg2);
442     reset_control("seq.kick.dsp.Gain",kickg);
443     reset_control("seq.snare.dsp.Gain",snareg);
444     reset_control("seq.hat_closed.dsp.Gain",hatg);
445 
446     is_active = false;
447  }
448 
delete_plugin_preset_popup(Gtk::Menu * presetMenu)449 static bool delete_plugin_preset_popup(Gtk::Menu *presetMenu) {
450     delete presetMenu;
451     return false;
452 }
453 
on_selection_done(Gtk::Menu * presetMenu)454 void SEQWindow::on_selection_done(Gtk::Menu *presetMenu) {
455     Glib::signal_idle().connect(sigc::bind(
456       sigc::ptr_fun(delete_plugin_preset_popup), presetMenu));
457 }
458 
on_preset_add_clicked()459 void SEQWindow::on_preset_add_clicked() {
460     if (!add_button->get_active()) return;
461     Gtk::MenuItem* item;
462     Gtk::Menu *presetMenu = Gtk::manage(new Gtk::Menu());
463     gx_preset::UnitPresetList presetnames;
464     machine.plugin_preset_list_load(machine.pluginlist_lookup_plugin("seq")->get_pdef(), presetnames);
465     for (gx_preset::UnitPresetList::iterator i = presetnames.begin(); i != presetnames.end(); ++i) {
466         if (!i->name.empty()) {
467             item = Gtk::manage(new Gtk::MenuItem(i->name, true));
468             presetMenu->append(*item);
469              item->signal_activate().connect(sigc::bind(sigc::mem_fun(
470               *this, &SEQWindow::append_plugin_preset),i->name));
471         }
472     }
473     presetMenu->signal_selection_done().connect(sigc::bind(sigc::mem_fun(
474       *this, &SEQWindow::on_selection_done),presetMenu));
475     presetMenu->show_all();
476     presetMenu->popup(1, gtk_get_current_event_time());
477     add_button->set_active(false);
478 }
479 
on_sec_length_changed(bool update)480 void SEQWindow::on_sec_length_changed(bool update) {
481     static int r_save = 24;
482     int r = int(seq_count->cp_get_value());
483     if ( r_save > r) {
484         FOR_DRUMS(
485             remove_seq_block(d.box, r);
486         );
487         r_save = r;
488     } else if( r_save < r) {
489         FOR_DRUMS(
490             append_seq_block(d.box,d.p, r,r_save);
491         );
492         r_save = r;
493     }
494     if (update) {
495         FOR_DRUMS(
496             on_seq_button_clicked(d.box,d.p);
497         );
498     }
499 }
500 
on_sec_tact_changed()501 void SEQWindow::on_sec_tact_changed() {
502     FOR_DRUMS(
503         seq_changed(&d.p->get_value(), d.box);
504     );
505 }
506 
append_seq_block(Gtk::Box * box,gx_engine::SeqParameter * p,int r,int r_save)507 void SEQWindow::append_seq_block(Gtk::Box * box, gx_engine::SeqParameter *p, int r, int r_save) {
508     Gtk::ToggleButton * ab;
509     for(int j = r_save; j<r; ++j) {
510         ab = new Gtk::ToggleButton();
511         box->pack_start(*Gtk::manage(ab),Gtk::PACK_EXPAND_WIDGET);
512         ab->signal_clicked().connect(
513           sigc::bind(sigc::bind(sigc::mem_fun(this, &SEQWindow::on_seq_button_clicked),p),box));
514           ab->show();
515     }
516 }
517 
remove_seq_block(Gtk::Box * box,int r)518 void SEQWindow::remove_seq_block(Gtk::Box * box, int r) {
519     Glib::ListHandle<Gtk::Widget*> boxList = box->get_children();
520     int i = 0;
521     for (Glib::ListHandle<Gtk::Widget*>::iterator itt = boxList.begin();itt != boxList.end(); ++itt) {
522         if (i>=r) {
523             box->remove(*(*itt));
524             delete((*itt));
525         }
526         ++i;
527     }
528 }
529 
scroll_playhead(float value)530 void SEQWindow::scroll_playhead(float value) {
531     Glib::RefPtr<Gtk::Adjustment> a = vp->get_hadjustment();
532     static float old_state = 0.0;
533     float u = a->get_upper();
534     float l = a->get_lower();
535     float s = a->get_page_size();
536     float set = (u-s) * ((value)/2300.0);
537     if (u>s) {
538         if (set>l && set<u) {
539             if(std::abs(set-old_state) > 10) {
540                 a->set_value(set);
541                 old_state = set;
542             }
543         }
544     }
545 
546 }
547 
get_sequencer_pos(Gxw::Regler * regler,const std::string id)548 bool SEQWindow::get_sequencer_pos(Gxw::Regler * regler, const std::string id) {
549     float value = 0;
550     if (machine.parameter_hasId(id)) {
551         if (machine.get_parameter_value<bool>(id.substr(0,id.find_last_of(".")+1)+"on_off")) {
552             value = machine.get_parameter_value<float>(id);
553             if (!machine.get_jack()) {
554                 if (value<99.0) return true;
555             }
556             machine.signal_parameter_value<float>(id)(value);
557             if (machine.get_jack()) machine.signal_parameter_value<float>("seq.step")(machine.get_parameter_value<float>("seq.step"));
558             if (machine.get_parameter_value<float>("seq.follow"))
559                 scroll_playhead(value);
560         }
561         return gtk_window->get_visible();
562     } else {
563         return false;
564     }
565 }
566 
on_key_press_event(GdkEventKey * event)567 bool SEQWindow::on_key_press_event(GdkEventKey *event) {
568     return true;
569 }
570 
on_seq_button_clicked(Gtk::Box * box,gx_engine::SeqParameter * p)571 void SEQWindow::on_seq_button_clicked(Gtk::Box *box, gx_engine::SeqParameter *p) {
572     Glib::signal_timeout().connect_once(sigc::bind(sigc::bind(sigc::mem_fun(this, &SEQWindow::on_seq_button_clicked_set),p),box),2);
573 }
574 
on_seq_button_clicked_set(Gtk::Box * box,gx_engine::SeqParameter * p)575 void SEQWindow::on_seq_button_clicked_set(Gtk::Box *box, gx_engine::SeqParameter *p) {
576     std::vector<int> sequence;
577     gx_engine::GxSeqSettings seqc;
578     Glib::ListHandle<Gtk::Widget*> seqList = box->get_children();
579     for (Glib::ListHandle<Gtk::Widget*>::iterator itt = seqList.begin();itt != seqList.end(); ++itt) {
580         sequence.push_back(dynamic_cast<Gtk::ToggleButton*>((*itt))->get_active());
581     }
582     seqc.setseqline(sequence);
583     p->set(seqc);
584 }
585 
check_preset_label()586 void SEQWindow::check_preset_label() {
587     Glib::ustring pset = " ";
588     gx_preset::UnitPresetList presetnames;
589     machine.plugin_preset_list_load(machine.pluginlist_lookup_plugin("seq")->get_pdef(), presetnames);
590     gx_preset::UnitPresetList::iterator i = presetnames.begin();
591     for ( i = presetnames.begin(); i != presetnames.end(); ++i) {
592         if (!i->name.empty()) {
593             if (i->is_set) {
594                 pset = i->name;
595                 break;
596             }
597         }
598     }
599     preset_label->set_label(pset);
600 }
601 
seq_changed(const gx_engine::GxSeqSettings * seqc,Gtk::Box * box)602 void SEQWindow::seq_changed(const gx_engine::GxSeqSettings* seqc, Gtk::Box *box) {
603 
604     Glib::ListHandle<Gtk::Widget*> seqList = box->get_children();
605     Glib::ListHandle<Gtk::Widget*>::iterator itt = seqList.begin();
606     std::vector<int> sequence = seqc->getseqline();
607     int ic = int(machine.get_parameter_value<float>("seq.tact"))-1;
608     int i0 = ic;
609     for (std::vector<int>::const_iterator i = sequence.begin(); i != sequence.end(); ++i) {
610         if (itt == seqList.end()) break;
611         dynamic_cast<Gtk::ToggleButton*>((*itt))->set_active(*i);
612         if (i0 == ic) {
613             dynamic_cast<Gtk::ToggleButton*>((*itt))->set_name("seq_button");
614             i0 = 0;
615         } else {
616             dynamic_cast<Gtk::ToggleButton*>((*itt))->set_name("seqbutton");
617             ++i0;
618         }
619         ++itt;
620     }
621     Glib::signal_idle().connect_once(sigc::mem_fun(this, &SEQWindow::check_preset_label));
622 }
623 
reload_and_show()624 void SEQWindow::reload_and_show() {
625     if (gtk_window->get_visible() && !(gtk_window->get_window()->get_state() & Gdk::WINDOW_STATE_ICONIFIED)) {
626         gtk_window->hide();
627     } else {
628         FOR_DRUMS(
629             seq_changed(&d.p->get_value(), d.box);
630         );
631         gtk_window->present();
632         std::string id;
633         seq_pos->get_property("var_id",id);
634 
635         int ti_o = 60;
636         if (!machine.get_jack()) ti_o = 250;
637         Glib::signal_timeout().connect(
638           sigc::bind<Gxw::Regler*>(sigc::bind<const std::string>(
639           sigc::mem_fun(*this, &SEQWindow::get_sequencer_pos),id), seq_pos), ti_o);
640     }
641 }
642 
~SEQWindow()643 SEQWindow::~SEQWindow() {
644     delete gtk_window;
645 }
646 
647 } // end namespace
648