OSC: Make Aux buses able to be separate.
[ardour.git] / libs / surfaces / osc / osc_gui.cc
1 /*
2     Copyright (C) 2016 Robin Gareus <robin@gareus.org
3     Copyright (C) 2009-2012 Paul Davis
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #include <iostream>
22 #include <list>
23 #include <string>
24 #include <vector>
25 //#include <glibmm/miscutils.h>
26
27 #include <errno.h>
28
29 #include "pbd/file_utils.h"
30
31 #include <gtkmm/box.h>
32 #include <gtkmm/notebook.h>
33 #include <gtkmm/table.h>
34 #include <gtkmm/label.h>
35 #include <gtkmm/button.h>
36 #include <gtkmm/spinbutton.h>
37 #include <gtkmm/comboboxtext.h>
38
39 #include "gtkmm2ext/gtk_ui.h"
40 #include "gtkmm2ext/gui_thread.h"
41 #include "gtkmm2ext/utils.h"
42
43 #include "ardour/filesystem_paths.h"
44
45 #include "osc.h"
46 #include "osc_gui.h"
47
48 #include "pbd/i18n.h"
49
50 using namespace PBD;
51 using namespace ARDOUR;
52 using namespace Gtk;
53 using namespace Gtkmm2ext;
54 using namespace ArdourSurface;
55
56 OSC_GUI::OSC_GUI (OSC& p)
57         : cp (p)
58 {
59         int n = 0; // table row
60         Table* table = manage (new Table);
61         Label* label;
62         Button* button;
63         table->set_row_spacings (10);
64         table->set_col_spacings (6);
65         table->set_border_width (12);
66         get_session ();
67         preset_busy = true;
68
69         // show our url
70         label = manage (new Gtk::Label(_("Connection:")));
71         label->set_alignment(1, .5);
72         table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
73         label = manage (new Gtk::Label(cp.get_server_url()));
74         table->attach (*label, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
75         ++n;
76
77         // show and set port to auto (default) or manual (one surface only)
78         label = manage (new Gtk::Label(_("Port Mode:")));
79         label->set_alignment(1, .5);
80         table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
81         table->attach (portmode_combo, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
82         std::vector<std::string> portmode_options;
83         portmode_options.push_back (_("Auto"));
84         portmode_options.push_back (_("Manual"));
85
86         set_popdown_strings (portmode_combo, portmode_options);
87         portmode_combo.set_active ((int)cp.get_portmode());
88         ++n;
89
90         // port entry box
91         label = manage (new Gtk::Label(_("Manual Port:")));
92         label->set_alignment(1, .5);
93         table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
94         table->attach (port_entry, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
95         port_entry.set_range(1024, 0xffff);
96         port_entry.set_increments (1, 100);
97         port_entry.set_text(cp.get_remote_port().c_str());
98         if (!cp.get_portmode()) {
99                 port_entry.set_sensitive (false);
100         }
101         ++n;
102
103         // default banksize setting
104         label = manage (new Gtk::Label(_("Bank Size:")));
105         label->set_alignment(1, .5);
106         table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
107         table->attach (bank_entry, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
108         bank_entry.set_range (0, 0xffff);
109         bank_entry.set_increments (1, 8);
110         bank_entry.set_value (cp.get_banksize());
111
112         ++n;
113
114         // Gain Mode
115         label = manage (new Gtk::Label(_("Gain Mode:")));
116         label->set_alignment(1, .5);
117         table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
118         table->attach (gainmode_combo, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
119         std::vector<std::string> gainmode_options;
120         gainmode_options.push_back (_("dB"));
121         gainmode_options.push_back (_("Position"));
122
123         set_popdown_strings (gainmode_combo, gainmode_options);
124         gainmode_combo.set_active ((int)cp.get_gainmode());
125         ++n;
126
127         // debug setting
128         label = manage (new Gtk::Label(_("Debug:")));
129         label->set_alignment(1, .5);
130         table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
131         table->attach (debug_combo, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
132
133         std::vector<std::string> debug_options;
134         debug_options.push_back (_("Off"));
135         debug_options.push_back (_("Log invalid messages"));
136         debug_options.push_back (_("Log all messages"));
137
138         set_popdown_strings (debug_combo, debug_options);
139         debug_combo.set_active ((int)cp.get_debug_mode());
140         ++n;
141
142         // Preset loader combo
143         label = manage (new Gtk::Label(_("Preset:")));
144         label->set_alignment(1, .5);
145         table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
146         table->attach (preset_combo, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
147
148         preset_files.clear();
149         // no files for these two
150         preset_options.push_back (_("Last Loaded Session"));
151         preset_options.push_back (_("Ardour Factory Setting"));
152         // user is special it appears in menu even if no file is present
153         preset_options.push_back ("User");
154         preset_files["User"] = "";
155         // scan for OSC .preset files
156         scan_preset_files ();
157
158         set_popdown_strings (preset_combo, preset_options);
159         preset_combo.set_active (0);
160         preset_combo.signal_changed().connect (sigc::mem_fun (*this, &OSC_GUI::preset_changed));
161         ++n;
162
163         // refresh button
164         button = manage (new Gtk::Button(_("Clear OSC Devices")));
165         table->attach (*button, 0, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 10);
166
167         table->show_all ();
168         append_page (*table, _("OSC Setup"));
169
170         debug_combo.signal_changed().connect (sigc::mem_fun (*this, &OSC_GUI::debug_changed));
171         portmode_combo.signal_changed().connect (sigc::mem_fun (*this, &OSC_GUI::portmode_changed));
172         gainmode_combo.signal_changed().connect (sigc::mem_fun (*this, &OSC_GUI::gainmode_changed));
173         button->signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::clear_device));
174         port_entry.signal_activate().connect (sigc::mem_fun (*this, &OSC_GUI::port_changed));
175         bank_entry.signal_activate().connect (sigc::mem_fun (*this, &OSC_GUI::bank_changed));
176
177         // Strip Types Calculate Page
178         int stn = 0; // table row
179         Table* sttable = manage (new Table);
180         sttable->set_row_spacings (8);
181         sttable->set_col_spacings (6);
182         sttable->set_border_width (25);
183
184         // show our url
185         label = manage (new Gtk::Label(_("Select Desired Types of Tracks")));
186         sttable->attach (*label, 0, 2, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
187         ++stn;
188
189         label = manage (new Gtk::Label(_("Strip Types Value:")));
190         label->set_alignment(1, .5);
191         sttable->attach (*label, 0, 1, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 15);
192         calculate_strip_types ();
193         current_strip_types.set_width_chars(10);
194         sttable->attach (current_strip_types, 1, 2, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 15);
195         ++stn;
196
197         label = manage (new Gtk::Label(_("Audio Tracks:")));
198         label->set_alignment(1, .5);
199         sttable->attach (*label, 0, 1, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
200         sttable->attach (audio_tracks, 1, 2, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
201         ++stn;
202
203         label = manage (new Gtk::Label(_("Midi Tracks:")));
204         label->set_alignment(1, .5);
205         sttable->attach (*label, 0, 1, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
206         sttable->attach (midi_tracks, 1, 2, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
207         ++stn;
208
209         label = manage (new Gtk::Label(_("Audio Buses:")));
210         label->set_alignment(1, .5);
211         sttable->attach (*label, 0, 1, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
212         sttable->attach (audio_buses, 1, 2, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
213         ++stn;
214
215         label = manage (new Gtk::Label(_("Audio Auxes:")));
216         label->set_alignment(1, .5);
217         sttable->attach (*label, 0, 1, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
218         sttable->attach (audio_auxes, 1, 2, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
219         ++stn;
220
221         label = manage (new Gtk::Label(_("Midi Buses:")));
222         label->set_alignment(1, .5);
223         sttable->attach (*label, 0, 1, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
224         sttable->attach (midi_buses, 1, 2, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
225         ++stn;
226
227         label = manage (new Gtk::Label(_("Control Masters:")));
228         label->set_alignment(1, .5);
229         sttable->attach (*label, 0, 1, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
230         sttable->attach (control_masters, 1, 2, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
231         ++stn;
232
233         label = manage (new Gtk::Label(_("Master (use /master instead):")));
234         label->set_alignment(1, .5);
235         sttable->attach (*label, 0, 1, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
236         sttable->attach (master_type, 1, 2, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
237         ++stn;
238
239         label = manage (new Gtk::Label(_("Monitor (use /monitor instead):")));
240         label->set_alignment(1, .5);
241         sttable->attach (*label, 0, 1, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
242         sttable->attach (monitor_type, 1, 2, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
243         ++stn;
244
245         label = manage (new Gtk::Label(_("Selected Tracks (use for selected tracks only):")));
246         label->set_alignment(1, .5);
247         sttable->attach (*label, 0, 1, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
248         sttable->attach (selected_tracks, 1, 2, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
249         ++stn;
250
251         label = manage (new Gtk::Label(_("Hidden Tracks:")));
252         label->set_alignment(1, .5);
253         sttable->attach (*label, 0, 1, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
254         sttable->attach (hidden_tracks, 1, 2, stn, stn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
255         ++stn;
256
257
258         sttable->show_all ();
259         append_page (*sttable, _("Default Strip Types"));
260
261
262         // Feedback Calculate Page
263         int fn = 0; // table row
264         Table* fbtable = manage (new Table);
265         fbtable->set_row_spacings (4);
266         fbtable->set_col_spacings (6);
267         fbtable->set_border_width (12);
268
269         // show our url
270         label = manage (new Gtk::Label(_("Select Desired Types of Feedback")));
271         fbtable->attach (*label, 0, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
272         ++fn;
273
274         label = manage (new Gtk::Label(_("Feedback Value:")));
275         label->set_alignment(1, .5);
276         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 15);
277         calculate_feedback ();
278         current_feedback.set_width_chars(10);
279         fbtable->attach (current_feedback, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 15);
280         ++fn;
281
282         label = manage (new Gtk::Label(_("Strip Buttons:")));
283         label->set_alignment(1, .5);
284         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
285         fbtable->attach (strip_buttons_button, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
286         ++fn;
287
288         label = manage (new Gtk::Label(_("Strip Controls:")));
289         label->set_alignment(1, .5);
290         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
291         fbtable->attach (strip_control_button, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
292         ++fn;
293
294         label = manage (new Gtk::Label(_("Use SSID as Path Extension:")));
295         label->set_alignment(1, .5);
296         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
297         fbtable->attach (ssid_as_path, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
298         ++fn;
299
300         label = manage (new Gtk::Label(_("Use Heart Beat:")));
301         label->set_alignment(1, .5);
302         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
303         fbtable->attach (heart_beat, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
304         ++fn;
305
306         label = manage (new Gtk::Label(_("Master Section:")));
307         label->set_alignment(1, .5);
308         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
309         fbtable->attach (master_fb, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
310         ++fn;
311
312         label = manage (new Gtk::Label(_("Play Head Position as Bar and Beat:")));
313         label->set_alignment(1, .5);
314         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
315         fbtable->attach (bar_and_beat, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
316         ++fn;
317
318         label = manage (new Gtk::Label(_("Play Head Position as SMPTE Time:")));
319         label->set_alignment(1, .5);
320         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
321         fbtable->attach (smpte, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
322         ++fn;
323
324         label = manage (new Gtk::Label(_("Metering as a Float:")));
325         label->set_alignment(1, .5);
326         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
327         fbtable->attach (meter_float, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
328         ++fn;
329
330         label = manage (new Gtk::Label(_("Metering as a LED Strip:")));
331         label->set_alignment(1, .5);
332         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
333         fbtable->attach (meter_led, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
334         ++fn;
335
336         label = manage (new Gtk::Label(_("Signal Present:")));
337         label->set_alignment(1, .5);
338         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
339         fbtable->attach (signal_present, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
340         ++fn;
341
342         label = manage (new Gtk::Label(_("Play Head Position as Samples:")));
343         label->set_alignment(1, .5);
344         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
345         fbtable->attach (hp_samples, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
346         ++fn;
347
348         label = manage (new Gtk::Label(_("Playhead Position as Minutes Seconds:")));
349         label->set_alignment(1, .5);
350         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
351         fbtable->attach (hp_min_sec, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
352         ++fn;
353
354         label = manage (new Gtk::Label(_("Playhead Position as per GUI Clock:")));
355         label->set_alignment(1, .5);
356         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
357         fbtable->attach (hp_gui, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
358         hp_gui.set_sensitive (false); // we don't have this yet (Mixbus wants)
359         ++fn;
360
361         label = manage (new Gtk::Label(_("Extra Select Only Feedback:")));
362         label->set_alignment(1, .5);
363         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
364         fbtable->attach (select_fb, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
365         ++fn;
366
367         fbtable->show_all ();
368         append_page (*fbtable, _("Default Feedback"));
369         // set strips and feedback from loaded default values
370         reshow_values ();
371         // connect signals
372         audio_tracks.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
373         midi_tracks.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
374         audio_buses.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
375         audio_auxes.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
376         midi_buses.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
377         control_masters.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
378         master_type.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
379         monitor_type.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
380         selected_tracks.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
381         hidden_tracks.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
382         strip_buttons_button.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
383         strip_control_button.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
384         ssid_as_path.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
385         heart_beat.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
386         master_fb.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
387         bar_and_beat.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
388         smpte.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
389         meter_float.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
390         meter_led.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
391         signal_present.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
392         hp_samples.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
393         hp_min_sec.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
394         hp_gui.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
395         select_fb.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
396         preset_busy = false;
397
398 }
399
400 OSC_GUI::~OSC_GUI ()
401 {
402 }
403
404 // static directory and file handling stuff
405 static Searchpath
406 preset_search_path ()
407 {
408         bool preset_path_defined = false;
409         std::string spath_env (Glib::getenv (preset_env_variable_name, preset_path_defined));
410
411         if (preset_path_defined) {
412                 return spath_env;
413         }
414
415         Searchpath spath (ardour_data_search_path());
416         spath.add_subdirectory_to_paths(preset_dir_name);
417
418         return spath;
419 }
420
421 static std::string
422 user_preset_directory ()
423 {
424         return Glib::build_filename (user_config_directory(), preset_dir_name);
425 }
426
427 static bool
428 preset_filter (const std::string &str, void* /*arg*/)
429 {
430         return (str.length() > strlen(preset_suffix) &&
431                 str.find (preset_suffix) == (str.length() - strlen (preset_suffix)));
432 }
433
434 static std::string
435 legalize_for_path (const std::string& str)
436 {
437         std::string::size_type pos;
438         std::string illegal_chars = "/\\"; /* DOS, POSIX. Yes, we're going to ignore HFS */
439         std::string legal;
440
441         legal = str;
442         pos = 0;
443
444         while ((pos = legal.find_first_of (illegal_chars, pos)) != std::string::npos) {
445                 legal.replace (pos, 1, "_");
446                 pos += 1;
447         }
448
449         return std::string (legal);
450 }
451
452 // end of static functions
453
454 void
455 OSC_GUI::debug_changed ()
456 {
457         std::string str = debug_combo.get_active_text ();
458         if (str == _("Off")) {
459                 cp.set_debug_mode (OSC::Off);
460         }
461         else if (str == _("Log invalid messages")) {
462                 cp.set_debug_mode (OSC::Unhandled);
463         }
464         else if (str == _("Log all messages")) {
465                 cp.set_debug_mode (OSC::All);
466         }
467         else {
468                 std::cerr << "Invalid OSC Debug Mode\n";
469                 assert (0);
470         }
471 }
472
473 void
474 OSC_GUI::portmode_changed ()
475 {
476         std::string str = portmode_combo.get_active_text ();
477         if (str == _("Auto")) {
478                 cp.set_portmode (0);
479                 port_entry.set_sensitive (false);
480         }
481         else if (str == _("Manual")) {
482                 cp.set_portmode (1);
483                 port_entry.set_sensitive (true);
484         }
485         else {
486                 std::cerr << "Invalid OSC Port Mode\n";
487                 assert (0);
488         }
489         save_user ();
490 }
491
492 void
493 OSC_GUI::port_changed ()
494 {
495         std::string str = port_entry.get_text ();
496         if (port_entry.get_value() == 3819) {
497                 str = "8000";
498                 port_entry.set_value (8000);
499         }
500         cp.set_remote_port (str);
501         save_user ();
502 }
503
504 void
505 OSC_GUI::bank_changed ()
506 {
507         uint32_t bsize = bank_entry.get_value ();
508         cp.set_banksize (bsize);
509         save_user ();
510
511 }
512
513 void
514 OSC_GUI::gainmode_changed ()
515 {
516         std::string str = gainmode_combo.get_active_text ();
517         if (str == _("dB")) {
518                 cp.set_gainmode (0);
519         }
520         else if (str == _("Position")) {
521                 cp.set_gainmode (1);
522         }
523         else {
524                 std::cerr << "Invalid OSC Gain Mode\n";
525                 assert (0);
526         }
527         save_user ();
528 }
529
530 void
531 OSC_GUI::clear_device ()
532 {
533         cp.clear_devices();
534 }
535
536 void
537 OSC_GUI::preset_changed ()
538 {
539         preset_busy = true;
540         std::string str = preset_combo.get_active_text ();
541         if (str == "Last Loaded Session") {
542                 restore_sesn_values ();
543         }
544         else if (str == "Ardour Factory Setting") {
545                 factory_reset ();
546         }
547         else if (str == "User") {
548                 load_preset ("User");
549         }
550         else {
551                 load_preset (str);
552         }
553         preset_busy = false;
554 }
555
556 void
557 OSC_GUI::factory_reset ()
558 {
559         cp.set_banksize (0);
560         bank_entry.set_value (0);
561         cp.set_defaultstrip (31);
562         cp.set_defaultfeedback (0);
563         reshow_values ();
564         cp.set_gainmode (0);
565         gainmode_combo.set_active (0);
566         cp.set_portmode (0);
567         portmode_combo.set_active (0);
568         cp.set_remote_port ("8000");
569         port_entry.set_value (8000);
570         cp.clear_devices();
571 }
572
573 void
574 OSC_GUI::reshow_values ()
575 {
576         def_strip = cp.get_defaultstrip();
577         audio_tracks.set_active(def_strip & 1);
578         midi_tracks.set_active(def_strip & 2);
579         audio_buses.set_active(def_strip & 4);
580         midi_buses.set_active(def_strip & 8);
581         control_masters.set_active(def_strip & 16);
582         master_type.set_active(def_strip & 32);
583         monitor_type.set_active(def_strip & 64);
584         selected_tracks.set_active(def_strip & 256);
585         hidden_tracks.set_active(def_strip & 512);
586         def_feedback = cp.get_defaultfeedback();
587         strip_buttons_button.set_active(def_feedback & 1);
588         strip_control_button.set_active(def_feedback & 2);
589         ssid_as_path.set_active(def_feedback & 4);
590         heart_beat.set_active(def_feedback & 8);
591         master_fb.set_active(def_feedback & 16);
592         bar_and_beat.set_active(def_feedback & 32);
593         smpte.set_active(def_feedback & 64);
594         meter_float.set_active(def_feedback & 128);
595         meter_led.set_active(def_feedback & 256);
596         signal_present.set_active(def_feedback & 512);
597         hp_samples.set_active(def_feedback & 1024);
598         hp_min_sec.set_active (def_feedback & 2048);
599         //hp_gui.set_active (false); // we don't have this yet (Mixbus wants)
600         select_fb.set_active(def_feedback & 8192);
601
602         calculate_strip_types ();
603         calculate_feedback ();
604 }
605
606 void
607 OSC_GUI::calculate_feedback ()
608 {
609         fbvalue = 0;
610         if (strip_buttons_button.get_active()) {
611                 fbvalue += 1;
612         }
613         if (strip_control_button.get_active()) {
614                 fbvalue += 2;
615         }
616         if (ssid_as_path.get_active()) {
617                 fbvalue += 4;
618         }
619         if (heart_beat.get_active()) {
620                 fbvalue += 8;
621         }
622         if (master_fb.get_active()) {
623                 fbvalue += 16;
624         }
625         if (bar_and_beat.get_active()) {
626                 fbvalue += 32;
627         }
628         if (smpte.get_active()) {
629                 fbvalue += 64;
630         }
631         if (meter_float.get_active()) {
632                 fbvalue += 128;
633         }
634         if (meter_led.get_active()) {
635                 fbvalue += 256;
636         }
637         if (signal_present.get_active()) {
638                 fbvalue += 512;
639         }
640         if (hp_samples.get_active()) {
641                 fbvalue += 1024;
642         }
643         if (hp_min_sec.get_active()) {
644                 fbvalue += 2048;
645         }
646         if (hp_gui.get_active()) {
647                 fbvalue += 4096;
648         }
649         if (select_fb.get_active()) {
650                 fbvalue += 8192;
651         }
652
653         current_feedback.set_text(string_compose("%1", fbvalue));
654 }
655
656 void
657 OSC_GUI::calculate_strip_types ()
658 {
659         stvalue = 0;
660         if (audio_tracks.get_active()) {
661                 stvalue += 1;
662         }
663         if (midi_tracks.get_active()) {
664                 stvalue += 2;
665         }
666         if (audio_buses.get_active()) {
667                 stvalue += 4;
668         }
669         if (midi_buses.get_active()) {
670                 stvalue += 8;
671         }
672         if (control_masters.get_active()) {
673                 stvalue += 16;
674         }
675         if (master_type.get_active()) {
676                 stvalue += 32;
677         }
678         if (monitor_type.get_active()) {
679                 stvalue += 64;
680         }
681         if (audio_auxes.get_active()) {
682                 stvalue += 128;
683         }
684         if (selected_tracks.get_active()) {
685                 stvalue += 256;
686         }
687         if (hidden_tracks.get_active()) {
688                 stvalue += 512;
689         }
690
691         current_strip_types.set_text(string_compose("%1", stvalue));
692 }
693
694 void
695 OSC_GUI::set_bitsets ()
696 {
697         if (preset_busy) {
698                 return;
699         }
700         calculate_strip_types ();
701         calculate_feedback ();
702         cp.set_defaultstrip (stvalue);
703         cp.set_defaultfeedback (fbvalue);
704         save_user ();
705 }
706
707 void
708 OSC_GUI::scan_preset_files ()
709 {
710         std::vector<std::string> presets;
711         Searchpath spath (preset_search_path());
712
713         find_files_matching_filter (presets, spath, preset_filter, 0, false, true);
714         //device_profiles.clear ();preset_list.clear // first two entries already there
715
716         if (presets.empty()) {
717                 error << "No OSC preset files found using " << spath.to_string() << endmsg;
718                 return;
719         }
720
721         for (std::vector<std::string>::iterator i = presets.begin(); i != presets.end(); ++i) {
722                 std::string fullpath = *i;
723                 //DeviceProfile dp; // has to be initial every loop or info from last added.
724
725                 XMLTree tree;
726
727                 if (!tree.read (fullpath.c_str())) {
728                         continue;
729                 }
730
731                 XMLNode* root = tree.root ();
732                 if (!root) {
733                         continue;
734                 }
735                 const XMLProperty* prop;
736                 const XMLNode* child;
737
738                 if (root->name() != "OSCPreset") {
739                         continue;
740                 }
741
742                 if ((child = root->child ("Name")) == 0 || (prop = child->property ("value")) == 0) {
743                         continue;
744                 } else {
745                         if (prop->value() == "User") {
746                                 // We already added user but no file name
747                                 preset_files[prop->value()] = fullpath;
748                         } else if (preset_files.find(prop->value()) == preset_files.end()) {
749                                 preset_options.push_back (prop->value());
750                                 preset_files[prop->value()] = fullpath;
751                         }
752                 }
753
754         }
755 }
756
757 void
758 OSC_GUI::save_user ()
759 {
760         if (preset_busy) {
761                 return;
762         }
763         std::string fullpath = user_preset_directory();
764
765         if (g_mkdir_with_parents (fullpath.c_str(), 0755) < 0) {
766                 error << string_compose(_("Session: cannot create user MCP profile folder \"%1\" (%2)"), fullpath, strerror (errno)) << endmsg;
767                 return;
768         }
769
770         fullpath = Glib::build_filename (fullpath, string_compose ("%1%2", legalize_for_path ("user"), preset_suffix));
771
772         XMLNode* node = new XMLNode ("OSCPreset");
773         XMLNode* child = new XMLNode ("Name");
774
775         child->add_property ("value", "User");
776         node->add_child_nocopy (*child);
777
778         child = new XMLNode ("PortMode");
779         child->add_property ("value", cp.get_portmode());
780         node->add_child_nocopy (*child);
781
782         child = new XMLNode ("Remote-Port");
783         child->add_property ("value", cp.get_remote_port());
784         node->add_child_nocopy (*child);
785
786         child = new XMLNode ("Bank-Size");
787         child->add_property ("value", cp.get_banksize());
788         node->add_child_nocopy (*child);
789
790         child = new XMLNode ("Strip-Types");
791         child->add_property ("value", cp.get_defaultstrip());
792         node->add_child_nocopy (*child);
793
794         child = new XMLNode ("Feedback");
795         child->add_property ("value", cp.get_defaultfeedback());
796         node->add_child_nocopy (*child);
797
798         child = new XMLNode ("Gain-Mode");
799         child->add_property ("value", cp.get_gainmode());
800         node->add_child_nocopy (*child);
801
802         XMLTree tree;
803         tree.set_root (node);
804
805         if (!tree.write (fullpath)) {
806                 error << string_compose ("MCP profile not saved to %1", fullpath) << endmsg;
807         }
808         preset_combo.set_active (2);
809
810 }
811
812 void
813 OSC_GUI::load_preset (std::string preset)
814 {
815         if (preset == "User" && preset_files["User"] == "") {
816                 restore_sesn_values ();
817         } else if (preset_files.find(preset) != preset_files.end()) {
818                 XMLTree tree;
819
820                 if (!tree.read (preset_files[preset])) {
821                         std::cerr << "preset file not found " << preset_files[preset] << "\n";
822                         return;
823                 }
824
825                 XMLNode* root = tree.root ();
826                 if (!root) {
827                         std::cerr << "invalid preset file " << preset_files[preset] << "\n";
828                         return;
829                 }
830                 const XMLProperty* prop;
831                 const XMLNode* child;
832
833                 if (root->name() != "OSCPreset") {
834                         std::cerr << "invalid preset file " << preset_files[preset] << "\n";
835                         return;
836                 }
837
838                 if ((child = root->child ("Name")) == 0 || (prop = child->property ("value")) == 0) {
839                         std::cerr << "preset file missing Name " << preset_files[preset] << "\n";
840                         return;
841                 }
842                 if ((child = root->child ("PortMode")) == 0 || (prop = child->property ("value")) == 0) {
843                         cp.set_portmode (sesn_portmode);
844                         portmode_combo.set_active (sesn_portmode);
845                 } else {
846                         cp.set_portmode (atoi (prop->value().c_str()));
847                         portmode_combo.set_active (atoi (prop->value().c_str()));
848                 }
849                 if ((child = root->child ("Remote-Port")) == 0 || (prop = child->property ("value")) == 0) {
850                         cp.set_remote_port (sesn_port);
851                         port_entry.set_text (sesn_port);
852                 } else {
853                         cp.set_remote_port (prop->value());
854                         port_entry.set_text (prop->value());
855                 }
856                 if ((child = root->child ("Bank-Size")) == 0 || (prop = child->property ("value")) == 0) {
857                         cp.set_banksize (sesn_bank);
858                         bank_entry.set_value (sesn_bank);
859                 } else {
860                         cp.set_banksize (atoi (prop->value().c_str()));
861                         bank_entry.set_value (atoi (prop->value().c_str()));
862                 }
863                 if ((child = root->child ("Strip-Types")) == 0 || (prop = child->property ("value")) == 0) {
864                         cp.set_defaultstrip (sesn_strips);
865                 } else {
866                         cp.set_defaultstrip (atoi (prop->value().c_str()));
867                 }
868                 if ((child = root->child ("Feedback")) == 0 || (prop = child->property ("value")) == 0) {
869                         cp.set_defaultfeedback (sesn_feedback);
870                 } else {
871                         cp.set_defaultfeedback (atoi (prop->value().c_str()));
872                 }
873                 reshow_values (); // show strip types and feed back in GUI
874
875                 if ((child = root->child ("Gain-Mode")) == 0 || (prop = child->property ("value")) == 0) {
876                         cp.set_gainmode (sesn_gainmode);
877                         gainmode_combo.set_active (sesn_gainmode);
878                 } else {
879                         cp.set_gainmode (atoi (prop->value().c_str()));
880                         gainmode_combo.set_active (atoi (prop->value().c_str()));
881                 }
882
883         }
884 }
885
886 void
887 OSC_GUI::get_session ()
888 {
889         sesn_portmode = cp.get_portmode ();
890         sesn_port = cp.get_remote_port ();
891         sesn_bank = cp.get_banksize ();
892         sesn_strips = cp.get_defaultstrip ();
893         sesn_feedback = cp.get_defaultfeedback ();
894         sesn_gainmode = cp.get_gainmode ();
895 }
896
897 void
898 OSC_GUI::restore_sesn_values ()
899 {
900         cp.set_portmode (sesn_portmode);
901         portmode_combo.set_active (sesn_portmode);
902         cp.set_remote_port (sesn_port);
903         port_entry.set_text (sesn_port);
904         cp.set_banksize (sesn_bank);
905         bank_entry.set_value (sesn_bank);
906         cp.set_defaultstrip (sesn_strips);
907         cp.set_defaultfeedback (sesn_feedback);
908         reshow_values ();
909         cp.set_gainmode (sesn_gainmode);
910         gainmode_combo.set_active (sesn_gainmode);
911 }