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