OSC: correct busses spelling in GUI
[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 Busses:")));
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 Busses:")));
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         label = manage (new Gtk::Label(_("Select Desired Types of Feedback")));
270         fbtable->attach (*label, 0, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
271         ++fn;
272
273         label = manage (new Gtk::Label(_("Feedback Value:")));
274         label->set_alignment(1, .5);
275         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 15);
276         calculate_feedback ();
277         current_feedback.set_width_chars(10);
278         fbtable->attach (current_feedback, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 15);
279         ++fn;
280
281         label = manage (new Gtk::Label(_("Strip Buttons:")));
282         label->set_alignment(1, .5);
283         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
284         fbtable->attach (strip_buttons_button, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
285         ++fn;
286
287         label = manage (new Gtk::Label(_("Strip Controls:")));
288         label->set_alignment(1, .5);
289         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
290         fbtable->attach (strip_control_button, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
291         ++fn;
292
293         label = manage (new Gtk::Label(_("Use SSID as Path Extension:")));
294         label->set_alignment(1, .5);
295         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
296         fbtable->attach (ssid_as_path, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
297         ++fn;
298
299         label = manage (new Gtk::Label(_("Use Heart Beat:")));
300         label->set_alignment(1, .5);
301         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
302         fbtable->attach (heart_beat, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
303         ++fn;
304
305         label = manage (new Gtk::Label(_("Master Section:")));
306         label->set_alignment(1, .5);
307         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
308         fbtable->attach (master_fb, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
309         ++fn;
310
311         label = manage (new Gtk::Label(_("Play Head Position as Bar and Beat:")));
312         label->set_alignment(1, .5);
313         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
314         fbtable->attach (bar_and_beat, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
315         ++fn;
316
317         label = manage (new Gtk::Label(_("Play Head Position as SMPTE Time:")));
318         label->set_alignment(1, .5);
319         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
320         fbtable->attach (smpte, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
321         ++fn;
322
323         label = manage (new Gtk::Label(_("Metering as a Float:")));
324         label->set_alignment(1, .5);
325         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
326         fbtable->attach (meter_float, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
327         ++fn;
328
329         label = manage (new Gtk::Label(_("Metering as a LED Strip:")));
330         label->set_alignment(1, .5);
331         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
332         fbtable->attach (meter_led, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
333         ++fn;
334
335         label = manage (new Gtk::Label(_("Signal Present:")));
336         label->set_alignment(1, .5);
337         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
338         fbtable->attach (signal_present, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
339         ++fn;
340
341         label = manage (new Gtk::Label(_("Play Head Position as Samples:")));
342         label->set_alignment(1, .5);
343         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
344         fbtable->attach (hp_samples, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
345         ++fn;
346
347         label = manage (new Gtk::Label(_("Playhead Position as Minutes Seconds:")));
348         label->set_alignment(1, .5);
349         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
350         fbtable->attach (hp_min_sec, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
351         ++fn;
352
353         label = manage (new Gtk::Label(_("Playhead Position as per GUI Clock:")));
354         label->set_alignment(1, .5);
355         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
356         fbtable->attach (hp_gui, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
357         hp_gui.set_sensitive (false); // we don't have this yet (Mixbus wants)
358         ++fn;
359
360         label = manage (new Gtk::Label(_("Extra Select Only Feedback:")));
361         label->set_alignment(1, .5);
362         fbtable->attach (*label, 0, 1, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
363         fbtable->attach (select_fb, 1, 2, fn, fn+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
364         ++fn;
365
366         fbtable->show_all ();
367         append_page (*fbtable, _("Default Feedback"));
368         // set strips and feedback from loaded default values
369         reshow_values ();
370         // connect signals
371         audio_tracks.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
372         midi_tracks.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
373         audio_buses.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
374         audio_auxes.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
375         midi_buses.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
376         control_masters.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
377         master_type.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
378         monitor_type.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
379         selected_tracks.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
380         hidden_tracks.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
381         strip_buttons_button.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
382         strip_control_button.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
383         ssid_as_path.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
384         heart_beat.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
385         master_fb.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
386         bar_and_beat.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
387         smpte.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
388         meter_float.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
389         meter_led.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
390         signal_present.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
391         hp_samples.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
392         hp_min_sec.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
393         hp_gui.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
394         select_fb.signal_clicked().connect (sigc::mem_fun (*this, &OSC_GUI::set_bitsets));
395         preset_busy = false;
396
397 }
398
399 OSC_GUI::~OSC_GUI ()
400 {
401 }
402
403 // static directory and file handling stuff
404 static Searchpath
405 preset_search_path ()
406 {
407         bool preset_path_defined = false;
408         std::string spath_env (Glib::getenv (preset_env_variable_name, preset_path_defined));
409
410         if (preset_path_defined) {
411                 return spath_env;
412         }
413
414         Searchpath spath (ardour_data_search_path());
415         spath.add_subdirectory_to_paths(preset_dir_name);
416
417         return spath;
418 }
419
420 static std::string
421 user_preset_directory ()
422 {
423         return Glib::build_filename (user_config_directory(), preset_dir_name);
424 }
425
426 static bool
427 preset_filter (const std::string &str, void* /*arg*/)
428 {
429         return (str.length() > strlen(preset_suffix) &&
430                 str.find (preset_suffix) == (str.length() - strlen (preset_suffix)));
431 }
432
433 static std::string
434 legalize_for_path (const std::string& str)
435 {
436         std::string::size_type pos;
437         std::string illegal_chars = "/\\"; /* DOS, POSIX. Yes, we're going to ignore HFS */
438         std::string legal;
439
440         legal = str;
441         pos = 0;
442
443         while ((pos = legal.find_first_of (illegal_chars, pos)) != std::string::npos) {
444                 legal.replace (pos, 1, "_");
445                 pos += 1;
446         }
447
448         return std::string (legal);
449 }
450
451 // end of static functions
452
453 void
454 OSC_GUI::debug_changed ()
455 {
456         std::string str = debug_combo.get_active_text ();
457         if (str == _("Off")) {
458                 cp.set_debug_mode (OSC::Off);
459         }
460         else if (str == _("Log invalid messages")) {
461                 cp.set_debug_mode (OSC::Unhandled);
462         }
463         else if (str == _("Log all messages")) {
464                 cp.set_debug_mode (OSC::All);
465         }
466         else {
467                 std::cerr << "Invalid OSC Debug Mode\n";
468                 assert (0);
469         }
470 }
471
472 void
473 OSC_GUI::portmode_changed ()
474 {
475         std::string str = portmode_combo.get_active_text ();
476         if (str == _("Auto")) {
477                 cp.set_portmode (0);
478                 port_entry.set_sensitive (false);
479         }
480         else if (str == _("Manual")) {
481                 cp.set_portmode (1);
482                 port_entry.set_sensitive (true);
483         }
484         else {
485                 std::cerr << "Invalid OSC Port Mode\n";
486                 assert (0);
487         }
488         save_user ();
489 }
490
491 void
492 OSC_GUI::port_changed ()
493 {
494         std::string str = port_entry.get_text ();
495         if (port_entry.get_value() == 3819) {
496                 str = "8000";
497                 port_entry.set_value (8000);
498         }
499         cp.set_remote_port (str);
500         save_user ();
501 }
502
503 void
504 OSC_GUI::bank_changed ()
505 {
506         uint32_t bsize = bank_entry.get_value ();
507         cp.set_banksize (bsize);
508         save_user ();
509
510 }
511
512 void
513 OSC_GUI::gainmode_changed ()
514 {
515         std::string str = gainmode_combo.get_active_text ();
516         if (str == _("dB")) {
517                 cp.set_gainmode (0);
518         }
519         else if (str == _("Position")) {
520                 cp.set_gainmode (1);
521         }
522         else {
523                 std::cerr << "Invalid OSC Gain Mode\n";
524                 assert (0);
525         }
526         save_user ();
527 }
528
529 void
530 OSC_GUI::clear_device ()
531 {
532         cp.clear_devices();
533 }
534
535 void
536 OSC_GUI::preset_changed ()
537 {
538         preset_busy = true;
539         std::string str = preset_combo.get_active_text ();
540         if (str == "Last Loaded Session") {
541                 restore_sesn_values ();
542         }
543         else if (str == "Ardour Factory Setting") {
544                 factory_reset ();
545         }
546         else if (str == "User") {
547                 load_preset ("User");
548         }
549         else {
550                 load_preset (str);
551         }
552         preset_busy = false;
553 }
554
555 void
556 OSC_GUI::factory_reset ()
557 {
558         cp.set_banksize (0);
559         bank_entry.set_value (0);
560         cp.set_defaultstrip (159);
561         cp.set_defaultfeedback (0);
562         reshow_values ();
563         cp.set_gainmode (0);
564         gainmode_combo.set_active (0);
565         cp.set_portmode (0);
566         portmode_combo.set_active (0);
567         cp.set_remote_port ("8000");
568         port_entry.set_value (8000);
569         cp.clear_devices ();
570         cp.gui_changed ();
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         cp.gui_changed();
811
812 }
813
814 void
815 OSC_GUI::load_preset (std::string preset)
816 {
817         if (preset == "User" && preset_files["User"] == "") {
818                 restore_sesn_values ();
819         } else if (preset_files.find(preset) != preset_files.end()) {
820                 XMLTree tree;
821
822                 if (!tree.read (preset_files[preset])) {
823                         std::cerr << "preset file not found " << preset_files[preset] << "\n";
824                         return;
825                 }
826
827                 XMLNode* root = tree.root ();
828                 if (!root) {
829                         std::cerr << "invalid preset file " << preset_files[preset] << "\n";
830                         return;
831                 }
832                 const XMLProperty* prop;
833                 const XMLNode* child;
834
835                 if (root->name() != "OSCPreset") {
836                         std::cerr << "invalid preset file " << preset_files[preset] << "\n";
837                         return;
838                 }
839
840                 if ((child = root->child ("Name")) == 0 || (prop = child->property ("value")) == 0) {
841                         std::cerr << "preset file missing Name " << preset_files[preset] << "\n";
842                         return;
843                 }
844                 if ((child = root->child ("PortMode")) == 0 || (prop = child->property ("value")) == 0) {
845                         cp.set_portmode (sesn_portmode);
846                         portmode_combo.set_active (sesn_portmode);
847                 } else {
848                         cp.set_portmode (atoi (prop->value().c_str()));
849                         portmode_combo.set_active (atoi (prop->value().c_str()));
850                 }
851                 if ((child = root->child ("Remote-Port")) == 0 || (prop = child->property ("value")) == 0) {
852                         cp.set_remote_port (sesn_port);
853                         port_entry.set_text (sesn_port);
854                 } else {
855                         cp.set_remote_port (prop->value());
856                         port_entry.set_text (prop->value());
857                 }
858                 if ((child = root->child ("Bank-Size")) == 0 || (prop = child->property ("value")) == 0) {
859                         cp.set_banksize (sesn_bank);
860                         bank_entry.set_value (sesn_bank);
861                 } else {
862                         cp.set_banksize (atoi (prop->value().c_str()));
863                         bank_entry.set_value (atoi (prop->value().c_str()));
864                 }
865                 if ((child = root->child ("Strip-Types")) == 0 || (prop = child->property ("value")) == 0) {
866                         cp.set_defaultstrip (sesn_strips);
867                 } else {
868                         cp.set_defaultstrip (atoi (prop->value().c_str()));
869                 }
870                 if ((child = root->child ("Feedback")) == 0 || (prop = child->property ("value")) == 0) {
871                         cp.set_defaultfeedback (sesn_feedback);
872                 } else {
873                         cp.set_defaultfeedback (atoi (prop->value().c_str()));
874                 }
875                 reshow_values (); // show strip types and feed back in GUI
876
877                 if ((child = root->child ("Gain-Mode")) == 0 || (prop = child->property ("value")) == 0) {
878                         cp.set_gainmode (sesn_gainmode);
879                         gainmode_combo.set_active (sesn_gainmode);
880                 } else {
881                         cp.set_gainmode (atoi (prop->value().c_str()));
882                         gainmode_combo.set_active (atoi (prop->value().c_str()));
883                 }
884                 cp.gui_changed();
885
886         }
887 }
888
889 void
890 OSC_GUI::get_session ()
891 {
892         sesn_portmode = cp.get_portmode ();
893         sesn_port = cp.get_remote_port ();
894         sesn_bank = cp.get_banksize ();
895         sesn_strips = cp.get_defaultstrip ();
896         sesn_feedback = cp.get_defaultfeedback ();
897         sesn_gainmode = cp.get_gainmode ();
898 }
899
900 void
901 OSC_GUI::restore_sesn_values ()
902 {
903         cp.set_portmode (sesn_portmode);
904         portmode_combo.set_active (sesn_portmode);
905         cp.set_remote_port (sesn_port);
906         port_entry.set_text (sesn_port);
907         cp.set_banksize (sesn_bank);
908         bank_entry.set_value (sesn_bank);
909         cp.set_defaultstrip (sesn_strips);
910         cp.set_defaultfeedback (sesn_feedback);
911         reshow_values ();
912         cp.set_gainmode (sesn_gainmode);
913         gainmode_combo.set_active (sesn_gainmode);
914 }