74bf849868de38b3805ab920c3c3d7e1a7e152f6
[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 (159);
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         audio_auxes.set_active(def_strip & 128);
585         selected_tracks.set_active(def_strip & 256);
586         hidden_tracks.set_active(def_strip & 512);
587         def_feedback = cp.get_defaultfeedback();
588         strip_buttons_button.set_active(def_feedback & 1);
589         strip_control_button.set_active(def_feedback & 2);
590         ssid_as_path.set_active(def_feedback & 4);
591         heart_beat.set_active(def_feedback & 8);
592         master_fb.set_active(def_feedback & 16);
593         bar_and_beat.set_active(def_feedback & 32);
594         smpte.set_active(def_feedback & 64);
595         meter_float.set_active(def_feedback & 128);
596         meter_led.set_active(def_feedback & 256);
597         signal_present.set_active(def_feedback & 512);
598         hp_samples.set_active(def_feedback & 1024);
599         hp_min_sec.set_active (def_feedback & 2048);
600         //hp_gui.set_active (false); // we don't have this yet (Mixbus wants)
601         select_fb.set_active(def_feedback & 8192);
602
603         calculate_strip_types ();
604         calculate_feedback ();
605 }
606
607 void
608 OSC_GUI::calculate_feedback ()
609 {
610         fbvalue = 0;
611         if (strip_buttons_button.get_active()) {
612                 fbvalue += 1;
613         }
614         if (strip_control_button.get_active()) {
615                 fbvalue += 2;
616         }
617         if (ssid_as_path.get_active()) {
618                 fbvalue += 4;
619         }
620         if (heart_beat.get_active()) {
621                 fbvalue += 8;
622         }
623         if (master_fb.get_active()) {
624                 fbvalue += 16;
625         }
626         if (bar_and_beat.get_active()) {
627                 fbvalue += 32;
628         }
629         if (smpte.get_active()) {
630                 fbvalue += 64;
631         }
632         if (meter_float.get_active()) {
633                 fbvalue += 128;
634         }
635         if (meter_led.get_active()) {
636                 fbvalue += 256;
637         }
638         if (signal_present.get_active()) {
639                 fbvalue += 512;
640         }
641         if (hp_samples.get_active()) {
642                 fbvalue += 1024;
643         }
644         if (hp_min_sec.get_active()) {
645                 fbvalue += 2048;
646         }
647         if (hp_gui.get_active()) {
648                 fbvalue += 4096;
649         }
650         if (select_fb.get_active()) {
651                 fbvalue += 8192;
652         }
653
654         current_feedback.set_text(string_compose("%1", fbvalue));
655 }
656
657 void
658 OSC_GUI::calculate_strip_types ()
659 {
660         stvalue = 0;
661         if (audio_tracks.get_active()) {
662                 stvalue += 1;
663         }
664         if (midi_tracks.get_active()) {
665                 stvalue += 2;
666         }
667         if (audio_buses.get_active()) {
668                 stvalue += 4;
669         }
670         if (midi_buses.get_active()) {
671                 stvalue += 8;
672         }
673         if (control_masters.get_active()) {
674                 stvalue += 16;
675         }
676         if (master_type.get_active()) {
677                 stvalue += 32;
678         }
679         if (monitor_type.get_active()) {
680                 stvalue += 64;
681         }
682         if (audio_auxes.get_active()) {
683                 stvalue += 128;
684         }
685         if (selected_tracks.get_active()) {
686                 stvalue += 256;
687         }
688         if (hidden_tracks.get_active()) {
689                 stvalue += 512;
690         }
691
692         current_strip_types.set_text(string_compose("%1", stvalue));
693 }
694
695 void
696 OSC_GUI::set_bitsets ()
697 {
698         if (preset_busy) {
699                 return;
700         }
701         calculate_strip_types ();
702         calculate_feedback ();
703         cp.set_defaultstrip (stvalue);
704         cp.set_defaultfeedback (fbvalue);
705         save_user ();
706 }
707
708 void
709 OSC_GUI::scan_preset_files ()
710 {
711         std::vector<std::string> presets;
712         Searchpath spath (preset_search_path());
713
714         find_files_matching_filter (presets, spath, preset_filter, 0, false, true);
715         //device_profiles.clear ();preset_list.clear // first two entries already there
716
717         if (presets.empty()) {
718                 error << "No OSC preset files found using " << spath.to_string() << endmsg;
719                 return;
720         }
721
722         for (std::vector<std::string>::iterator i = presets.begin(); i != presets.end(); ++i) {
723                 std::string fullpath = *i;
724                 //DeviceProfile dp; // has to be initial every loop or info from last added.
725
726                 XMLTree tree;
727
728                 if (!tree.read (fullpath.c_str())) {
729                         continue;
730                 }
731
732                 XMLNode* root = tree.root ();
733                 if (!root) {
734                         continue;
735                 }
736                 const XMLProperty* prop;
737                 const XMLNode* child;
738
739                 if (root->name() != "OSCPreset") {
740                         continue;
741                 }
742
743                 if ((child = root->child ("Name")) == 0 || (prop = child->property ("value")) == 0) {
744                         continue;
745                 } else {
746                         if (prop->value() == "User") {
747                                 // We already added user but no file name
748                                 preset_files[prop->value()] = fullpath;
749                         } else if (preset_files.find(prop->value()) == preset_files.end()) {
750                                 preset_options.push_back (prop->value());
751                                 preset_files[prop->value()] = fullpath;
752                         }
753                 }
754
755         }
756 }
757
758 void
759 OSC_GUI::save_user ()
760 {
761         if (preset_busy) {
762                 return;
763         }
764         std::string fullpath = user_preset_directory();
765
766         if (g_mkdir_with_parents (fullpath.c_str(), 0755) < 0) {
767                 error << string_compose(_("Session: cannot create user MCP profile folder \"%1\" (%2)"), fullpath, strerror (errno)) << endmsg;
768                 return;
769         }
770
771         fullpath = Glib::build_filename (fullpath, string_compose ("%1%2", legalize_for_path ("user"), preset_suffix));
772
773         XMLNode* node = new XMLNode ("OSCPreset");
774         XMLNode* child = new XMLNode ("Name");
775
776         child->add_property ("value", "User");
777         node->add_child_nocopy (*child);
778
779         child = new XMLNode ("PortMode");
780         child->add_property ("value", cp.get_portmode());
781         node->add_child_nocopy (*child);
782
783         child = new XMLNode ("Remote-Port");
784         child->add_property ("value", cp.get_remote_port());
785         node->add_child_nocopy (*child);
786
787         child = new XMLNode ("Bank-Size");
788         child->add_property ("value", cp.get_banksize());
789         node->add_child_nocopy (*child);
790
791         child = new XMLNode ("Strip-Types");
792         child->add_property ("value", cp.get_defaultstrip());
793         node->add_child_nocopy (*child);
794
795         child = new XMLNode ("Feedback");
796         child->add_property ("value", cp.get_defaultfeedback());
797         node->add_child_nocopy (*child);
798
799         child = new XMLNode ("Gain-Mode");
800         child->add_property ("value", cp.get_gainmode());
801         node->add_child_nocopy (*child);
802
803         XMLTree tree;
804         tree.set_root (node);
805
806         if (!tree.write (fullpath)) {
807                 error << string_compose ("MCP profile not saved to %1", fullpath) << endmsg;
808         }
809         preset_combo.set_active (2);
810
811 }
812
813 void
814 OSC_GUI::load_preset (std::string preset)
815 {
816         if (preset == "User" && preset_files["User"] == "") {
817                 restore_sesn_values ();
818         } else if (preset_files.find(preset) != preset_files.end()) {
819                 XMLTree tree;
820
821                 if (!tree.read (preset_files[preset])) {
822                         std::cerr << "preset file not found " << preset_files[preset] << "\n";
823                         return;
824                 }
825
826                 XMLNode* root = tree.root ();
827                 if (!root) {
828                         std::cerr << "invalid preset file " << preset_files[preset] << "\n";
829                         return;
830                 }
831                 const XMLProperty* prop;
832                 const XMLNode* child;
833
834                 if (root->name() != "OSCPreset") {
835                         std::cerr << "invalid preset file " << preset_files[preset] << "\n";
836                         return;
837                 }
838
839                 if ((child = root->child ("Name")) == 0 || (prop = child->property ("value")) == 0) {
840                         std::cerr << "preset file missing Name " << preset_files[preset] << "\n";
841                         return;
842                 }
843                 if ((child = root->child ("PortMode")) == 0 || (prop = child->property ("value")) == 0) {
844                         cp.set_portmode (sesn_portmode);
845                         portmode_combo.set_active (sesn_portmode);
846                 } else {
847                         cp.set_portmode (atoi (prop->value().c_str()));
848                         portmode_combo.set_active (atoi (prop->value().c_str()));
849                 }
850                 if ((child = root->child ("Remote-Port")) == 0 || (prop = child->property ("value")) == 0) {
851                         cp.set_remote_port (sesn_port);
852                         port_entry.set_text (sesn_port);
853                 } else {
854                         cp.set_remote_port (prop->value());
855                         port_entry.set_text (prop->value());
856                 }
857                 if ((child = root->child ("Bank-Size")) == 0 || (prop = child->property ("value")) == 0) {
858                         cp.set_banksize (sesn_bank);
859                         bank_entry.set_value (sesn_bank);
860                 } else {
861                         cp.set_banksize (atoi (prop->value().c_str()));
862                         bank_entry.set_value (atoi (prop->value().c_str()));
863                 }
864                 if ((child = root->child ("Strip-Types")) == 0 || (prop = child->property ("value")) == 0) {
865                         cp.set_defaultstrip (sesn_strips);
866                 } else {
867                         cp.set_defaultstrip (atoi (prop->value().c_str()));
868                 }
869                 if ((child = root->child ("Feedback")) == 0 || (prop = child->property ("value")) == 0) {
870                         cp.set_defaultfeedback (sesn_feedback);
871                 } else {
872                         cp.set_defaultfeedback (atoi (prop->value().c_str()));
873                 }
874                 reshow_values (); // show strip types and feed back in GUI
875
876                 if ((child = root->child ("Gain-Mode")) == 0 || (prop = child->property ("value")) == 0) {
877                         cp.set_gainmode (sesn_gainmode);
878                         gainmode_combo.set_active (sesn_gainmode);
879                 } else {
880                         cp.set_gainmode (atoi (prop->value().c_str()));
881                         gainmode_combo.set_active (atoi (prop->value().c_str()));
882                 }
883
884         }
885 }
886
887 void
888 OSC_GUI::get_session ()
889 {
890         sesn_portmode = cp.get_portmode ();
891         sesn_port = cp.get_remote_port ();
892         sesn_bank = cp.get_banksize ();
893         sesn_strips = cp.get_defaultstrip ();
894         sesn_feedback = cp.get_defaultfeedback ();
895         sesn_gainmode = cp.get_gainmode ();
896 }
897
898 void
899 OSC_GUI::restore_sesn_values ()
900 {
901         cp.set_portmode (sesn_portmode);
902         portmode_combo.set_active (sesn_portmode);
903         cp.set_remote_port (sesn_port);
904         port_entry.set_text (sesn_port);
905         cp.set_banksize (sesn_bank);
906         bank_entry.set_value (sesn_bank);
907         cp.set_defaultstrip (sesn_strips);
908         cp.set_defaultfeedback (sesn_feedback);
909         reshow_values ();
910         cp.set_gainmode (sesn_gainmode);
911         gainmode_combo.set_active (sesn_gainmode);
912 }