Guitarix
gx_main_window.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert
3  * Copyright (C) 2011 Pete Shorthose
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  * ---------------------------------------------------------------------------
19  *
20  * This is the gx_head GUI main class
21  *
22  * ----------------------------------------------------------------------------
23  */
24 
25 #include <guitarix.h>
26 #include <gxw/GxLevelSlider.h>
27 #include <gtkmm/accelmap.h>
28 #include "jsonrpc.h"
29 
30 /****************************************************************
31  ** class TextLoggingBox
32  */
33 
34 // color depending on msg type
35 TextLoggingBox::tab_table TextLoggingBox::tagdefs[] = {
36  {"colinfo", "#cccccc"},
37  {"colwarn", "#77994f"},
38  {"colerr", "#ff8800"},
39 };
40 
42  : box(),
43  ok_button(Gtk::Stock::OK),
44  buttonbox(),
45  scrollbox(),
46  tbox(),
47  highest_unseen_msg_level(-1),
48  msg_level_changed() {
49 
50  set_default_size(640, 320);
51  set_decorated(true);
52  set_resizable(true);
53  set_gravity(Gdk::GRAVITY_SOUTH);
54  set_keep_below(false);
55  set_title(_("Logging Window"));
56  set_type_hint(Gdk::WINDOW_TYPE_HINT_UTILITY);
57  set_border_width(4);
58 
59  box.set_border_width(0);
60  scrollbox.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
61 
62  add(box);
63 
64  tbox.set_wrap_mode(Gtk::WRAP_WORD_CHAR);
65  tbox.set_border_width(0);
66  tbox.set_editable(false);
67  tbox.set_cursor_visible(false);
68  tbox.set_pixels_above_lines(0);
69  tbox.set_pixels_below_lines(2);
70  tbox.set_justification(Gtk::JUSTIFY_LEFT);
71  tbox.set_left_margin(5);
72  tbox.set_indent(0);
73 
74  Glib::RefPtr<Gtk::TextBuffer> buffer = tbox.get_buffer();
75  for (int i = 0; i < GxLogger::kMessageTypeCount; i++) {
76  tags[i] = buffer->create_tag(tagdefs[i].tagname);
77  tags[i]->property_foreground() = tagdefs[i].tag_color;
78  }
79 
80  box.add(scrollbox);
81  box.pack_end(buttonbox, Gtk::PACK_SHRINK);
82  buttonbox.set_layout(Gtk::BUTTONBOX_END);
83  buttonbox.add(ok_button);
84  buttonbox.set_border_width(4);
85  ok_button.set_can_default();
86  ok_button.grab_default();
87  ok_button.signal_clicked().connect(sigc::mem_fun(this, &TextLoggingBox::hide));
88  //signal_activate().connect(sigc::mem_fun(this, &TextLoggingBox::hide));
89  scrollbox.add(tbox);
90  tbox.set_size_request(-1, 50);
91  box.show_all();
93  sigc::mem_fun(*this, &TextLoggingBox::show_msg));
95 }
96 
98 }
99 
100 bool TextLoggingBox::on_key_press_event(GdkEventKey *event) {
101  if (event->keyval == GDK_KEY_Escape && (event->state & Gtk::AccelGroup::get_default_mod_mask()) == 0) {
102  hide();
103  return true;
104  }
105  return Gtk::Window::on_key_press_event(event);
106 }
107 
108 void TextLoggingBox::on_show() {
109  highest_unseen_msg_level = GxLogger::kMessageTypeCount;
110  Gtk::Window::on_show();
111 }
112 
113 void TextLoggingBox::on_hide() {
114  highest_unseen_msg_level = -1;
115  Gtk::Window::on_hide();
116 }
117 
119  highest_unseen_msg_level = GxLogger::kMessageTypeCount;
120  msg_level_changed();
121  highest_unseen_msg_level = -1;
122 }
123 
124 void TextLoggingBox::show_msg(string msgbuf, GxLogger::MsgType msgtype, bool plugged) {
125  assert(0 <= msgtype && msgtype < GxLogger::kMessageTypeCount);
126 
127  // retrieve gtk text buffer
128  Glib::RefPtr<Gtk::TextBuffer> buffer = tbox.get_buffer();
129 
130  // how many lines to keep
131  const int nlines = 50;
132 
133  // delete first line when window filled up
134  int linecount = buffer->get_line_count(); // empty buffer == 1 line
135  if (linecount >= nlines) {
136  Gtk::TextIter iter1 = buffer->get_iter_at_line(0);
137  Gtk::TextIter iter2 = buffer->get_iter_at_line(1);
138  buffer->erase(iter1, iter2);
139  }
140 
141  Gtk::TextIter iter = buffer->end();
142  if (buffer->get_char_count() > 0) {
143  iter = buffer->insert(iter, "\n");
144  }
145 
146  buffer->insert_with_tag(iter, msgbuf, tags[msgtype]);
147  scrollbox.get_vadjustment()->set_value(10000);
148  // scroll to end (big value, gets clamped to max)
149 
150  // modify expander bg color is closed
151  if (msgtype > highest_unseen_msg_level) {
152  highest_unseen_msg_level = msgtype;
153  msg_level_changed();
154  }
155 }
156 
157 #if false // unused
158 /****************************************************************
159  ** KeyFinder
160  ** finds next unused Key in a GtkAccelGroup
161  */
162 
163 class KeyFinder {
164 private:
165  typedef list<GtkAccelKey> accel_list;
166  unsigned int next_key;
167  accel_list l;
168  static gboolean add_keys_to_list(GtkAccelKey *key, GClosure *cl, gpointer data);
169 public:
170  KeyFinder(Glib::RefPtr<Gtk::AccelGroup> group);
171  ~KeyFinder();
172  int operator()();
173 };
174 
175 KeyFinder::KeyFinder(Glib::RefPtr<Gtk::AccelGroup> group) {
176  next_key = GDK_a;
177  gtk_accel_group_find(group->gobj(), add_keys_to_list, static_cast<gpointer>(&l));
178 }
179 
180 KeyFinder::~KeyFinder() {
181 }
182 
183 gboolean KeyFinder::add_keys_to_list(GtkAccelKey *key, GClosure *cl, gpointer data) {
184  accel_list* l = (accel_list*)data;
185  if (key->accel_mods == GDK_SHIFT_MASK) {
186  l->push_back(*key);
187  }
188  return false;
189 }
190 
191 int KeyFinder::operator()() {
192  while (next_key <= GDK_z) {
193  bool found = false;
194  for (accel_list::iterator i = l.begin(); i != l.end(); ++i) {
195  if (next_key == i->accel_key) {
196  found = true;
197  break;
198  }
199  }
200  if (!found) {
201  return next_key++;
202  }
203  next_key++;
204  }
205  return -1;
206 }
207 #endif
208 
209 /****************************************************************
210  ** GxUiRadioMenu
211  ** adds the values of an EnumParameter as Gtk::RadioMenuItem's
212  ** to a Gtk::MenuShell
213  */
214 
215 class TubeKeys {
216 private:
217  static unsigned int keysep[];
218  unsigned int ks;
219 public:
220  TubeKeys(): ks(0) {};
221  int operator()();
222 };
223 
224 unsigned int TubeKeys::keysep[] = {
225  GDK_a, GDK_b, GDK_c, GDK_d, GDK_e, 0,
226  GDK_f, 0,
227  GDK_g, GDK_h, GDK_i, GDK_j, 0,
228  GDK_k, GDK_l, GDK_m, GDK_n, 0,
229  GDK_o, GDK_p, GDK_q, GDK_r
230 };
231 
232 inline int TubeKeys::operator()() {
233  if (ks < sizeof(keysep)/sizeof(keysep[0])) {
234  return keysep[ks++];
235  }
236  return -1;
237 }
238 
239 GxUiRadioMenu::GxUiRadioMenu(gx_engine::GxMachineBase& machine_, const std::string& id_)
240  : machine(machine_),
241  id(id_) {
242  machine.signal_parameter_value<int>(id).connect(
243  sigc::mem_fun(this, &GxUiRadioMenu::set_value));
244 }
245 
246 void GxUiRadioMenu::setup(const Glib::ustring& prefix, const Glib::ustring& postfix,
247  Glib::RefPtr<Gtk::UIManager>& uimanager, Glib::RefPtr<Gtk::ActionGroup>& actiongroup) {
248  int i, c;
249  const value_pair *p;
250  TubeKeys next_key;
251  Glib::ustring s = prefix;
252  Gtk::RadioButtonGroup group;
253  gx_engine::IntParameter& param = machine.get_parameter(id).getInt();
254  for (p = param.getValueNames(), i = 0; p->value_id; p++, i++) {
255  c = next_key();
256  if (c == 0) {
257  s += "<separator/>";
258  c = next_key();
259  }
260  Glib::ustring actname = Glib::ustring::compose("Enum_%1.%2", param.id(), p->value_id);
261  s += Glib::ustring::compose("<menuitem action=\"%1\"/>", actname);
262  Glib::RefPtr<Gtk::RadioAction> act = Gtk::RadioAction::create(group, actname, param.value_label(*p));
263  act->property_value().set_value(static_cast<int>(param.getLowerAsFloat())+i);
264  if (c > 0) {
265  actiongroup->add(act, Gtk::AccelKey(Glib::ustring::compose("<shift>%1", (char)c)));
266  } else {
267  actiongroup->add(act);
268  }
269  if (i == 0) {
270  act->signal_changed().connect(
271  sigc::mem_fun(*this, &GxUiRadioMenu::on_changed));
272  action = act;
273  }
274  //fprintf(stderr, "%s \n", p->value_id);
275  }
276  s.append(postfix);
277  uimanager->add_ui_from_string(s);
278 }
279 
280 void GxUiRadioMenu::set_value(unsigned int v) {
281  action->set_current_value(v);
282 }
283 
284 void GxUiRadioMenu::on_changed(Glib::RefPtr<Gtk::RadioAction> act) {
285  machine.set_parameter_value(id, act->get_current_value());
286 }
287 
288 
289 /****************************************************************
290  ** class Freezer
291  */
292 
294  : window(0), tag(), need_thaw(false), size_x(-1), size_y(-1) {
295 }
296 
298  thaw();
299 }
300 
301 void Freezer::freeze(Gtk::Window *w, int width, int height) {
302  if (window) {
303  thaw();
304  }
305  size_x = width;
306  size_y = height;
307  window = w;
308  Glib::RefPtr<Gdk::Window> win = window->get_window();
309  if (win) {
310  need_thaw = true;
311  win->freeze_updates();
312  }
313 }
314 
315 void Freezer::set_slot(sigc::slot<void> w) {
316  if (size_x == -1) {
317  w();
318  } else {
319  work = w;
320  }
321 }
322 
323 void Freezer::freeze_until_width_update(Gtk::Window *w, int width) {
324  int wd, ht;
325  w->get_size(wd, ht);
326  if (wd == width) {
327  return;
328  }
329  freeze(w, width, -1);
330 }
331 
332 void Freezer::freeze_and_size_request(Gtk::Window *w, int width, int height) {
333  int wd, ht;
334  w->get_size(wd, ht);
335  if (wd >= width && ht == height) {
336  return;
337  }
338  freeze(w, width, height);
339  w->set_size_request(width, height);
340 }
341 
342 bool Freezer::thaw_timeout() {
343 #ifndef NDEBUG
344  gx_print_error("freezer", "timeout");
345 #else
346  gx_print_warning("freezer", "timeout");
347 #endif
348  if (size_y != -1) {
349  window->set_size_request(-1,-1);
350  }
351  do_thaw();
352  return false;
353 }
354 
355 void Freezer::do_thaw() {
356  size_x = size_y = -1;
357  Glib::RefPtr<Gdk::Window> win = window->get_window();
358  window = 0;
359  if (!win) {
360  return;
361  }
362  if (!work.empty()) {
363  Glib::signal_idle().connect_once(work);
364  work.disconnect();
365  }
366  if (need_thaw) {
367  win->thaw_updates();
368  }
369 }
370 
371 void Freezer::thaw() {
372  if (size_x != -1) {
373  tag.disconnect();
374  do_thaw();
375  }
376 }
377 
378 bool Freezer::check_thaw(int width, int height) {
379  if (size_x == -1) {
380  return true;
381  }
382  Glib::RefPtr<Gdk::Window> win = window->get_window();
383  if (win && win->get_state()) {
384  thaw();
385  return true;
386  }
387  if (size_y == -1) {
388  if (size_x == width) {
389  window->set_size_request(-1,-1);
390  thaw();
391  return true;
392  }
393  }
394  if (size_x <= width && size_y == height) {
395  window->set_size_request(-1,-1);
396  thaw();
397  return true;
398  }
399  if (!tag.connected()) {
400  tag = Glib::signal_timeout().connect(sigc::mem_fun(*this, &Freezer::thaw_timeout), 500);
401  }
402  return false;
403 }
404 
405 
406 /****************************************************************
407  ** class MainWindow
408  */
409 
410 template <class T>
412  gx_engine::GxMachineBase& machine_, const std::string& id_, const Glib::ustring& name, const Glib::ustring& icon_name,
413  const Glib::ustring& label, const Glib::ustring& tooltip,
414  bool is_active)
415  : Gtk::ToggleAction(name, icon_name, label, tooltip, is_active),
416  machine(machine_),
417  id(id_) {
418  set_active(machine.get_parameter_value<T>(id));
419  machine.signal_parameter_value<T>(id).connect(
420  sigc::mem_fun(this, &UiToggleAction::set_active));
421 }
422 
423 template <class T>
425 }
426 
427 template <class T>
429  machine.set_parameter_value(id, get_active());
430 }
431 
432 void update_scrolled_window(Gtk::ScrolledWindow& w) {
433  Gtk::PolicyType hp, vp;
434  w.get_policy(hp, vp);
435  w.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
436  w.set_policy(hp, vp);
437 }
438 
439 /*
440 ** moving / hiding / showing parts of the UI
441 */
442 
443 void MainWindow::maybe_shrink_horizontally(bool preset_no_rack) {
444  Glib::RefPtr<Gdk::Window> w = window->get_window();
445  if (!w) {
446  return;
447  }
448  int state = w->get_state();
449  if (state & (Gdk::WINDOW_STATE_MAXIMIZED | Gdk::WINDOW_STATE_FULLSCREEN)) {
450  return;
451  }
452  Gtk::Requisition req;
453  window->size_request(req);
454  int x, y;
455  window->get_position(x, y);
456  Gdk::Geometry geom;
457  geom.min_width = req.width;
458  geom.min_height = req.height;
459  w->set_geometry_hints(geom, Gdk::HINT_MIN_SIZE);
460  if (preset_no_rack) {
461  req.height += options.preset_window_height - preset_scrolledbox->size_request().height;
462  } else {
463  req.height = std::max(req.height, options.window_height);
464  }
465  w->move_resize(x, y, req.width, req.height);
466  if (!state) {
467  freezer.freeze_until_width_update(window, req.width);
468  }
469 }
470 
471 void MainWindow::on_move_tuner() {
472  bool v = actions.tuner->get_active();
473  if(tunerbox->get_parent() == upper_rackbox) {
474  tunerbox->set_visible(false);
475  upper_rackbox->remove(*tunerbox);
476  tuner_box_no_rack->pack_start(*tunerbox,false,false);
477  } else if(tunerbox->get_parent() == tuner_box_no_rack) {
478  tunerbox->set_visible(false);
479  tuner_box_no_rack->remove(*tunerbox);
480  upper_rackbox->add(*tunerbox);
481  }
482  on_livetuner_toggled();
483  tunerbox->set_visible(v);
484  update_scrolled_window(*vrack_scrolledbox);
485 }
486 
487 void MainWindow::on_show_tuner() {
488  bool v = actions.tuner->get_active();
489  on_livetuner_toggled();
490  tunerbox->set_visible(v);
491  update_scrolled_window(*vrack_scrolledbox);
492 }
493 
494 void MainWindow::load_widget_pointers() {
495  bld->get_toplevel("MainWindow", window);
496  bld->find_widget("tunerbox", tunerbox);
497  bld->find_widget("tuner_box_no_rack", tuner_box_no_rack);
498  bld->find_widget("vrack_scrolledbox", vrack_scrolledbox);
499  bld->find_widget("stereorackcontainerH", stereorackcontainerH);
500  bld->find_widget("stereorackcontainerV", stereorackcontainerV);
501  bld->find_widget("rackcontainer", rackcontainer);
502  bld->find_widget("stereorackbox", stereorackbox);
503  bld->find_widget("monorackcontainer", monocontainer);
504  bld->find_widget("monoampcontainer:ampdetails", monoampcontainer);
505  bld->find_widget("main_vpaned", main_vpaned);
506  bld->find_widget("amp_toplevel_box", amp_toplevel_box);
507  bld->find_widget("monobox", monobox);
508  bld->find_widget("upper_rackbox", upper_rackbox);
509  bld->find_widget("preset_scrolledbox", preset_scrolledbox);
510  bld->find_widget("preset_box_no_rack", preset_box_no_rack);
511  bld->find_widget("effects_frame_paintbox", effects_frame_paintbox);
512  bld->find_widget("insert_image", insert_image);
513  bld->find_widget("status_image", status_image);
514  bld->find_widget("jackd_image", jackd_image);
515  bld->find_widget("logstate_image", logstate_image);
516  bld->find_widget("menubox", menubox);
517  bld->find_widget("show_rack:barbutton", show_rack_button);
518  bld->find_widget("rack_order_h:barbutton", rack_order_h_button);
519  bld->find_widget("config_mode:barbutton", config_mode_button);
520  bld->find_widget("liveplay:barbutton", liveplay_button);
521  bld->find_widget("tuner:barbutton", tuner_button);
522  bld->find_widget("effects:barbutton", effects_button);
523  bld->find_widget("presets:barbutton", presets_button);
524  bld->find_widget("compress:barbutton", compress_button);
525  bld->find_widget("expand:barbutton", expand_button);
526  bld->find_widget("effects_toolpalette", effects_toolpalette);
527  bld->find_widget("amp_background:ampbox", amp_background);
528  bld->find_widget("tuner_on_off", tuner_on_off);
529  bld->find_widget("tuner_mode", tuner_mode);
530  bld->find_widget("tuner_reference_pitch", tuner_reference_pitch);
531  bld->find_widget("tuner_tuning", tuner_tuning);
532  bld->find_widget("tuner_temperament", tuner_temperament);
533  bld->find_widget("racktuner", racktuner);
534  bld->find_widget("ampdetail_compress:effect_reset", ampdetail_compress);
535  bld->find_widget("ampdetail_expand:effect_reset", ampdetail_expand);
536  bld->find_widget("ampdetail_mini", ampdetail_mini);
537  bld->find_widget("ampdetail_normal", ampdetail_normal);
538  bld->find_widget("fastmeterL", fastmeter[0]);
539  bld->find_widget("fastmeterR", fastmeter[1]);
540  bld->find_widget("preset_status", preset_status);
541  bld->find_widget("midi_out_box", midi_out_box);
542  bld->find_widget("midi_out_normal", midi_out_normal);
543  bld->find_widget("midi_out_mini", midi_out_mini);
544  bld->find_widget("midi_out_compress:effect_reset", midi_out_compress);
545  bld->find_widget("midi_out_expand:effect_reset", midi_out_expand);
546  bld->find_widget("midi_out_presets_mini", midi_out_presets_mini);
547  bld->find_widget("midi_out_presets_normal", midi_out_presets_normal);
548  bld->find_widget("channel1_button", channel1_button);
549  bld->find_widget("channel1_box", channel1_box);
550  bld->find_widget("channel2_button", channel2_button);
551  bld->find_widget("channel2_box", channel2_box);
552  bld->find_widget("channel3_button", channel3_button);
553  bld->find_widget("channel3_box", channel3_box);
554 }
555 
556 
557 void MainWindow::set_next_preset_controller() {
558  if (!machine.midi_get_config_mode()) {
559  new gx_main_midi::MidiConnect(0, machine.get_parameter("engine.next_preset"), machine);
560  }
561 }
562 
563 void MainWindow::set_previus_preset_controller() {
564  if (!machine.midi_get_config_mode()) {
565  new gx_main_midi::MidiConnect(0, machine.get_parameter("engine.previus_preset"), machine);
566  }
567 }
568 
569 void MainWindow::on_select_preset(int idx) {
570  keyswitch.process_preset_key(idx);
571 }
572 
573 void MainWindow::on_next_preset() {
574  if (machine.setting_is_preset()) {
575  machine.next_preset_switch();
576  }
577 }
578 
579 void MainWindow::on_previus_preset() {
580  if (machine.setting_is_preset()) {
581  machine.previus_preset_switch();
582  }
583 }
584 
585 void MainWindow::rebuild_preset_menu() {
586  if (preset_list_merge_id) {
587  uimanager->remove_ui(preset_list_merge_id);
588  uimanager->remove_action_group(preset_list_actiongroup);
589  preset_list_menu_bank.clear();
590  preset_list_merge_id = 0;
591  preset_list_actiongroup.reset();
592  uimanager->ensure_update();
593  }
594  if (!machine.setting_is_preset()) {
595  return;
596  }
598  if (!pf) {
599  return;
600  }
601  preset_list_actiongroup = Gtk::ActionGroup::create("PresetList");
602  preset_list_menu_bank = machine.get_current_bank();
603  Glib::ustring s = "<menubar><menu action=\"PresetsMenu\"><menu action=\"PresetListMenu\">";
604  int idx = 0;
605  for (gx_system::PresetFile::iterator i = pf->begin(); i != pf->end(); ++i, ++idx) {
606  Glib::ustring actname = "PresetList_" + i->name;
607  Glib::RefPtr<Gtk::Action> action = Gtk::Action::create(actname, i->name);
608  preset_list_actiongroup->add(
609  action, sigc::bind(sigc::mem_fun(*this, &MainWindow::on_select_preset), idx));
610  if (idx <= 9) {
611  char c = '0' + idx;
612  Gtk::AccelMap::change_entry(action->get_accel_path(), c, Gdk::ModifierType(0), true);
613  }
614  s += Glib::ustring::compose("<menuitem action=\"%1\"/>", actname);
615  }
616  s += "</menu></menu></menubar>";
617  uimanager->insert_action_group(preset_list_actiongroup);
618  preset_list_merge_id = uimanager->add_ui_from_string(s);
619  dynamic_cast<Gtk::MenuItem*>(uimanager->get_widget("/menubar/PresetsMenu/PresetListMenu"))->set_label(_("_Bank: ")+preset_list_menu_bank);
620 }
621 
622 void MainWindow::show_selected_preset() {
623  keyswitch.deactivate();
624  Glib::ustring t;
625  if (machine.setting_is_preset()) {
626  t = machine.get_current_bank() + " / " + machine.get_current_name();
627  if (preset_list_menu_bank != machine.get_current_bank()) {
628  rebuild_preset_menu();
629  }
630  }
631  preset_status->set_text(t);
632 }
633 
634 bool MainWindow::is_variable_size() {
635  return actions.presets->get_active() || actions.show_rack->get_active();
636 }
637 
638 void MainWindow::maybe_change_resizable() {
639  Glib::RefPtr<Gdk::Window> w = window->get_window();
640  if (w && w->get_state() != 0) {
641  return;
642  }
643  if (!is_variable_size() && window->get_resizable()) {
644  window->set_resizable(false);
645  } else if (!window->get_resizable()) {
646  window->set_resizable(true);
647  }
648 }
649 
650 void MainWindow::set_vpaned_handle() {
651  int w, h;
652  main_vpaned->get_handle_window()->get_size(w, h);
653  int pos = main_vpaned->get_allocation().get_height() - options.preset_window_height - h;
654  main_vpaned->set_position(pos);
655 }
656 
657 void MainWindow::on_show_rack() {
658  Gtk::Widget *w;
659  if (rackbox_stacked_vertical()) {
660  w = stereorackcontainerV;
661  } else {
662  w = stereorackbox;
663  }
664  bool v = options.system_show_rack = actions.show_rack->get_active();
665  actions.rackh->set_sensitive(v);
666  stereorackcontainer.set_visible(v);
667  rack_order_h_button->set_visible(v);
668  compress_button->set_visible(v);
669  expand_button->set_visible(v);
670  if (actions.presets->get_active() && preset_scrolledbox->get_mapped()) {
671  options.preset_window_height = preset_scrolledbox->get_allocation().get_height();
672  }
673  if (v) {
674  midi_out_box->set_visible(actions.midi_out->get_active());
675  options.window_height = max(options.window_height, window->size_request().height);
676  main_vpaned->set_position(oldpos);
677  w->show();
678  monoampcontainer->show();
679  monorackcontainer.show_entries();
680  vrack_scrolledbox->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
681  vrack_scrolledbox->set_size_request(scrl_size_x, scrl_size_y);
682  if (preset_scrolledbox->get_parent() != main_vpaned) {
683  preset_box_no_rack->remove(*preset_scrolledbox);
684  main_vpaned->add(*preset_scrolledbox);
685  change_expand(*preset_box_no_rack, false);
686  change_expand(*main_vpaned, true);
687  }
688  Glib::RefPtr<Gdk::Window> win = window->get_window();
689  if (!win || win->get_state() == 0) {
690  Gtk::Requisition req;
691  window->size_request(req);
692  req.height = max(req.height, options.window_height);
693  freezer.freeze_and_size_request(window, req.width, req.height);
694  if (win && actions.presets->get_active()) {
695  freezer.set_slot(sigc::mem_fun(this, &MainWindow::set_vpaned_handle));
696  }
697  }
698  } else {
699  if (actions.midi_out->get_active()) {
700  midi_out_box->set_visible(false);
701  }
702  actions.show_plugin_bar->set_active(false);
703  oldpos = main_vpaned->get_position();
704  w->hide();
705  monoampcontainer->hide();
706  monorackcontainer.hide_entries();
707  if (preset_scrolledbox->get_parent() == main_vpaned) {
708  main_vpaned->remove(*preset_scrolledbox);
709  preset_box_no_rack->add(*preset_scrolledbox);
710  change_expand(*main_vpaned, false);
711  change_expand(*preset_box_no_rack, true);
712  }
713  preset_box_no_rack->set_visible(actions.presets->get_active());
714  vrack_scrolledbox->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
715  vrack_scrolledbox->get_size_request(scrl_size_x, scrl_size_y);
716  vrack_scrolledbox->set_size_request(-1,-1);
717  if (actions.presets->get_active()) {
718  maybe_shrink_horizontally(true);
719  } else {
720  maybe_shrink_horizontally();
721  }
722  }
723  maybe_change_resizable();
724 }
725 
726 void MainWindow::on_compress_all() {
727  plugin_dict.compress(true);
728  on_ampdetail_switch(true, true);
729  actions.midi_out_plug->set_active(true);
730 }
731 
732 void MainWindow::on_expand_all() {
733  plugin_dict.compress(false);
734  on_ampdetail_switch(false, true);
735  actions.midi_out_plug->set_active(false);
736 }
737 
738 void MainWindow::on_rack_configuration() {
739  bool v = actions.rack_config->get_active();
740  actions.show_plugin_bar->set_sensitive(!v);
741  actions.show_rack->set_sensitive(!v);
742  actions.tuner->set_sensitive(!v);
743  actions.compress->set_sensitive(!v);
744  actions.expand->set_sensitive(!v);
745  actions.live_play->set_sensitive(!v);
746  Gtk::Requisition req;
747  monobox->size_request(req);
748  stereorackcontainer.set_config_mode(v);
749  monorackcontainer.set_config_mode(v);
750  szg_rack_units->set_ignore_hidden(v);
751  bool plugin_bar = actions.show_plugin_bar->get_active();
752  if (v) {
753  pre_act = actions.presets->get_active();
754  if (pre_act) {
755  actions.presets->set_active(false);
756  }
757  actions.show_rack->set_active(true);
758  effects_frame_paintbox->show();
759  upper_rackbox->hide();
760  Gtk::Requisition req2;
761  effects_frame_paintbox->size_request(req2);
762  int width = req.width;
763  if (!plugin_bar) {
764  if (rackbox_stacked_vertical()) {
765  width -= req2.width;
766  } else {
767  if (req2.width & 1) {
768  req2.width += 1;
769  }
770  width -= req2.width/2;
771  }
772  }
773  effects_frame_paintbox->set_size_request(req2.width, -1);
774  monobox->set_size_request(width,-1);
775  } else {
776  if (!plugin_bar) {
777  effects_frame_paintbox->hide();
778  }
779  upper_rackbox->show();
780  effects_frame_paintbox->set_size_request(-1,-1);
781  monobox->set_size_request(-1,-1);
782  if (pre_act) {
783  actions.presets->set_active(true);
784  }
785  }
786  if (!plugin_bar) {
787  update_width();
788  maybe_shrink_horizontally();
789  }
790 }
791 
792 void MainWindow::on_show_plugin_bar() {
793  bool v = options.system_show_toolbar = actions.show_plugin_bar->get_active();
794  if (v) {
795  actions.show_rack->set_active(true);
796  }
797  effects_frame_paintbox->set_visible(v);
798  if (!v) {
799  //update_scrolled_window(*vrack_scrolledbox);
800  //update_scrolled_window(*stereorackbox);
801  maybe_shrink_horizontally();
802  }
803 }
804 
805 void MainWindow::move_widget(Gtk::Widget& w, Gtk::Box& b1, Gtk::Box& b2) {
806  // reparent does not always work when child is hidden
807  // (sometimes wrong position when shown later),
808  // use remove / add
809  b1.remove(w);
810  b1.hide();
811  b2.pack_start(w);
812  b2.show();
813 }
814 
815 int MainWindow::rackbox_stacked_vertical() const {
816  return !actions.rackh->get_active();
817 }
818 
819 void MainWindow::change_expand(Gtk::Widget& w, bool value) {
820  Gtk::Box *p = dynamic_cast<Gtk::Box*>(w.get_parent());
821  int expand, fill;
822  unsigned int padding;
823  GtkPackType pack_type;
824  gtk_box_query_child_packing(p->gobj(), w.gobj(), &expand, &fill, &padding, &pack_type);
825  gtk_box_set_child_packing(p->gobj(), w.gobj(), value, value, padding, pack_type);
826 }
827 
828 double MainWindow::stop_at_stereo_bottom(double off, double step_size, double pagesize) {
829  Gtk::Allocation alloc = stereorackcontainer.get_allocation();
830  double lim = alloc.get_y() + alloc.get_height() - pagesize;
831  if (off >= lim) {
832  return off;
833  }
834  return min(off+step_size, lim);
835 }
836 
837 double MainWindow::stop_at_mono_top(double off, double step_size) {
838  Gtk::Allocation alloc = monorackcontainer.get_allocation();
839  if (off < alloc.get_y()) {
840  return off;
841  }
842  return max(off-step_size, double(alloc.get_y()));
843 }
844 
845 void MainWindow::on_dir_changed() {
846  bool v = options.system_order_rack_h = actions.rackh->get_active();
847  if (v) {
848  // horizontally
849  move_widget(stereorackcontainer, *stereorackcontainerV, *stereorackcontainerH);
850  change_expand(*monobox, true);
851  stereorackbox->show();
852  } else {
853  move_widget(stereorackcontainer, *stereorackcontainerH, *stereorackcontainerV);
854  change_expand(*monobox, false);
855  stereorackbox->hide();
856  maybe_shrink_horizontally();
857  }
858 }
859 
860 void MainWindow::on_configure_event(GdkEventConfigure *ev) {
861  if (freezer.check_thaw(ev->width, ev->height)) {
862  if (actions.show_rack->get_active()) {
863  options.window_height = ev->height;
864  }
865  }
866 }
867 
869 {
870  if (ch == &monorackcontainer && !actions.rackh->get_active()) {
871  stereorackcontainer.queue_draw();
872  }
873 }
874 
876  update_scrolled_window(*vrack_scrolledbox);
877  update_scrolled_window(*stereorackbox);
878 }
879 
880 RackBox *MainWindow::add_rackbox_internal(PluginUI& plugin, Gtk::Widget *mainwidget, Gtk::Widget *miniwidget,
881  bool mini, int pos, bool animate, Gtk::Widget *bare) {
882  RackBox *r = new RackBox(plugin, *this, bare);
883  if (mini) {
884  r->swtch(true);
885  }
886  r->pack(mainwidget, miniwidget, szg_rack_units);
887  update_width();
888  if (plugin.get_type() == PLUGIN_TYPE_MONO) {
889  monorackcontainer.add(*manage(r), pos);
890  } else {
891  stereorackcontainer.add(*manage(r), pos);
892  }
893  if (animate) {
894  r->animate_insert();
895  }
896  return r;
897 }
898 
899 RackBox *MainWindow::add_rackbox(PluginUI& pl, bool mini, int pos, bool animate) {
900  Gtk::Widget *mainwidget = 0;
901  Gtk::Widget *miniwidget = 0;
902  boxbuilder.get_box(pl.get_id(), mainwidget, miniwidget);
903  if (!mainwidget) {
904  gx_gui::UiBuilderImpl builder(this, &boxbuilder);
905 
906  if (machine.load_unit(builder, pl.plugin->get_pdef())) {
907  boxbuilder.fetch(mainwidget, miniwidget);
908  }
909  }
910  return add_rackbox_internal(pl, mainwidget, miniwidget, mini, pos, animate);
911 }
912 
913 void MainWindow::add_icon(const std::string& name) {
914  PluginUI *p = plugin_dict[name];
915  p->toolitem->show();
916 }
917 
918 void MainWindow::on_show_values() {
919  options.system_show_value = actions.show_values->get_active();
920  std::string s =
921  "style \"ShowValue\" {\n"
922  " GxRegler::show-value = " + gx_system::to_string(options.system_show_value) + "\n"
923  "}\n"
924  "class \"*GxRegler*\" style:highest \"ShowValue\"\n";
925  gtk_rc_parse_string(s.c_str());
926  gtk_rc_reset_styles(gtk_settings_get_default());
927 }
928 
929 void MainWindow::on_preset_action() {
930  bool v = options.system_show_presets = actions.presets->get_active();
931  if (!v && preset_scrolledbox->get_mapped()) {
932  options.preset_window_height = preset_scrolledbox->get_allocation().get_height();
933  }
934  maybe_change_resizable();
935  if (v && !actions.show_rack->get_active()) {
936  Glib::RefPtr<Gdk::Window> win = window->get_window();
937  if (!win || win->get_state() == 0) {
938  Gtk::Requisition req;
939  window->size_request(req);
940  freezer.freeze_and_size_request(window, req.width, req.height+options.preset_window_height);
941  }
942  }
943  preset_box_no_rack->set_visible(v);
944  preset_window->on_preset_select(v, use_animations() && actions.show_rack->get_active(), options.preset_window_height);
945 }
946 
947 /*
948 ** UI initialization
949 */
950 
951 bool MainWindow::on_my_leave_out(GdkEventCrossing *focus) {
952  Glib::RefPtr<Gdk::Window> wind = window->get_window();
953  wind->set_cursor();
954  return true;
955 }
956 
957 bool MainWindow::on_my_enter_in(GdkEventCrossing *focus) {
958  Glib::RefPtr<Gdk::Window> wind = window->get_window();
959  Gdk::Cursor cursor(Gdk::HAND1);
960  wind->set_cursor(cursor);
961  return true;
962 }
963 
964 void MainWindow::add_toolitem(PluginUI& pl, Gtk::ToolItemGroup *gw) {
965  Gtk::ToolItem *tb = new Gtk::ToolItem();
966  tb->set_use_drag_window(true);
967  tb->signal_drag_begin().connect(sigc::bind(sigc::mem_fun(*this, &MainWindow::on_ti_drag_begin), sigc::ref(pl)));
968  tb->signal_drag_end().connect(sigc::mem_fun(*this, &MainWindow::on_ti_drag_end));
969  tb->signal_drag_data_delete().connect(sigc::bind(sigc::mem_fun(*this, &MainWindow::on_ti_drag_data_delete), pl.get_id()));
970  tb->signal_button_press_event().connect(sigc::bind(sigc::mem_fun(*this, &MainWindow::on_ti_button_press), pl.get_id()));
971  tb->add_events(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
972  tb->signal_leave_notify_event().connect(sigc::mem_fun(*this, &MainWindow::on_my_leave_out));
973  tb->signal_enter_notify_event().connect(sigc::mem_fun(*this, &MainWindow::on_my_enter_in));
974  std::vector<Gtk::TargetEntry> listTargets;
975  if (pl.get_type() == PLUGIN_TYPE_MONO) {
976  listTargets.push_back(Gtk::TargetEntry("application/x-gtk-tool-palette-item-mono", Gtk::TARGET_SAME_APP, 0));
977  } else {
978  listTargets.push_back(Gtk::TargetEntry("application/x-gtk-tool-palette-item-stereo", Gtk::TARGET_SAME_APP, 0));
979  }
980  tb->drag_source_set(listTargets, Gdk::BUTTON1_MASK, Gdk::ACTION_MOVE);
981  tb->signal_drag_data_get().connect(sigc::bind(sigc::mem_fun(*this, &MainWindow::on_ti_drag_data_get), pl.get_id()));
982  Gtk::Image *img = new Gtk::Image(pl.icon);
983  if (!pl.tooltip.empty()) {
984  img->set_tooltip_text(pl.tooltip);
985  }
986  tb->add(*manage(img));
987  tb->show_all();
988  pl.toolitem = tb;
989  gw->add(*manage(tb));
990  pl.group = gw;
991 }
992 
993 bool MainWindow::on_visibility_notify(GdkEventVisibility *ev) {
994  bool v = ev->state != GDK_VISIBILITY_FULLY_OBSCURED;
995  if (v == is_visible) {
996  return false;
997  }
998  is_visible = v;
999  return false;
1000 }
1001 
1002 void MainWindow::on_live_play() {
1003  live_play->on_live_play(actions.live_play);
1004 }
1005 
1006 void MainWindow::on_ti_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context, const PluginUI& plugin) {
1007  drag_icon = new DragIcon(plugin, context, options);
1008 }
1009 
1010 void MainWindow::on_ti_drag_end(const Glib::RefPtr<Gdk::DragContext>& context) {
1011  if (drag_icon) {
1012  delete drag_icon;
1013  drag_icon = 0;
1014  }
1015 }
1016 
1017 void MainWindow::on_ti_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection, int info, int timestamp, const char *effect_id) {
1018  selection.set(*context->get_targets().begin(), effect_id);
1019 }
1020 
1021 void MainWindow::hide_effect(const std::string& name) {
1022  Gtk::ToolItem *toolitem = plugin_dict[name]->toolitem;
1023  if (toolitem) {
1024  toolitem->hide();
1025  }
1026 }
1027 
1028 void MainWindow::on_ti_drag_data_delete(const Glib::RefPtr<Gdk::DragContext>& context, const char *effect_id) {
1029  hide_effect(effect_id);
1030 }
1031 
1032 bool MainWindow::on_ti_button_press(GdkEventButton *ev, const char *effect_id) {
1033  if (ev->type == GDK_2BUTTON_PRESS) {
1034  get_plugin(effect_id)->display_new();
1035  return true;
1036  }
1037  return false;
1038 }
1039 
1040 void MainWindow::on_tp_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& data, int info, int timestamp) {
1041  Glib::ustring id = data.get_data_as_string();
1042  PluginUI *p = get_plugin(id);
1043  p->display(false, false);
1044  add_icon(id);
1045  p->group->set_collapsed(false);
1046 }
1047 
1048 void MainWindow::jack_connection() {
1049  bool v = actions.jackserverconnection->get_active();
1050  if (!connect_jack(v)) {
1051  actions.jackserverconnection->set_active(!v);
1052  }
1053 }
1054 
1055 void MainWindow::on_portmap_response(int) {
1056  actions.jackports->set_active(false);
1057 }
1058 
1059 void MainWindow::on_portmap_activate() {
1060  gx_jack::GxJack *jack = machine.get_jack();
1061  if (!jack) {
1062  return;
1063  }
1064  if (actions.jackports->get_active()) {
1065  if (portmap_window) {
1066  return;
1067  }
1068  portmap_window = gx_portmap::PortMapWindow::create(machine, actions.accels);
1069  portmap_window->signal_response().connect(
1070  sigc::mem_fun(*this, &MainWindow::on_portmap_response));
1071  } else {
1072  if (!portmap_window) {
1073  return;
1074  }
1075  delete portmap_window;
1076  portmap_window = 0;
1077  }
1078 }
1079 
1080 void MainWindow::on_miditable_toggle() {
1081  gx_main_midi::MidiControllerTable::toggle(machine, actions.midicontroller);
1082 }
1083 
1084 void MainWindow::change_skin(Glib::RefPtr<Gtk::RadioAction> action) {
1085  set_new_skin(options.skin[action->get_current_value()]);
1086 }
1087 
1088 void MainWindow::set_new_skin(const Glib::ustring& skin_name) {
1089  if (!skin_name.empty()) {
1090  options.skin_name = skin_name;
1091  string rcfile = options.get_style_filepath(
1092  "gx_head_" + skin_name + ".rc");
1093  gtk_rc_parse(rcfile.c_str());
1094  gtk_rc_reset_styles(gtk_settings_get_default());
1095  make_icons();
1096  }
1097 }
1098 
1099 void MainWindow::add_skin_menu() {
1100  Glib::ustring s = "<menubar><menu action=\"OptionsMenu\"><menu action=\"SkinMenu\">";
1101  int idx = 0;
1102  Gtk::RadioButtonGroup sg;
1103  for (vector<Glib::ustring>::iterator i = options.skin.skin_list.begin();
1104  i != options.skin.skin_list.end();
1105  ++i) {
1106  Glib::ustring name = *i;
1107  Glib::ustring actname = Glib::ustring::compose("ChangeSkin_%1", name);
1108  s += Glib::ustring::compose("<menuitem action=\"%1\"/>", actname);
1109  Glib::RefPtr<Gtk::RadioAction> action = Gtk::RadioAction::create(sg, actname, name);
1110  if (name == options.skin_name) {
1111  action->set_active(true);
1112  }
1113  actions.group->add(action);
1114  if (idx == 0) {
1115  actions.skin = action;
1116  }
1117  action->property_value().set_value(idx++);
1118  }
1119  actions.skin->signal_changed().connect(
1120  sigc::mem_fun(*this, &MainWindow::change_skin));
1121  s.append("</menu></menu></menubar>");
1122  uimanager->add_ui_from_string(s);
1123 }
1124 
1128 };
1129 
1130 // check user's decision to turn off latency change warning
1131 void MainWindow::user_disable_latency_warn(Gtk::CheckButton* disable_warn) {
1132  options.no_warn_latency = disable_warn->get_active();
1133 }
1134 
1135 int MainWindow::gx_wait_latency_warn() {
1136  Gtk::Dialog warn_dialog;
1137  // no set_destroy_with_parent() ??
1138  warn_dialog.property_destroy_with_parent().set_value(true);
1139 
1140  Gtk::VBox box(0, 4);
1141  Gtk::Label labelt(_("\nWARNING\n"));
1142  Gtk::Label labelt1(
1143  _("CHANGING THE JACK_BUFFER_SIZE ON THE FLY \n"
1144  "MAY CAUSE UNPREDICTABLE EFFECTS \n"
1145  "TO OTHER RUNNING JACK APPLICATIONS. \n"
1146  "DO YOU WANT TO PROCEED ?"));
1147  Gdk::Color colorGreen("#969292");
1148  labelt1.modify_fg(Gtk::STATE_NORMAL, colorGreen);
1149  Pango::FontDescription font = labelt1.get_style()->get_font();
1150  font.set_size(10*Pango::SCALE);
1151  font.set_weight(Pango::WEIGHT_BOLD);
1152  labelt1.modify_font(font);
1153 
1154  Gdk::Color colorWhite("#ffffff");
1155  labelt.modify_fg(Gtk::STATE_NORMAL, colorWhite);
1156  font = labelt.get_style()->get_font();
1157  font.set_size(14*Pango::SCALE);
1158  font.set_weight(Pango::WEIGHT_BOLD);
1159  labelt.modify_font(font);
1160 
1161  warn_dialog.add_button(_("Yes"), kChangeLatency);
1162  warn_dialog.add_button(_("No"), kKeepLatency);
1163 
1164  Gtk::HBox box1(0, 4);
1165  Gtk::HBox box2(0, 4);
1166 
1167  Gtk::CheckButton disable_warn;
1168  disable_warn.signal_clicked().connect(
1169  sigc::bind(
1170  sigc::mem_fun(*this, &MainWindow::user_disable_latency_warn),
1171  &disable_warn));
1172 
1173  Gtk::Label labelt2(
1174  _("Don't bother me again with such a question, "
1175  "I know what I am doing"));
1176 
1177  box.add(labelt);
1178  box.add(labelt1);
1179  box.add(box2);
1180  box.add(box1);
1181  box1.add(disable_warn);
1182  box1.add(labelt2);
1183  warn_dialog.get_vbox()->add(box);
1184 
1185  labelt2.modify_fg(Gtk::STATE_NORMAL, colorWhite);
1186 
1187  font = labelt2.get_style()->get_font();
1188  font.set_size(8*Pango::SCALE);
1189  font.set_weight(Pango::WEIGHT_NORMAL);
1190  labelt2.modify_font(font);
1191 
1192  box.show_all();
1193 
1194  return warn_dialog.run();
1195 }
1196 
1197 void MainWindow::change_latency(Glib::RefPtr<Gtk::RadioAction> action) {
1198  // are we a proper jack gxjack.client ?
1199  gx_jack::GxJack *jack = machine.get_jack();
1200  if (!jack) {
1201  return;
1202  }
1203  if (!jack->client) {
1205  _("Jack Buffer Size setting"),
1206  _("we are not a jack gxjack.client, server may be down")
1207  );
1208  return;
1209  }
1210  jack_nframes_t buf_size = action->get_current_value();
1211  if (buf_size == jack->get_jack_bs()) {
1212  return;
1213  }
1214  if (!options.no_warn_latency && gx_wait_latency_warn() != kChangeLatency) {
1215  Glib::signal_idle().connect_once(
1216  sigc::bind(
1217  sigc::mem_fun(action.operator->(), &Gtk::RadioAction::set_current_value), jack->get_jack_bs()));
1218  } else {
1219  if (jack_set_buffer_size(jack->client, buf_size) != 0)
1220  gx_print_warning(_("Setting Jack Buffer Size"),
1221  _("Could not change latency"));
1222  }
1223  gx_print_info(
1224  _("Jack Buffer Size"),
1225  boost::format(_("latency is %1%")) % jack_get_buffer_size(jack->client));
1226 }
1227 
1228 void MainWindow::add_latency_menu() {
1229  Glib::ustring s = "<menubar><menu action=\"EngineMenu\"><menu action=\"JackLatency\">";
1230  Gtk::RadioButtonGroup group;
1231  const int min_pow = 4; // 2**4 = 16
1232  const int max_pow = 13; // 2**13 = 8192
1233  int jack_buffer_size = 16;
1234  for (int i = 0; i <= max_pow-min_pow; ++i) {
1235  Glib::ustring name = gx_system::to_string(jack_buffer_size);
1236  Glib::ustring actname = Glib::ustring::compose("Latency_%1", name);
1237  s += Glib::ustring::compose("<menuitem action=\"%1\"/>", actname);
1238  Glib::RefPtr<Gtk::RadioAction> action = Gtk::RadioAction::create(group, actname, name);
1239  actions.group->add(action);
1240  if (i == 0) {
1241  action->signal_changed().connect(
1242  sigc::mem_fun(*this, &MainWindow::change_latency));
1243  actions.latency = action;
1244  }
1245  action->property_value().set_value(jack_buffer_size);
1246  jack_buffer_size *= 2;
1247  }
1248  s.append("</menu></menu></menubar>");
1249  uimanager->add_ui_from_string(s);
1250 }
1251 
1252 void MainWindow::set_latency() {
1253  gx_jack::GxJack *jack = machine.get_jack();
1254  if (!jack) {
1255  return;
1256  }
1257  jack_nframes_t n = jack->get_jack_bs();
1258  if (n > 0) {
1259  actions.latency->set_current_value(n);
1260  }
1261  if (n > 1023) actions.osc_buffer_menu->set_sensitive(false);
1262  else actions.osc_buffer_menu->set_sensitive(true);
1263 }
1264 
1266  GError *error = NULL;
1267  gtk_show_uri(gdk_screen_get_default(), "http://guitarix.sourceforge.net/forum/",
1268  gtk_get_current_event_time(), &error);
1269  if (error)
1270  {
1271  gx_print_error("guitarix help",
1272  _("failed to load online help "));
1273  g_error_free(error);
1274  }
1275 }
1276 
1278  Glib::signal_idle().connect_once(sigc::ptr_fun( show_forum_help));
1279 }
1280 
1281 // ----menu funktion about
1283  static string about;
1284  if (about.empty()) {
1285  about +=_("<b>Guitarix:gx_head</b> (");
1286  about += GX_VERSION;
1287  about +=
1288  _(")\n\nThis Application is to a large extent provided"
1289  "\nwith the marvelous faust compiler.Yann Orlary"
1290  "\n(http://faust.grame.fr/)"
1291  "\n\nA large part is based on the work of Julius Orion Smith"
1292  "\n(htttp://ccrma.stanford.edu/realsimple/faust/)"
1293  "\nand Albert Graef\n(http://q-lang.sourceforge.net/examples.html#Faust)"
1294  "\n\n");
1295 
1296 
1297  about +=
1298  _("for impulse response it use zita-convolver"
1299  "\nby Fons Adriaensen"
1300  "\n(http://www.kokkinizita.net/linuxaudio/index.html)"
1301  "\n\nThe included IR-files are contributed by"
1302  "\nDavid Fau Casquel (BESTPLUGINS)"
1303  "\nhome: http://www.youtube.com/bestplugins"
1304  "\n\nauthors: Hermann Meyer &lt;brummer-@web.de&gt;"
1305  "\nauthors: James Warden &lt;warjamy@yahoo.com&gt;"
1306  "\nauthors: Andreas Degert &lt;andreas.degert@googlemail.com&gt;"
1307  "\nauthors: Pete Shorthose &lt;pshorthose@gmail.com&gt;"
1308  "\nauthors: Markus Schmidt &lt;schmidt@boomshop.net&gt;"
1309  "\n\nwebsite: http://guitarix.org/\n");
1310  }
1311 
1312  gx_gui::gx_message_popup(about.c_str());
1313 }
1314 
1315 void MainWindow::set_tooltips() {
1316  options.system_show_tooltips = actions.tooltips->get_active();
1317  gtk_settings_set_long_property(
1318  gtk_settings_get_default(), "gtk-enable-tooltips", options.system_show_tooltips,
1319  "gx_head menu-option");
1320 }
1321 
1322 void MainWindow::set_animations() {
1323  options.system_animations = actions.animations->get_active();
1324 }
1325 
1326 void MainWindow::on_select_jack_control() {
1327  if (select_jack_control) {
1328  select_jack_control->present();
1329  } else {
1330  select_jack_control = gx_gui::SelectJackControlPgm::create(options, machine);
1331  select_jack_control->signal_close().connect(
1332  sigc::mem_fun(*this, &MainWindow::delete_select_jack_control));
1333  select_jack_control->set_transient_for(*window);
1334  select_jack_control->show();
1335  }
1336 }
1337 
1338 void MainWindow::delete_select_jack_control() {
1339  delete select_jack_control;
1340  select_jack_control = 0;
1341 }
1342 
1343 // show loggingbox
1344 void MainWindow::on_log_activate() {
1345  if (actions.loggingbox->get_active()) {
1346  gint rxorg, ryorg;
1347  window->get_position(rxorg, ryorg);
1348  fLoggingWindow.move(rxorg+5, ryorg+272);
1349  fLoggingWindow.show_all();
1350  on_msg_level_changed();
1351  } else {
1352  fLoggingWindow.hide();
1353  }
1354 }
1355 // show loggingbox
1356 bool MainWindow::on_log_activated(GdkEventButton* ev) {
1357  if (ev->type == GDK_BUTTON_PRESS && ev->button == 1) {
1358  if (!actions.loggingbox->get_active()) {
1359  actions.loggingbox->set_active(true);
1360  gint rxorg, ryorg;
1361  window->get_position(rxorg, ryorg);
1362  fLoggingWindow.move(rxorg+5, ryorg+272);
1363  fLoggingWindow.show_all();
1364  on_msg_level_changed();
1365  } else {
1366  fLoggingWindow.hide();
1367  actions.loggingbox->set_active(false);
1368  }
1369  }else if (ev->type == GDK_BUTTON_PRESS && ev->button == 2) {
1370  fLoggingWindow.reset_msg_level();
1371  }
1372  return true;
1373 }
1374 
1375 bool MainWindow::on_log_scrolled(GdkEventScroll* ev) {
1376  if (!actions.loggingbox->get_active()) {
1377  actions.loggingbox->set_active(true);
1378  gint rxorg, ryorg;
1379  window->get_position(rxorg, ryorg);
1380  fLoggingWindow.move(rxorg+5, ryorg+272);
1381  fLoggingWindow.show_all();
1382  on_msg_level_changed();
1383  } else {
1384  fLoggingWindow.hide();
1385  actions.loggingbox->set_active(false);
1386  }
1387  return true;
1388 }
1389 
1390 void MainWindow::on_engine_toggled() {
1392  if (actions.engine_mute->get_active()) {
1394  } else if (actions.engine_bypass->get_active()) {
1396  } else {
1398  }
1399  machine.set_state(s);
1400 }
1401 
1402 void MainWindow::set_switcher_controller() {
1403  if (!machine.midi_get_config_mode()) {
1404  new gx_main_midi::MidiConnect(0, machine.get_parameter("ui.live_play_switcher"), machine);
1405  }
1406 }
1407 
1408 void MainWindow::set_bypass_controller() {
1409  if (!machine.midi_get_config_mode()) {
1410  new gx_main_midi::MidiConnect(0, machine.get_parameter("engine.bypass"), machine);
1411  }
1412 }
1413 
1414 void MainWindow::on_show_midi_out() {
1415 #ifdef USE_MIDI_OUT
1416  if (actions.midi_out->get_active()) {
1417  actions.show_rack->set_active(true);
1418  midi_out_box->set_visible(true);
1419  } else {
1420  midi_out_box->set_visible(false);
1421  machine.pluginlist_lookup_plugin("midi_out")->set_on_off(false);
1422  }
1423 #endif
1424 }
1425 
1426 void MainWindow::on_show_midi_out_plug() {
1427  if (actions.midi_out_plug->get_active()) {
1428  midi_out_normal->hide();
1429  midi_out_mini->show();
1430  } else {
1431  midi_out_mini->hide();
1432  midi_out_normal->show();
1433  }
1434 }
1435 
1436 void MainWindow::on_midi_out_channel_toggled(Gtk::RadioButton *rb, Gtk::Container *c) {
1437  c->set_visible(rb->get_active());
1438 }
1439 
1440 void MainWindow::on_livetuner_toggled() {
1441  if (actions.livetuner->get_active()) {
1442  if (actions.live_play->get_active()) {
1443  live_play->display_tuner(true);
1444  racktuner->set_sensitive(false);
1445  machine.tuner_used_for_display(true);
1446  } else {
1447  live_play->display_tuner(false);
1448  if (actions.tuner->get_active()) {
1449  racktuner->set_sensitive(true);
1450  machine.tuner_used_for_display(true);
1451  } else {
1452  machine.tuner_used_for_display(false);
1453  }
1454  }
1455  } else {
1456  live_play->display_tuner(false);
1457  racktuner->set_sensitive(false);
1458  machine.tuner_used_for_display(false);
1459  }
1460 }
1461 
1462 void MainWindow::create_actions() {
1463  gx_jack::GxJack *jack = machine.get_jack();
1464  actions.group = Gtk::ActionGroup::create("Main");
1465  /*
1466  ** Menu actions
1467  */
1468  actions.group->add(Gtk::Action::create("EngineMenu",_("_Engine")));
1469  actions.jack_latency_menu = Gtk::Action::create("JackLatency",_("_Latency"));
1470  actions.group->add(actions.jack_latency_menu);
1471  actions.osc_buffer_menu = Gtk::Action::create("OscBuffer",_("Osc. Buffer-size"));
1472  actions.group->add(actions.osc_buffer_menu);
1473 
1474  actions.group->add(Gtk::Action::create("PresetsMenu",_("_Presets")));
1475  actions.group->add(Gtk::Action::create("NextPreset",_("Next Preset")),
1476  sigc::mem_fun(*this, &MainWindow::on_next_preset));
1477  actions.group->add(Gtk::Action::create("PreviusPreset",_("Previous Preset")),
1478  sigc::mem_fun(*this, &MainWindow::on_previus_preset));
1479 
1480  actions.group->add(Gtk::Action::create("SetNextPresetSwitcher", _("Next Preset Midi Switch")),
1481  sigc::mem_fun(this, &MainWindow::set_next_preset_controller));
1482 
1483  actions.group->add(Gtk::Action::create("SetPreviusPresetSwitcher", _("Previous Preset Midi Switch")),
1484  sigc::mem_fun(this, &MainWindow::set_previus_preset_controller));
1485 
1486  actions.group->add(Gtk::Action::create("PresetListMenu","--"));
1487  actions.group->add(Gtk::Action::create("PluginsMenu",_("P_lugins")));
1488  actions.group->add(Gtk::Action::create("MonoPlugins",_("_Mono Plugins")));
1489  actions.group->add(Gtk::Action::create("StereoPlugins",_("_Stereo Plugins")));
1490  actions.group->add(Gtk::Action::create("TubeMenu",_("_Tube")));
1491  actions.group->add(Gtk::Action::create("OptionsMenu",_("_Options")));
1492  actions.group->add(Gtk::Action::create("SkinMenu", _("_Skin...")));
1493  actions.group->add(Gtk::Action::create("AboutMenu",_("_About")));
1494 
1495  /*
1496  ** engine actions
1497  */
1498  actions.jackserverconnection = Gtk::ToggleAction::create("JackServerConnection", _("Jack Server _Connection"));
1499  actions.group->add(
1500  actions.jackserverconnection,
1501  sigc::mem_fun(*this, &MainWindow::jack_connection));
1502 
1503  actions.jackports = Gtk::ToggleAction::create("JackPorts", _("Jack _Ports"));
1504  actions.group->add(
1505  actions.jackports,
1506  sigc::mem_fun(*this, &MainWindow::on_portmap_activate));
1507 
1508  actions.midicontroller = Gtk::ToggleAction::create("MidiController", _("M_idi Controller"));
1509  actions.group->add(
1510  actions.midicontroller,
1511  sigc::mem_fun(*this, &MainWindow::on_miditable_toggle));
1512 
1513  actions.engine_mute = Gtk::ToggleAction::create("EngineMute", _("Engine _Mute"));
1514  actions.group->add(actions.engine_mute);
1515  actions.engine_mute_conn = actions.engine_mute->signal_toggled().connect(
1516  sigc::mem_fun(*this, &MainWindow::on_engine_toggled));
1517 
1518  actions.engine_bypass = Gtk::ToggleAction::create("EngineBypass", _("Engine _Bypass"));
1519  actions.group->add(actions.engine_bypass);
1520  actions.engine_bypass_conn = actions.engine_bypass->signal_toggled().connect(
1521  sigc::mem_fun(*this, &MainWindow::on_engine_toggled));
1522 
1523  actions.quit = Gtk::Action::create("Quit",_("_Quit"));
1524  actions.group->add(
1525  actions.quit,
1526  sigc::hide_return(sigc::mem_fun(this, &MainWindow::on_quit)));
1527 
1528  /*
1529  ** actions to open other (sub)windows
1530  */
1531  actions.presets = Gtk::ToggleAction::create(
1532  "Presets",_("_Preset Selection"));
1533  actions.group->add(actions.presets,
1534  sigc::mem_fun(*this, &MainWindow::on_preset_action));
1535 
1536  actions.show_plugin_bar = Gtk::ToggleAction::create(
1537  "ShowPluginBar",_("Show Plugin _Bar"));
1538  actions.group->add(actions.show_plugin_bar,
1539  sigc::mem_fun(*this, &MainWindow::on_show_plugin_bar));
1540 
1541  actions.show_rack = Gtk::ToggleAction::create(
1542  "ShowRack",_("Show _Rack"), "", true);
1543  actions.group->add(actions.show_rack,
1544  sigc::mem_fun(*this, &MainWindow::on_show_rack));
1545 
1546  actions.loggingbox = Gtk::ToggleAction::create("LoggingBox", _("Show _Logging Box"));
1547  actions.group->add(
1548  actions.loggingbox,
1549  sigc::mem_fun(*this, &MainWindow::on_log_activate));
1550 
1551  actions.live_play = Gtk::ToggleAction::create("Liveplay",_("Live _Display"));
1552  actions.group->add(actions.live_play,
1553  sigc::mem_fun(*this, &MainWindow::on_live_play));
1554 
1555  actions.meterbridge = Gtk::ToggleAction::create("Meterbridge", _("_Meterbridge"));
1556  if (jack) {
1557  actions.group->add(
1558  actions.meterbridge,
1559  sigc::bind(sigc::ptr_fun(gx_child_process::Meterbridge::start_stop),
1560  sigc::ref(actions.meterbridge), sigc::ref(*jack)));
1561  } else {
1562  actions.group->add(actions.meterbridge);
1563  }
1564 
1565  actions.livetuner = UiBoolToggleAction::create(
1566  machine, "ui.racktuner", "LiveTuner", "??");
1567  actions.group->add(actions.livetuner);
1568  actions.livetuner->signal_toggled().connect(
1569  sigc::mem_fun(this, &MainWindow::on_livetuner_toggled));
1570 
1571  actions.midi_out = UiBoolToggleAction::create(
1572  machine, "ui.midi_out", "MidiOut", _("M_idi Out"));
1573  actions.group->add(
1574  actions.midi_out,
1575  sigc::mem_fun(this, &MainWindow::on_show_midi_out));
1576 
1577  actions.midi_out_plug = UiBoolToggleAction::create(
1578  machine, "midi_out.s_h", "MidiOutSH", "??");
1579  actions.group->add(
1580  actions.midi_out_plug,
1581  sigc::mem_fun(this, &MainWindow::on_show_midi_out_plug));
1582 
1583  /*
1584  ** rack actions
1585  */
1586  actions.tuner = UiBoolToggleAction::create(
1587  machine, "system.show_tuner", "Tuner",_("_Tuner show"));
1588  actions.group->add(actions.tuner,
1589  sigc::mem_fun(*this, &MainWindow::on_show_tuner));
1590  actions.tunermove = UiBoolToggleAction::create(
1591  machine, "system.stick_tuner", "Tunermove",_("Tuner stic_k "));
1592  actions.group->add(actions.tunermove,
1593  sigc::mem_fun(*this, &MainWindow::on_move_tuner));
1594 
1595  actions.rack_config = Gtk::ToggleAction::create("RackConfig", _("R_ack Configuration"));
1596  actions.group->add(actions.rack_config,
1597  sigc::mem_fun(*this, &MainWindow::on_rack_configuration));
1598 
1599  actions.compress = Gtk::Action::create("Compress",_("C_ompress all"));
1600  actions.group->add(actions.compress,
1601  sigc::mem_fun(*this, &MainWindow::on_compress_all));
1602 
1603  actions.expand = Gtk::Action::create("Expand",_("E_xpand all"));
1604  actions.group->add(actions.expand,
1605  sigc::mem_fun(*this, &MainWindow::on_expand_all));
1606 
1607  actions.rackh = Gtk::ToggleAction::create(
1608  "RackH", _("Order Rack _Horizontally"));
1609  actions.group->add(actions.rackh,
1610  sigc::mem_fun(*this, &MainWindow::on_dir_changed));
1611 
1612  /*
1613  ** option actions
1614  */
1615  actions.show_values = Gtk::ToggleAction::create(
1616  "ShowValues",_("_Show _Values"), "", true);
1617  actions.group->add(actions.show_values,
1618  sigc::mem_fun(*this, &MainWindow::on_show_values));
1619 
1620  actions.tooltips = Gtk::ToggleAction::create(
1621  "ShowTooltips", _("Show _Tooltips"), "", true);
1622  actions.group->add(
1623  actions.tooltips,
1624  sigc::mem_fun(this, &MainWindow::set_tooltips));
1625 
1626  actions.midi_in_presets = UiSwitchToggleAction::create(
1627  machine, "system.midi_in_preset", "MidiInPresets", _("Include MIDI in _presets"));
1628  actions.group->add(actions.midi_in_presets);
1629 
1630  actions.jackstartup = Gtk::Action::create("JackStartup", _("_Jack Startup Control"));
1631  actions.group->add(
1632  actions.jackstartup,
1633  sigc::mem_fun(*this, &MainWindow::on_select_jack_control));
1634 
1635  actions.loadladspa = Gtk::Action::create("LoadLADSPA", _("LADSPA/LV2 Pl_ugins"));
1636  actions.group->add(
1637  actions.loadladspa,
1638  sigc::mem_fun(this, &MainWindow::on_load_ladspa));
1639 
1640  actions.group->add(Gtk::Action::create("ResetAll", _("Reset _All Parameters")),
1641  sigc::mem_fun(machine, &gx_engine::GxMachineBase::set_init_values));
1642 
1643  actions.animations = Gtk::ToggleAction::create(
1644  "Animations", _("_Use Animations"),"",true);
1645  actions.group->add(actions.animations,
1646  sigc::mem_fun(this, &MainWindow::set_animations));
1647 
1648  actions.group->add(Gtk::Action::create("SetPresetSwitcher", _("L_iveplay Midi Switch")),
1649  sigc::mem_fun(this, &MainWindow::set_switcher_controller));
1650 
1651  actions.group->add(Gtk::Action::create("SetBypassSwitcher", _("B_ypass Midi Switch")),
1652  sigc::mem_fun(this, &MainWindow::set_bypass_controller));
1653 
1654  /*
1655  ** Help and About
1656  */
1657  actions.group->add(Gtk::Action::create("Help", _("_Help")),
1658  sigc::ptr_fun(gx_show_help));
1659  actions.group->add(Gtk::Action::create("About", _("_About")),
1660  sigc::ptr_fun(gx_show_about));
1661 
1662  if (!jack) {
1663  actions.jack_latency_menu->set_visible(false);
1664  actions.jackserverconnection->set_visible(false);
1665  actions.jackports->set_visible(false);
1666  actions.meterbridge->set_visible(false);
1667  }
1668 }
1669 
1670 #if false // unused
1671 int get_current_workarea_height_from_desktop(GdkWindow *root) {
1672  // use "xprop -root" to view desktop properties
1673  GdkAtom actual_type, atom_cardinal;
1674  gint actual_format;
1675  gint num_items;
1676  int *ret_data_ptr;
1677  int idx;
1678  atom_cardinal = gdk_atom_intern("CARDINAL", false);
1679  if (!gdk_property_get(
1680  root, gdk_atom_intern("_NET_CURRENT_DESKTOP", false), atom_cardinal,
1681  0, 1, false, &actual_type, &actual_format, &num_items,
1682  (guchar**)&ret_data_ptr)) {
1683  return -1;
1684  }
1685  idx = *ret_data_ptr * 4 + 3; // [x, y, width, height] * desktop_count
1686  g_free(ret_data_ptr);
1687  if (!gdk_property_get(
1688  root, gdk_atom_intern("_NET_WORKAREA", false), atom_cardinal,
1689  idx, 1, false, &actual_type, &actual_format, &num_items,
1690  (guchar**)&ret_data_ptr)) {
1691  return -1;
1692  }
1693  if (idx >= num_items) {
1694  //??
1695  return -1;
1696  }
1697  int height = *ret_data_ptr;
1698  g_free(ret_data_ptr);
1699  return height;
1700 }
1701 
1702 int get_current_workarea_height() {
1703  // Helper fetching the current workarea (i.e. usable space) size
1704  GdkWindow *root = gdk_get_default_root_window();
1705  int height = get_current_workarea_height_from_desktop(root);
1706  if (height > 0) {
1707  return height;
1708  }
1709  int x, y, width, depth;
1710  gdk_window_get_geometry(root, &x, &y, &width, &height, &depth);
1711  return height;
1712 }
1713 #endif
1714 
1716  new PluginPresetPopup(pdef, machine);
1717 }
1718 
1719 void MainWindow::plugin_preset_popup(const PluginDef *pdef, const Glib::ustring& name) {
1720  new PluginPresetPopup(pdef, machine, name);
1721 }
1722 
1723 void MainWindow::clear_box(Gtk::Container& box) {
1724  std::vector<Gtk::Widget*> l = box.get_children();
1725  for (std::vector<Gtk::Widget*>::iterator p = l.begin(); p != l.end(); ++p) {
1726  box.remove(**p);
1727  }
1728 }
1729 
1730 void MainWindow::make_icons(bool force) {
1731  Gtk::OffscreenWindow w;
1732  w.set_type_hint(Gdk::WINDOW_TYPE_HINT_DOCK); // circumvent canberra-gtk-module bug on AV Linux
1733  Glib::RefPtr<Gdk::Screen> screen = w.get_screen();
1734  Glib::RefPtr<Gdk::Colormap> rgba = screen->get_rgba_colormap();
1735  if (rgba) {
1736  w.set_colormap(rgba);
1737  }
1738  Gtk::VBox vb;
1739  w.add(vb);
1740  Glib::RefPtr<Gtk::SizeGroup> sz = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_BOTH);
1741  std::vector<std::pair<PluginUI*,Gtk::Widget*> > l;
1742  for (std::map<std::string, PluginUI*>::iterator i = plugin_dict.begin(); i != plugin_dict.end(); ++i) {
1743  if (!force && i->second->icon) {
1744  continue;
1745  }
1746  Gtk::Widget *r = RackBox::create_icon_widget(*i->second, options);
1747  r->hide();
1748  r->set_no_show_all(true);
1749  vb.add(*manage(r));
1750  sz->add_widget(*r);
1751  l.push_back(std::pair<PluginUI*,Gtk::Widget*>(i->second, r));
1752  }
1753  //FIXME hack to set a minimum size
1754  l.begin()->second->show();
1755  if (vb.size_request().width < 110) {
1756  vb.set_size_request(110, -1);
1757  }
1758  w.show_all();
1759  for (std::vector<std::pair<PluginUI*,Gtk::Widget*> >::iterator i = l.begin(); i != l.end(); ++i) {
1760  i->second->show();
1761  w.show();
1762  w.get_window()->process_updates(true);
1763  i->first->icon = w.get_pixbuf();
1764  if (i->first->toolitem) {
1765  dynamic_cast<Gtk::Image*>(i->first->toolitem->get_child())->set(i->first->icon);
1766  }
1767  w.hide();
1768  i->second->hide();
1769  }
1770 
1771  // Amp padding
1772  hanl = gtk_widget_render_icon(GTK_WIDGET(window->gobj()), "handle_left", (GtkIconSize)-1, NULL);
1773  hanr = gtk_widget_render_icon(GTK_WIDGET(window->gobj()), "handle_right", (GtkIconSize)-1, NULL);
1774  gint wl = gdk_pixbuf_get_width(hanl);
1775  gint wr = gdk_pixbuf_get_width(hanr);
1776  g_object_unref(hanl);
1777  g_object_unref(hanr);
1778  bld->find_widget("amp_padding", vbam);
1779  vbam->set_padding(0, 4, wl, wr);
1780  bld->find_widget("tuner_padding", vbam);
1781  vbam->set_padding(0, 4, wl, wr);
1782  bld->find_widget("details_padding", vbam);
1783  vbam->set_padding(0, 4, wl, wr);
1784 }
1785 
1786 class JConvPluginUI: public PluginUI {
1787 private:
1788  virtual void on_plugin_preset_popup();
1789 public:
1790  JConvPluginUI(MainWindow& main, const char* id,
1791  const Glib::ustring& tooltip="")
1792  : PluginUI(main, id, tooltip) {
1793  }
1794 };
1795 
1796 void JConvPluginUI::on_plugin_preset_popup() {
1798  &main.get_machine().get_parameter(std::string(get_id())+".convolver"));
1799  assert(jcp);
1800  Glib::ustring name = jcp->get_value().getIRFile();
1801  Glib::ustring::size_type n = name.find_last_of('.');
1802  if (n != Glib::ustring::npos) {
1803  name.erase(n);
1804  }
1805  main.plugin_preset_popup(plugin->get_pdef(), name);
1806 }
1807 
1808 void MainWindow::on_plugin_changed(gx_engine::Plugin *pl, gx_engine::PluginChange::pc c) {
1809  if (!pl) { // end of update sequence
1810  make_icons(true); // re-create all icons, width might have changed
1811  } else if (c == gx_engine::PluginChange::add) {
1812  register_plugin(new PluginUI(*this, pl->get_pdef()->id, ""));
1813  } else {
1814  PluginUI *pui = plugin_dict[pl->get_pdef()->id];
1816  plugin_dict.remove(pui);
1817  pui->unset_ui_merge_id(uimanager);
1818  uimanager->ensure_update();
1819  actions.group->remove(pui->get_action());
1820  machine.remove_rack_unit(pui->get_id(), pui->get_type());
1821  std::string group_id = pui->get_category();
1822  delete pui;
1823  Gtk::ToolItemGroup * group = groupmap[group_id];
1824  if (group->get_n_items() == 0) {
1825  Glib::ustring groupname = Glib::ustring::compose("PluginCategory_%1", group_id);
1826  Glib::RefPtr<Gtk::Action> act = actions.group->get_action(groupname);
1827  actions.group->remove(actions.group->get_action(groupname));
1828  groupmap.erase(group_id);
1829  delete group;
1830  }
1831  } else {
1833  //if (!pui->plugin->get_box_visible())
1834  bool state = pui->plugin->get_on_off();
1835  pui->update_rackbox();
1836  pui->plugin->set_on_off(state);
1838  pui->unset_ui_merge_id(uimanager);
1839  pui->group = add_plugin_category(pui->get_category());
1840  pui->toolitem->reparent(*pui->group);
1841  add_plugin_menu_entry(pui);
1842  }
1843  }
1844  }
1845 }
1846 
1847 void MainWindow::on_ladspa_finished(bool reload, bool quit) {
1848  if (reload) {
1849  machine.commit_ladspa_changes();
1850  }
1851  if (quit) {
1852  Glib::signal_idle().connect(sigc::mem_fun(this, &MainWindow::delete_ladspalist_window));
1853  }
1854 }
1855 
1856 bool MainWindow::delete_ladspalist_window() {
1857  if (ladspalist_window) {
1858  //ladspalist_window->hide();
1859  delete ladspalist_window;
1860  ladspalist_window = 0;
1861  }
1862  return false;
1863 }
1864 
1865 void MainWindow::on_load_ladspa() {
1866  if (ladspalist_window) {
1867  ladspalist_window->present();
1868  } else {
1869  ladspalist_window = new ladspa::PluginDisplay(machine, gx_head_icon, sigc::mem_fun(this, &MainWindow::on_ladspa_finished));
1870  }
1871 }
1872 
1873 void MainWindow::add_plugin(std::vector<PluginUI*>& p, const char *id, const Glib::ustring& tooltip) {
1874  if (PluginUI::is_registered(machine, id)) {
1875  return;
1876  }
1877  p.push_back(new PluginUI(*this, id, tooltip));
1878 }
1879 
1880 #ifdef accel_keys_for_plugins
1881 struct accel_search {
1882  unsigned int key;
1883  bool res;
1884 };
1885 
1886 static void accel_search_callback(gpointer data, const gchar *accel_path, guint accel_key, GdkModifierType accel_mods, gboolean changed) {
1887  accel_search *s = static_cast<accel_search*>(data);
1888  if (accel_key == s->key && accel_mods == 0) {
1889  s->res = true;
1890  }
1891 }
1892 
1893 static bool accel_map_has_key(unsigned int accel_key) {
1894  accel_search s;
1895  s.key = accel_key;
1896  s.res = false;
1897  gtk_accel_map_foreach_unfiltered(gpointer(&s), accel_search_callback);
1898  return s.res;
1899 }
1900 
1901 static bool accel_map_next_key(unsigned int *accel_key) {
1902  while (*accel_key <= GDK_z) {
1903  if (!accel_map_has_key(*accel_key)) {
1904  return true;
1905  }
1906  *accel_key += 1;
1907  }
1908  return false;
1909 }
1910 #endif
1911 
1912 struct PluginDesc {
1913  Glib::ustring group;
1914  std::vector<PluginUI*> *plugins;
1915  PluginDesc(const Glib::ustring& g, std::vector<PluginUI*> *p)
1916  : group(g), plugins(p) {}
1917 };
1918 
1919 Gtk::ToolItemGroup *MainWindow::add_plugin_category(const char *group, bool collapse) {
1920  std::map<Glib::ustring, Gtk::ToolItemGroup*>::iterator it = groupmap.find(group);
1921  if (it != groupmap.end()) {
1922  return it->second;
1923  }
1924  Glib::ustring ui_template =
1925  "<menubar><menu action=\"PluginsMenu\"><menu action=\"%1Plugins\"><menu action=\"%2\">"
1926  "</menu></menu></menu></menubar>";
1927  Glib::ustring groupname = Glib::ustring::compose("PluginCategory_%1", group);
1928  uimanager->add_ui_from_string(Glib::ustring::compose(ui_template, "Mono", groupname));
1929  uimanager->add_ui_from_string(Glib::ustring::compose(ui_template, "Stereo", groupname));
1930  actions.group->add(Gtk::Action::create(groupname, gettext(group)));
1931  Gtk::ToolItemGroup *gw = new Gtk::ToolItemGroup(gettext(group));
1932  groupmap[group] = gw;
1933  gw->set_collapsed(collapse);
1934  effects_toolpalette->add(*manage(gw));
1935  effects_toolpalette->set_exclusive(*gw, true);
1936  effects_toolpalette->set_expand(*gw, true);
1937  return gw;
1938 }
1939 
1940 Glib::ustring MainWindow::add_plugin_menu_entry(PluginUI *pui) {
1941  Glib::ustring ui_template =
1942  "<menubar><menu action=\"PluginsMenu\"><menu action=\"%1Plugins\"><menu action=\"%2\">"
1943  "<menuitem action=\"%3\"/>"
1944  "</menu></menu></menu></menubar>";
1945  const char *group = pui->get_category();
1946  Glib::ustring groupname = Glib::ustring::compose("PluginCategory_%1", group);
1947  Glib::ustring actionname = Glib::ustring::compose("Plugin_%1", pui->get_id());
1948  const char *tp = (pui->get_type() == PLUGIN_TYPE_MONO ? "Mono" : "Stereo");
1949  pui->set_ui_merge_id(uimanager->add_ui_from_string(Glib::ustring::compose(ui_template, tp, groupname, actionname)));
1950  //fprintf(stderr, "%s : %s : %s \n", tp, group, pui->get_name());
1951  return actionname;
1952 }
1953 
1954 void MainWindow::register_plugin(PluginUI *pui) {
1955  plugin_dict.add(pui);
1956  Gtk::ToolItemGroup *gw = add_plugin_category(pui->get_category());
1957  Glib::ustring actionname = add_plugin_menu_entry(pui);
1958  add_toolitem(*pui, gw);
1959  Glib::RefPtr<Gtk::ToggleAction> act = Gtk::ToggleAction::create(actionname, pui->get_name());
1960  actions.group->add(act);
1961 #ifdef accel_keys_for_plugins
1962  unsigned int key = GDK_a;
1963  if (accel_map_next_key(&key)) {
1964  Gtk::AccelMap::add_entry(act->get_accel_path(), key, Gdk::ModifierType(0));
1965  ++key;
1966  }
1967 #endif
1968  if (pui->rackbox && pui->rackbox->get_box_visible()) {
1969  act->set_active(true);
1970  }
1971  pui->set_action(act);
1972 }
1973 
1974 void MainWindow::fill_pluginlist() {
1975  // define order of categories by registering
1976  // them first
1977  add_plugin_category(N_("Tone Control"), false);
1978  add_plugin_category(N_("Distortion"));
1979  add_plugin_category(N_("Fuzz"));
1980  add_plugin_category(N_("Reverb"));
1981  add_plugin_category(N_("Echo / Delay"));
1982  add_plugin_category(N_("Modulation"));
1983  add_plugin_category(N_("Guitar Effects"));
1984  add_plugin_category(N_("Misc"));
1985 
1986  std::vector<PluginUI*> p;
1987  p.push_back(new JConvPluginUI(*this, "jconv"));
1988  p.push_back(new JConvPluginUI(*this, "jconv_mono"));
1989 
1990  gx_gui::UiBuilderImpl builder(this, &boxbuilder, &p);
1991  machine.pluginlist_append_rack(builder);
1992 
1993  std::sort(p.begin(), p.end(), plugins_by_name_less);
1994  for (std::vector<PluginUI*>::iterator v = p.begin(); v != p.end(); ++v) {
1995  register_plugin(*v);
1996  }
1997 }
1998 
1999 // start_jack() returns:
2000 // 1: success
2001 // 0: fail
2002 // -1: no start command configured
2003 int MainWindow::start_jack() {
2004  gx_jack::GxJack *jack = machine.get_jack();
2005  if (!jack) {
2006  return -1;
2007  }
2008  int wait_after_connect = 0;
2009  gx_engine::EnumParameter& jack_starter = machine.get_parameter("ui.jack_starter_idx").getEnum();
2010  string v_id = jack_starter.get_pair().value_id;
2011  if (v_id == "autostart") {
2012  return jack->gx_jack_connection(true, true, wait_after_connect, options) ? 1 : 0;
2013  }
2014  string cmd;
2015  if (v_id == "other") {
2016  cmd = machine.get_parameter("ui.jack_starter").getString().get_value();
2017  if (cmd.empty()) {
2018  return -1;
2019  }
2020  } else if (v_id == "qjackctl") {
2021  wait_after_connect = 500000;
2022  cmd = "qjackctl --start";
2023  } else {
2024  assert(false);
2025  }
2026  gx_system::gx_system_call(cmd, true, true);
2027  for (int i = 0; i < 10; i++) {
2028  if (jack->gx_jack_connection(true,false,wait_after_connect, options)) {
2029  return 1;
2030  }
2031  usleep(500000);
2032  }
2034  _("main"),
2035  string(_("I really tried to get jack up and running, sorry ... ")));
2036  return 0;
2037 }
2038 
2039 bool MainWindow::connect_jack(bool v, Gtk::Window *splash) {
2040  gx_jack::GxJack *jack = machine.get_jack();
2041  if (!jack) {
2042  return false;
2043  }
2044  if (jack->gx_jack_connection(v, false, 0, options)) {
2045  return true;
2046  }
2047  if (!v) {
2048  gx_print_error(_("main"), _("can't disconnect jack"));
2049  return false;
2050  }
2051  bool ask = machine.get_parameter_value<bool>("ui.ask_for_jack_starter");
2052  if (!ask) {
2053  switch (start_jack()) {
2054  case 1: return true; // connected
2055  case -1: return false; // no starter, do nothing
2056  default: break; // failed, ask user
2057  }
2058  }
2059  if (splash) {
2060  splash->hide();
2061  }
2062  if (!gx_gui::gx_start_jack_dialog(gx_head_icon)) {
2063  gx_print_warning(_("main"), string(_("Ignoring jackd ...")));
2064  return false;
2065  }
2066  return start_jack() == 1;
2067 }
2068 
2069 void MainWindow::on_jack_client_changed() {
2070  if (!window) {
2071  return;
2072  }
2073  gx_jack::GxJack *jack = machine.get_jack();
2074  if (!jack) {
2075  return;
2076  }
2077  bool v = (jack->client != 0);
2078  if (!v) {
2080  }
2081  actions.jackserverconnection->set_active(v);
2082  Glib::ustring s = "Guitarix: ";
2083  if (v) {
2084  s += jack->get_instancename();
2085  } else {
2086  s += "("+jack->get_instancename()+")";
2087  }
2088  window->set_title(s);
2089  actions.jack_latency_menu->set_sensitive(v);
2090  actions.engine_mute->set_sensitive(v);
2091  actions.engine_bypass->set_sensitive(v);
2092  status_image->set_sensitive(v);
2093  if (!v) {
2094  jackd_image->set(pixbuf_jack_disconnected);
2095  } else {
2096  jackd_image->set(pixbuf_jack_connected);
2097  }
2098 }
2099 
2100 void MainWindow::on_engine_state_change(gx_engine::GxEngineState state) {
2101  switch (state) {
2102  case gx_engine::kEngineOff:
2103  actions.engine_mute_conn.block();
2104  actions.engine_mute->set_active(true);
2105  actions.engine_mute_conn.unblock();
2106  status_image->set(pixbuf_off);
2107  machine.msend_midi_cc(0xB0,120,127,3);
2108  break;
2109  case gx_engine::kEngineOn:
2110  actions.engine_mute_conn.block();
2111  actions.engine_bypass_conn.block();
2112  actions.engine_mute->set_active(false);
2113  actions.engine_bypass->set_active(false);
2114  actions.engine_mute_conn.unblock();
2115  actions.engine_bypass_conn.unblock();
2116  status_image->set(pixbuf_on);
2117  machine.msend_midi_cc(0xB0,120,0,3);
2118  break;
2120  actions.engine_mute_conn.block();
2121  actions.engine_bypass_conn.block();
2122  actions.engine_mute->set_active(false);
2123  actions.engine_bypass->set_active(true);
2124  actions.engine_mute_conn.unblock();
2125  actions.engine_bypass_conn.unblock();
2126  status_image->set(pixbuf_bypass);
2127  break;
2128  }
2129 }
2130 
2131 void MainWindow::set_tuning(Gxw::RackTuner& tuner) {
2132  static struct TuningTab {
2133  const char *name;
2134  const char* key;
2135  bool flat;
2136  int notes[6];
2137  } tuning_tab[] = {
2138  { "Standard", "E", false, {40, 45, 50, 55, 59, 64}},
2139  { "Standard/Es", "Es", true, {39, 44, 49, 54, 58, 63}},
2140  { "Open E", "E", false, {40, 47, 52, 56, 59, 64}},
2141  { "Drop D", "D", false, {38, 45, 50, 55, 59, 64}},
2142  { "Half Step Down", "E", false, {39, 44, 49, 54, 58, 63}},
2143  { "Full Step Down", "D", false, {38, 43, 48, 53, 57, 62}},
2144  { "1 and 1/2 Steps Down", "E", false, {37, 42, 47, 52, 56, 61}},
2145  { "Double Drop D", "D", false, {38, 45, 50, 55, 59, 62}},
2146  { "Drop C", "C", false, {36, 43, 48, 53, 57, 62}},
2147  { "Drop C#", "C#", false, {37, 44, 49, 54, 58, 63}},
2148  { "Drop B", "B", false, {35, 42, 47, 52, 56, 61}},
2149  { "Drop A#", "A#", false, {34, 41, 46, 51, 55, 60}},
2150  { "Drop A", "A", false, {33, 40, 45, 50, 54, 59}},
2151  { "Open D", "D", false, {38, 45, 50, 54, 57, 62}},
2152  { "Open D Minor", "D", false, {38, 45, 50, 53, 57, 62}},
2153  { "Open G", "G", false, {38, 43, 50, 55, 59, 62}},
2154  { "Open G Minor", "G", false, {38, 43, 50, 55, 58, 62}},
2155  { "Open C", "C", false, {36, 43, 48, 55, 60, 64}},
2156  { "Open C#", "C#", false, {37, 42, 59, 52, 56, 61}},
2157  { "Open C Minor", "C", false, {36, 43, 48, 55, 60, 63}},
2158  { "Open E7", "E7", false, {40, 44, 50, 52, 59, 64}},
2159  { "Open E Minor7", "E", false, {40, 47, 50, 55, 59, 64}},
2160  { "Open G Major7", "G", false, {38, 43, 50, 54, 59, 62}},
2161  { "Open A Minor", "A", false, {40, 45, 52, 57, 60, 64}},
2162  { "Open A Minor7", "A", false, {40, 45, 52, 55, 60, 64}},
2163  { "Open A", "A", false, {40, 45, 49, 52, 57, 64}},
2164  { "C Tuning", "C", false, {36, 41, 46, 51, 55, 60}},
2165  { "C# Tuning", "C#", false, {37, 42, 47, 52, 56, 61}},
2166  { "Bb Tuning", "Bb", false, {34, 39, 44, 49, 53, 58}},
2167  { "A to A (Baritone)", "A", false, {33, 38, 43, 48, 52, 57}},
2168  { "Open Dsus2", "D", false, {38, 45, 50, 55, 57, 62}},
2169  { "Open Gsus2", "G", false, {38, 43, 50, 55, 60, 62}},
2170  { "G6", "G6", false, {38, 43, 50, 55, 59, 64}},
2171  { "Modal G", "G", false, {38, 43, 50, 55, 60, 62}},
2172  { "Overtone", "E", false, {48, 52, 55, 58, 60, 62}},
2173  { "Pentatonic", "E", false, {45, 48, 50, 52, 55, 69}},
2174  { "Minor Third", "E", false, {48, 51, 54, 57, 60, 63}},
2175  { "Major Third", "E", false, {48, 52, 56, 60, 64, 68}},
2176  { "All Fourths", "E", false, {40, 45, 50, 55, 60, 65}},
2177  { "Augmented Fourths", "E", false, {36, 42, 48, 54, 60, 66}},
2178  { "Slow Motion", "E", false, {38, 43, 50, 53, 60, 62}},
2179  { "Admiral", "E", false, {36, 43, 50, 55, 59, 60}},
2180  { "Buzzard", "E", false, {36, 41, 48, 55, 58, 65}},
2181  { "Face", "E", false, {36, 43, 50, 55, 57, 62}},
2182  { "Four and Twenty", "E", false, {38, 45, 50, 50, 57, 62}},
2183  { "Ostrich", "E", false, {38, 50, 50, 50, 62, 62}},
2184  { "Capo 200", "E", false, {36, 43, 50, 51, 62, 63}},
2185  { "Balalaika", "E", false, {40, 45, 50, 52, 52, 57}},
2186  { "Cittern One", "E", false, {36, 41, 48, 55, 60, 62}},
2187  { "Cittern Two", "E", false, {36, 43, 48, 55, 60, 67}},
2188  { "Dobro", "E", false, {43, 47, 50, 55, 59, 62}},
2189  { "Lefty", "E", false, {64, 59, 55, 50, 45, 40}},
2190  { "Mandoguitar", "E", false, {36, 43, 50, 57, 64, 71}},
2191  { "Rusty Cage", "E", false, {35, 45, 50, 55, 59, 64}},
2192  { "Hardcore", "C", false, {36, 43, 48, 53, 57, 58}},
2193  };
2194  int mode = tuner_tuning->get_value();
2195  tuner.clear_notes();
2196  if (mode > 0) {
2197  tuner.set_display_flat(tuning_tab[mode-1].flat);
2198  for (int i = 0; i < 6; ++i) {
2199  tuner.push_note(tuning_tab[mode-1].notes[i], 69, 12);
2200  }
2201  } else {
2202  tuner.set_display_flat(false);
2203  }
2204 }
2205 
2206 void MainWindow::set_tuner_tet(Gxw::RackTuner& tuner) {
2207  Glib::ustring tet = options.get_tuner_tet();
2208  int t = 0;
2209  if (tet.find("12") !=Glib::ustring::npos) t=0;
2210  else if (tet.find("19") !=Glib::ustring::npos) t=1;
2211  else if (tet.find("24") !=Glib::ustring::npos) t=2;
2212  else if (tet.find("31") !=Glib::ustring::npos) t=3;
2213  else if (tet.find("53") !=Glib::ustring::npos) t=4;
2214  else t = tuner_temperament->get_value();
2215  machine.set_parameter_value("racktuner.temperament", t);
2216  tuner.set_temperament(tuner_temperament->get_value());
2217  set_tuning(tuner);
2218 }
2219 
2220 void MainWindow::set_tuner_ref(Gxw::RackTuner& tuner) {
2221  Glib::ustring ref = options.get_tuner_ref();
2222  float t = atof(ref.c_str());
2223  machine.set_parameter_value("ui.tuner_reference_pitch", t);
2224  tuner.set_reference_pitch(tuner_reference_pitch->get_value());
2225  set_tuning(tuner);
2226 }
2227 
2228 void MainWindow::setup_tuner_temperament(Gxw::RackTuner& tuner) {
2229  tuner.set_temperament(tuner_temperament->get_value());
2230  set_tuning(tuner);
2231 }
2232 
2233 void MainWindow::setup_tuner(Gxw::RackTuner& tuner) {
2234  tuner.signal_frequency_poll().connect(
2235  sigc::compose(
2236  sigc::mem_fun(tuner, &Gxw::RackTuner::set_freq),
2237  sigc::mem_fun(machine, &gx_engine::GxMachineBase::get_tuner_freq)));
2238  tuner_mode->signal_value_changed().connect(
2239  sigc::compose(
2240  sigc::mem_fun(tuner, &Gxw::RackTuner::set_streaming),
2241  sigc::mem_fun(*tuner_mode, &Gxw::Selector::get_value)));
2242  tuner_reference_pitch->signal_value_changed().connect(
2243  sigc::compose(
2244  sigc::mem_fun(tuner, &Gxw::RackTuner::set_reference_pitch),
2245  sigc::mem_fun(*tuner_reference_pitch, &Gxw::ValueDisplay::get_value)));
2246  tuner_tuning->signal_value_changed().connect(
2247  sigc::bind(sigc::mem_fun(*this, &MainWindow::set_tuning), sigc::ref(tuner)));
2248  tuner_temperament->signal_value_changed().connect(
2249  sigc::bind(sigc::mem_fun(*this, &MainWindow::setup_tuner_temperament), sigc::ref(tuner)));
2250  tuner.set_temperament(tuner_temperament->get_value());
2251 }
2252 
2253 bool MainWindow::on_toggle_mute(GdkEventButton* ev) {
2254  if (ev->type == GDK_BUTTON_PRESS && ev->button == 1) {
2255  if (machine.get_state() == gx_engine::kEngineOff) {
2256  machine.set_state(gx_engine::kEngineOn);
2257  } else {
2258  machine.set_state(gx_engine::kEngineOff);
2259  }
2260  }
2261  return true;
2262 }
2263 
2264 bool MainWindow::on_scroll_toggle(GdkEventScroll* ev) {
2265  if (ev->direction == GDK_SCROLL_UP) {
2266  if (machine.get_state() == gx_engine::kEngineOff) {
2267  machine.set_state(gx_engine::kEngineOn);
2268  } else if (machine.get_state() == gx_engine::kEngineOn) {
2269  machine.set_state(gx_engine::kEngineBypass);
2270  } else {
2271  machine.set_state(gx_engine::kEngineOff);
2272  }
2273  } else if (ev->direction == GDK_SCROLL_DOWN) {
2274  if (machine.get_state() == gx_engine::kEngineOff) {
2275  machine.set_state(gx_engine::kEngineBypass);
2276  } else if (machine.get_state() == gx_engine::kEngineBypass) {
2277  machine.set_state(gx_engine::kEngineOn);
2278  } else {
2279  machine.set_state(gx_engine::kEngineOff);
2280  }
2281  }
2282 
2283  return true;
2284 }
2285 
2286 bool MainWindow::on_toggle_insert(GdkEventButton* ev) {
2287  if (ev->type == GDK_BUTTON_PRESS && ev->button == 1) {
2288  if (machine.get_parameter_value<bool>("engine.insert")) {
2289  machine.set_parameter_value("engine.insert",false);
2290  } else {
2291  machine.set_parameter_value("engine.insert",true);
2292  }
2293  }
2294  return true;
2295 }
2296 
2297 bool MainWindow::on_scroll_toggle_insert(GdkEventScroll* ev) {
2298  if (machine.get_parameter_value<bool>("engine.insert")) {
2299  machine.set_parameter_value("engine.insert",false);
2300  } else {
2301  machine.set_parameter_value("engine.insert",true);
2302  }
2303  return true;
2304 }
2305 
2306 void MainWindow::on_insert_jack_changed(bool s) {
2307  if (s) {
2308  insert_image->set(pixbuf_insert_off);
2309  } else {
2310  insert_image->set(pixbuf_insert_on);
2311  }
2312 }
2313 
2314 bool MainWindow::on_jackserverconnection(GdkEventButton* ev) {
2315  if (ev->type == GDK_BUTTON_PRESS && ev->button == 1) {
2316  bool v = actions.jackserverconnection->get_active();
2317  actions.jackserverconnection->set_active(!v);
2318  }
2319  return true;
2320 }
2321 
2322 bool MainWindow::on_jackserverconnection_scroll(GdkEventScroll* ev) {
2323  bool v = actions.jackserverconnection->get_active();
2324  actions.jackserverconnection->set_active(!v);
2325  return true;
2326 }
2327 
2328 void MainWindow::on_msg_level_changed() {
2329  switch (fLoggingWindow.get_unseen_msg_level()) {
2330  case GxLogger::kWarning: logstate_image->set(pixbuf_log_yellow); break;
2331  case GxLogger::kError: logstate_image->set(pixbuf_log_red); break;
2332  default: logstate_image->set(pixbuf_log_grey); break;
2333  }
2334 }
2335 
2336 //static void toggle_action(Glib::RefPtr<Gtk::ToggleAction> act) {
2337 // act->set_active(!act->get_active());
2338 //}
2339 
2340 void MainWindow::on_ampdetail_switch(bool compress, bool setparam) {
2341  if (compress) {
2342  ampdetail_normal->hide();
2343  ampdetail_mini->show();
2344  } else {
2345  ampdetail_mini->hide();
2346  ampdetail_normal->show();
2347  }
2348  if (setparam) {
2349  machine.set_parameter_value("ui.mp_s_h", compress);
2350  }
2351 }
2352 
2353 /****************************************************************
2354  ** oscilloscope handling
2355  */
2356 
2357 void MainWindow::set_osc_size() {
2358  //int osc_size = engine.oscilloscope.get_mul_buffer();
2359  if (options.mul_buffer > 0) {
2360  actions.osc_buffer_size->set_current_value(options.mul_buffer);
2361  }
2362 }
2363 
2364 void MainWindow::change_osc_buffer(Glib::RefPtr<Gtk::RadioAction> action) {
2365  gx_jack::GxJack *jack = machine.get_jack();
2366  if (!jack || jack->client) {
2367  options.mul_buffer = action->get_current_value();
2368  on_oscilloscope_activate(false);
2369  machine.set_oscilloscope_mul_buffer(options.mul_buffer);
2370  on_oscilloscope_activate(true);
2371  } else {
2372  set_osc_size();
2373  }
2374 }
2375 
2376 void MainWindow::add_osc_size_menu() {
2377  Glib::ustring s = "<menubar><menu action=\"OptionsMenu\"><menu action=\"OscBuffer\">";
2378  Gtk::RadioButtonGroup group;
2379  int osc_buffer_size = 1;
2380  for (int i = 1; i <= 6; ++i) {
2381  Glib::ustring name = "*" + gx_system::to_string(osc_buffer_size);
2382  Glib::ustring actname = Glib::ustring::compose("buffer size %1", name);
2383  s += Glib::ustring::compose("<menuitem action=\"%1\"/>", actname);
2384  Glib::RefPtr<Gtk::RadioAction> action = Gtk::RadioAction::create(group, actname, name);
2385  actions.group->add(action);
2386  if (i == 1) {
2387  action->signal_changed().connect(
2388  sigc::mem_fun(*this, &MainWindow::change_osc_buffer));
2389  actions.osc_buffer_size = action;
2390  }
2391  action->property_value().set_value(osc_buffer_size);
2392  osc_buffer_size++;
2393  }
2394  s.append("</menu></menu></menubar>");
2395  uimanager->add_ui_from_string(s);
2396 }
2397 
2398 void MainWindow::on_show_oscilloscope(bool v) {
2399  if (v) {
2400  // FIXME G_PRIORITY_DEFAULT_IDLE??
2401  Glib::signal_timeout().connect(
2402  sigc::mem_fun(*this, &MainWindow::on_refresh_oscilloscope), 60);
2403  }
2404 }
2405 
2406 void MainWindow::set_waveview_buffer(unsigned int size) {
2407  fWaveView.set_frame(machine.get_oscilloscope_buffer(), size);
2408 }
2409 
2410 void MainWindow::on_oscilloscope_post_pre(int post_pre) {
2411  // if (post_pre) {
2412  // fWaveView.set_multiplicator(150.,250.);
2413  // } else {
2414  fWaveView.set_multiplicator(20.,60.);
2415  // }
2416 }
2417 
2418 int MainWindow::on_oscilloscope_activate(bool start) {
2419  if (!start) {
2420  machine.clear_oscilloscope_buffer();
2421  fWaveView.queue_draw();
2422  }
2423  return 0;
2424 }
2425 
2426 bool MainWindow::on_refresh_oscilloscope() {
2427  int load, frames;
2428  bool is_rt;
2429  jack_nframes_t bsize;
2430  machine.get_oscilloscope_info(load, frames, is_rt, bsize);
2431  static struct {
2432  int load, frames;
2433  jack_nframes_t bsize;
2434  bool rt;
2435  } oc;
2436  if (!oc.bsize || oc.load != load) {
2437  oc.load = load;
2438  fWaveView.set_text(
2439  (boost::format(_("DSP Load %1% %%")) % oc.load).str().c_str(),
2440  Gtk::CORNER_TOP_LEFT);
2441  }
2442  if (!oc.bsize || oc.frames != frames) {
2443  oc.frames = frames;
2444  fWaveView.set_text(
2445  (boost::format(_("HT Frames %1%")) % oc.frames).str().c_str(),
2446  Gtk::CORNER_BOTTOM_LEFT);
2447  }
2448  if (!oc.bsize || oc.rt != is_rt) {
2449  oc.rt = is_rt;
2450  fWaveView.set_text(
2451  oc.rt ? _("RT Mode YES ") : _("RT mode <span color=\"#cc1a1a\">NO</span>"),
2452  Gtk::CORNER_BOTTOM_RIGHT);
2453  }
2454  if (!oc.bsize || oc.bsize != bsize) {
2455  oc.bsize = bsize;
2456  fWaveView.set_text(
2457  (boost::format(_("Latency %1%")) % oc.bsize).str().c_str(),
2458  Gtk::CORNER_TOP_RIGHT);
2459  }
2460  fWaveView.queue_draw();
2461  return machine.oscilloscope_plugin_box_visible();
2462 }
2463 
2464 /* --------- calculate power (percent) to decibel -------- */
2465 // Note: could use fast_log10 (see ardour code) to make it faster
2466 inline float power2db(float power) {
2467  return 20.*log10(power);
2468 }
2469 
2470 bool MainWindow::refresh_meter_level(float falloff) {
2471  const unsigned int channels = sizeof(fastmeter)/sizeof(fastmeter[0]);
2472  gx_jack::GxJack *jack = machine.get_jack();
2473  if (jack && !jack->client) {
2474  return true;
2475  }
2476 
2477  // Note: removed RMS calculation, we will only focus on max peaks
2478  static float old_peak_db[channels] = {-INFINITY, -INFINITY};
2479 
2480  // fill up from engine buffers
2481  float level[channels];
2482  machine.maxlevel_get(channels, level);
2483  for (unsigned int c = 0; c < channels; c++) {
2484  // update meters (consider falloff as well)
2485  // calculate peak dB and translate into meter
2486  float peak_db = -INFINITY;
2487  if (level[c] > 0) {
2488  peak_db = power2db(level[c]);
2489  }
2490  // retrieve old meter value and consider falloff
2491  if (peak_db < old_peak_db[c]) {
2492  peak_db = max(peak_db, old_peak_db[c] - falloff);
2493  }
2494  fastmeter[c]->set(log_meter(peak_db));
2495  old_peak_db[c] = peak_db;
2496  }
2497  return true;
2498 }
2499 
2500 bool MainWindow::survive_jack_shutdown() {
2501  gx_jack::GxJack *jack = machine.get_jack();
2502  if (!jack) {
2503  return false;
2504  }
2505  // return if jack is not down
2506  if (gx_system::gx_system_call("pgrep jackd", true) == SYSTEM_OK) {
2507  if (jack->is_jack_down()) {
2508  sleep(2);
2509  jack->set_jack_down(false);
2510  }
2511  // let's make sure we get out of here
2512  gx_print_warning("Jack Shutdown",
2513  _("jack has bumped us out!! "));
2514  actions.jackserverconnection->set_active(true);
2515  // run only one time whem jackd is running
2516  return false;
2517  } else if (!jack->is_jack_down()) {
2518  // refresh some stuff. Note that it can be executed
2519  // more than once, no harm here
2520  actions.jackserverconnection->set_active(false);
2521  jack->set_jack_down(true);
2522  gx_print_error("Jack Shutdown",
2523  _("jack has bumped us out!! "));
2524  }
2525  // run as long jackd is down
2526  return true;
2527 }
2528 
2529 void MainWindow::gx_jack_is_down() {
2530  actions.jackserverconnection->set_active(false);
2531  Glib::signal_timeout().connect(
2532  sigc::mem_fun(*this, &MainWindow::survive_jack_shutdown),
2533  200, Glib::PRIORITY_LOW);
2534 }
2535 
2536 #ifdef HAVE_JACK_SESSION
2537 void MainWindow::jack_session_event() {
2538  gx_jack::GxJack *jack = machine.get_jack();
2539  if (!jack) {
2540  return;
2541  }
2542  const char *statefile = "gx_head.state";
2543  jack_session_event_t *event = jack->get_last_session_event();
2544  set_in_session();
2545  machine.set_statefilename(string(event->session_dir) + statefile);
2546  machine.save_to_state();
2547 
2548 #ifndef NDEBUG
2549  string cmd(options.get_path_to_program());
2550 #else
2551  string cmd("guitarix");
2552 #endif
2553  cmd += " -U ";
2554  cmd += event->client_uuid;
2555  cmd += " -A ";
2556  cmd += jack->get_uuid_insert();
2557  cmd += " -f ${SESSION_DIR}";
2558  cmd += statefile; // no space after SESSION_DIR
2559  event->command_line = strdup(cmd.c_str());
2560 
2561  JackSessionEventType tp = event->type;
2562  if (jack->return_last_session_event() == 0) {
2563  if (tp == JackSessionSaveAndQuit) {
2564  GxExit::get_instance().exit_program("** session exit **");
2565  }
2566  }
2567 }
2568 
2569 void MainWindow::jack_session_event_ins() {
2570  gx_jack::GxJack *jack = machine.get_jack();
2571  if (!jack) {
2572  return;
2573  }
2574  jack_session_event_t *event = jack->get_last_session_event_ins();
2575  set_in_session();
2576  event->command_line = strdup("true ${SESSION_DIR}");
2577  JackSessionEventType tp = event->type;
2578  if (jack->return_last_session_event_ins() == 0) {
2579  if (tp == JackSessionSaveAndQuit) {
2580  GxExit::get_instance().exit_program("** session exit **");
2581  }
2582  }
2583 }
2584 #endif
2585 
2586 void MainWindow::set_in_session() {
2587  if (!in_session) {
2588  in_session = true;
2589  // it seems in a session we generally don't know
2590  // where to save and from where to recall data
2591  // it's all controlled by the session manager
2592  machine.disable_autosave(true);
2593  }
2594 }
2595 
2596 void MainWindow::systray_menu(guint button, guint32 activate_time) {
2597  Gtk::Menu *menu = dynamic_cast<Gtk::MenuItem*>(uimanager->get_widget("/menubar/EngineMenu"))->get_submenu();
2598  menu->popup(2, gtk_get_current_event_time());
2599 }
2600 
2601 void MainWindow::overload_status_changed(gx_engine::MidiAudioBuffer::Load l) {
2602  switch (l) {
2604  status_icon->set(gx_head_midi);
2605  break;
2608  status_icon->set(gx_head_icon);
2609  break;
2611  status_icon->set(gx_head_warn);
2612  break;
2613  default:
2614  assert(false);
2615  }
2616 }
2617 
2618 bool MainWindow::on_window_state_changed(GdkEventWindowState* event) {
2619  if (event->changed_mask & event->new_window_state & (Gdk::WINDOW_STATE_ICONIFIED|Gdk::WINDOW_STATE_WITHDRAWN)) {
2620  window->get_window()->get_root_origin(options.mainwin_x, options.mainwin_y);
2621  }
2622  return false;
2623 }
2624 
2625 void MainWindow::hide_extended_settings() {
2626  if (!is_visible ||
2627  (window->get_window()->get_state()
2628  & (Gdk::WINDOW_STATE_ICONIFIED|Gdk::WINDOW_STATE_WITHDRAWN))) {
2629  window->move(options.mainwin_x, options.mainwin_y);
2630  window->present();
2631  //window->deiconify();
2632  } else {
2633  window->hide();
2634  //window->iconify();
2635  }
2636 }
2637 
2638 //bool MainWindow::ui_sleep() {
2639 // usleep(1900);
2640  //cout<<"timeout"<<endl;
2641 // return true;
2642 //}
2643 
2645  int port = options.get_rpcport();
2646  if (machine.get_jack() && port != RPCPORT_DEFAULT && port != RPCPORT_NONE) {
2647  machine.start_socket(sigc::ptr_fun(Gtk::Main::quit), options.get_rpcaddress(), port);
2648  window->show();
2649  if (options.get_liveplaygui()) liveplay_button->set_active();
2650  Gtk::Main::run();
2651  } else {
2652  window->show();
2653  if (options.get_liveplaygui()) liveplay_button->set_active();
2654  // Glib::signal_timeout().connect (mem_fun (*this, &MainWindow::ui_sleep), 2);
2655  Gtk::Main::run();
2656  }
2657 }
2658 
2659 bool MainWindow::on_meter_button_release(GdkEventButton* ev) {
2660  if (ev->button == 1) {
2661  for (unsigned int i = 0; i < sizeof(fastmeter)/sizeof(fastmeter[0]); i++) {
2662  fastmeter[i]->clear();
2663  }
2664  return true;
2665  }
2666  return false;
2667 }
2668 
2669 void MainWindow::display_preset_msg(const Glib::ustring& bank, const Glib::ustring& preset) {
2670  preset_status->set_text(bank + " / " + preset);
2671 }
2672 
2673 bool MainWindow::on_key_press_event(GdkEventKey *event) {
2674  if ((event->state & Gtk::AccelGroup::get_default_mod_mask()) != 0) {
2675  return false;
2676  }
2677  if (event->keyval >= GDK_KEY_0 && event->keyval <= GDK_KEY_9) {
2678  keyswitch.process_preset_key(event->keyval - GDK_KEY_0);
2679  return true;
2680  }
2681  if (event->keyval >= GDK_KEY_KP_0 && event->keyval <= GDK_KEY_KP_9) {
2682  keyswitch.process_preset_key(event->keyval - GDK_KEY_KP_0);
2683  return true;
2684  }
2685  if (event->keyval >= GDK_KEY_a && event->keyval <= GDK_KEY_z) {
2686  keyswitch.process_bank_key(event->keyval - GDK_KEY_a);
2687  return true;
2688  }
2689  return false;
2690 }
2691 
2692 bool MainWindow::on_quit() {
2693  if (ladspalist_window && !ladspalist_window->check_exit()) {
2694  return true;
2695  }
2696  machine.stop_socket();
2697  Gtk::Main::quit();
2698  return false;
2699 }
2700 
2701 void MainWindow::amp_controls_visible(Gtk::Range *rr) {
2702  //FIXME
2703  bool v = std::abs(rr->get_value() - machine.get_parameter("tube.select").getUpperAsFloat()) < 0.5;
2704  const char *knobs1[] = {"gxmediumknobpregain","gxmediumknobdrive","gxmediumknobdist","gxmediumknobgain", "labelpregain:effekt_label", "labeldrive:effekt_label", "labeldist:effekt_label", "labelgain:effekt_label"};
2705  const char *knobs2[] = {"gxbigknobgain", "labelgain2:effekt_label"};
2706  for (unsigned int i = 0; i < sizeof(knobs1)/sizeof(knobs1[1]); ++i) {
2707  Gtk::Widget *w;
2708  bld->find_widget(knobs1[i], w);
2709  w->set_visible(!v);
2710  }
2711  for (unsigned int i = 0; i < sizeof(knobs2)/sizeof(knobs2[1]); ++i) {
2712  Gtk::Widget *w;
2713  bld->find_widget(knobs2[i], w);
2714  w->set_visible(v);
2715  }
2716 }
2717 
2719  Gtk::Window *splash, const Glib::ustring& title)
2720  : sigc::trackable(),
2721  options(options_),
2722  machine(machine_),
2723  bld(),
2724  freezer(),
2725  plugin_dict(),
2726  oldpos(0),
2727  scrl_size_x(-1),
2728  scrl_size_y(-1),
2729  monorackcontainer(PLUGIN_TYPE_MONO, *this),
2730  stereorackcontainer(PLUGIN_TYPE_STEREO, *this),
2731  pre_act(false),
2732  is_visible(false),
2733  drag_icon(0),
2734  preset_list_menu_bank(),
2735  preset_list_merge_id(0),
2736  preset_list_actiongroup(),
2737  uimanager(),
2738  live_play(),
2739  preset_window(),
2740  fWaveView(),
2741  convolver_filename_label(),
2742  convolver_mono_filename_label(),
2743  gx_head_icon(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("gx_head.png"))),
2744  boxbuilder(machine_, fWaveView, convolver_filename_label, convolver_mono_filename_label, gx_head_icon),
2745  portmap_window(0),
2746  select_jack_control(0),
2747  fLoggingWindow(),
2748  amp_radio_menu(machine_, "tube.select"),
2749  pixbuf_insert_on(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("insert_on.png"))),
2750  pixbuf_insert_off(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("insert_off.png"))),
2751  pixbuf_on(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("gx_on.png"))),
2752  pixbuf_off(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("gx_off.png"))),
2753  pixbuf_bypass(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("gx_bypass.png"))),
2754  pixbuf_jack_connected(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("jackd_on.png"))),
2755  pixbuf_jack_disconnected(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("jackd_off.png"))),
2756  pixbuf_log_grey(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("gx_log_grey.png"))),
2757  pixbuf_log_yellow(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("gx_log_yellow.png"))),
2758  pixbuf_log_red(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("gx_log_red.png"))),
2759  in_session(false),
2760  status_icon(Gtk::StatusIcon::create(gx_head_icon)),
2761  gx_head_midi(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("gx_head-midi.png"))),
2762  gx_head_warn(Gdk::Pixbuf::create_from_file(options.get_pixmap_filepath("gx_head-warn.png"))),
2763  actions(),
2764  keyswitch(machine, sigc::mem_fun(this, &MainWindow::display_preset_msg)),
2765  groupmap(),
2766  ladspalist_window(),
2767  szg_rack_units(Gtk::SizeGroup::create(Gtk::SIZE_GROUP_HORIZONTAL)) {
2768 
2769  convolver_filename_label.set_ellipsize(Pango::ELLIPSIZE_END);
2770  convolver_mono_filename_label.set_ellipsize(Pango::ELLIPSIZE_END);
2771 
2772  /*
2773  ** create actions and some parameters
2774  */
2775  create_actions();
2776 
2777  /*
2778  ** load key accelerator table and glade window definition
2779  **
2780  ** at this point all parameters that are used in the main window glade file must be defined
2781  */
2782  Gtk::AccelMap::load(options.get_builder_filepath("accels_rc"));
2783 
2784  const char *id_list[] = { "MainWindow", "amp_background:ampbox", "bank_liststore", "target_liststore",
2785  "bank_combo_liststore", 0 };
2786  bld = gx_gui::GxBuilder::create_from_file(options_.get_builder_filepath("mainpanel.glade"), &machine, id_list);
2787  load_widget_pointers();
2788  rackcontainer->set_homogeneous(true); // setting it in glade is awkward to use with glade tool
2789  szg_rack_units->add_widget(*ampdetail_mini);
2790  szg_rack_units->add_widget(*ampdetail_normal);
2791 
2792  // remove marker labels from boxes (used in glade to make display clearer)
2793  clear_box(*monocontainer);
2794  clear_box(*stereorackcontainerH);
2795  clear_box(*stereorackcontainerV);
2796  clear_box(*preset_box_no_rack);
2797 
2798  // create left column for equal width
2799  left_column = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2800  Gtk::ScrolledWindow *swe;
2801  bld->find_widget("scrolledwindow_effects", swe);
2802  gtk_size_group_add_widget(left_column, GTK_WIDGET(swe->gobj()));
2803  Gtk::Button *pb;
2804  bld->find_widget("presets:barbutton", pb);
2805  gtk_size_group_add_widget(left_column, GTK_WIDGET(pb->gobj()));
2806 
2807  // preset window also creates some actions
2808  preset_window = new PresetWindow(bld, machine, options, actions, left_column);
2809 
2810  // create uimanager and load menu
2811  uimanager = Gtk::UIManager::create();
2812  uimanager->insert_action_group(actions.group);
2813  uimanager->add_ui_from_file(options.get_builder_filepath("menudef.xml"));
2814 
2815  // add dynamic submenus
2816  if (!options.get_clear_rc()) {
2817  add_skin_menu();
2818  }
2819  add_latency_menu();
2820  add_osc_size_menu();
2821  amp_radio_menu.setup("<menubar><menu action=\"TubeMenu\">","</menu></menubar>",uimanager,actions.group);
2822 
2823  // add menubar, accelgroup and icon to main window
2824  Gtk::Widget *menubar = uimanager->get_widget("/menubar");
2825  actions.accels = uimanager->get_accel_group();
2826  menubox->pack_start(*menubar);
2827  window->add_accel_group(actions.accels);
2828  window->set_icon(gx_head_icon);
2829  boxbuilder.set_accelgroup(actions.accels);
2830 
2831  /*
2832  ** connect main window signals
2833  */
2834  window->signal_window_state_event().connect(
2835  sigc::mem_fun(*this, &MainWindow::on_window_state_changed));
2836  window->signal_delete_event().connect(
2837  sigc::hide(sigc::mem_fun(this, &MainWindow::on_quit)));
2838  window->signal_configure_event().connect_notify(
2839  sigc::mem_fun(*this, &MainWindow::on_configure_event));
2840  window->signal_visibility_notify_event().connect(
2841  sigc::mem_fun(*this, &MainWindow::on_visibility_notify));
2842  window->signal_key_press_event().connect(
2843  sigc::mem_fun(*this, &MainWindow::on_key_press_event));
2844 
2845  /*
2846  ** status icon signal connections
2847  */
2848  status_icon->signal_activate().connect(
2849  sigc::mem_fun(*this, &MainWindow::hide_extended_settings));
2850  status_icon->signal_popup_menu().connect(
2851  sigc::mem_fun(*this, &MainWindow::systray_menu));
2852 
2853  // add rack container
2854  stereorackcontainerV->pack_start(stereorackcontainer, Gtk::PACK_EXPAND_WIDGET);
2855  monocontainer->pack_start(monorackcontainer, Gtk::PACK_EXPAND_WIDGET);
2856 
2857  /*
2858  ** jack, engine, and controller_map signal connections and related settings
2859  */
2861  gx_jack::GxJack *jack = machine.get_jack();
2862  if (jack) {
2863  jack->shutdown.connect(sigc::mem_fun(*this, &MainWindow::gx_jack_is_down));
2864  jack->signal_buffersize_change().connect(
2865  sigc::mem_fun(*this, &MainWindow::set_latency));
2866  jack->signal_client_change().connect(
2867  sigc::mem_fun(*this, &MainWindow::on_jack_client_changed));
2868 #ifdef HAVE_JACK_SESSION
2869  jack->session.connect(sigc::mem_fun(*this, &MainWindow::jack_session_event));
2870  jack->session_ins.connect(sigc::mem_fun(*this, &MainWindow::jack_session_event_ins));
2871  if (!options.get_jack_uuid().empty()) {
2872  set_in_session();
2873  }
2874 #endif
2875  }
2876 
2877  machine.signal_state_change().connect(
2878  sigc::mem_fun(*this, &MainWindow::on_engine_state_change));
2879  machine.signal_jack_load_change().connect(
2880  sigc::mem_fun(*this, &MainWindow::overload_status_changed));
2881  machine.signal_plugin_changed().connect(
2882  sigc::mem_fun(this, &MainWindow::on_plugin_changed));
2883  /*
2884  ** GxSettings signal connections
2885  */
2886  machine.signal_presetlist_changed().connect(
2887  sigc::mem_fun(*this, &MainWindow::rebuild_preset_menu));
2888  machine.signal_selection_changed().connect(
2889  sigc::mem_fun(*this, &MainWindow::show_selected_preset));
2890  machine.signal_selection_changed().connect(
2891  sigc::mem_fun(monorackcontainer, &RackContainer::check_order));
2892  machine.signal_selection_changed().connect(
2893  sigc::mem_fun(stereorackcontainer, &RackContainer::check_order));
2894 
2895  /*
2896  ** DnD setup for effects toolpalette
2897  */
2898  std::vector<Gtk::TargetEntry> listTargets;
2899  listTargets.push_back(Gtk::TargetEntry("application/x-guitarix-mono", Gtk::TARGET_SAME_APP, 1));
2900  listTargets.push_back(Gtk::TargetEntry("application/x-guitarix-stereo", Gtk::TARGET_SAME_APP, 2));
2901  effects_toolpalette->drag_dest_set(listTargets, Gtk::DEST_DEFAULT_ALL, Gdk::ACTION_MOVE);
2902  effects_toolpalette->signal_drag_data_received().connect(sigc::mem_fun(*this, &MainWindow::on_tp_drag_data_received));
2903 
2904  /*
2905  ** init jack connection image widget
2906  */
2907  if (jack) {
2908  jackd_image->set(pixbuf_jack_disconnected);
2909  jackd_image->get_parent()->add_events(Gdk::SCROLL_MASK);
2910  jackd_image->get_parent()->signal_button_press_event().connect(
2911  sigc::mem_fun(*this, &MainWindow::on_jackserverconnection));
2912  jackd_image->get_parent()->signal_scroll_event().connect(
2913  sigc::mem_fun(*this, &MainWindow::on_jackserverconnection_scroll));
2914  //jackd_image->get_parent()->signal_button_press_event().connect(
2915  // sigc::bind_return(
2916  // sigc::group(
2917  // sigc::ptr_fun(toggle_action),
2918  // actions.jackserverconnection),
2919  // true));
2920  } else {
2921  jackd_image->hide();
2922  }
2923 
2924  /*
2925  ** setup racktuner parameter and signals
2926  */
2927  setup_tuner(*racktuner);
2928  tuner_on_off->set_name("effect_on_off");
2929  tuner_on_off->signal_toggled().connect(
2930  sigc::compose(
2931  sigc::mem_fun(*racktuner, &Gxw::RackTuner::set_sensitive),
2932  sigc::mem_fun(*tuner_on_off, &Gxw::Switch::get_active)));
2933  racktuner->signal_poll_status_changed().connect(
2934  sigc::mem_fun(machine, &gx_engine::GxMachineBase::tuner_used_for_display));
2935 
2936  /*
2937  ** oscilloscope signal connections
2938  */
2939  machine.signal_oscilloscope_post_pre().connect(
2940  sigc::mem_fun(*this, &MainWindow::on_oscilloscope_post_pre));
2941  machine.signal_oscilloscope_visible().connect(
2942  sigc::mem_fun(*this, &MainWindow::on_show_oscilloscope));
2943  machine.signal_oscilloscope_activation().connect(
2944  sigc::mem_fun(*this, &MainWindow::on_oscilloscope_activate));
2945  machine.signal_oscilloscope_size_change().connect(
2946  sigc::mem_fun(*this, &MainWindow::set_waveview_buffer));
2947 
2948  /*
2949  ** fastmeter initialization and signal connections
2950  */
2951  for (unsigned int i = 0; i < sizeof(fastmeter)/sizeof(fastmeter[0]); ++i) {
2952  fastmeter[i]->signal_button_release_event().connect(
2953  sigc::mem_fun(*this, &MainWindow::on_meter_button_release));
2954  fastmeter[i]->set_tooltip_text(_("Overall Rack output"));
2955  }
2956  const float meter_falloff = 27; // in dB/sec.
2957  const float meter_display_timeout = 60; // in millisec
2958  const float falloff = meter_falloff * meter_display_timeout * 0.001;
2959  Glib::signal_timeout().connect(
2960  sigc::bind(sigc::mem_fun(this, &MainWindow::refresh_meter_level), falloff),
2961  meter_display_timeout);
2962 
2963  /*
2964  ** amp top box signal connections
2965  */
2966  ampdetail_compress->signal_clicked().connect(
2967  sigc::bind(sigc::mem_fun(*this, &MainWindow::on_ampdetail_switch), true, true));
2968  ampdetail_expand->signal_clicked().connect(
2969  sigc::bind(sigc::mem_fun(*this, &MainWindow::on_ampdetail_switch), false, true));
2970  machine.signal_parameter_value<bool>("ui.mp_s_h").connect(
2971  sigc::bind(sigc::mem_fun(*this, &MainWindow::on_ampdetail_switch), false));
2972 
2973  /*
2974  ** midi out signal connections
2975  */
2976  midi_out_compress->signal_clicked().connect(
2977  sigc::bind(
2978  sigc::mem_fun(actions.midi_out_plug.operator->(), &Gtk::ToggleAction::set_active),
2979  true));
2980  midi_out_expand->signal_clicked().connect(
2981  sigc::bind(
2982  sigc::mem_fun(actions.midi_out_plug.operator->(), &Gtk::ToggleAction::set_active),
2983  false));
2984  midi_out_presets_mini->signal_clicked().connect(
2985  sigc::bind(
2986  sigc::mem_fun1(this, &MainWindow::plugin_preset_popup),
2987  machine.pluginlist_lookup_plugin("midi_out")->get_pdef()));
2988  midi_out_presets_normal->signal_clicked().connect(
2989  sigc::bind(
2990  sigc::mem_fun1(this, &MainWindow::plugin_preset_popup),
2991  machine.pluginlist_lookup_plugin("midi_out")->get_pdef()));
2992  channel1_button->signal_toggled().connect(
2993  sigc::bind(
2994  sigc::mem_fun(this, &MainWindow::on_midi_out_channel_toggled),
2995  channel1_button, channel1_box));
2996  channel2_button->signal_toggled().connect(
2997  sigc::bind(
2998  sigc::mem_fun(this, &MainWindow::on_midi_out_channel_toggled),
2999  channel2_button, channel2_box));
3000  channel3_button->signal_toggled().connect(
3001  sigc::bind(
3002  sigc::mem_fun(this, &MainWindow::on_midi_out_channel_toggled),
3003  channel3_button, channel3_box));
3004 
3005  /*
3006  ** init status image widget
3007  */
3008  status_image->set(pixbuf_on);
3009  status_image->get_parent()->add_events(Gdk::SCROLL_MASK);
3010  gx_gui::connect_midi_controller(status_image->get_parent(), "engine.mute", machine);
3011  status_image->get_parent()->signal_button_press_event().connect(
3012  sigc::mem_fun(*this, &MainWindow::on_toggle_mute));
3013  status_image->get_parent()->signal_scroll_event().connect(
3014  sigc::mem_fun(*this, &MainWindow::on_scroll_toggle));
3015  on_engine_state_change(machine.get_state());
3016 
3017  /*
3018  ** init insert image widget
3019  */
3020  insert_image->set(pixbuf_insert_on);
3021  insert_image->get_parent()->add_events(Gdk::SCROLL_MASK);
3022  gx_gui::connect_midi_controller(insert_image->get_parent(), "engine.insert", machine);
3023  insert_image->get_parent()->signal_button_press_event().connect(
3024  sigc::mem_fun(*this, &MainWindow::on_toggle_insert));
3025  insert_image->get_parent()->signal_scroll_event().connect(
3026  sigc::mem_fun(*this, &MainWindow::on_scroll_toggle_insert));
3027  gx_engine::BoolParameter& ip = machine.get_parameter("engine.insert").getBool();
3028  ip.signal_changed().connect(sigc::mem_fun(*this, &MainWindow::on_insert_jack_changed));
3029 
3030  /*
3031  ** connect buttons with actions
3032  */
3033  gtk_activatable_set_related_action(GTK_ACTIVATABLE(show_rack_button->gobj()), GTK_ACTION(actions.show_rack->gobj()));
3034  gtk_activatable_set_related_action(GTK_ACTIVATABLE(rack_order_h_button->gobj()), GTK_ACTION(actions.rackh->gobj()));
3035  gtk_activatable_set_related_action(GTK_ACTIVATABLE(config_mode_button->gobj()), GTK_ACTION(actions.rack_config->gobj()));
3036  gtk_activatable_set_related_action(GTK_ACTIVATABLE(liveplay_button->gobj()),GTK_ACTION(actions.live_play->gobj()));
3037  gtk_activatable_set_related_action(GTK_ACTIVATABLE(tuner_button->gobj()),GTK_ACTION(actions.tuner->gobj()));
3038  gtk_activatable_set_related_action(GTK_ACTIVATABLE(effects_button->gobj()), GTK_ACTION(actions.show_plugin_bar->gobj()));
3039  gtk_activatable_set_related_action(GTK_ACTIVATABLE(presets_button->gobj()), GTK_ACTION(actions.presets->gobj()));
3040  gtk_activatable_set_related_action(GTK_ACTIVATABLE(compress_button->gobj()), GTK_ACTION(actions.compress->gobj()));
3041  gtk_activatable_set_related_action(GTK_ACTIVATABLE(expand_button->gobj()), GTK_ACTION(actions.expand->gobj()));
3042 
3043  /*
3044  ** setup window initial configuration
3045  */
3046  tunerbox->set_visible(machine.get_parameter_value<bool>("system.show_tuner"));
3047  racktuner->set_sensitive(machine.get_parameter_value<bool>("ui.racktuner"));
3048  actions.show_plugin_bar->set_active(false);
3049 
3050  /*
3051  ** create liveplay and setup liveplay racktuner
3052  */
3053  live_play = new Liveplay(options, machine, options.get_builder_filepath("mainpanel.glade"), actions);
3054  setup_tuner(live_play->get_tuner());
3055  live_play->get_tuner().signal_poll_status_changed().connect(
3056  sigc::mem_fun1(machine, &gx_engine::GxMachineBase::tuner_used_for_display));
3057 
3058  /*
3059  ** init logging window and logstate image widget
3060  */
3061  fLoggingWindow.set_transient_for(*window);
3062  fLoggingWindow.set_icon(gx_head_icon);
3063  fLoggingWindow.signal_msg_level_changed().connect(
3064  sigc::mem_fun(*this, &MainWindow::on_msg_level_changed));
3065  fLoggingWindow.signal_hide().connect(
3066  sigc::bind(
3067  sigc::mem_fun(actions.loggingbox.operator->(), &Gtk::ToggleAction::set_active),
3068  false));
3069  on_msg_level_changed();
3070  logstate_image->get_parent()->add_events(Gdk::SCROLL_MASK);
3071  logstate_image->get_parent()->signal_button_press_event().connect(
3072  sigc::mem_fun(*this, &MainWindow::on_log_activated));
3073  logstate_image->get_parent()->signal_scroll_event().connect(
3074  sigc::mem_fun(*this, &MainWindow::on_log_scrolled));
3075 
3076  //logstate_image->get_parent()->signal_button_press_event().connect(
3077  //sigc::bind_return(
3078  // sigc::group(
3079  // sigc::ptr_fun(toggle_action),
3080  // actions.loggingbox),
3081  // true));
3082 
3083  /*
3084  ** load plugin definitions into plugin_dict, add to effects_toolpalette
3085  **
3086  ** icons will be added after state loading when we know the skin
3087  ** UI definitions will be loaded on demand
3088  */
3089  fill_pluginlist();
3090  PluginUI *mainamp_plugin = new PluginUI(*this, "ampstack");
3091  plugin_dict.add(mainamp_plugin);
3092  mainamp_plugin->rackbox = add_rackbox_internal(*mainamp_plugin, 0, 0, false, -1, false, amp_background);
3093  //effects_toolpalette->set_name("effects_toolpalette");
3094  effects_toolpalette->show();
3095  if (!options.get_clear_rc()) {
3096  //g_object_set (gtk_settings_get_default (),"gtk-theme-name",NULL, NULL);
3097  set_new_skin(options.skin_name);
3098  } else {
3099  gtk_rc_parse(
3100  (options.get_style_filepath("clear.rc")).c_str());
3101  make_icons();
3102  }
3103 
3104  // call some action functions to sync state
3105  // with settings defined in create_actions()
3106  actions.rackh->set_active(options.system_order_rack_h);
3107  actions.presets->set_active(options.system_show_presets);
3108  actions.show_plugin_bar->set_active(options.system_show_toolbar);
3109  actions.show_rack->set_active(options.system_show_rack);
3110  actions.show_values->set_active(options.system_show_value);
3111  actions.tooltips->set_active(options.system_show_tooltips);
3112  actions.animations->set_active(options.system_animations);
3113 
3114  if (!title.empty()) {
3115  window->set_title(title);
3116  }
3117 
3118  /*
3119  ** Jack client connection and subsequent initalizations
3120  */
3121 
3122  // state must be loaded before starting jack because connect_jack() uses
3123  // some settings. If the jack client name changes (from the predefined value)
3124  // on connect the jack client-change signal will trigger the load of another
3125  // state file, which means that the jack starter options are read from the
3126  // standard state file (gx_head_rc or similar if -n is used)
3127  machine.loadstate();
3128  if (!in_session) {
3129  machine.disable_autosave(options.get_opt_save_on_exit());
3130  }
3131  if (!connect_jack(true, splash)) {
3132  // not connected, must synthesize signal for initialization
3133  if (jack) {
3134  jack->signal_client_change()();
3135  }
3136  }
3137  set_latency(); // make sure latency menu is updated
3138  set_osc_size();
3139 
3140  if (options.mainwin_height > 0) { // initially use the default set in mainpanel.glade
3141  window->set_default_size(-1, min(options.window_height, options.mainwin_height));
3142  }
3143 
3144  // set window position (make this optional??)
3145  if (options.mainwin_x > 0) {
3146  window->move(options.mainwin_x, options.mainwin_y);
3147  }
3148 
3149  Gtk::Range *rr;
3150  bld->find_widget("gxselector1:amp_selector", rr);
3151  rr->signal_value_changed().connect(
3152  sigc::bind(
3153  sigc::mem_fun(this, &MainWindow::amp_controls_visible),
3154  rr));
3155  amp_controls_visible(rr);
3156 
3157  // set insert_image state
3158  if (machine.get_parameter_value<bool>("engine.insert")) {
3159  insert_image->set(pixbuf_insert_off);
3160  machine.set_jack_insert(true);
3161  } else {
3162  insert_image->set(pixbuf_insert_on);
3163  machine.set_jack_insert(false);
3164  }
3165  if (!options.get_tuner_tet().empty()) set_tuner_tet(*racktuner);
3166 
3167  }
3168 
3170 #if false // set true to generate a new keyboard accel file
3171  gtk_accel_map_add_filter("<Actions>/Main/ChangeSkin_*");
3172  gtk_accel_map_add_filter("<Actions>/Main/Enum_tube.select.*");
3173  gtk_accel_map_add_filter("<Actions>/Main/Latency_*");
3174  gtk_accel_map_add_filter("<Actions>/Main/Plugin_*");
3175  gtk_accel_map_add_filter("<Actions>/PresetList/PresetList_*");
3176  Gtk::AccelMap::save(options.get_user_filepath("accels_rc"));
3177 #endif
3178 
3179  int mainwin_width;
3180  window->get_size(mainwin_width, options.mainwin_height);
3181  Glib::RefPtr<Gdk::Window> win = window->get_window();
3182  if (win) {
3183  win->get_root_origin(options.mainwin_x, options.mainwin_y);
3184  }
3185  if (actions.presets->get_active()) {
3186  options.preset_window_height = preset_scrolledbox->get_allocation().get_height();
3187  }
3188  plugin_dict.cleanup();
3189  delete live_play;
3190  delete preset_window;
3191  delete window;
3192  window = 0;
3193  //if (ladspalist_window) {
3194  //delete ladspalist_window;
3195  //ladspalist_window = 0;
3196  //}
3197 }
iterator end()
Definition: gx_json.h:366
virtual GxEngineState get_state()=0
virtual gx_system::PresetFileGui * get_current_bank_file()=0
void gx_print_info(const char *, const std::string &)
Definition: gx_logging.cpp:183
void check_order()
Definition: rack.cpp:1632
virtual float getLowerAsFloat() const
void cleanup()
Definition: rack.cpp:213
CmdConnection::msg_type start
Definition: jsonrpc.cpp:255
void set_jack_down(bool v)
Definition: gx_jack.h:188
double stop_at_mono_top(double off, double step_size)
#define GDK_KEY_Escape
Definition: guitarix.h:53
void set_streaming(bool p1)
Definition: racktuner.cc:290
Glib::RefPtr< Gtk::ToggleAction > get_action()
virtual sigc::signal< void, int > & signal_oscilloscope_post_pre()=0
PluginDef * get_pdef()
void set_display_flat(bool p1)
Definition: racktuner.cc:300
Glib::RefPtr< UiBoolToggleAction > midi_out_plug
void freeze_and_size_request(Gtk::Window *w, int width, int height)
void add_icon(const std::string &name)
#define RPCPORT_DEFAULT
Definition: gx_system.h:350
std::string get_builder_filepath(const std::string &basename) const
Definition: gx_system.h:373
virtual sigc::signal< void, GxEngineState > & signal_state_change()=0
static Glib::RefPtr< UiToggleAction > create(gx_engine::GxMachineBase &machine, const std::string &id, const Glib::ustring &name, const Glib::ustring &label=Glib::ustring(), const Glib::ustring &tooltip=Glib::ustring(), bool is_active=false)
virtual sigc::signal< void > & signal_presetlist_changed()=0
const char * get_name() const
virtual sigc::signal< void, bool > & signal_oscilloscope_visible()=0
void display(bool v, bool animate)
Definition: rack.cpp:137
int operator()()
#define GDK_KEY_9
Definition: guitarix.h:48
const char * value_id
Definition: gx_plugin.h:118
virtual Parameter & get_parameter(const std::string &id)=0
void set_temperament(int p1)
Definition: racktuner.cc:330
bool get_box_visible()
void set_ui_merge_id(Gtk::UIManager::ui_merge_id id)
Glib::ustring tooltip
#define N_(String)
GxJackLatencyChange
Glib::ustring skin_name
Definition: gx_system.h:445
virtual void set_state(GxEngineState state)=0
int gx_system_call(const std::string &, bool devnull=false, bool escape=false)
Definition: gx_system.cpp:950
static void rt_watchdog_set_limit(int limit)
Definition: gx_jack.cpp:146
bool get_on_off() const
static bool is_registered(gx_engine::GxMachineBase &m, const char *name)
Definition: rack.cpp:86
Glib::RefPtr< Gtk::ToggleAction > show_values
virtual sigc::signal< void, unsigned int > & signal_oscilloscope_size_change()=0
Glib::RefPtr< Gdk::Pixbuf > icon
void plugin_preset_popup(const PluginDef *pdef)
GxUiRadioMenu(gx_engine::GxMachineBase &machine, const std::string &id)
virtual void set_init_values()=0
bool check_thaw(int width, int height)
void set_reference_pitch(double p1)
Definition: tuner.cc:137
GtkSizeGroup * left_column
virtual void tuner_used_for_display(bool on)=0
Glib::RefPtr< Gtk::ToggleAction > tooltips
virtual gx_jack::GxJack * get_jack()=0
jack_nframes_t get_jack_bs()
Definition: gx_jack.h:179
std::vector< Position >::iterator iterator
Definition: gx_json.h:321
Glib::RefPtr< Gtk::ToggleAction > rackh
void set_freq(double p1)
Definition: racktuner.cc:265
void hide_effect(const std::string &name)
UiToggleAction(gx_engine::GxMachineBase &machine_, const std::string &id, const Glib::ustring &name, const Glib::ustring &icon_name, const Glib::ustring &label=Glib::ustring(), const Glib::ustring &tooltip=Glib::ustring(), bool is_active=false)
void pack(Gtk::Widget *mainbox, Gtk::Widget *minibox, const Glib::RefPtr< Gtk::SizeGroup > &szg)
Definition: rack.cpp:1221
virtual bool setting_is_preset()=0
std::string get_style_filepath(const std::string &basename) const
Definition: gx_system.h:461
double stop_at_stereo_bottom(double off, double step_size, double pagesize)
PluginDesc(const Glib::ustring &g, std::vector< PluginUI *> *p)
int get_idle_thread_timeout() const
Definition: gx_system.h:505
Glib::RefPtr< Gtk::ToggleAction > rack_config
Glib::RefPtr< Gtk::ToggleAction > show_rack
jack_client_t * client
Definition: gx_jack.h:171
static Gtk::Widget * create_icon_widget(const PluginUI &plugin, gx_system::CmdlineOptions &options)
Definition: rack.cpp:907
Glib::RefPtr< Gtk::ToggleAction > animations
void gx_print_error(const char *, const std::string &)
Definition: gx_logging.cpp:166
Gtk::ToolItemGroup * group
gx_engine::Plugin * plugin
#define RPCPORT_NONE
Definition: gx_system.h:351
Glib::RefPtr< Gtk::ActionGroup > group
static GxLogger & get_logger()
Definition: gx_logging.cpp:50
void update_width()
Glib::SignalProxy1< void, bool > signal_poll_status_changed()
Definition: racktuner.cc:357
Glib::RefPtr< Gtk::Action > expand
virtual bool load_unit(gx_gui::UiBuilderImpl &builder, PluginDef *pdef)=0
#define GDK_KEY_0
Definition: guitarix.h:46
void gx_show_about()
Glib::SignalProxy0< void > signal_frequency_poll()
Definition: racktuner.cc:351
float power2db(float power)
#define min(x, y)
bool is_jack_down()
Definition: gx_jack.h:208
void clear_notes()
Definition: racktuner.cc:340
T get_parameter_value(const std::string &id)
const char * id
Definition: gx_plugin.h:187
void animate_insert()
Definition: rack.cpp:1091
virtual const Glib::ustring & get_current_bank()=0
void show_forum_help()
#define max(x, y)
RackBox * add_rackbox(PluginUI &pl, bool mini=false, int pos=-1, bool animate=false)
sigc::signal< void > & signal_msg_level_changed()
sigc::signal< void, bool > & signal_changed()
Definition: gx_parameter.h:377
virtual float get_tuner_freq()=0
#define SYSTEM_OK
Definition: gx_system.h:81
MainWindow(gx_engine::GxMachineBase &machine, gx_system::CmdlineOptions &options, Gtk::Window *splash, const Glib::ustring &title)
static GxExit & get_instance()
Definition: gx_logging.cpp:205
PluginType get_type() const
static void toggle(gx_engine::GxMachineBase &machine, Glib::RefPtr< Gtk::ToggleAction > item)
const std::string & getIRFile() const
msg_signal & signal_message()
Definition: gx_logging.cpp:77
virtual sigc::signal< void, Plugin *, PluginChange::pc > & signal_plugin_changed()=0
JConvPluginUI(MainWindow &main, const char *id, const Glib::ustring &tooltip="")
virtual void set_parameter_value(const std::string &id, int value)=0
void set_action(Glib::RefPtr< Gtk::ToggleAction > &act)
Definition: rack.cpp:99
virtual sigc::signal< void > & signal_selection_changed()=0
std::string to_string(const T &t)
Definition: gx_system.h:525
std::vector< PluginUI * > * plugins
void add_plugin(std::vector< PluginUI *> &p, const char *id, const Glib::ustring &tooltip_="")
Glib::RefPtr< Gtk::ToggleAction > live_play
void connect_midi_controller(Gtk::Widget *w, const std::string &id, gx_engine::GxMachineBase &machine)
bool plugins_by_name_less(PluginUI *a, PluginUI *b)
Definition: rack.cpp:186
Glib::RefPtr< Gtk::AccelGroup > accels
Glib::ustring group
virtual void next_preset_switch()=0
void set_slot(sigc::slot< void > w)
Gtk::ToolItem * toolitem
bool get_opt_save_on_exit() const
Definition: gx_system.h:502
void unset_ui_merge_id(Glib::RefPtr< Gtk::UIManager > uimanager)
Definition: rack.cpp:75
void gx_print_warning(const char *, const std::string &)
Definition: gx_logging.cpp:161
Glib::RefPtr< UiBoolToggleAction > tuner
const Glib::ustring & get_tuner_tet()
Definition: gx_system.h:488
virtual void disable_autosave(bool v)=0
bool gx_start_jack_dialog(Glib::RefPtr< Gdk::Pixbuf > gw_ib)
void update_rackbox()
Definition: rack.cpp:164
void exit_program(std::string msg="", int errcode=1)
Definition: gx_logging.cpp:196
const string & get_instancename()
Definition: gx_jack.h:202
const GxJConvSettings & get_value() const
int main(int argc, char *argv[])
Definition: gxw_demo.cc:62
#define GDK_KEY_z
Definition: guitarix.h:63
void swtch(bool mini)
Definition: rack.cpp:1140
void add(PluginUI *p)
Definition: rack.cpp:203
void setup(const Glib::ustring &prefix, const Glib::ustring &postfix, Glib::RefPtr< Gtk::UIManager > &uimanager, Glib::RefPtr< Gtk::ActionGroup > &actiongroup)
static void start_stop(Glib::RefPtr< Gtk::ToggleAction > &action, gx_jack::GxJack &jack)
std::string get_user_filepath(const std::string &basename) const
Definition: gx_system.h:371
Glib::Dispatcher shutdown
Definition: gx_jack.h:207
void gx_show_help()
const char * get_id() const
IntParameter & getInt()
Definition: gx_parameter.h:458
Glib::RefPtr< Gtk::ToggleAction > presets
const Glib::ustring & get_jack_uuid() const
Definition: gx_system.h:496
virtual Plugin * pluginlist_lookup_plugin(const std::string &id) const =0
EnumParameter & getEnum()
Definition: gx_parameter.h:463
bool gx_jack_connection(bool connect, bool startserver, int wait_after_connect, const gx_system::CmdlineOptions &opt)
Definition: gx_jack.cpp:437
#define GDK_KEY_KP_9
Definition: guitarix.h:56
virtual void previus_preset_switch()=0
Glib::RefPtr< Gtk::ToggleAction > show_plugin_bar
virtual void set_jack_insert(bool v)=0
void push_note(int p1, int p2, int p3)
Definition: racktuner.cc:345
virtual const Glib::ustring & get_current_name()=0
void set_on_off(bool v) const
Gxw::RackTuner & get_tuner()
bool get_clear_rc() const
Definition: gx_system.h:483
const char * get_category()
virtual sigc::signal< int, bool > & signal_oscilloscope_activation()=0
static const char * value_label(const value_pair &vp)
Definition: gx_parameter.h:199
virtual bool midi_get_config_mode(int *ctl=0)=0
sigc::signal< void, T > & signal_parameter_value(const std::string &id)
BoolParameter & getBool()
Definition: gx_parameter.h:469
void update_scrolled_window(Gtk::ScrolledWindow &w)
const string & id() const
Definition: gx_parameter.h:173
int gx_message_popup(const char *)
void resize_finished(RackContainer *ch)
const value_pair & get_pair()
Definition: gx_parameter.h:340
#define GDK_KEY_a
Definition: guitarix.h:49
RackBox * rackbox
void set_accelgroup(Glib::RefPtr< Gtk::AccelGroup > accels_)
virtual void loadstate()=0
#define GDK_KEY_KP_0
Definition: guitarix.h:54
void unplug_queue()
Definition: gx_logging.cpp:82
Glib::RefPtr< Gtk::Action > compress
Glib::RefPtr< Gtk::ToggleAction > loggingbox
static PortMapWindow * create(gx_engine::GxMachineBase &machine, Glib::RefPtr< Gtk::AccelGroup > ag)
Definition: gx_portmap.cpp:549
sigc::signal< void, MidiAudioBuffer::Load > & signal_jack_load_change()
Definition: machine.h:93
static SelectJackControlPgm * create(gx_system::CmdlineOptions &opt, gx_engine::GxMachineBase &machine)
void freeze_until_width_update(Gtk::Window *w, int width)
virtual const value_pair * getValueNames() const