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