Add option to hide the 2ndary clock
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2013 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #include "gtk2ardour-version.h"
23 #endif
24
25 #include <algorithm>
26 #include <cmath>
27 #include <iostream>
28 #include <cerrno>
29
30 #include <stdarg.h>
31
32 #ifndef PLATFORM_WINDOWS
33 #include <sys/resource.h>
34 #endif
35
36 #ifdef __FreeBSD__
37 #include <sys/types.h>
38 #include <sys/sysctl.h>
39 #endif
40
41 #include <stdint.h>
42 #include <fcntl.h>
43 #include <signal.h>
44 #include <unistd.h>
45 #include <time.h>
46
47 #include <glib.h>
48 #include "pbd/gstdio_compat.h"
49
50 #include <gtkmm/messagedialog.h>
51 #include <gtkmm/accelmap.h>
52 #include <gtkmm/stock.h>
53
54 #include "pbd/error.h"
55 #include "pbd/basename.h"
56 #include "pbd/compose.h"
57 #include "pbd/convert.h"
58 #include "pbd/failed_constructor.h"
59 #include "pbd/file_archive.h"
60 #include "pbd/enumwriter.h"
61 #include "pbd/memento_command.h"
62 #include "pbd/openuri.h"
63 #include "pbd/stl_delete.h"
64 #include "pbd/file_utils.h"
65 #include "pbd/localtime_r.h"
66 #include "pbd/pthread_utils.h"
67 #include "pbd/replace_all.h"
68 #include "pbd/xml++.h"
69
70 #include "gtkmm2ext/application.h"
71 #include "gtkmm2ext/bindings.h"
72 #include "gtkmm2ext/gtk_ui.h"
73 #include "gtkmm2ext/utils.h"
74 #include "gtkmm2ext/click_box.h"
75 #include "gtkmm2ext/fastmeter.h"
76 #include "gtkmm2ext/popup.h"
77 #include "gtkmm2ext/window_title.h"
78
79 #include "ardour/ardour.h"
80 #include "ardour/audio_backend.h"
81 #include "ardour/audio_track.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audiofilesource.h"
84 #include "ardour/automation_watch.h"
85 #include "ardour/diskstream.h"
86 #include "ardour/filename_extensions.h"
87 #include "ardour/filesystem_paths.h"
88 #include "ardour/ltc_file_reader.h"
89 #include "ardour/midi_track.h"
90 #include "ardour/port.h"
91 #include "ardour/plugin_manager.h"
92 #include "ardour/process_thread.h"
93 #include "ardour/profile.h"
94 #include "ardour/recent_sessions.h"
95 #include "ardour/record_enable_control.h"
96 #include "ardour/session_directory.h"
97 #include "ardour/session_route.h"
98 #include "ardour/session_state_utils.h"
99 #include "ardour/session_utils.h"
100 #include "ardour/source_factory.h"
101 #include "ardour/slave.h"
102 #include "ardour/system_exec.h"
103 #include "ardour/track.h"
104 #include "ardour/vca_manager.h"
105 #include "ardour/utils.h"
106
107 #include "LuaBridge/LuaBridge.h"
108
109 #ifdef WINDOWS_VST_SUPPORT
110 #include <fst.h>
111 #endif
112 #ifdef AUDIOUNIT_SUPPORT
113 #include "ardour/audio_unit.h"
114 #endif
115
116 // fix for OSX (nsm.h has a check function, AU/Apple defines check)
117 #ifdef check
118 #undef check
119 #endif
120
121 #include "timecode/time.h"
122
123 typedef uint64_t microseconds_t;
124
125 #include "about.h"
126 #include "editing.h"
127 #include "actions.h"
128 #include "add_route_dialog.h"
129 #include "ambiguous_file_dialog.h"
130 #include "ardour_ui.h"
131 #include "audio_clock.h"
132 #include "audio_region_view.h"
133 #include "big_clock_window.h"
134 #include "bundle_manager.h"
135 #include "duplicate_routes_dialog.h"
136 #include "debug.h"
137 #include "engine_dialog.h"
138 #include "export_video_dialog.h"
139 #include "export_video_infobox.h"
140 #include "gain_meter.h"
141 #include "global_port_matrix.h"
142 #include "gui_object.h"
143 #include "gui_thread.h"
144 #include "keyboard.h"
145 #include "keyeditor.h"
146 #include "location_ui.h"
147 #include "lua_script_manager.h"
148 #include "luawindow.h"
149 #include "main_clock.h"
150 #include "missing_file_dialog.h"
151 #include "missing_plugin_dialog.h"
152 #include "mixer_ui.h"
153 #include "meterbridge.h"
154 #include "mouse_cursors.h"
155 #include "nsm.h"
156 #include "opts.h"
157 #include "pingback.h"
158 #include "processor_box.h"
159 #include "prompter.h"
160 #include "public_editor.h"
161 #include "rc_option_editor.h"
162 #include "route_time_axis.h"
163 #include "route_params_ui.h"
164 #include "save_as_dialog.h"
165 #include "script_selector.h"
166 #include "session_archive_dialog.h"
167 #include "session_dialog.h"
168 #include "session_metadata_dialog.h"
169 #include "session_option_editor.h"
170 #include "speaker_dialog.h"
171 #include "splash.h"
172 #include "startup.h"
173 #include "theme_manager.h"
174 #include "time_axis_view_item.h"
175 #include "time_info_box.h"
176 #include "timers.h"
177 #include "utils.h"
178 #include "video_server_dialog.h"
179 #include "add_video_dialog.h"
180 #include "transcode_video_dialog.h"
181
182 #include "pbd/i18n.h"
183
184 using namespace ARDOUR;
185 using namespace ARDOUR_UI_UTILS;
186 using namespace PBD;
187 using namespace Gtkmm2ext;
188 using namespace Gtk;
189 using namespace std;
190 using namespace Editing;
191
192 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
193
194 sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock;
195 sigc::signal<void>      ARDOUR_UI::CloseAllDialogs;
196
197 static bool
198 ask_about_configuration_copy (string const & old_dir, string const & new_dir, int version)
199 {
200         MessageDialog msg (string_compose (_("%1 %2.x has discovered configuration files from %1 %3.x.\n\n"
201                                              "Would you like these files to be copied and used for %1 %2.x?\n\n"
202                                              "(This will require you to restart %1.)"),
203                                            PROGRAM_NAME, PROGRAM_VERSION, version),
204                            false, /* no markup */
205                            Gtk::MESSAGE_INFO,
206                            Gtk::BUTTONS_YES_NO,
207                            true /* modal, though it hardly matters since it is the only window */
208                 );
209
210         msg.set_default_response (Gtk::RESPONSE_YES);
211         msg.show_all ();
212
213         return (msg.run() == Gtk::RESPONSE_YES);
214 }
215
216 static void
217 libxml_generic_error_func (void* /* parsing_context*/,
218                    const char* msg,
219                    ...)
220 {
221         va_list ap;
222         char buf[2048];
223
224         va_start (ap, msg);
225         vsnprintf (buf, sizeof (buf), msg, ap);
226         error << buf << endmsg;
227         va_end (ap);
228 }
229
230 static void
231 libxml_structured_error_func (void* /* parsing_context*/,
232                               xmlErrorPtr err)
233 {
234         string msg;
235
236         if (err->message)
237                 msg = err->message;
238
239         replace_all (msg, "\n", "");
240
241         if (!msg.empty()) {
242                 if (err->file && err->line) {
243                         error << X_("XML error: ") << msg << " in " << err->file << " at line " << err->line;
244
245                         if (err->int2) {
246                                 error << ':' << err->int2;
247                         }
248
249                         error << endmsg;
250                 } else {
251                         error << X_("XML error: ") << msg << endmsg;
252                 }
253         }
254 }
255
256
257 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
258         : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
259         , session_loaded (false)
260         , gui_object_state (new GUIObjectState)
261         , primary_clock   (new MainClock (X_("primary"),   X_("transport"), true ))
262         , secondary_clock (new MainClock (X_("secondary"), X_("secondary"), false))
263         , big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false))
264         , video_timeline(0)
265         , global_actions (X_("global"))
266         , ignore_dual_punch (false)
267         , main_window_visibility (0)
268         , editor (0)
269         , mixer (0)
270         , nsm (0)
271         , _was_dirty (false)
272         , _mixer_on_top (false)
273         , _initial_verbose_plugin_scan (false)
274         , first_time_engine_run (true)
275         , secondary_clock_spacer (0)
276         , roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll))
277         , stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop))
278         , goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart))
279         , goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd))
280         , auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop))
281         , play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection))
282         , rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable))
283         , time_info_box (0)
284         , auto_return_button (ArdourButton::led_default_elements)
285         , follow_edits_button (ArdourButton::led_default_elements)
286         , auto_input_button (ArdourButton::led_default_elements)
287         , auditioning_alert_button (_("Audition"))
288         , solo_alert_button (_("Solo"))
289         , feedback_alert_button (_("Feedback"))
290         , error_alert_button ( ArdourButton::just_led_default_elements )
291         , editor_meter(0)
292         , editor_meter_peak_display()
293         , _numpad_locate_happening (false)
294         , _session_is_new (false)
295         , last_key_press_time (0)
296         , save_as_dialog (0)
297         , meterbridge (0)
298         , luawindow (0)
299         , rc_option_editor (0)
300         , speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
301         , add_route_dialog (X_("add-routes"), _("Add Tracks/Busses"))
302         , about (X_("about"), _("About"))
303         , location_ui (X_("locations"), S_("Ranges|Locations"))
304         , route_params (X_("inspector"), _("Tracks and Busses"))
305         , audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup"))
306         , export_video_dialog (X_("video-export"), _("Video Export Dialog"))
307         , lua_script_window (X_("script-manager"), _("Script Manager"))
308         , session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this))
309         , add_video_dialog (X_("add-video"), _("Add Video"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
310         , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
311         , big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this))
312         , audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO))
313         , midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI))
314         , key_editor (X_("key-editor"), _("Bindings Editor"), boost::bind (&ARDOUR_UI::create_key_editor, this))
315         , video_server_process (0)
316         , splash (0)
317         , have_configure_timeout (false)
318         , last_configure_time (0)
319         , last_peak_grab (0)
320         , have_disk_speed_dialog_displayed (false)
321         , _status_bar_visibility (X_("status-bar"))
322         , _feedback_exists (false)
323         , _log_not_acknowledged (LogLevelNone)
324         , duplicate_routes_dialog (0)
325         , editor_visibility_button (S_("Window|Editor"))
326         , mixer_visibility_button (S_("Window|Mixer"))
327         , prefs_visibility_button (S_("Window|Preferences"))
328 {
329         Gtkmm2ext::init (localedir);
330
331         UIConfiguration::instance().post_gui_init ();
332
333         if (ARDOUR::handle_old_configuration_files (boost::bind (ask_about_configuration_copy, _1, _2, _3))) {
334                 MessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true);
335                 msg.run ();
336                 /* configuration was modified, exit immediately */
337                 _exit (0);
338         }
339
340
341         if (string (VERSIONSTRING).find (".pre") != string::npos) {
342                 /* check this is not being run from ./ardev etc. */
343                 if (!running_from_source_tree ()) {
344                         pre_release_dialog ();
345                 }
346         }
347
348         if (theArdourUI == 0) {
349                 theArdourUI = this;
350         }
351
352         /* track main window visibility */
353
354         main_window_visibility = new VisibilityTracker (_main_window);
355
356         /* stop libxml from spewing to stdout/stderr */
357
358         xmlSetGenericErrorFunc (this, libxml_generic_error_func);
359         xmlSetStructuredErrorFunc (this, libxml_structured_error_func);
360
361         UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::parameter_changed));
362         boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
363         UIConfiguration::instance().map_parameters (pc);
364
365         roll_button.set_controllable (roll_controllable);
366         stop_button.set_controllable (stop_controllable);
367         goto_start_button.set_controllable (goto_start_controllable);
368         goto_end_button.set_controllable (goto_end_controllable);
369         auto_loop_button.set_controllable (auto_loop_controllable);
370         play_selection_button.set_controllable (play_selection_controllable);
371         rec_button.set_controllable (rec_controllable);
372
373         roll_button.set_name ("transport button");
374         stop_button.set_name ("transport button");
375         goto_start_button.set_name ("transport button");
376         goto_end_button.set_name ("transport button");
377         auto_loop_button.set_name ("transport button");
378         play_selection_button.set_name ("transport button");
379         rec_button.set_name ("transport recenable button");
380         midi_panic_button.set_name ("transport button");
381
382         ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
383         ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
384
385         ARDOUR::Session::VersionMismatch.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_format_mismatch, this, _1, _2), gui_context());
386
387         /* handle dialog requests */
388
389         ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
390
391         /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
392
393         ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
394
395         /* handle Audio/MIDI setup when session requires it */
396
397         ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_audio_midi_setup, this, _1));
398
399         /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
400
401         ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
402
403         /* handle sr mismatch with a dialog - cross-thread from engine */
404         ARDOUR::Session::NotifyAboutSampleRateMismatch.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::sr_mismatch_message, this, _1, _2), gui_context ());
405
406         /* handle requests to quit (coming from JACK session) */
407
408         ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::finish, this), gui_context ());
409
410         /* tell the user about feedback */
411
412         ARDOUR::Session::FeedbackDetected.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::feedback_detected, this), gui_context ());
413         ARDOUR::Session::SuccessfulGraphSort.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::successful_graph_sort, this), gui_context ());
414
415         /* handle requests to deal with missing files */
416
417         ARDOUR::Session::MissingFile.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::missing_file, this, _1, _2, _3));
418
419         /* and ambiguous files */
420
421         ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2));
422
423         /* also plugin scan messages */
424         ARDOUR::PluginScanMessage.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_dialog, this, _1, _2, _3), gui_context());
425         ARDOUR::PluginScanTimeout.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_timeout, this, _1), gui_context());
426
427         ARDOUR::GUIIdle.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::gui_idle_handler, this), gui_context());
428
429         Config->ParameterChanged.connect ( forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::set_flat_buttons, this), gui_context() );
430         set_flat_buttons();
431
432         /* lets get this party started */
433
434         setup_gtk_ardour_enums ();
435         setup_profile ();
436
437         SessionEvent::create_per_thread_pool ("GUI", 4096);
438
439         /* we like keyboards */
440
441         keyboard = new ArdourKeyboard(*this);
442
443         XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
444         if (node) {
445                 keyboard->set_state (*node, Stateful::loading_state_version);
446         }
447
448         UIConfiguration::instance().reset_dpi ();
449
450         TimeAxisViewItem::set_constant_heights ();
451
452         /* Set this up so that our window proxies can register actions */
453
454         ActionManager::init ();
455
456         /* The following must happen after ARDOUR::init() so that Config is set up */
457
458         const XMLNode* ui_xml = Config->extra_xml (X_("UI"));
459
460         if (ui_xml) {
461                 key_editor.set_state (*ui_xml, 0);
462                 session_option_editor.set_state (*ui_xml, 0);
463                 speaker_config_window.set_state (*ui_xml, 0);
464                 about.set_state (*ui_xml, 0);
465                 add_route_dialog.set_state (*ui_xml, 0);
466                 add_video_dialog.set_state (*ui_xml, 0);
467                 route_params.set_state (*ui_xml, 0);
468                 bundle_manager.set_state (*ui_xml, 0);
469                 location_ui.set_state (*ui_xml, 0);
470                 big_clock_window.set_state (*ui_xml, 0);
471                 audio_port_matrix.set_state (*ui_xml, 0);
472                 midi_port_matrix.set_state (*ui_xml, 0);
473                 export_video_dialog.set_state (*ui_xml, 0);
474                 lua_script_window.set_state (*ui_xml, 0);
475         }
476
477         /* Separate windows */
478
479         WM::Manager::instance().register_window (&key_editor);
480         WM::Manager::instance().register_window (&session_option_editor);
481         WM::Manager::instance().register_window (&speaker_config_window);
482         WM::Manager::instance().register_window (&about);
483         WM::Manager::instance().register_window (&add_route_dialog);
484         WM::Manager::instance().register_window (&add_video_dialog);
485         WM::Manager::instance().register_window (&route_params);
486         WM::Manager::instance().register_window (&audio_midi_setup);
487         WM::Manager::instance().register_window (&export_video_dialog);
488         WM::Manager::instance().register_window (&lua_script_window);
489         WM::Manager::instance().register_window (&bundle_manager);
490         WM::Manager::instance().register_window (&location_ui);
491         WM::Manager::instance().register_window (&big_clock_window);
492         WM::Manager::instance().register_window (&audio_port_matrix);
493         WM::Manager::instance().register_window (&midi_port_matrix);
494
495         /* do not retain position for add route dialog */
496         add_route_dialog.set_state_mask (WindowProxy::Size);
497
498         /* Trigger setting up the color scheme and loading the GTK RC file */
499
500         UIConfiguration::instance().load_rc_file (false);
501
502         _process_thread = new ProcessThread ();
503         _process_thread->init ();
504
505         UIConfiguration::instance().DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::resize_text_widgets));
506
507         attach_to_engine ();
508 }
509
510 void
511 ARDOUR_UI::pre_release_dialog ()
512 {
513         ArdourDialog d (_("Pre-Release Warning"), true, false);
514         d.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
515
516         Label* label = manage (new Label);
517         label->set_markup (string_compose (_("<b>Welcome to this pre-release build of %1 %2</b>\n\n\
518 There are still several issues and bugs to be worked on,\n\
519 as well as general workflow improvements, before this can be considered\n\
520 release software. So, a few guidelines:\n\
521 \n\
522 1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
523    though it may be so, depending on your workflow.\n\
524 2) Please wait for a helpful writeup of new features.\n\
525 3) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
526 4) Please <b>DO</b> use the bugtracker at http://tracker.ardour.org/ to report issues\n\
527    making sure to note the product version number as 5.0-pre.\n\
528 5) Please <b>DO</b> use the ardour-users mailing list to discuss ideas and pass on comments.\n\
529 6) Please <b>DO</b> join us on IRC for real time discussions about %1 %2. You\n\
530    can get there directly from within the program via the Help->Chat menu option.\n\
531 \n\
532 Full information on all the above can be found on the support page at\n\
533 \n\
534                 http://ardour.org/support\n\
535 "), PROGRAM_NAME, VERSIONSTRING));
536
537         d.get_vbox()->set_border_width (12);
538         d.get_vbox()->pack_start (*label, false, false, 12);
539         d.get_vbox()->show_all ();
540
541         d.run ();
542 }
543
544 GlobalPortMatrixWindow*
545 ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type)
546 {
547         if (!_session) {
548                 return 0;
549         }
550         return new GlobalPortMatrixWindow (_session, type);
551 }
552
553 void
554 ARDOUR_UI::attach_to_engine ()
555 {
556         AudioEngine::instance()->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
557         ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
558 }
559
560 void
561 ARDOUR_UI::engine_stopped ()
562 {
563         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
564         ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
565         ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
566         update_sample_rate (0);
567         update_cpu_load ();
568 }
569
570 void
571 ARDOUR_UI::engine_running ()
572 {
573         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
574         if (first_time_engine_run) {
575                 post_engine();
576                 first_time_engine_run = false;
577         }
578
579         if (_session) {
580                 _session->reset_xrun_count ();
581         }
582         update_disk_space ();
583         update_cpu_load ();
584         update_xrun_count ();
585         update_sample_rate (AudioEngine::instance()->sample_rate());
586         update_timecode_format ();
587         update_peak_thread_work ();
588         ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, true);
589         ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, false);
590 }
591
592 void
593 ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
594 {
595         if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
596                 /* we can't rely on the original string continuing to exist when we are called
597                    again in the GUI thread, so make a copy and note that we need to
598                    free it later.
599                 */
600                 char *copy = strdup (reason);
601                 Gtkmm2ext::UI::instance()->call_slot (MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
602                 return;
603         }
604
605         ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
606         ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
607
608         update_sample_rate (0);
609
610         string msgstr;
611
612         /* if the reason is a non-empty string, it means that the backend was shutdown
613            rather than just Ardour.
614         */
615
616         if (strlen (reason)) {
617                 msgstr = string_compose (_("The audio backend was shutdown because:\n\n%1"), reason);
618         } else {
619                 msgstr = string_compose (_("\
620 The audio backend has either been shutdown or it\n\
621 disconnected %1 because %1\n\
622 was not fast enough. Try to restart\n\
623 the audio backend and save the session."), PROGRAM_NAME);
624         }
625
626         MessageDialog msg (_main_window, msgstr);
627         pop_back_splash (msg);
628         msg.run ();
629
630         if (free_reason) {
631                 free (const_cast<char*> (reason));
632         }
633 }
634
635 void
636 ARDOUR_UI::post_engine ()
637 {
638         /* Things to be done once (and once ONLY) after we have a backend running in the AudioEngine
639          */
640 #ifdef AUDIOUNIT_SUPPORT
641         std::string au_msg;
642         if (AUPluginInfo::au_get_crashlog(au_msg)) {
643                 popup_error(_("Audio Unit Plugin Scan Failed. Automatic AU scanning has been disabled. Please see the log window for further details."));
644                 error << _("Audio Unit Plugin Scan Failed:") << endmsg;
645                 info << au_msg << endmsg;
646         }
647 #endif
648
649         ARDOUR::init_post_engine ();
650
651         /* connect to important signals */
652
653         AudioEngine::instance()->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
654         AudioEngine::instance()->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
655         AudioEngine::instance()->BufferSizeChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
656         AudioEngine::instance()->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
657         AudioEngine::instance()->BecameSilent.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::audioengine_became_silent, this), gui_context());
658
659         if (setup_windows ()) {
660                 throw failed_constructor ();
661         }
662
663         /* Do this after setup_windows (), as that's when the _status_bar_visibility is created */
664         XMLNode* n = Config->extra_xml (X_("UI"));
665         if (n) {
666                 _status_bar_visibility.set_state (*n);
667         }
668
669         check_memory_locking();
670
671         /* this is the first point at which all the possible actions are
672          * available, because some of the available actions are dependent on
673          * aspects of the engine/backend.
674          */
675
676         if (ARDOUR_COMMAND_LINE::show_key_actions) {
677
678
679                 vector<string> paths;
680                 vector<string> labels;
681                 vector<string> tooltips;
682                 vector<string> keys;
683                 vector<Glib::RefPtr<Gtk::Action> > actions;
684
685                 Gtkmm2ext::ActionMap::get_all_actions (paths, labels, tooltips, keys, actions);
686
687                 vector<string>::iterator k;
688                 vector<string>::iterator p;
689
690                 for (p = paths.begin(), k = keys.begin(); p != paths.end(); ++k, ++p) {
691
692                         if ((*k).empty()) {
693                                 cout << *p << endl;
694                         } else {
695                                 cout << *p << " => " << *k << endl;
696                         }
697                 }
698
699                 halt_connection.disconnect ();
700                 AudioEngine::instance()->stop ();
701                 exit (0);
702         }
703
704         /* this being a GUI and all, we want peakfiles */
705
706         AudioFileSource::set_build_peakfiles (true);
707         AudioFileSource::set_build_missing_peakfiles (true);
708
709         /* set default clock modes */
710
711         primary_clock->set_mode (AudioClock::Timecode);
712         secondary_clock->set_mode (AudioClock::BBT);
713
714         /* start the time-of-day-clock */
715
716 #ifndef __APPLE__
717         /* OS X provides a nearly-always visible wallclock, so don't be stupid */
718         update_wall_clock ();
719         Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1);
720 #endif
721
722         {
723                 DisplaySuspender ds;
724                 Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
725                 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
726                 Config->map_parameters (pc);
727
728                 UIConfiguration::instance().map_parameters (pc);
729         }
730 }
731
732 ARDOUR_UI::~ARDOUR_UI ()
733 {
734         UIConfiguration::instance().save_state();
735
736         stop_video_server();
737
738         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
739                 // don't bother at 'real' exit. the OS cleans up for us.
740                 delete big_clock; big_clock = 0;
741                 delete primary_clock; primary_clock = 0;
742                 delete secondary_clock; secondary_clock = 0;
743                 delete _process_thread; _process_thread = 0;
744                 delete time_info_box; time_info_box = 0;
745                 delete meterbridge; meterbridge = 0;
746                 delete luawindow; luawindow = 0;
747                 delete editor; editor = 0;
748                 delete mixer; mixer = 0;
749                 delete nsm; nsm = 0;
750                 delete gui_object_state; gui_object_state = 0;
751                 delete main_window_visibility;
752                 FastMeter::flush_pattern_cache ();
753                 PixFader::flush_pattern_cache ();
754         }
755
756 #ifndef NDEBUG
757         /* Small trick to flush main-thread event pool.
758          * Other thread-pools are destroyed at pthread_exit(),
759          * but tmain thread termination is too late to trigger Pool::~Pool()
760          */
761         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Clear, SessionEvent::Immediate, 0, 0); // get the pool reference, values don't matter since the event is never queued.
762         delete ev->event_pool();
763 #endif
764 }
765
766 void
767 ARDOUR_UI::pop_back_splash (Gtk::Window& win)
768 {
769         if (Splash::instance()) {
770                 Splash::instance()->pop_back_for (win);
771         }
772 }
773
774 gint
775 ARDOUR_UI::configure_timeout ()
776 {
777         if (last_configure_time == 0) {
778                 /* no configure events yet */
779                 return true;
780         }
781
782         /* force a gap of 0.5 seconds since the last configure event
783          */
784
785         if (get_microseconds() - last_configure_time < 500000) {
786                 return true;
787         } else {
788                 have_configure_timeout = false;
789                 save_ardour_state ();
790                 return false;
791         }
792 }
793
794 gboolean
795 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
796 {
797         if (have_configure_timeout) {
798                 last_configure_time = get_microseconds();
799         } else {
800                 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
801                 have_configure_timeout = true;
802         }
803
804         return FALSE;
805 }
806
807 void
808 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
809 {
810         XMLProperty const * prop;
811
812         if ((prop = node.property ("roll")) != 0) {
813                 roll_controllable->set_id (prop->value());
814         }
815         if ((prop = node.property ("stop")) != 0) {
816                 stop_controllable->set_id (prop->value());
817         }
818         if ((prop = node.property ("goto-start")) != 0) {
819                 goto_start_controllable->set_id (prop->value());
820         }
821         if ((prop = node.property ("goto-end")) != 0) {
822                 goto_end_controllable->set_id (prop->value());
823         }
824         if ((prop = node.property ("auto-loop")) != 0) {
825                 auto_loop_controllable->set_id (prop->value());
826         }
827         if ((prop = node.property ("play-selection")) != 0) {
828                 play_selection_controllable->set_id (prop->value());
829         }
830         if ((prop = node.property ("rec")) != 0) {
831                 rec_controllable->set_id (prop->value());
832         }
833         if ((prop = node.property ("shuttle")) != 0) {
834                 shuttle_box.controllable()->set_id (prop->value());
835         }
836 }
837
838 XMLNode&
839 ARDOUR_UI::get_transport_controllable_state ()
840 {
841         XMLNode* node = new XMLNode(X_("TransportControllables"));
842         char buf[64];
843
844         roll_controllable->id().print (buf, sizeof (buf));
845         node->add_property (X_("roll"), buf);
846         stop_controllable->id().print (buf, sizeof (buf));
847         node->add_property (X_("stop"), buf);
848         goto_start_controllable->id().print (buf, sizeof (buf));
849         node->add_property (X_("goto_start"), buf);
850         goto_end_controllable->id().print (buf, sizeof (buf));
851         node->add_property (X_("goto_end"), buf);
852         auto_loop_controllable->id().print (buf, sizeof (buf));
853         node->add_property (X_("auto_loop"), buf);
854         play_selection_controllable->id().print (buf, sizeof (buf));
855         node->add_property (X_("play_selection"), buf);
856         rec_controllable->id().print (buf, sizeof (buf));
857         node->add_property (X_("rec"), buf);
858         shuttle_box.controllable()->id().print (buf, sizeof (buf));
859         node->add_property (X_("shuttle"), buf);
860
861         return *node;
862 }
863
864 void
865 ARDOUR_UI::save_session_at_its_request (std::string snapshot_name)
866 {
867         if (_session) {
868                 _session->save_state (snapshot_name);
869         }
870 }
871
872 gint
873 ARDOUR_UI::autosave_session ()
874 {
875         if (g_main_depth() > 1) {
876                 /* inside a recursive main loop,
877                    give up because we may not be able to
878                    take a lock.
879                 */
880                 return 1;
881         }
882
883         if (!Config->get_periodic_safety_backups()) {
884                 return 1;
885         }
886
887         if (_session) {
888                 _session->maybe_write_autosave();
889         }
890
891         return 1;
892 }
893
894 void
895 ARDOUR_UI::session_dirty_changed ()
896 {
897         update_autosave ();
898         update_title ();
899 }
900
901 void
902 ARDOUR_UI::update_autosave ()
903 {
904         if (_session && _session->dirty()) {
905                 if (_autosave_connection.connected()) {
906                         _autosave_connection.disconnect();
907                 }
908
909                 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
910                                 Config->get_periodic_safety_backup_interval() * 1000);
911
912         } else {
913                 if (_autosave_connection.connected()) {
914                         _autosave_connection.disconnect();
915                 }
916         }
917 }
918
919 void
920 ARDOUR_UI::check_announcements ()
921 {
922 #ifdef PHONE_HOME
923         string _annc_filename;
924
925 #ifdef __APPLE__
926         _annc_filename = PROGRAM_NAME "_announcements_osx_";
927 #elif defined PLATFORM_WINDOWS
928         _annc_filename = PROGRAM_NAME "_announcements_windows_";
929 #else
930         _annc_filename = PROGRAM_NAME "_announcements_linux_";
931 #endif
932         _annc_filename.append (VERSIONSTRING);
933
934         _announce_string = "";
935
936         std::string path = Glib::build_filename (user_config_directory(), _annc_filename);
937         FILE* fin = g_fopen (path.c_str(), "rb");
938         if (fin) {
939                 while (!feof (fin)) {
940                         char tmp[1024];
941                         size_t len;
942                         if ((len = fread (tmp, sizeof(char), 1024, fin)) == 0 || ferror (fin)) {
943                                 break;
944                         }
945                         _announce_string.append (tmp, len);
946                 }
947                 fclose (fin);
948         }
949
950         pingback (VERSIONSTRING, path);
951 #endif
952 }
953
954 static bool
955 _hide_splash (gpointer arg)
956 {
957         ((ARDOUR_UI*)arg)->hide_splash();
958         return false;
959 }
960
961 int
962 ARDOUR_UI::starting ()
963 {
964         Application* app = Application::instance ();
965         const char *nsm_url;
966         bool brand_new_user = ArdourStartup::required ();
967
968         app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
969         app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::load_from_application_api));
970
971         if (ARDOUR_COMMAND_LINE::check_announcements) {
972                 check_announcements ();
973         }
974
975         app->ready ();
976
977         /* we need to create this early because it may need to set the
978          *  audio backend end up.
979          */
980
981         try {
982                 audio_midi_setup.get (true);
983         } catch (...) {
984                 std::cerr << "audio-midi engine setup failed."<< std::endl;
985                 return -1;
986         }
987
988         if ((nsm_url = g_getenv ("NSM_URL")) != 0) {
989                 nsm = new NSM_Client;
990                 if (!nsm->init (nsm_url)) {
991                         /* the ardour executable may have different names:
992                          *
993                          * waf's obj.target for distro versions: eg ardour4, ardourvst4
994                          * Ardour4, Mixbus3 for bundled versions + full path on OSX & windows
995                          * argv[0] does not apply since we need the wrapper-script (not the binary itself)
996                          *
997                          * The wrapper startup script should set the environment variable 'ARDOUR_SELF'
998                          */
999                         const char *process_name = g_getenv ("ARDOUR_SELF");
1000                         nsm->announce (PROGRAM_NAME, ":dirty:", process_name ? process_name : "ardour4");
1001
1002                         unsigned int i = 0;
1003                         // wait for announce reply from nsm server
1004                         for ( i = 0; i < 5000; ++i) {
1005                                 nsm->check ();
1006
1007                                 Glib::usleep (i);
1008                                 if (nsm->is_active()) {
1009                                         break;
1010                                 }
1011                         }
1012                         if (i == 5000) {
1013                                 error << _("NSM server did not announce itself") << endmsg;
1014                                 return -1;
1015                         }
1016                         // wait for open command from nsm server
1017                         for ( i = 0; i < 5000; ++i) {
1018                                 nsm->check ();
1019                                 Glib::usleep (1000);
1020                                 if (nsm->client_id ()) {
1021                                         break;
1022                                 }
1023                         }
1024
1025                         if (i == 5000) {
1026                                 error << _("NSM: no client ID provided") << endmsg;
1027                                 return -1;
1028                         }
1029
1030                         if (_session && nsm) {
1031                                 _session->set_nsm_state( nsm->is_active() );
1032                         } else {
1033                                 error << _("NSM: no session created") << endmsg;
1034                                 return -1;
1035                         }
1036
1037                         // nsm requires these actions disabled
1038                         vector<string> action_names;
1039                         action_names.push_back("SaveAs");
1040                         action_names.push_back("Rename");
1041                         action_names.push_back("New");
1042                         action_names.push_back("Open");
1043                         action_names.push_back("Recent");
1044                         action_names.push_back("Close");
1045
1046                         for (vector<string>::const_iterator n = action_names.begin(); n != action_names.end(); ++n) {
1047                                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), (*n).c_str());
1048                                 if (act) {
1049                                         act->set_sensitive (false);
1050                                 }
1051                         }
1052
1053                 } else {
1054                         delete nsm;
1055                         nsm = 0;
1056                         error << _("NSM: initialization failed") << endmsg;
1057                         return -1;
1058                 }
1059
1060         } else  {
1061
1062                 if (brand_new_user) {
1063                         _initial_verbose_plugin_scan = true;
1064                         ArdourStartup s;
1065                         s.present ();
1066                         main().run();
1067                         s.hide ();
1068                         _initial_verbose_plugin_scan = false;
1069                         switch (s.response ()) {
1070                         case Gtk::RESPONSE_OK:
1071                                 break;
1072                         default:
1073                                 return -1;
1074                         }
1075                 }
1076
1077                 // TODO: maybe IFF brand_new_user
1078                 if (ARDOUR::Profile->get_mixbus () && Config->get_copy_demo_sessions ()) {
1079                         std::string dspd (Config->get_default_session_parent_dir());
1080                         Searchpath ds (ARDOUR::ardour_data_search_path());
1081                         ds.add_subdirectory_to_paths ("sessions");
1082                         vector<string> demos;
1083                         find_files_matching_pattern (demos, ds, "*.tar.xz");
1084
1085                         ARDOUR::RecentSessions rs;
1086                         ARDOUR::read_recent_sessions (rs);
1087
1088                         for (vector<string>::iterator i = demos.begin(); i != demos.end (); ++i) {
1089                                 /* "demo-session" must be inside "demo-session.tar.xz"
1090                                  * strip ".tar.xz"
1091                                  */
1092                                 std::string name = basename_nosuffix (basename_nosuffix (*i));
1093                                 std::string path = Glib::build_filename (dspd, name);
1094                                 /* skip if session-dir already exists */
1095                                 if (Glib::file_test(path.c_str(), Glib::FILE_TEST_IS_DIR)) {
1096                                         continue;
1097                                 }
1098                                 /* skip sessions that are already in 'recent'.
1099                                  * eg. a new user changed <session-default-dir> shorly after installation
1100                                  */
1101                                 for (ARDOUR::RecentSessions::iterator r = rs.begin(); r != rs.end(); ++r) {
1102                                         if ((*r).first == name) {
1103                                                 continue;
1104                                         }
1105                                 }
1106                                 try {
1107                                         PBD::FileArchive ar (*i);
1108                                         if (0 == ar.inflate (dspd)) {
1109                                                 store_recent_sessions (name, path);
1110                                                 info << string_compose (_("Copied Demo Session %1."), name) << endmsg;
1111                                         }
1112                                 } catch (...) {}
1113                         }
1114                 }
1115
1116 #ifdef NO_PLUGIN_STATE
1117
1118                 ARDOUR::RecentSessions rs;
1119                 ARDOUR::read_recent_sessions (rs);
1120
1121                 string path = Glib::build_filename (user_config_directory(), ".iknowaboutfreeversion");
1122
1123                 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS) && !rs.empty()) {
1124
1125                         /* already used Ardour, have sessions ... warn about plugin state */
1126
1127                         ArdourDialog d (_("Free/Demo Version Warning"), true);
1128                         Label l;
1129                         Button b (string_compose (_("Subscribe and support development of %1"), PROGRAM_NAME));
1130                         CheckButton c (_("Don't warn me about this again"));
1131
1132                         l.set_markup (string_compose (_("<span weight=\"bold\" size=\"large\">%1</span>\n\n<b>%2</b>\n\n<i>%3</i>\n\n%4"),
1133                                                       string_compose (_("This is a free/demo version of %1"), PROGRAM_NAME),
1134                                                       _("It will not restore OR save any plugin settings"),
1135                                                       _("If you load an existing session with plugin settings\n"
1136                                                         "they will not be used and will be lost."),
1137                                                       _("To get full access to updates without this limitation\n"
1138                                                         "consider becoming a subscriber for a low cost every month.")));
1139                         l.set_justify (JUSTIFY_CENTER);
1140
1141                         b.signal_clicked().connect (mem_fun(*this, &ARDOUR_UI::launch_subscribe));
1142
1143                         d.get_vbox()->pack_start (l, true, true);
1144                         d.get_vbox()->pack_start (b, false, false, 12);
1145                         d.get_vbox()->pack_start (c, false, false, 12);
1146
1147                         d.add_button (_("Quit now"), RESPONSE_CANCEL);
1148                         d.add_button (string_compose (_("Continue using %1"), PROGRAM_NAME), RESPONSE_OK);
1149
1150                         d.show_all ();
1151
1152                         c.signal_toggled().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (toggle_file_existence), path)));
1153
1154                         if (d.run () != RESPONSE_OK) {
1155                                 _exit (0);
1156                         }
1157                 }
1158 #endif
1159
1160                 /* go get a session */
1161
1162                 const bool new_session_required = (ARDOUR_COMMAND_LINE::new_session || brand_new_user);
1163
1164                 if (get_session_parameters (false, new_session_required, ARDOUR_COMMAND_LINE::load_template)) {
1165                         std::cerr << "Cannot get session parameters."<< std::endl;
1166                         return -1;
1167                 }
1168         }
1169
1170         use_config ();
1171
1172         WM::Manager::instance().show_visible ();
1173
1174         /* We have to do this here since goto_editor_window() ends up calling show_all() on the
1175          * editor window, and we may want stuff to be hidden.
1176          */
1177         _status_bar_visibility.update ();
1178
1179         BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
1180
1181         if (splash && splash->is_visible()) {
1182                 // in 1 second, hide the splash screen
1183                 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
1184         }
1185
1186         /* all other dialogs are created conditionally */
1187
1188         return 0;
1189 }
1190
1191 void
1192 ARDOUR_UI::check_memory_locking ()
1193 {
1194 #if defined(__APPLE__) || defined(PLATFORM_WINDOWS)
1195         /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
1196         return;
1197 #else // !__APPLE__
1198
1199         XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
1200
1201         if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) {
1202
1203                 struct rlimit limits;
1204                 int64_t ram;
1205                 long pages, page_size;
1206 #ifdef __FreeBSD__
1207                 size_t pages_len=sizeof(pages);
1208                 if ((page_size = getpagesize()) < 0 ||
1209                                 sysctlbyname("hw.availpages", &pages, &pages_len, NULL, 0))
1210 #else
1211                 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0)
1212 #endif
1213                 {
1214                         ram = 0;
1215                 } else {
1216                         ram = (int64_t) pages * (int64_t) page_size;
1217                 }
1218
1219                 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
1220                         return;
1221                 }
1222
1223                 if (limits.rlim_cur != RLIM_INFINITY) {
1224
1225                         if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
1226
1227                                 MessageDialog msg (
1228                                         string_compose (
1229                                                 _("WARNING: Your system has a limit for maximum amount of locked memory. "
1230                                                   "This might cause %1 to run out of memory before your system "
1231                                                   "runs out of memory. \n\n"
1232                                                   "You can view the memory limit with 'ulimit -l', "
1233                                                   "and it is normally controlled by %2"),
1234                                                 PROGRAM_NAME,
1235 #ifdef __FreeBSD__
1236                                                 X_("/etc/login.conf")
1237 #else
1238                                                 X_(" /etc/security/limits.conf")
1239 #endif
1240                                         ).c_str());
1241
1242                                 msg.set_default_response (RESPONSE_OK);
1243
1244                                 VBox* vbox = msg.get_vbox();
1245                                 HBox hbox;
1246                                 CheckButton cb (_("Do not show this window again"));
1247                                 hbox.pack_start (cb, true, false);
1248                                 vbox->pack_start (hbox);
1249                                 cb.show();
1250                                 vbox->show();
1251                                 hbox.show ();
1252
1253                                 pop_back_splash (msg);
1254
1255                                 msg.run ();
1256
1257                                 if (cb.get_active()) {
1258                                         XMLNode node (X_("no-memory-warning"));
1259                                         Config->add_instant_xml (node);
1260                                 }
1261                         }
1262                 }
1263         }
1264 #endif // !__APPLE__
1265 }
1266
1267
1268 void
1269 ARDOUR_UI::queue_finish ()
1270 {
1271         Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::idle_finish));
1272 }
1273
1274 bool
1275 ARDOUR_UI::idle_finish ()
1276 {
1277         finish ();
1278         return false; /* do not call again */
1279 }
1280
1281 void
1282 ARDOUR_UI::finish()
1283 {
1284         if (_session) {
1285                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
1286
1287                 if (_session->dirty()) {
1288                         vector<string> actions;
1289                         actions.push_back (_("Don't quit"));
1290                         actions.push_back (_("Just quit"));
1291                         actions.push_back (_("Save and quit"));
1292                         switch (ask_about_saving_session(actions)) {
1293                         case -1:
1294                                 return;
1295                                 break;
1296                         case 1:
1297                                 /* use the default name */
1298                                 if (save_state_canfail ("")) {
1299                                         /* failed - don't quit */
1300                                         MessageDialog msg (_main_window,
1301                                                            string_compose (_("\
1302 %1 was unable to save your session.\n\n\
1303 If you still wish to quit, please use the\n\n\
1304 \"Just quit\" option."), PROGRAM_NAME));
1305                                         pop_back_splash(msg);
1306                                         msg.run ();
1307                                         return;
1308                                 }
1309                                 break;
1310                         case 0:
1311                                 break;
1312                         }
1313                 }
1314
1315                 second_connection.disconnect ();
1316                 point_one_second_connection.disconnect ();
1317                 point_zero_something_second_connection.disconnect();
1318                 fps_connection.disconnect();
1319         }
1320
1321         delete ARDOUR_UI::instance()->video_timeline;
1322         ARDOUR_UI::instance()->video_timeline = NULL;
1323         stop_video_server();
1324
1325         /* Save state before deleting the session, as that causes some
1326            windows to be destroyed before their visible state can be
1327            saved.
1328         */
1329         save_ardour_state ();
1330
1331         if (key_editor.get (false)) {
1332                 key_editor->disconnect ();
1333         }
1334
1335         close_all_dialogs ();
1336
1337         if (_session) {
1338                 _session->set_clean ();
1339                 _session->remove_pending_capture_state ();
1340                 delete _session;
1341                 _session = 0;
1342         }
1343
1344         halt_connection.disconnect ();
1345         AudioEngine::instance()->stop ();
1346 #ifdef WINDOWS_VST_SUPPORT
1347         fst_stop_threading();
1348 #endif
1349         quit ();
1350 }
1351
1352 int
1353 ARDOUR_UI::ask_about_saving_session (const vector<string>& actions)
1354 {
1355         ArdourDialog window (_("Unsaved Session"));
1356         Gtk::HBox dhbox;  // the hbox for the image and text
1357         Gtk::Label  prompt_label;
1358         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
1359
1360         string msg;
1361
1362         assert (actions.size() >= 3);
1363
1364         window.add_button (actions[0], RESPONSE_REJECT);
1365         window.add_button (actions[1], RESPONSE_APPLY);
1366         window.add_button (actions[2], RESPONSE_ACCEPT);
1367
1368         window.set_default_response (RESPONSE_ACCEPT);
1369
1370         Gtk::Button noquit_button (msg);
1371         noquit_button.set_name ("EditorGTKButton");
1372
1373         string prompt;
1374
1375         if (_session->snap_name() == _session->name()) {
1376                 prompt = string_compose(_("The session \"%1\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
1377                                         _session->snap_name());
1378         } else {
1379                 prompt = string_compose(_("The snapshot \"%1\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
1380                                         _session->snap_name());
1381         }
1382
1383         prompt_label.set_text (prompt);
1384         prompt_label.set_name (X_("PrompterLabel"));
1385         prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
1386
1387         dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
1388         dhbox.set_homogeneous (false);
1389         dhbox.pack_start (*dimage, false, false, 5);
1390         dhbox.pack_start (prompt_label, true, false, 5);
1391         window.get_vbox()->pack_start (dhbox);
1392
1393         window.set_name (_("Prompter"));
1394         window.set_modal (true);
1395         window.set_resizable (false);
1396
1397         dhbox.show();
1398         prompt_label.show();
1399         dimage->show();
1400         window.show();
1401         window.present ();
1402
1403         ResponseType r = (ResponseType) window.run();
1404
1405         window.hide ();
1406
1407         switch (r) {
1408         case RESPONSE_ACCEPT: // save and get out of here
1409                 return 1;
1410         case RESPONSE_APPLY:  // get out of here
1411                 return 0;
1412         default:
1413                 break;
1414         }
1415
1416         return -1;
1417 }
1418
1419
1420 void
1421 ARDOUR_UI::every_second ()
1422 {
1423         update_cpu_load ();
1424         update_xrun_count ();
1425         update_buffer_load ();
1426         update_disk_space ();
1427         update_timecode_format ();
1428         update_peak_thread_work ();
1429
1430         if (nsm && nsm->is_active ()) {
1431                 nsm->check ();
1432
1433                 if (!_was_dirty && _session->dirty ()) {
1434                         nsm->is_dirty ();
1435                         _was_dirty = true;
1436                 }
1437                 else if (_was_dirty && !_session->dirty ()){
1438                         nsm->is_clean ();
1439                         _was_dirty = false;
1440                 }
1441         }
1442 }
1443
1444 void
1445 ARDOUR_UI::every_point_one_seconds ()
1446 {
1447         // TODO get rid of this..
1448         // ShuttleControl is updated directly via TransportStateChange signal
1449 }
1450
1451 void
1452 ARDOUR_UI::every_point_zero_something_seconds ()
1453 {
1454         // august 2007: actual update frequency: 25Hz (40ms), not 100Hz
1455
1456         if (editor_meter && UIConfiguration::instance().get_show_editor_meter() && editor_meter_peak_display.is_mapped ()) {
1457                 float mpeak = editor_meter->update_meters();
1458                 if (mpeak > editor_meter_max_peak) {
1459                         if (mpeak >= UIConfiguration::instance().get_meter_peak()) {
1460                                 editor_meter_peak_display.set_active_state ( Gtkmm2ext::ExplicitActive );
1461                         }
1462                 }
1463         }
1464 }
1465
1466 void
1467 ARDOUR_UI::set_fps_timeout_connection ()
1468 {
1469         unsigned int interval = 40;
1470         if (!_session) return;
1471         if (_session->timecode_frames_per_second() != 0) {
1472                 /* ideally we'll use a select() to sleep and not accumulate
1473                  * idle time to provide a regular periodic signal.
1474                  * See linux_vst_gui_support.cc 'elapsed_time_ms'.
1475                  * However, that'll require a dedicated thread and cross-thread
1476                  * signals to the GUI Thread..
1477                  */
1478                 interval = floor(500. /* update twice per FPS, since Glib::signal_timeout is very irregular */
1479                                 * _session->frame_rate() / _session->nominal_frame_rate()
1480                                 / _session->timecode_frames_per_second()
1481                                 );
1482 #ifdef PLATFORM_WINDOWS
1483                 // the smallest windows scheduler time-slice is ~15ms.
1484                 // periodic GUI timeouts shorter than that will cause
1485                 // WaitForSingleObject to spinlock (100% of one CPU Core)
1486                 // and gtk never enters idle mode.
1487                 // also changing timeBeginPeriod(1) does not affect that in
1488                 // any beneficial way, so we just limit the max rate for now.
1489                 interval = std::max(30u, interval); // at most ~33Hz.
1490 #else
1491                 interval = std::max(8u, interval); // at most 120Hz.
1492 #endif
1493         }
1494         fps_connection.disconnect();
1495         Timers::set_fps_interval (interval);
1496 }
1497
1498 void
1499 ARDOUR_UI::update_sample_rate (framecnt_t)
1500 {
1501         char buf[64];
1502
1503         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
1504
1505         if (!AudioEngine::instance()->connected()) {
1506
1507                 snprintf (buf, sizeof (buf), "%s", _("Audio: <span foreground=\"red\">none</span>"));
1508
1509         } else {
1510
1511                 framecnt_t rate = AudioEngine::instance()->sample_rate();
1512
1513                 if (rate == 0) {
1514                         /* no sample rate available */
1515                         snprintf (buf, sizeof (buf), "%s", _("Audio: <span foreground=\"red\">none</span>"));
1516                 } else {
1517
1518                         if (fmod (rate, 1000.0) != 0.0) {
1519                                 snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"),
1520                                           (float) rate / 1000.0f,
1521                                           (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
1522                         } else {
1523                                 snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"),
1524                                           rate/1000,
1525                                           (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
1526                         }
1527                 }
1528         }
1529         sample_rate_label.set_markup (buf);
1530 }
1531
1532 void
1533 ARDOUR_UI::update_format ()
1534 {
1535         if (!_session) {
1536                 format_label.set_text ("");
1537                 return;
1538         }
1539
1540         stringstream s;
1541         s << _("File:") << X_(" <span foreground=\"green\">");
1542
1543         switch (_session->config.get_native_file_header_format ()) {
1544         case BWF:
1545                 s << _("BWF");
1546                 break;
1547         case WAVE:
1548                 s << _("WAV");
1549                 break;
1550         case WAVE64:
1551                 s << _("WAV64");
1552                 break;
1553         case CAF:
1554                 s << _("CAF");
1555                 break;
1556         case AIFF:
1557                 s << _("AIFF");
1558                 break;
1559         case iXML:
1560                 s << _("iXML");
1561                 break;
1562         case RF64:
1563                 s << _("RF64");
1564                 break;
1565         case RF64_WAV:
1566                 s << _("RF64/WAV");
1567                 break;
1568         case MBWF:
1569                 s << _("MBWF");
1570                 break;
1571         }
1572
1573         s << " ";
1574
1575         switch (_session->config.get_native_file_data_format ()) {
1576         case FormatFloat:
1577                 s << _("32-float");
1578                 break;
1579         case FormatInt24:
1580                 s << _("24-int");
1581                 break;
1582         case FormatInt16:
1583                 s << _("16-int");
1584                 break;
1585         }
1586
1587         s << X_("</span>");
1588
1589         format_label.set_markup (s.str ());
1590 }
1591
1592 void
1593 ARDOUR_UI::update_xrun_count ()
1594 {
1595         char buf[64];
1596
1597         /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1598            should also be changed.
1599         */
1600
1601         if (_session) {
1602                 const unsigned int x = _session->get_xrun_count ();
1603                 if (x > 9999) {
1604                         snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">&gt;10K</span>"), X_("red"));
1605                 } else {
1606                         snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">%u</span>"), x > 0 ? X_("red") : X_("green"), x);
1607                 }
1608         } else {
1609                 snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">?</span>"), X_("yellow"));
1610         }
1611         xrun_label.set_markup (buf);
1612         set_tip (xrun_label, _("Audio dropouts. Shift+click to reset"));
1613 }
1614
1615 void
1616 ARDOUR_UI::update_cpu_load ()
1617 {
1618         char buf[64];
1619
1620         /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1621            should also be changed.
1622         */
1623
1624         double const c = AudioEngine::instance()->get_dsp_load ();
1625         snprintf (buf, sizeof (buf), _("DSP: <span foreground=\"%s\">%5.1f%%</span>"), c >= 90 ? X_("red") : X_("green"), c);
1626         cpu_load_label.set_markup (buf);
1627 }
1628
1629 void
1630 ARDOUR_UI::update_peak_thread_work ()
1631 {
1632         char buf[64];
1633         const int c = SourceFactory::peak_work_queue_length ();
1634         if (c > 0) {
1635                 snprintf (buf, sizeof (buf), _("PkBld: <span foreground=\"%s\">%d</span>"), c >= 2 ? X_("red") : X_("green"), c);
1636                 peak_thread_work_label.set_markup (buf);
1637         } else {
1638                 peak_thread_work_label.set_markup (X_(""));
1639         }
1640 }
1641
1642 void
1643 ARDOUR_UI::update_buffer_load ()
1644 {
1645         char buf[256];
1646
1647         uint32_t const playback = _session ? _session->playback_load () : 100;
1648         uint32_t const capture = _session ? _session->capture_load () : 100;
1649
1650         /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1651            should also be changed.
1652         */
1653
1654         if (_session) {
1655                 snprintf (
1656                         buf, sizeof (buf),
1657                         _("Buffers: <span foreground=\"green\">p:</span><span foreground=\"%s\">%" PRIu32 "%%</span> "
1658                                    "<span foreground=\"green\">c:</span><span foreground=\"%s\">%" PRIu32 "%%</span>"),
1659                         playback <= 5 ? X_("red") : X_("green"),
1660                         playback,
1661                         capture <= 5 ? X_("red") : X_("green"),
1662                         capture
1663                         );
1664
1665                 buffer_load_label.set_markup (buf);
1666         } else {
1667                 buffer_load_label.set_text ("");
1668         }
1669 }
1670
1671 void
1672 ARDOUR_UI::count_recenabled_streams (Route& route)
1673 {
1674         Track* track = dynamic_cast<Track*>(&route);
1675         if (track && track->rec_enable_control()->get_value()) {
1676                 rec_enabled_streams += track->n_inputs().n_total();
1677         }
1678 }
1679
1680 void
1681 ARDOUR_UI::update_disk_space()
1682 {
1683         if (_session == 0) {
1684                 return;
1685         }
1686
1687         boost::optional<framecnt_t> opt_frames = _session->available_capture_duration();
1688         char buf[64];
1689         framecnt_t fr = _session->frame_rate();
1690
1691         if (fr == 0) {
1692                 /* skip update - no SR available */
1693                 return;
1694         }
1695
1696         if (!opt_frames) {
1697                 /* Available space is unknown */
1698                 snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">Unknown</span>"));
1699         } else if (opt_frames.get_value_or (0) == max_framecnt) {
1700                 snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">24hrs+</span>"));
1701         } else {
1702                 rec_enabled_streams = 0;
1703                 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams, false);
1704
1705                 framecnt_t frames = opt_frames.get_value_or (0);
1706
1707                 if (rec_enabled_streams) {
1708                         frames /= rec_enabled_streams;
1709                 }
1710
1711                 int hrs;
1712                 int mins;
1713                 int secs;
1714
1715                 hrs  = frames / (fr * 3600);
1716
1717                 if (hrs > 24) {
1718                         snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">&gt;24 hrs</span>"));
1719                 } else {
1720                         frames -= hrs * fr * 3600;
1721                         mins = frames / (fr * 60);
1722                         frames -= mins * fr * 60;
1723                         secs = frames / fr;
1724
1725                         bool const low = (hrs == 0 && mins <= 30);
1726
1727                         snprintf (
1728                                 buf, sizeof(buf),
1729                                 _("Disk: <span foreground=\"%s\">%02dh:%02dm:%02ds</span>"),
1730                                 low ? X_("red") : X_("green"),
1731                                 hrs, mins, secs
1732                                 );
1733                 }
1734         }
1735
1736         disk_space_label.set_markup (buf);
1737 }
1738
1739 void
1740 ARDOUR_UI::update_timecode_format ()
1741 {
1742         char buf[64];
1743
1744         if (_session) {
1745                 bool matching;
1746                 TimecodeSlave* tcslave;
1747                 SyncSource sync_src = Config->get_sync_source();
1748
1749                 if ((sync_src == LTC || sync_src == MTC) && (tcslave = dynamic_cast<TimecodeSlave*>(_session->slave())) != 0) {
1750                         matching = (tcslave->apparent_timecode_format() == _session->config.get_timecode_format());
1751                 } else {
1752                         matching = true;
1753                 }
1754
1755                 snprintf (buf, sizeof (buf), S_("Timecode|TC: <span foreground=\"%s\">%s</span>"),
1756                           matching ? X_("green") : X_("red"),
1757                           Timecode::timecode_format_name (_session->config.get_timecode_format()).c_str());
1758         } else {
1759                 snprintf (buf, sizeof (buf), "TC: n/a");
1760         }
1761
1762         timecode_format_label.set_markup (buf);
1763 }
1764
1765 gint
1766 ARDOUR_UI::update_wall_clock ()
1767 {
1768         time_t now;
1769         struct tm *tm_now;
1770         static int last_min = -1;
1771
1772         time (&now);
1773         tm_now = localtime (&now);
1774         if (last_min != tm_now->tm_min) {
1775                 char buf[16];
1776                 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1777                 wall_clock_label.set_text (buf);
1778                 last_min = tm_now->tm_min;
1779         }
1780
1781         return TRUE;
1782 }
1783
1784 void
1785 ARDOUR_UI::open_recent_session ()
1786 {
1787         bool can_return = (_session != 0);
1788
1789         SessionDialog recent_session_dialog;
1790
1791         while (true) {
1792
1793                 ResponseType r = (ResponseType) recent_session_dialog.run ();
1794
1795                 switch (r) {
1796                 case RESPONSE_ACCEPT:
1797                         break;
1798                 default:
1799                         if (can_return) {
1800                                 recent_session_dialog.hide();
1801                                 return;
1802                         } else {
1803                                 exit (1);
1804                         }
1805                 }
1806
1807                 recent_session_dialog.hide();
1808
1809                 bool should_be_new;
1810
1811                 std::string path = recent_session_dialog.session_folder();
1812                 std::string state = recent_session_dialog.session_name (should_be_new);
1813
1814                 if (should_be_new == true) {
1815                         continue;
1816                 }
1817
1818                 _session_is_new = false;
1819
1820                 if (load_session (path, state) == 0) {
1821                         break;
1822                 }
1823
1824                 can_return = false;
1825         }
1826         if (splash && splash->is_visible()) {
1827                 // in 1 second, hide the splash screen
1828                 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
1829         }
1830 }
1831
1832 bool
1833 ARDOUR_UI::check_audioengine (Gtk::Window& parent)
1834 {
1835         if (!AudioEngine::instance()->connected()) {
1836                 MessageDialog msg (parent, string_compose (
1837                                            _("%1 is not connected to any audio backend.\n"
1838                                              "You cannot open or close sessions in this condition"),
1839                                            PROGRAM_NAME));
1840                 pop_back_splash (msg);
1841                 msg.run ();
1842                 return false;
1843         }
1844         return true;
1845 }
1846
1847 void
1848 ARDOUR_UI::open_session ()
1849 {
1850         if (!check_audioengine (_main_window)) {
1851                 return;
1852         }
1853
1854         /* ardour sessions are folders */
1855         Gtk::FileChooserDialog open_session_selector(_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1856         open_session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1857         open_session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1858         open_session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
1859
1860         if (_session) {
1861                 string session_parent_dir = Glib::path_get_dirname(_session->path());
1862                 open_session_selector.set_current_folder(session_parent_dir);
1863         } else {
1864                 open_session_selector.set_current_folder(Config->get_default_session_parent_dir());
1865         }
1866
1867         Gtkmm2ext::add_volume_shortcuts (open_session_selector);
1868         try {
1869                 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
1870                 string default_session_folder = Config->get_default_session_parent_dir();
1871                 open_session_selector.add_shortcut_folder (default_session_folder);
1872         }
1873         catch (Glib::Error & e) {
1874                 std::cerr << "open_session_selector.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
1875         }
1876
1877         FileFilter session_filter;
1878         session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
1879         session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1880         open_session_selector.add_filter (session_filter);
1881         open_session_selector.set_filter (session_filter);
1882
1883         int response = open_session_selector.run();
1884         open_session_selector.hide ();
1885
1886         if (response == Gtk::RESPONSE_CANCEL) {
1887                 return;
1888         }
1889
1890         string session_path = open_session_selector.get_filename();
1891         string path, name;
1892         bool isnew;
1893
1894         if (session_path.length() > 0) {
1895                 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1896                         _session_is_new = isnew;
1897                         load_session (path, name);
1898                 }
1899         }
1900 }
1901
1902 void
1903 ARDOUR_UI::session_add_vca (const string& name_template, uint32_t n)
1904 {
1905         if (!_session) {
1906                 return;
1907         }
1908
1909         _session->vca_manager().create_vca (n, name_template);
1910 }
1911
1912 void
1913 ARDOUR_UI::session_add_mixed_track (
1914                 const ChanCount& input,
1915                 const ChanCount& output,
1916                 RouteGroup* route_group,
1917                 uint32_t how_many,
1918                 const string& name_template,
1919                 bool strict_io,
1920                 PluginInfoPtr instrument,
1921                 Plugin::PresetRecord* pset,
1922                 ARDOUR::PresentationInfo::order_t order)
1923 {
1924         list<boost::shared_ptr<MidiTrack> > tracks;
1925
1926         if (_session == 0) {
1927                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1928                 return;
1929         }
1930
1931         try {
1932                 tracks = _session->new_midi_track (input, output, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal);
1933
1934                 if (tracks.size() != how_many) {
1935                         error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg;
1936                 }
1937         }
1938
1939         catch (...) {
1940                 display_insufficient_ports_message ();
1941                 return;
1942         }
1943
1944         if (strict_io) {
1945                 for (list<boost::shared_ptr<MidiTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
1946                         (*i)->set_strict_io (true);
1947                 }
1948         }
1949 }
1950
1951 void
1952 ARDOUR_UI::session_add_midi_bus (
1953                 RouteGroup* route_group,
1954                 uint32_t how_many,
1955                 const string& name_template,
1956                 bool strict_io,
1957                 PluginInfoPtr instrument,
1958                 Plugin::PresetRecord* pset,
1959                 ARDOUR::PresentationInfo::order_t order)
1960 {
1961         RouteList routes;
1962
1963         if (_session == 0) {
1964                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1965                 return;
1966         }
1967
1968         try {
1969
1970                 routes = _session->new_midi_route (route_group, how_many, name_template, instrument, pset, PresentationInfo::MidiBus, order);
1971                 if (routes.size() != how_many) {
1972                         error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg;
1973                 }
1974
1975         }
1976         catch (...) {
1977                 display_insufficient_ports_message ();
1978                 return;
1979         }
1980
1981         if (strict_io) {
1982                 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1983                         (*i)->set_strict_io (true);
1984                 }
1985         }
1986 }
1987
1988 void
1989 ARDOUR_UI::session_add_midi_route (
1990                 bool disk,
1991                 RouteGroup* route_group,
1992                 uint32_t how_many,
1993                 const string& name_template,
1994                 bool strict_io,
1995                 PluginInfoPtr instrument,
1996                 Plugin::PresetRecord* pset,
1997                 ARDOUR::PresentationInfo::order_t order)
1998 {
1999         ChanCount one_midi_channel;
2000         one_midi_channel.set (DataType::MIDI, 1);
2001
2002         if (disk) {
2003                 session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, strict_io, instrument, pset, order);
2004         } else {
2005                 session_add_midi_bus (route_group, how_many, name_template, strict_io, instrument, pset, order);
2006         }
2007 }
2008
2009 void
2010 ARDOUR_UI::session_add_audio_route (
2011         bool track,
2012         int32_t input_channels,
2013         int32_t output_channels,
2014         ARDOUR::TrackMode mode,
2015         RouteGroup* route_group,
2016         uint32_t how_many,
2017         string const & name_template,
2018         bool strict_io,
2019         ARDOUR::PresentationInfo::order_t order)
2020 {
2021         list<boost::shared_ptr<AudioTrack> > tracks;
2022         RouteList routes;
2023
2024         if (_session == 0) {
2025                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
2026                 return;
2027         }
2028
2029         try {
2030                 if (track) {
2031                         tracks = _session->new_audio_track (input_channels, output_channels, route_group, how_many, name_template, order, mode);
2032
2033                         if (tracks.size() != how_many) {
2034                                 error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many)
2035                                       << endmsg;
2036                         }
2037
2038                 } else {
2039
2040                         routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template, PresentationInfo::AudioBus, order);
2041
2042                         if (routes.size() != how_many) {
2043                                 error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many)
2044                                       << endmsg;
2045                         }
2046                 }
2047         }
2048
2049         catch (...) {
2050                 display_insufficient_ports_message ();
2051                 return;
2052         }
2053
2054         if (strict_io) {
2055                 for (list<boost::shared_ptr<AudioTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
2056                         (*i)->set_strict_io (true);
2057                 }
2058                 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2059                         (*i)->set_strict_io (true);
2060                 }
2061         }
2062 }
2063
2064 void
2065 ARDOUR_UI::display_insufficient_ports_message ()
2066 {
2067         MessageDialog msg (_main_window,
2068                         string_compose (_("There are insufficient ports available\n\
2069 to create a new track or bus.\n\
2070 You should save %1, exit and\n\
2071 restart with more ports."), PROGRAM_NAME));
2072         pop_back_splash (msg);
2073         msg.run ();
2074 }
2075
2076 void
2077 ARDOUR_UI::transport_goto_start ()
2078 {
2079         if (_session) {
2080                 _session->goto_start();
2081
2082                 /* force displayed area in editor to start no matter
2083                    what "follow playhead" setting is.
2084                 */
2085
2086                 if (editor) {
2087                         editor->center_screen (_session->current_start_frame ());
2088                 }
2089         }
2090 }
2091
2092 void
2093 ARDOUR_UI::transport_goto_zero ()
2094 {
2095         if (_session) {
2096                 _session->request_locate (0);
2097
2098                 /* force displayed area in editor to start no matter
2099                    what "follow playhead" setting is.
2100                 */
2101
2102                 if (editor) {
2103                         editor->reset_x_origin (0);
2104                 }
2105         }
2106 }
2107
2108 void
2109 ARDOUR_UI::transport_goto_wallclock ()
2110 {
2111         if (_session && editor) {
2112
2113                 time_t now;
2114                 struct tm tmnow;
2115                 framepos_t frames;
2116
2117                 time (&now);
2118                 localtime_r (&now, &tmnow);
2119
2120                 framecnt_t frame_rate = _session->frame_rate();
2121
2122                 if (frame_rate == 0) {
2123                         /* no frame rate available */
2124                         return;
2125                 }
2126
2127                 frames = tmnow.tm_hour * (60 * 60 * frame_rate);
2128                 frames += tmnow.tm_min * (60 * frame_rate);
2129                 frames += tmnow.tm_sec * frame_rate;
2130
2131                 _session->request_locate (frames, _session->transport_rolling ());
2132
2133                 /* force displayed area in editor to start no matter
2134                    what "follow playhead" setting is.
2135                 */
2136
2137                 if (editor) {
2138                         editor->center_screen (frames);
2139                 }
2140         }
2141 }
2142
2143 void
2144 ARDOUR_UI::transport_goto_end ()
2145 {
2146         if (_session) {
2147                 framepos_t const frame = _session->current_end_frame();
2148                 _session->request_locate (frame);
2149
2150                 /* force displayed area in editor to start no matter
2151                    what "follow playhead" setting is.
2152                 */
2153
2154                 if (editor) {
2155                         editor->center_screen (frame);
2156                 }
2157         }
2158 }
2159
2160 void
2161 ARDOUR_UI::transport_stop ()
2162 {
2163         if (!_session) {
2164                 return;
2165         }
2166
2167         if (_session->is_auditioning()) {
2168                 _session->cancel_audition ();
2169                 return;
2170         }
2171
2172         _session->request_stop (false, true);
2173 }
2174
2175 /** Check if any tracks are record enabled. If none are, record enable all of them.
2176  * @return true if track record-enabled status was changed, false otherwise.
2177  */
2178 bool
2179 ARDOUR_UI::trx_record_enable_all_tracks ()
2180 {
2181         if (!_session) {
2182                 return false;
2183         }
2184
2185         boost::shared_ptr<RouteList> rl = _session->get_tracks ();
2186         bool none_record_enabled = true;
2187
2188         for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
2189                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*r);
2190                 assert (t);
2191
2192                 if (t->rec_enable_control()->get_value()) {
2193                         none_record_enabled = false;
2194                         break;
2195                 }
2196         }
2197
2198         if (none_record_enabled) {
2199                 _session->set_controls (route_list_to_control_list (rl, &Stripable::rec_enable_control), 1.0, Controllable::NoGroup);
2200         }
2201
2202         return none_record_enabled;
2203 }
2204
2205 void
2206 ARDOUR_UI::transport_record (bool roll)
2207 {
2208         if (_session) {
2209                 switch (_session->record_status()) {
2210                 case Session::Disabled:
2211                         if (_session->ntracks() == 0) {
2212                                 MessageDialog msg (_main_window, _("Please create one or more tracks before trying to record.\nYou can do this with the \"Add Track or Bus\" option in the Session menu."));
2213                                 msg.run ();
2214                                 return;
2215                         }
2216                         if (Profile->get_trx()) {
2217                                 roll = trx_record_enable_all_tracks ();
2218                         }
2219                         _session->maybe_enable_record ();
2220                         if (roll) {
2221                                 transport_roll ();
2222                         }
2223                         break;
2224                 case Session::Recording:
2225                         if (roll) {
2226                                 _session->request_stop();
2227                         } else {
2228                                 _session->disable_record (false, true);
2229                         }
2230                         break;
2231
2232                 case Session::Enabled:
2233                         _session->disable_record (false, true);
2234                 }
2235         }
2236 }
2237
2238 void
2239 ARDOUR_UI::transport_roll ()
2240 {
2241         if (!_session) {
2242                 return;
2243         }
2244
2245         if (_session->is_auditioning()) {
2246                 return;
2247         }
2248
2249 #if 0
2250         if (_session->config.get_external_sync()) {
2251                 switch (Config->get_sync_source()) {
2252                 case Engine:
2253                         break;
2254                 default:
2255                         /* transport controlled by the master */
2256                         return;
2257                 }
2258         }
2259 #endif
2260
2261         bool rolling = _session->transport_rolling();
2262
2263         if (_session->get_play_loop()) {
2264
2265                 /* If loop playback is not a mode, then we should cancel
2266                    it when this action is requested. If it is a mode
2267                    we just leave it in place.
2268                 */
2269
2270                 if (!Config->get_loop_is_mode()) {
2271                         /* XXX it is not possible to just leave seamless loop and keep
2272                            playing at present (nov 4th 2009)
2273                         */
2274                         if (!Config->get_seamless_loop()) {
2275                                 /* stop loop playback and stop rolling */
2276                                 _session->request_play_loop (false, true);
2277                         } else if (rolling) {
2278                                 /* stop loop playback but keep rolling */
2279                                 _session->request_play_loop (false, false);
2280                         }
2281                 }
2282
2283         } else if (_session->get_play_range () ) {
2284                 /* stop playing a range if we currently are */
2285                 _session->request_play_range (0, true);
2286         }
2287
2288         if (!rolling) {
2289                 _session->request_transport_speed (1.0f);
2290         }
2291 }
2292
2293 bool
2294 ARDOUR_UI::get_smart_mode() const
2295 {
2296         return ( editor->get_smart_mode() );
2297 }
2298
2299
2300 void
2301 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
2302 {
2303         if (!_session) {
2304                 return;
2305         }
2306
2307         if (_session->is_auditioning()) {
2308                 _session->cancel_audition ();
2309                 return;
2310         }
2311
2312         if (_session->config.get_external_sync()) {
2313                 switch (Config->get_sync_source()) {
2314                 case Engine:
2315                         break;
2316                 default:
2317                         /* transport controlled by the master */
2318                         return;
2319                 }
2320         }
2321
2322         bool rolling = _session->transport_rolling();
2323         bool affect_transport = true;
2324
2325         if (rolling && roll_out_of_bounded_mode) {
2326                 /* drop out of loop/range playback but leave transport rolling */
2327                 if (_session->get_play_loop()) {
2328                         if (_session->actively_recording()) {
2329
2330                                 /* just stop using the loop, then actually stop
2331                                  * below
2332                                  */
2333                                 _session->request_play_loop (false, affect_transport);
2334
2335                         } else {
2336                                 if (Config->get_seamless_loop()) {
2337                                         /* the disk buffers contain copies of the loop - we can't
2338                                            just keep playing, so stop the transport. the user
2339                                            can restart as they wish.
2340                                         */
2341                                         affect_transport = true;
2342                                 } else {
2343                                         /* disk buffers are normal, so we can keep playing */
2344                                         affect_transport = false;
2345                                 }
2346                                 _session->request_play_loop (false, affect_transport);
2347                         }
2348                 } else if (_session->get_play_range ()) {
2349                         affect_transport = false;
2350                         _session->request_play_range (0, true);
2351                 }
2352         }
2353
2354         if (affect_transport) {
2355                 if (rolling) {
2356                         _session->request_stop (with_abort, true);
2357
2358                 } else if (!with_abort) { /* with_abort == true means the
2359                                            * command was intended to stop
2360                                            * transport, not start.
2361                                            */
2362
2363                         /* the only external sync condition we can be in here
2364                          * would be Engine (JACK) sync, in which case we still
2365                          * want to do this.
2366                          */
2367
2368                         if (UIConfiguration::instance().get_follow_edits() && ( editor->get_selection().time.front().start == _session->transport_frame() ) ) {  //if playhead is exactly at the start of a range, we can assume it was placed there by follow_edits
2369                                 _session->request_play_range (&editor->get_selection().time, true);
2370                                 _session->set_requested_return_frame( editor->get_selection().time.front().start );  //force an auto-return here
2371                         }
2372                         _session->request_transport_speed (1.0f);
2373                 }
2374         }
2375 }
2376
2377 void
2378 ARDOUR_UI::toggle_session_auto_loop ()
2379 {
2380         if (!_session) {
2381                 return;
2382         }
2383
2384         Location * looploc = _session->locations()->auto_loop_location();
2385
2386         if (!looploc) {
2387                 return;
2388         }
2389
2390         if (_session->get_play_loop()) {
2391
2392                 /* looping enabled, our job is to disable it */
2393
2394                 _session->request_play_loop (false);
2395
2396         } else {
2397
2398                 /* looping not enabled, our job is to enable it.
2399
2400                    loop-is-NOT-mode: this action always starts the transport rolling.
2401                    loop-IS-mode:     this action simply sets the loop play mechanism, but
2402                                         does not start transport.
2403                 */
2404                 if (Config->get_loop_is_mode()) {
2405                         _session->request_play_loop (true, false);
2406                 } else {
2407                         _session->request_play_loop (true, true);
2408                 }
2409         }
2410
2411         //show the loop markers
2412         looploc->set_hidden (false, this);
2413 }
2414
2415 void
2416 ARDOUR_UI::transport_play_selection ()
2417 {
2418         if (!_session) {
2419                 return;
2420         }
2421
2422         editor->play_selection ();
2423 }
2424
2425 void
2426 ARDOUR_UI::transport_play_preroll ()
2427 {
2428         if (!_session) {
2429                 return;
2430         }
2431         editor->play_with_preroll ();
2432 }
2433
2434 void
2435 ARDOUR_UI::transport_rewind (int option)
2436 {
2437         float current_transport_speed;
2438
2439         if (_session) {
2440                 current_transport_speed = _session->transport_speed();
2441
2442                 if (current_transport_speed >= 0.0f) {
2443                         switch (option) {
2444                         case 0:
2445                                 _session->request_transport_speed (-1.0f);
2446                                 break;
2447                         case 1:
2448                                 _session->request_transport_speed (-4.0f);
2449                                 break;
2450                         case -1:
2451                                 _session->request_transport_speed (-0.5f);
2452                                 break;
2453                         }
2454                 } else {
2455                         /* speed up */
2456                         _session->request_transport_speed (current_transport_speed * 1.5f);
2457                 }
2458         }
2459 }
2460
2461 void
2462 ARDOUR_UI::transport_forward (int option)
2463 {
2464         if (!_session) {
2465                 return;
2466         }
2467
2468         float current_transport_speed = _session->transport_speed();
2469
2470         if (current_transport_speed <= 0.0f) {
2471                 switch (option) {
2472                 case 0:
2473                         _session->request_transport_speed (1.0f);
2474                         break;
2475                 case 1:
2476                         _session->request_transport_speed (4.0f);
2477                         break;
2478                 case -1:
2479                         _session->request_transport_speed (0.5f);
2480                         break;
2481                 }
2482         } else {
2483                 /* speed up */
2484                 _session->request_transport_speed (current_transport_speed * 1.5f);
2485         }
2486 }
2487
2488 void
2489 ARDOUR_UI::toggle_record_enable (uint16_t rid)
2490 {
2491         if (!_session) {
2492                 return;
2493         }
2494
2495         boost::shared_ptr<Route> r;
2496
2497         if ((r = _session->get_remote_nth_route (rid)) != 0) {
2498
2499                 boost::shared_ptr<Track> t;
2500
2501                 if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
2502                         t->rec_enable_control()->set_value (!t->rec_enable_control()->get_value(), Controllable::UseGroup);
2503                 }
2504         }
2505 }
2506
2507 void
2508 ARDOUR_UI::map_transport_state ()
2509 {
2510         if (!_session) {
2511                 auto_loop_button.unset_active_state ();
2512                 play_selection_button.unset_active_state ();
2513                 roll_button.unset_active_state ();
2514                 stop_button.set_active_state (Gtkmm2ext::ExplicitActive);
2515                 layered_button.set_sensitive (false);
2516                 return;
2517         }
2518
2519         shuttle_box.map_transport_state ();
2520
2521         float sp = _session->transport_speed();
2522
2523         if (sp != 0.0f) {
2524
2525                 /* we're rolling */
2526
2527                 if (_session->get_play_range()) {
2528
2529                         play_selection_button.set_active_state (Gtkmm2ext::ExplicitActive);
2530                         roll_button.unset_active_state ();
2531                         auto_loop_button.unset_active_state ();
2532
2533                 } else if (_session->get_play_loop ()) {
2534
2535                         auto_loop_button.set_active (true);
2536                         play_selection_button.set_active (false);
2537                         if (Config->get_loop_is_mode()) {
2538                                 roll_button.set_active (true);
2539                         } else {
2540                                 roll_button.set_active (false);
2541                         }
2542
2543                 } else {
2544
2545                         roll_button.set_active (true);
2546                         play_selection_button.set_active (false);
2547                         auto_loop_button.set_active (false);
2548                 }
2549
2550                 if (UIConfiguration::instance().get_follow_edits() && !_session->config.get_external_sync()) {
2551                         /* light up both roll and play-selection if they are joined */
2552                         roll_button.set_active (true);
2553                         play_selection_button.set_active (true);
2554                 }
2555                 layered_button.set_sensitive (!_session->actively_recording ());
2556
2557                 stop_button.set_active (false);
2558
2559         } else {
2560
2561                 layered_button.set_sensitive (true);
2562                 stop_button.set_active (true);
2563                 roll_button.set_active (false);
2564                 play_selection_button.set_active (false);
2565                 if (Config->get_loop_is_mode ()) {
2566                         auto_loop_button.set_active (_session->get_play_loop());
2567                 } else {
2568                         auto_loop_button.set_active (false);
2569                 }
2570                 update_disk_space ();
2571         }
2572 }
2573
2574 void
2575 ARDOUR_UI::blink_handler (bool blink_on)
2576 {
2577         transport_rec_enable_blink (blink_on);
2578         solo_blink (blink_on);
2579         sync_blink (blink_on);
2580         audition_blink (blink_on);
2581         feedback_blink (blink_on);
2582         error_blink (blink_on);
2583 }
2584
2585 void
2586 ARDOUR_UI::update_clocks ()
2587 {
2588         if (!_session) return;
2589
2590         if (editor && !editor->dragging_playhead()) {
2591                 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD)); /* EMIT_SIGNAL */
2592         }
2593 }
2594
2595 void
2596 ARDOUR_UI::start_clocking ()
2597 {
2598         if (UIConfiguration::instance().get_super_rapid_clock_update()) {
2599                 clock_signal_connection = Timers::fps_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2600         } else {
2601                 clock_signal_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2602         }
2603 }
2604
2605 void
2606 ARDOUR_UI::stop_clocking ()
2607 {
2608         clock_signal_connection.disconnect ();
2609 }
2610
2611 bool
2612 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
2613 {
2614         char buf[256];
2615
2616         snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
2617
2618         label->set_text (buf);
2619         bar->set_fraction (fraction);
2620
2621         /* process events, redraws, etc. */
2622
2623         while (gtk_events_pending()) {
2624                 gtk_main_iteration ();
2625         }
2626
2627         return true; /* continue with save-as */
2628 }
2629
2630 void
2631 ARDOUR_UI::save_session_as ()
2632 {
2633         if (!_session) {
2634                 return;
2635         }
2636
2637         if (!save_as_dialog) {
2638                 save_as_dialog = new SaveAsDialog;
2639         }
2640
2641         save_as_dialog->set_name (_session->name());
2642
2643         int response = save_as_dialog->run ();
2644
2645         save_as_dialog->hide ();
2646
2647         switch (response) {
2648         case Gtk::RESPONSE_OK:
2649                 break;
2650         default:
2651                 return;
2652         }
2653
2654
2655         Session::SaveAs sa;
2656
2657         sa.new_parent_folder = save_as_dialog->new_parent_folder ();
2658         sa.new_name = save_as_dialog->new_name ();
2659         sa.switch_to = save_as_dialog->switch_to();
2660         sa.copy_media = save_as_dialog->copy_media();
2661         sa.copy_external = save_as_dialog->copy_external();
2662         sa.include_media = save_as_dialog->include_media ();
2663
2664         /* Only bother with a progress dialog if we're going to copy
2665            media into the save-as target. Without that choice, this
2666            will be very fast because we're only talking about a few kB's to
2667            perhaps a couple of MB's of data.
2668         */
2669
2670         ArdourDialog progress_dialog (_("Save As"), true);
2671
2672         if (sa.include_media && sa.copy_media) {
2673
2674                 Gtk::Label label;
2675                 Gtk::ProgressBar progress_bar;
2676
2677                 progress_dialog.get_vbox()->pack_start (label);
2678                 progress_dialog.get_vbox()->pack_start (progress_bar);
2679                 label.show ();
2680                 progress_bar.show ();
2681
2682                 /* this signal will be emitted from within this, the calling thread,
2683                  * after every file is copied. It provides information on percentage
2684                  * complete (in terms of total data to copy), the number of files
2685                  * copied so far, and the total number to copy.
2686                  */
2687
2688                 ScopedConnection c;
2689
2690                 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, &label, &progress_bar));
2691
2692                 progress_dialog.show_all ();
2693                 progress_dialog.present ();
2694         }
2695
2696         if (_session->save_as (sa)) {
2697                 /* ERROR MESSAGE */
2698                 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
2699                 msg.run ();
2700         }
2701
2702         if (!sa.include_media) {
2703                 unload_session (false);
2704                 load_session (sa.final_session_folder_name, sa.new_name);
2705         }
2706 }
2707
2708 void
2709 ARDOUR_UI::archive_session ()
2710 {
2711         if (!_session) {
2712                 return;
2713         }
2714
2715         time_t n;
2716         time (&n);
2717         Glib::DateTime gdt (Glib::DateTime::create_now_local (n));
2718
2719         SessionArchiveDialog sad;
2720         sad.set_name (_session->name() + gdt.format ("_%F_%H%M%S"));
2721         int response = sad.run ();
2722
2723         if (response != Gtk::RESPONSE_OK) {
2724                 sad.hide ();
2725                 return;
2726         }
2727
2728         if (_session->archive_session (sad.target_folder(), sad.name(), sad.encode_option (), sad.only_used_sources (), &sad)) {
2729                 MessageDialog msg (_("Session Archiving failed."));
2730                 msg.run ();
2731         }
2732 }
2733
2734 void
2735 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
2736 {
2737                 char timebuf[128];
2738                 time_t n;
2739                 struct tm local_time;
2740
2741                 time (&n);
2742                 localtime_r (&n, &local_time);
2743                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2744
2745                 save_state (timebuf, switch_to_it);
2746 }
2747
2748
2749 bool
2750 ARDOUR_UI::process_snapshot_session_prompter (ArdourPrompter& prompter, bool switch_to_it)
2751 {
2752         string snapname;
2753
2754         prompter.get_result (snapname);
2755
2756         bool do_save = (snapname.length() != 0);
2757
2758         if (do_save) {
2759                 char illegal = Session::session_name_is_legal(snapname);
2760                 if (illegal) {
2761                         MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2762                                              "snapshot names may not contain a '%1' character"), illegal));
2763                         msg.run ();
2764                         return false;
2765                 }
2766         }
2767
2768         vector<std::string> p;
2769         get_state_files_in_directory (_session->session_directory().root_path(), p);
2770         vector<string> n = get_file_names_no_extension (p);
2771
2772         if (find (n.begin(), n.end(), snapname) != n.end()) {
2773
2774                 do_save = overwrite_file_dialog (prompter,
2775                                                  _("Confirm Snapshot Overwrite"),
2776                                                  _("A snapshot already exists with that name. Do you want to overwrite it?"));
2777         }
2778
2779         if (do_save) {
2780                 save_state (snapname, switch_to_it);
2781         }
2782         else {
2783                 return false;
2784         }
2785
2786         return true;
2787 }
2788
2789
2790 /** Ask the user for the name of a new snapshot and then take it.
2791  */
2792
2793 void
2794 ARDOUR_UI::snapshot_session (bool switch_to_it)
2795 {
2796         ArdourPrompter prompter (true);
2797
2798         prompter.set_name ("Prompter");
2799         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2800         if (switch_to_it) {
2801                 prompter.set_title (_("Snapshot and switch"));
2802                 prompter.set_prompt (_("New session name"));
2803         } else {
2804                 prompter.set_title (_("Take Snapshot"));
2805                 prompter.set_prompt (_("Name of new snapshot"));
2806         }
2807
2808         if (switch_to_it) {
2809                 prompter.set_initial_text (_session->snap_name());
2810         } else {
2811                 Glib::DateTime tm (g_date_time_new_now_local ());
2812                 prompter.set_initial_text (tm.format ("%FT%H.%M.%S"));
2813         }
2814
2815         bool finished = false;
2816         while (!finished) {
2817                 switch (prompter.run()) {
2818                 case RESPONSE_ACCEPT:
2819                 {
2820                         finished = process_snapshot_session_prompter (prompter, switch_to_it);
2821                         break;
2822                 }
2823
2824                 default:
2825                         finished = true;
2826                         break;
2827                 }
2828         }
2829 }
2830
2831 /** Ask the user for a new session name and then rename the session to it.
2832  */
2833
2834 void
2835 ARDOUR_UI::rename_session ()
2836 {
2837         if (!_session) {
2838                 return;
2839         }
2840
2841         ArdourPrompter prompter (true);
2842         string name;
2843
2844         prompter.set_name ("Prompter");
2845         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2846         prompter.set_title (_("Rename Session"));
2847         prompter.set_prompt (_("New session name"));
2848
2849   again:
2850         switch (prompter.run()) {
2851         case RESPONSE_ACCEPT:
2852         {
2853                 prompter.get_result (name);
2854
2855                 bool do_rename = (name.length() != 0);
2856
2857                 if (do_rename) {
2858                         char illegal = Session::session_name_is_legal (name);
2859
2860                         if (illegal) {
2861                                 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2862                                                                      "session names may not contain a '%1' character"), illegal));
2863                                 msg.run ();
2864                                 goto again;
2865                         }
2866
2867                         switch (_session->rename (name)) {
2868                         case -1: {
2869                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2870                                 msg.set_position (WIN_POS_MOUSE);
2871                                 msg.run ();
2872                                 goto again;
2873                                 break;
2874                         }
2875                         case 0:
2876                                 break;
2877                         default: {
2878                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2879                                 msg.set_position (WIN_POS_MOUSE);
2880                                 msg.run ();
2881                                 break;
2882                         }
2883                         }
2884                 }
2885
2886                 break;
2887         }
2888
2889         default:
2890                 break;
2891         }
2892 }
2893
2894 void
2895 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2896 {
2897         if (!_session || _session->deletion_in_progress()) {
2898                 return;
2899         }
2900
2901         XMLNode* node = new XMLNode (X_("UI"));
2902
2903         WM::Manager::instance().add_state (*node);
2904
2905         node->add_child_nocopy (gui_object_state->get_state());
2906
2907         _session->add_extra_xml (*node);
2908
2909         if (export_video_dialog) {
2910                 _session->add_extra_xml (export_video_dialog->get_state());
2911         }
2912
2913         save_state_canfail (name, switch_to_it);
2914 }
2915
2916 int
2917 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2918 {
2919         if (_session) {
2920                 int ret;
2921
2922                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2923                         return ret;
2924                 }
2925         }
2926
2927         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2928         return 0;
2929 }
2930
2931 void
2932 ARDOUR_UI::primary_clock_value_changed ()
2933 {
2934         if (_session) {
2935                 _session->request_locate (primary_clock->current_time ());
2936         }
2937 }
2938
2939 void
2940 ARDOUR_UI::big_clock_value_changed ()
2941 {
2942         if (_session) {
2943                 _session->request_locate (big_clock->current_time ());
2944         }
2945 }
2946
2947 void
2948 ARDOUR_UI::secondary_clock_value_changed ()
2949 {
2950         if (_session) {
2951                 _session->request_locate (secondary_clock->current_time ());
2952         }
2953 }
2954
2955 void
2956 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2957 {
2958         if (_session == 0) {
2959                 return;
2960         }
2961
2962         if (_session->step_editing()) {
2963                 return;
2964         }
2965
2966         Session::RecordState const r = _session->record_status ();
2967         bool const h = _session->have_rec_enabled_track ();
2968
2969         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2970                 if (onoff) {
2971                         rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2972                 } else {
2973                         rec_button.set_active_state (Gtkmm2ext::Off);
2974                 }
2975         } else if (r == Session::Recording && h) {
2976                 rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2977         } else {
2978                 rec_button.unset_active_state ();
2979         }
2980 }
2981
2982 bool
2983 ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
2984 {
2985         string name;
2986
2987         prompter.get_result (name);
2988
2989         if (name.length()) {
2990                 int failed = _session->save_template (name);
2991
2992                 if (failed == -2) { /* file already exists. */
2993                         bool overwrite = overwrite_file_dialog (prompter,
2994                                                                 _("Confirm Template Overwrite"),
2995                                                                 _("A template already exists with that name. Do you want to overwrite it?"));
2996
2997                         if (overwrite) {
2998                                 _session->save_template (name, true);
2999                         }
3000                         else {
3001                                 return false;
3002                         }
3003                 }
3004         }
3005
3006         return true;
3007 }
3008
3009 void
3010 ARDOUR_UI::save_template ()
3011 {
3012         ArdourPrompter prompter (true);
3013
3014         if (!check_audioengine (_main_window)) {
3015                 return;
3016         }
3017
3018         prompter.set_name (X_("Prompter"));
3019         prompter.set_title (_("Save Template"));
3020         prompter.set_prompt (_("Name for template:"));
3021         prompter.set_initial_text(_session->name() + _("-template"));
3022         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
3023
3024         bool finished = false;
3025         while (!finished) {
3026                 switch (prompter.run()) {
3027                 case RESPONSE_ACCEPT:
3028                         finished = process_save_template_prompter (prompter);
3029                         break;
3030
3031                 default:
3032                         finished = true;
3033                         break;
3034                 }
3035         }
3036 }
3037
3038 void
3039 ARDOUR_UI::edit_metadata ()
3040 {
3041         SessionMetadataEditor dialog;
3042         dialog.set_session (_session);
3043         dialog.grab_focus ();
3044         dialog.run ();
3045 }
3046
3047 void
3048 ARDOUR_UI::import_metadata ()
3049 {
3050         SessionMetadataImporter dialog;
3051         dialog.set_session (_session);
3052         dialog.run ();
3053 }
3054
3055 bool
3056 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
3057 {
3058         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
3059
3060         MessageDialog msg (str,
3061                            false,
3062                            Gtk::MESSAGE_WARNING,
3063                            Gtk::BUTTONS_YES_NO,
3064                            true);
3065
3066
3067         msg.set_name (X_("OpenExistingDialog"));
3068         msg.set_title (_("Open Existing Session"));
3069         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
3070         msg.set_position (Gtk::WIN_POS_CENTER);
3071         pop_back_splash (msg);
3072
3073         switch (msg.run()) {
3074         case RESPONSE_YES:
3075                 return true;
3076                 break;
3077         }
3078         return false;
3079 }
3080
3081 int
3082 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
3083 {
3084         BusProfile bus_profile;
3085
3086         if (nsm) {
3087
3088                 bus_profile.master_out_channels = 2;
3089                 bus_profile.input_ac = AutoConnectPhysical;
3090                 bus_profile.output_ac = AutoConnectMaster;
3091                 bus_profile.requested_physical_in = 0; // use all available
3092                 bus_profile.requested_physical_out = 0; // use all available
3093
3094         } else {
3095
3096                 /* get settings from advanced section of NSD */
3097
3098                 if (sd.create_master_bus()) {
3099                         bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
3100                 } else {
3101                         bus_profile.master_out_channels = 0;
3102                 }
3103
3104                 if (sd.connect_inputs()) {
3105                         bus_profile.input_ac = AutoConnectPhysical;
3106                 } else {
3107                         bus_profile.input_ac = AutoConnectOption (0);
3108                 }
3109
3110                 bus_profile.output_ac = AutoConnectOption (0);
3111
3112                 if (sd.connect_outputs ()) {
3113                         if (sd.connect_outs_to_master()) {
3114                                 bus_profile.output_ac = AutoConnectMaster;
3115                         } else if (sd.connect_outs_to_physical()) {
3116                                 bus_profile.output_ac = AutoConnectPhysical;
3117                         }
3118                 }
3119
3120                 bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
3121                 bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
3122         }
3123
3124         if (build_session (session_path, session_name, bus_profile)) {
3125                 return -1;
3126         }
3127
3128         return 0;
3129 }
3130
3131 void
3132 ARDOUR_UI::load_from_application_api (const std::string& path)
3133 {
3134         /* OS X El Capitan (and probably later) now somehow passes the command
3135            line arguments to an app via the openFile delegate protocol. Ardour 
3136            already does its own command line processing, and having both
3137            pathways active causes crashes. So, if the command line was already
3138            set, do nothing here.
3139         */
3140
3141         if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3142                 return;
3143         }
3144
3145         ARDOUR_COMMAND_LINE::session_name = path;
3146
3147         /* Cancel SessionDialog if it's visible to make OSX delegates work.
3148          *
3149          * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
3150          * race-condition:
3151          *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
3152          *    -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
3153          *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
3154          *    -> SessionDialog is not displayed
3155          */
3156
3157         if (_session_dialog) {
3158                 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3159                 std::string session_path = path;
3160                 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
3161                         session_path = Glib::path_get_dirname (session_path);
3162                 }
3163                 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
3164                 _session_dialog->set_provided_session (session_name, session_path);
3165                 _session_dialog->response (RESPONSE_NONE);
3166                 _session_dialog->hide();
3167                 return;
3168         }
3169
3170         int rv;
3171         if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
3172                 /* /path/to/foo => /path/to/foo, foo */
3173                 rv = load_session (path, basename_nosuffix (path));
3174         } else {
3175                 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
3176                 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
3177         }
3178
3179         // if load_session fails -> pop up SessionDialog.
3180         if (rv) {
3181                 ARDOUR_COMMAND_LINE::session_name = "";
3182
3183                 if (get_session_parameters (true, false)) {
3184                         exit (1);
3185                 }
3186         }
3187 }
3188
3189 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
3190 int
3191 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
3192 {
3193         string session_name;
3194         string session_path;
3195         string template_name;
3196         int ret = -1;
3197         bool likely_new = false;
3198         bool cancel_not_quit;
3199
3200         /* deal with any existing DIRTY session now, rather than later. don't
3201          * treat a non-dirty session this way, so that it stays visible
3202          * as we bring up the new session dialog.
3203          */
3204
3205         if (_session && ARDOUR_UI::instance()->video_timeline) {
3206                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
3207         }
3208
3209         /* if there is already a session, relabel the button
3210            on the SessionDialog so that we don't Quit directly
3211         */
3212         cancel_not_quit = (_session != 0);
3213
3214         if (_session && _session->dirty()) {
3215                 if (unload_session (false)) {
3216                         /* unload cancelled by user */
3217                         return 0;
3218                 }
3219                 ARDOUR_COMMAND_LINE::session_name = "";
3220         }
3221
3222         if (!load_template.empty()) {
3223                 should_be_new = true;
3224                 template_name = load_template;
3225         }
3226
3227         session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3228         session_path = ARDOUR_COMMAND_LINE::session_name;
3229
3230         if (!session_path.empty()) {
3231                 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
3232                         if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
3233                                 /* session/snapshot file, change path to be dir */
3234                                 session_path = Glib::path_get_dirname (session_path);
3235                         }
3236                 }
3237         }
3238
3239         SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
3240
3241         _session_dialog = &session_dialog;
3242         while (ret != 0) {
3243
3244                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3245
3246                         /* if they named a specific statefile, use it, otherwise they are
3247                            just giving a session folder, and we want to use it as is
3248                            to find the session.
3249                         */
3250
3251                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
3252
3253                         if (suffix != string::npos) {
3254                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
3255                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
3256                                 session_name = Glib::path_get_basename (session_name);
3257                         } else {
3258                                 session_path = ARDOUR_COMMAND_LINE::session_name;
3259                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
3260                         }
3261                 } else {
3262                         session_path = "";
3263                         session_name = "";
3264                         session_dialog.clear_given ();
3265                 }
3266
3267                 if (should_be_new || session_name.empty()) {
3268                         /* need the dialog to get info from user */
3269
3270                         cerr << "run dialog\n";
3271
3272                         switch (session_dialog.run()) {
3273                         case RESPONSE_ACCEPT:
3274                                 break;
3275                         case RESPONSE_NONE:
3276                                 /* this is used for async * app->ShouldLoad(). */
3277                                 continue; // while loop
3278                                 break;
3279                         default:
3280                                 if (quit_on_cancel) {
3281                                         // JE - Currently (July 2014) this section can only get reached if the
3282                                         // user quits from the main 'Session Setup' dialog (i.e. reaching this
3283                                         // point does NOT indicate an abnormal termination). Therefore, let's
3284                                         // behave gracefully (i.e. let's do some cleanup) before we call exit()
3285                                         ARDOUR::cleanup ();
3286                                         pthread_cancel_all ();
3287
3288                                         exit (1);
3289                                 } else {
3290                                         return ret;
3291                                 }
3292                         }
3293
3294                         session_dialog.hide ();
3295                 }
3296
3297                 /* if we run the startup dialog again, offer more than just "new session" */
3298
3299                 should_be_new = false;
3300
3301                 session_name = session_dialog.session_name (likely_new);
3302                 session_path = session_dialog.session_folder ();
3303
3304                 if (nsm) {
3305                         likely_new = true;
3306                 }
3307
3308                 string::size_type suffix = session_name.find (statefile_suffix);
3309
3310                 if (suffix != string::npos) {
3311                         session_name = session_name.substr (0, suffix);
3312                 }
3313
3314                 /* this shouldn't happen, but we catch it just in case it does */
3315
3316                 if (session_name.empty()) {
3317                         continue;
3318                 }
3319
3320                 if (session_dialog.use_session_template()) {
3321                         template_name = session_dialog.session_template_name();
3322                         _session_is_new = true;
3323                 }
3324
3325                 if (session_name[0] == G_DIR_SEPARATOR ||
3326 #ifdef PLATFORM_WINDOWS
3327                     (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3328 #else
3329                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3330                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3331 #endif
3332                          )
3333                 {
3334
3335                         /* absolute path or cwd-relative path specified for session name: infer session folder
3336                            from what was given.
3337                         */
3338
3339                         session_path = Glib::path_get_dirname (session_name);
3340                         session_name = Glib::path_get_basename (session_name);
3341
3342                 } else {
3343
3344                         session_path = session_dialog.session_folder();
3345
3346                         char illegal = Session::session_name_is_legal (session_name);
3347
3348                         if (illegal) {
3349                                 MessageDialog msg (session_dialog,
3350                                                    string_compose (_("To ensure compatibility with various systems\n"
3351                                                                      "session names may not contain a '%1' character"),
3352                                                                    illegal));
3353                                 msg.run ();
3354                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3355                                 continue;
3356                         }
3357                 }
3358
3359                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3360
3361
3362                         if (likely_new && !nsm) {
3363
3364                                 std::string existing = Glib::build_filename (session_path, session_name);
3365
3366                                 if (!ask_about_loading_existing_session (existing)) {
3367                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3368                                         continue;
3369                                 }
3370                         }
3371
3372                         _session_is_new = false;
3373
3374                 } else {
3375
3376                         if (!likely_new) {
3377                                 pop_back_splash (session_dialog);
3378                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3379                                 msg.run ();
3380                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3381                                 continue;
3382                         }
3383
3384                         char illegal = Session::session_name_is_legal(session_name);
3385
3386                         if (illegal) {
3387                                 pop_back_splash (session_dialog);
3388                                 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3389                                                                                     "session names may not contain a '%1' character"), illegal));
3390                                 msg.run ();
3391                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3392                                 continue;
3393                         }
3394
3395                         _session_is_new = true;
3396                 }
3397
3398                 if (likely_new && template_name.empty()) {
3399
3400                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3401
3402                 } else {
3403
3404                         ret = load_session (session_path, session_name, template_name);
3405
3406                         if (ret == -2) {
3407                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3408                                 exit (1);
3409                         }
3410
3411                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3412                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3413                                 exit (1);
3414                         }
3415
3416                         /* clear this to avoid endless attempts to load the
3417                            same session.
3418                         */
3419
3420                         ARDOUR_COMMAND_LINE::session_name = "";
3421                 }
3422         }
3423
3424         _session_dialog = NULL;
3425
3426         return ret;
3427 }
3428
3429 void
3430 ARDOUR_UI::close_session()
3431 {
3432         if (!check_audioengine (_main_window)) {
3433                 return;
3434         }
3435
3436         if (unload_session (true)) {
3437                 return;
3438         }
3439
3440         ARDOUR_COMMAND_LINE::session_name = "";
3441
3442         if (get_session_parameters (true, false)) {
3443                 exit (1);
3444         }
3445         if (splash && splash->is_visible()) {
3446                 // in 1 second, hide the splash screen
3447                 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
3448         }
3449 }
3450
3451 /** @param snap_name Snapshot name (without .ardour suffix).
3452  *  @return -2 if the load failed because we are not connected to the AudioEngine.
3453  */
3454 int
3455 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3456 {
3457         Session *new_session;
3458         int unload_status;
3459         int retval = -1;
3460
3461         if (_session) {
3462                 unload_status = unload_session ();
3463
3464                 if (unload_status < 0) {
3465                         goto out;
3466                 } else if (unload_status > 0) {
3467                         retval = 0;
3468                         goto out;
3469                 }
3470         }
3471
3472         session_loaded = false;
3473
3474         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3475
3476         try {
3477                 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3478         }
3479
3480         /* this one is special */
3481
3482         catch (AudioEngine::PortRegistrationFailure& err) {
3483
3484                 MessageDialog msg (err.what(),
3485                                    true,
3486                                    Gtk::MESSAGE_INFO,
3487                                    Gtk::BUTTONS_CLOSE);
3488
3489                 msg.set_title (_("Port Registration Error"));
3490                 msg.set_secondary_text (_("Click the Close button to try again."));
3491                 msg.set_position (Gtk::WIN_POS_CENTER);
3492                 pop_back_splash (msg);
3493                 msg.present ();
3494
3495                 int response = msg.run ();
3496
3497                 msg.hide ();
3498
3499                 switch (response) {
3500                 case RESPONSE_CANCEL:
3501                         exit (1);
3502                 default:
3503                         break;
3504                 }
3505                 goto out;
3506         }
3507         catch (SessionException e) {
3508                 MessageDialog msg (string_compose(
3509                                            _("Session \"%1 (snapshot %2)\" did not load successfully: %3"),
3510                                            path, snap_name, e.what()),
3511                                    true,
3512                                    Gtk::MESSAGE_INFO,
3513                                    BUTTONS_OK);
3514
3515                 msg.set_title (_("Loading Error"));
3516                 msg.set_position (Gtk::WIN_POS_CENTER);
3517                 pop_back_splash (msg);
3518                 msg.present ();
3519
3520                 dump_errors (cerr);
3521
3522                 (void) msg.run ();
3523                 msg.hide ();
3524
3525                 goto out;
3526         }
3527         catch (...) {
3528
3529                 MessageDialog msg (string_compose(
3530                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
3531                                            path, snap_name),
3532                                    true,
3533                                    Gtk::MESSAGE_INFO,
3534                                    BUTTONS_OK);
3535
3536                 msg.set_title (_("Loading Error"));
3537                 msg.set_position (Gtk::WIN_POS_CENTER);
3538                 pop_back_splash (msg);
3539                 msg.present ();
3540
3541                 dump_errors (cerr);
3542
3543                 (void) msg.run ();
3544                 msg.hide ();
3545
3546                 goto out;
3547         }
3548
3549         {
3550                 list<string> const u = new_session->unknown_processors ();
3551                 if (!u.empty()) {
3552                         MissingPluginDialog d (_session, u);
3553                         d.run ();
3554                 }
3555         }
3556
3557         if (!new_session->writable()) {
3558                 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3559                                    true,
3560                                    Gtk::MESSAGE_INFO,
3561                                    BUTTONS_OK);
3562
3563                 msg.set_title (_("Read-only Session"));
3564                 msg.set_position (Gtk::WIN_POS_CENTER);
3565                 pop_back_splash (msg);
3566                 msg.present ();
3567                 (void) msg.run ();
3568                 msg.hide ();
3569         }
3570
3571
3572         /* Now the session been created, add the transport controls */
3573         new_session->add_controllable(roll_controllable);
3574         new_session->add_controllable(stop_controllable);
3575         new_session->add_controllable(goto_start_controllable);
3576         new_session->add_controllable(goto_end_controllable);
3577         new_session->add_controllable(auto_loop_controllable);
3578         new_session->add_controllable(play_selection_controllable);
3579         new_session->add_controllable(rec_controllable);
3580
3581         set_session (new_session);
3582
3583         session_loaded = true;
3584
3585         if (_session) {
3586                 _session->set_clean ();
3587         }
3588
3589 #ifdef WINDOWS_VST_SUPPORT
3590         fst_stop_threading();
3591 #endif
3592
3593         {
3594                 Timers::TimerSuspender t;
3595                 flush_pending (10);
3596         }
3597
3598 #ifdef WINDOWS_VST_SUPPORT
3599         fst_start_threading();
3600 #endif
3601         retval = 0;
3602
3603   out:
3604         return retval;
3605 }
3606
3607 int
3608 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
3609 {
3610         Session *new_session;
3611         int x;
3612
3613         session_loaded = false;
3614         x = unload_session ();
3615
3616         if (x < 0) {
3617                 return -1;
3618         } else if (x > 0) {
3619                 return 0;
3620         }
3621
3622         _session_is_new = true;
3623
3624         try {
3625                 new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
3626         }
3627
3628         catch (SessionException e) {
3629                 cerr << "Here are the errors associated with this failed session:\n";
3630                 dump_errors (cerr);
3631                 cerr << "---------\n";
3632                 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3633                 msg.set_title (_("Loading Error"));
3634                 msg.set_position (Gtk::WIN_POS_CENTER);
3635                 pop_back_splash (msg);
3636                 msg.run ();
3637                 return -1;
3638         }
3639         catch (...) {
3640                 cerr << "Here are the errors associated with this failed session:\n";
3641                 dump_errors (cerr);
3642                 cerr << "---------\n";
3643                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3644                 msg.set_title (_("Loading Error"));
3645                 msg.set_position (Gtk::WIN_POS_CENTER);
3646                 pop_back_splash (msg);
3647                 msg.run ();
3648                 return -1;
3649         }
3650
3651         /* Give the new session the default GUI state, if such things exist */
3652
3653         XMLNode* n;
3654         n = Config->instant_xml (X_("Editor"));
3655         if (n) {
3656                 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3657                 new_session->add_instant_xml (*n, false);
3658         }
3659         n = Config->instant_xml (X_("Mixer"));
3660         if (n) {
3661                 new_session->add_instant_xml (*n, false);
3662         }
3663
3664         n = Config->instant_xml (X_("Preferences"));
3665         if (n) {
3666                 new_session->add_instant_xml (*n, false);
3667         }
3668
3669         /* Put the playhead at 0 and scroll fully left */
3670         n = new_session->instant_xml (X_("Editor"));
3671         if (n) {
3672                 n->add_property (X_("playhead"), X_("0"));
3673                 n->add_property (X_("left-frame"), X_("0"));
3674         }
3675
3676         set_session (new_session);
3677
3678         session_loaded = true;
3679
3680         new_session->save_state(new_session->name());
3681
3682         return 0;
3683 }
3684
3685 void
3686 ARDOUR_UI::launch_chat ()
3687 {
3688         MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3689
3690         dialog.set_title (_("About the Chat"));
3691         dialog.set_secondary_text (_("When you're inside the chat just ask your question and wait for an answer. The chat is occupied by real people with real lives so many of them are passively online and might not read your question before minutes or hours later.\nSo please be patient and wait for an answer.\n\nYou should just leave the chat window open and check back regularly until someone has answered your question."));
3692
3693         switch (dialog.run()) {
3694         case RESPONSE_OK:
3695 #ifdef __APPLE__
3696                 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
3697 #elif defined PLATFORM_WINDOWS
3698                 open_uri("http://webchat.freenode.net/?channels=ardour-windows");
3699 #else
3700                 open_uri("http://webchat.freenode.net/?channels=ardour");
3701 #endif
3702                 break;
3703         default:
3704                 break;
3705         }
3706 }
3707
3708 void
3709 ARDOUR_UI::launch_manual ()
3710 {
3711         PBD::open_uri (Config->get_tutorial_manual_url());
3712 }
3713
3714 void
3715 ARDOUR_UI::launch_reference ()
3716 {
3717         PBD::open_uri (Config->get_reference_manual_url());
3718 }
3719
3720 void
3721 ARDOUR_UI::launch_tracker ()
3722 {
3723         PBD::open_uri ("http://tracker.ardour.org");
3724 }
3725
3726 void
3727 ARDOUR_UI::launch_subscribe ()
3728 {
3729         PBD::open_uri ("https://community.ardour.org/s/subscribe");
3730 }
3731
3732 void
3733 ARDOUR_UI::launch_cheat_sheet ()
3734 {
3735 #ifdef __APPLE__
3736         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
3737 #else
3738         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
3739 #endif
3740 }
3741
3742 void
3743 ARDOUR_UI::launch_website ()
3744 {
3745         PBD::open_uri ("http://ardour.org");
3746 }
3747
3748 void
3749 ARDOUR_UI::launch_website_dev ()
3750 {
3751         PBD::open_uri ("http://ardour.org/development.html");
3752 }
3753
3754 void
3755 ARDOUR_UI::launch_forums ()
3756 {
3757         PBD::open_uri ("https://community.ardour.org/forums");
3758 }
3759
3760 void
3761 ARDOUR_UI::launch_howto_report ()
3762 {
3763         PBD::open_uri ("http://ardour.org/reporting_bugs");
3764 }
3765
3766 void
3767 ARDOUR_UI::loading_message (const std::string& msg)
3768 {
3769         if (ARDOUR_COMMAND_LINE::no_splash) {
3770                 return;
3771         }
3772
3773         if (!splash) {
3774                 show_splash ();
3775         }
3776
3777         splash->message (msg);
3778 }
3779
3780 void
3781 ARDOUR_UI::show_splash ()
3782 {
3783         if (splash == 0) {
3784                 try {
3785                         splash = new Splash;
3786                 } catch (...) {
3787                         return;
3788                 }
3789         }
3790
3791         splash->display ();
3792 }
3793
3794 void
3795 ARDOUR_UI::hide_splash ()
3796 {
3797         delete splash;
3798         splash = 0;
3799 }
3800
3801 void
3802 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
3803 {
3804         size_t removed;
3805
3806         removed = rep.paths.size();
3807
3808         if (removed == 0) {
3809                 MessageDialog msgd (_main_window,
3810                                     _("No files were ready for clean-up"),
3811                                     true,
3812                                     Gtk::MESSAGE_INFO,
3813                                     Gtk::BUTTONS_OK);
3814                 msgd.set_title (_("Clean-up"));
3815                 msgd.set_secondary_text (_("If this seems suprising, \n\
3816 check for any existing snapshots.\n\
3817 These may still include regions that\n\
3818 require some unused files to continue to exist."));
3819
3820                 msgd.run ();
3821                 return;
3822         }
3823
3824         ArdourDialog results (_("Clean-up"), true, false);
3825
3826         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3827             CleanupResultsModelColumns() {
3828                     add (visible_name);
3829                     add (fullpath);
3830             }
3831             Gtk::TreeModelColumn<std::string> visible_name;
3832             Gtk::TreeModelColumn<std::string> fullpath;
3833         };
3834
3835
3836         CleanupResultsModelColumns results_columns;
3837         Glib::RefPtr<Gtk::ListStore> results_model;
3838         Gtk::TreeView results_display;
3839
3840         results_model = ListStore::create (results_columns);
3841         results_display.set_model (results_model);
3842         results_display.append_column (list_title, results_columns.visible_name);
3843
3844         results_display.set_name ("CleanupResultsList");
3845         results_display.set_headers_visible (true);
3846         results_display.set_headers_clickable (false);
3847         results_display.set_reorderable (false);
3848
3849         Gtk::ScrolledWindow list_scroller;
3850         Gtk::Label txt;
3851         Gtk::VBox dvbox;
3852         Gtk::HBox dhbox;  // the hbox for the image and text
3853         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3854         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
3855
3856         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3857
3858         const string dead_directory = _session->session_directory().dead_path();
3859
3860         /* subst:
3861            %1 - number of files removed
3862            %2 - location of "dead"
3863            %3 - size of files affected
3864            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3865         */
3866
3867         const char* bprefix;
3868         double space_adjusted = 0;
3869
3870         if (rep.space < 1000) {
3871                 bprefix = X_("");
3872                 space_adjusted = rep.space;
3873         } else if (rep.space < 1000000) {
3874                 bprefix = _("kilo");
3875                 space_adjusted = floorf((float)rep.space / 1000.0);
3876         } else if (rep.space < 1000000 * 1000) {
3877                 bprefix = _("mega");
3878                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
3879         } else {
3880                 bprefix = _("giga");
3881                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
3882         }
3883
3884         if (msg_delete) {
3885                 txt.set_markup (string_compose (P_("\
3886 The following file was deleted from %2,\n\
3887 releasing %3 %4bytes of disk space", "\
3888 The following %1 files were deleted from %2,\n\
3889 releasing %3 %4bytes of disk space", removed),
3890                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3891         } else {
3892                 txt.set_markup (string_compose (P_("\
3893 The following file was not in use and \n\
3894 has been moved to: %2\n\n\
3895 After a restart of %5\n\n\
3896 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3897 will release an additional %3 %4bytes of disk space.\n", "\
3898 The following %1 files were not in use and \n\
3899 have been moved to: %2\n\n\
3900 After a restart of %5\n\n\
3901 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3902 will release an additional %3 %4bytes of disk space.\n", removed),
3903                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3904         }
3905
3906         dhbox.pack_start (*dimage, true, false, 5);
3907         dhbox.pack_start (txt, true, false, 5);
3908
3909         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3910                 TreeModel::Row row = *(results_model->append());
3911                 row[results_columns.visible_name] = *i;
3912                 row[results_columns.fullpath] = *i;
3913         }
3914
3915         list_scroller.add (results_display);
3916         list_scroller.set_size_request (-1, 150);
3917         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3918
3919         dvbox.pack_start (dhbox, true, false, 5);
3920         dvbox.pack_start (list_scroller, true, false, 5);
3921         ddhbox.pack_start (dvbox, true, false, 5);
3922
3923         results.get_vbox()->pack_start (ddhbox, true, false, 5);
3924         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3925         results.set_default_response (RESPONSE_CLOSE);
3926         results.set_position (Gtk::WIN_POS_MOUSE);
3927
3928         results_display.show();
3929         list_scroller.show();
3930         txt.show();
3931         dvbox.show();
3932         dhbox.show();
3933         ddhbox.show();
3934         dimage->show();
3935
3936         //results.get_vbox()->show();
3937         results.set_resizable (false);
3938
3939         results.run ();
3940
3941 }
3942
3943 void
3944 ARDOUR_UI::cleanup ()
3945 {
3946         if (_session == 0) {
3947                 /* shouldn't happen: menu item is insensitive */
3948                 return;
3949         }
3950
3951
3952         MessageDialog checker (_("Are you sure you want to clean-up?"),
3953                                 true,
3954                                 Gtk::MESSAGE_QUESTION,
3955                                 Gtk::BUTTONS_NONE);
3956
3957         checker.set_title (_("Clean-up"));
3958
3959         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3960 ALL undo/redo information will be lost if you clean-up.\n\
3961 Clean-up will move all unused files to a \"dead\" location."));
3962
3963         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3964         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3965         checker.set_default_response (RESPONSE_CANCEL);
3966
3967         checker.set_name (_("CleanupDialog"));
3968         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3969         checker.set_position (Gtk::WIN_POS_MOUSE);
3970
3971         switch (checker.run()) {
3972         case RESPONSE_ACCEPT:
3973                 break;
3974         default:
3975                 return;
3976         }
3977
3978         ARDOUR::CleanupReport rep;
3979
3980         editor->prepare_for_cleanup ();
3981
3982         /* do not allow flush until a session is reloaded */
3983
3984         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3985         if (act) {
3986                 act->set_sensitive (false);
3987         }
3988
3989         if (_session->cleanup_sources (rep)) {
3990                 editor->finish_cleanup ();
3991                 return;
3992         }
3993
3994         editor->finish_cleanup ();
3995
3996         checker.hide();
3997         display_cleanup_results (rep, _("Cleaned Files"), false);
3998 }
3999
4000 void
4001 ARDOUR_UI::flush_trash ()
4002 {
4003         if (_session == 0) {
4004                 /* shouldn't happen: menu item is insensitive */
4005                 return;
4006         }
4007
4008         ARDOUR::CleanupReport rep;
4009
4010         if (_session->cleanup_trash_sources (rep)) {
4011                 return;
4012         }
4013
4014         display_cleanup_results (rep, _("deleted file"), true);
4015 }
4016
4017 void
4018 ARDOUR_UI::cleanup_peakfiles ()
4019 {
4020         if (_session == 0) {
4021                 /* shouldn't happen: menu item is insensitive */
4022                 return;
4023         }
4024
4025         if (! _session->can_cleanup_peakfiles ()) {
4026                 return;
4027         }
4028
4029         // get all region-views in this session
4030         RegionSelection rs;
4031         TrackViewList empty;
4032         empty.clear();
4033         editor->get_regions_after(rs, (framepos_t) 0, empty);
4034         std::list<RegionView*> views = rs.by_layer();
4035
4036         // remove displayed audio-region-views waveforms
4037         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4038                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4039                 if (!arv) { continue ; }
4040                 arv->delete_waves();
4041         }
4042
4043         // cleanup peak files:
4044         // - stop pending peakfile threads
4045         // - close peakfiles if any
4046         // - remove peak dir in session
4047         // - setup peakfiles (background thread)
4048         _session->cleanup_peakfiles ();
4049
4050         // re-add waves to ARV
4051         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4052                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4053                 if (!arv) { continue ; }
4054                 arv->create_waves();
4055         }
4056 }
4057
4058 PresentationInfo::order_t
4059 ARDOUR_UI::translate_order (RouteDialogs::InsertAt place)
4060 {
4061         if (editor->get_selection().tracks.empty()) {
4062                 return PresentationInfo::max_order;
4063         }
4064
4065         PresentationInfo::order_t order_hint = PresentationInfo::max_order;
4066
4067         /*
4068           we want the new routes to have their order keys set starting from
4069           the highest order key in the selection + 1 (if available).
4070         */
4071
4072         if (place == RouteDialogs::AfterSelection) {
4073                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
4074                 if (rtav) {
4075                         order_hint = rtav->route()->presentation_info().order();
4076                         order_hint++;
4077                 }
4078         } else if (place == RouteDialogs::BeforeSelection) {
4079                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
4080                 if (rtav) {
4081                         order_hint = rtav->route()->presentation_info().order();
4082                 }
4083         } else if (place == RouteDialogs::First) {
4084                 order_hint = 0;
4085         } else {
4086                 /* leave order_hint at max_order */
4087         }
4088
4089         return order_hint;
4090 }
4091
4092 void
4093 ARDOUR_UI::start_duplicate_routes ()
4094 {
4095         if (!duplicate_routes_dialog) {
4096                 duplicate_routes_dialog = new DuplicateRouteDialog;
4097         }
4098
4099         if (duplicate_routes_dialog->restart (_session)) {
4100                 return;
4101         }
4102
4103         duplicate_routes_dialog->present ();
4104 }
4105
4106 void
4107 ARDOUR_UI::add_route ()
4108 {
4109         if (!add_route_dialog.get (false)) {
4110                 add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_finished));
4111         }
4112
4113         if (!_session) {
4114                 return;
4115         }
4116
4117         if (add_route_dialog->is_visible()) {
4118                 /* we're already doing this */
4119                 return;
4120         }
4121
4122         add_route_dialog->set_position (WIN_POS_MOUSE);
4123         add_route_dialog->present();
4124 }
4125
4126 void
4127 ARDOUR_UI::add_route_dialog_finished (int r)
4128 {
4129         int count;
4130
4131         add_route_dialog->hide();
4132
4133         switch (r) {
4134                 case RESPONSE_ACCEPT:
4135                         break;
4136                 default:
4137                         return;
4138                         break;
4139         }
4140
4141         if ((count = add_route_dialog->count()) <= 0) {
4142                 return;
4143         }
4144
4145         PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at());
4146         string template_path = add_route_dialog->track_template();
4147         DisplaySuspender ds;
4148
4149         if (!template_path.empty()) {
4150                 if (add_route_dialog->name_template_is_default())  {
4151                         _session->new_route_from_template (count, order, template_path, string());
4152                 } else {
4153                         _session->new_route_from_template (count, order, template_path, add_route_dialog->name_template());
4154                 }
4155                 return;
4156         }
4157
4158         ChanCount input_chan= add_route_dialog->channels ();
4159         ChanCount output_chan;
4160         string name_template = add_route_dialog->name_template ();
4161         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
4162         RouteGroup* route_group = add_route_dialog->route_group ();
4163         AutoConnectOption oac = Config->get_output_auto_connect();
4164         bool strict_io = add_route_dialog->use_strict_io ();
4165
4166         if (oac & AutoConnectMaster) {
4167                 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
4168                 output_chan.set (DataType::MIDI, 0);
4169         } else {
4170                 output_chan = input_chan;
4171         }
4172
4173         /* XXX do something with name template */
4174
4175         Session::ProcessorChangeBlocker pcb (_session);
4176
4177         switch (add_route_dialog->type_wanted()) {
4178         case AddRouteDialog::AudioTrack:
4179                 session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io, order);
4180                 break;
4181         case AddRouteDialog::MidiTrack:
4182                 session_add_midi_track (route_group, count, name_template, strict_io, instrument, 0, order);
4183                 break;
4184         case AddRouteDialog::MixedTrack:
4185                 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0, order);
4186                 break;
4187         case AddRouteDialog::AudioBus:
4188                 session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template, strict_io, order);
4189                 break;
4190         case AddRouteDialog::MidiBus:
4191                 session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order);
4192                 break;
4193         case AddRouteDialog::VCAMaster:
4194                 session_add_vca (name_template, count);
4195                 break;
4196         }
4197 }
4198
4199 void
4200 ARDOUR_UI::add_lua_script ()
4201 {
4202         if (!_session) {
4203                 return;
4204         }
4205
4206         LuaScriptInfoPtr spi;
4207         ScriptSelector ss ("Add Lua Session Script", LuaScriptInfo::Session);
4208         switch (ss.run ()) {
4209                 case Gtk::RESPONSE_ACCEPT:
4210                         spi = ss.script();
4211                         break;
4212                 default:
4213                         return;
4214         }
4215         ss.hide();
4216
4217         std::string script = "";
4218
4219         try {
4220                 script = Glib::file_get_contents (spi->path);
4221         } catch (Glib::FileError e) {
4222                 string msg = string_compose (_("Cannot read session script '%1': %2"), spi->path, e.what());
4223                 MessageDialog am (msg);
4224                 am.run ();
4225                 return;
4226         }
4227
4228         LuaScriptParamList lsp = LuaScriptParams::script_params (spi, "sess_params");
4229         std::vector<std::string> reg = _session->registered_lua_functions ();
4230
4231         ScriptParameterDialog spd (_("Set Script Parameters"), spi, reg, lsp);
4232         switch (spd.run ()) {
4233                 case Gtk::RESPONSE_ACCEPT:
4234                         break;
4235                 default:
4236                         return;
4237         }
4238
4239         try {
4240                 _session->register_lua_function (spd.name(), script, lsp);
4241         } catch (luabridge::LuaException const& e) {
4242                 string msg = string_compose (_("Session script '%1' instantiation failed: %2"), spd.name(), e.what ());
4243                 MessageDialog am (msg);
4244                 am.run ();
4245         } catch (SessionException e) {
4246                 string msg = string_compose (_("Loading Session script '%1' failed: %2"), spd.name(), e.what ());
4247                 MessageDialog am (msg);
4248                 am.run ();
4249         }
4250 }
4251
4252 void
4253 ARDOUR_UI::remove_lua_script ()
4254 {
4255         if (!_session) {
4256                 return;
4257         }
4258         if (_session->registered_lua_function_count () ==  0) {
4259                 string msg = _("There are no active Lua session scripts present in this session.");
4260                 MessageDialog am (msg);
4261                 am.run ();
4262                 return;
4263         }
4264
4265         std::vector<std::string> reg = _session->registered_lua_functions ();
4266         SessionScriptManager sm ("Remove Lua Session Script", reg);
4267         switch (sm.run ()) {
4268                 case Gtk::RESPONSE_ACCEPT:
4269                         break;
4270                 default:
4271                         return;
4272         }
4273         try {
4274                 _session->unregister_lua_function (sm.name());
4275         } catch (luabridge::LuaException const& e) {
4276                 string msg = string_compose (_("Session script '%1' removal failed: %2"), sm.name(), e.what ());
4277                 MessageDialog am (msg);
4278                 am.run ();
4279         }
4280 }
4281
4282 void
4283 ARDOUR_UI::stop_video_server (bool ask_confirm)
4284 {
4285         if (!video_server_process && ask_confirm) {
4286                 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
4287         }
4288         if (video_server_process) {
4289                 if(ask_confirm) {
4290                         ArdourDialog confirm (_("Stop Video-Server"), true);
4291                         Label m (_("Do you really want to stop the Video Server?"));
4292                         confirm.get_vbox()->pack_start (m, true, true);
4293                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
4294                         confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
4295                         confirm.show_all ();
4296                         if (confirm.run() == RESPONSE_CANCEL) {
4297                                 return;
4298                         }
4299                 }
4300                 delete video_server_process;
4301                 video_server_process =0;
4302         }
4303 }
4304
4305 void
4306 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
4307 {
4308   ARDOUR_UI::start_video_server( float_window, true);
4309 }
4310
4311 bool
4312 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
4313 {
4314         if (!_session) {
4315                 return false;
4316         }
4317         if (popup_msg) {
4318                 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
4319                         if (video_server_process) {
4320                                 popup_error(_("The Video Server is already started."));
4321                         } else {
4322                                 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
4323                         }
4324                 }
4325         }
4326
4327         int firsttime = 0;
4328         while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4329                 if (firsttime++) {
4330                         warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4331                 }
4332                 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
4333                 if (float_window) {
4334                         video_server_dialog->set_transient_for (*float_window);
4335                 }
4336
4337                 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
4338                         video_server_dialog->hide();
4339                 } else {
4340                         ResponseType r = (ResponseType) video_server_dialog->run ();
4341                         video_server_dialog->hide();
4342                         if (r != RESPONSE_ACCEPT) { return false; }
4343                         if (video_server_dialog->show_again()) {
4344                                 Config->set_show_video_server_dialog(false);
4345                         }
4346                 }
4347
4348                 std::string icsd_exec = video_server_dialog->get_exec_path();
4349                 std::string icsd_docroot = video_server_dialog->get_docroot();
4350                 if (icsd_docroot.empty()) {
4351 #ifndef PLATFORM_WINDOWS
4352                         icsd_docroot = X_("/");
4353 #else
4354                         icsd_docroot = X_("C:\\");
4355 #endif
4356                 }
4357
4358                 GStatBuf sb;
4359                 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
4360                         warning << _("Specified docroot is not an existing directory.") << endmsg;
4361                         continue;
4362                 }
4363 #ifndef PLATFORM_WINDOWS
4364                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4365                      || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
4366                         warning << _("Given Video Server is not an executable file.") << endmsg;
4367                         continue;
4368                 }
4369 #else
4370                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4371                      || (sb.st_mode & (S_IXUSR)) == 0 ) {
4372                         warning << _("Given Video Server is not an executable file.") << endmsg;
4373                         continue;
4374                 }
4375 #endif
4376
4377                 char **argp;
4378                 argp=(char**) calloc(9,sizeof(char*));
4379                 argp[0] = strdup(icsd_exec.c_str());
4380                 argp[1] = strdup("-P");
4381                 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4382                 argp[3] = strdup("-p");
4383                 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4384                 argp[5] = strdup("-C");
4385                 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4386                 argp[7] = strdup(icsd_docroot.c_str());
4387                 argp[8] = 0;
4388                 stop_video_server();
4389
4390                 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4391                         Config->set_video_advanced_setup(false);
4392                 } else {
4393                         std::ostringstream osstream;
4394                         osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/";
4395                         Config->set_video_server_url(osstream.str());
4396                         Config->set_video_server_docroot(icsd_docroot);
4397                         Config->set_video_advanced_setup(true);
4398                 }
4399
4400                 if (video_server_process) {
4401                         delete video_server_process;
4402                 }
4403
4404                 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4405                 if (video_server_process->start()) {
4406                         warning << _("Cannot launch the video-server") << endmsg;
4407                         continue;
4408                 }
4409                 int timeout = 120; // 6 sec
4410                 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4411                         Glib::usleep (50000);
4412                         gui_idle_handler();
4413                         if (--timeout <= 0 || !video_server_process->is_running()) break;
4414                 }
4415                 if (timeout <= 0) {
4416                         warning << _("Video-server was started but does not respond to requests...") << endmsg;
4417                 } else {
4418                         if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4419                                 delete video_server_process;
4420                                 video_server_process = 0;
4421                         }
4422                 }
4423         }
4424         return true;
4425 }
4426
4427 void
4428 ARDOUR_UI::add_video (Gtk::Window* float_window)
4429 {
4430         if (!_session) {
4431                 return;
4432         }
4433
4434         if (!start_video_server(float_window, false)) {
4435                 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4436                 return;
4437         }
4438
4439         if (float_window) {
4440                 add_video_dialog->set_transient_for (*float_window);
4441         }
4442
4443         if (add_video_dialog->is_visible()) {
4444                 /* we're already doing this */
4445                 return;
4446         }
4447
4448         ResponseType r = (ResponseType) add_video_dialog->run ();
4449         add_video_dialog->hide();
4450         if (r != RESPONSE_ACCEPT) { return; }
4451
4452         bool local_file, orig_local_file;
4453         std::string path = add_video_dialog->file_name(local_file);
4454
4455         std::string orig_path = path;
4456         orig_local_file = local_file;
4457
4458         bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4459
4460         if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4461                 warning << string_compose(_("could not open %1"), path) << endmsg;
4462                 return;
4463         }
4464         if (!local_file && path.length() == 0) {
4465                 warning << _("no video-file selected") << endmsg;
4466                 return;
4467         }
4468
4469         std::string audio_from_video;
4470         bool detect_ltc = false;
4471
4472         switch (add_video_dialog->import_option()) {
4473                 case VTL_IMPORT_TRANSCODE:
4474                         {
4475                                 TranscodeVideoDialog *transcode_video_dialog;
4476                                 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4477                                 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4478                                 transcode_video_dialog->hide();
4479                                 if (r != RESPONSE_ACCEPT) {
4480                                         delete transcode_video_dialog;
4481                                         return;
4482                                 }
4483
4484                                 audio_from_video = transcode_video_dialog->get_audiofile();
4485
4486                                 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4487                                         detect_ltc = true;
4488                                 }
4489                                 else if (!audio_from_video.empty()) {
4490                                         editor->embed_audio_from_video(
4491                                                         audio_from_video,
4492                                                         video_timeline->get_offset(),
4493                                                         (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4494                                                         );
4495                                 }
4496                                 switch (transcode_video_dialog->import_option()) {
4497                                         case VTL_IMPORT_TRANSCODED:
4498                                                 path = transcode_video_dialog->get_filename();
4499                                                 local_file = true;
4500                                                 break;
4501                                         case VTL_IMPORT_REFERENCE:
4502                                                 break;
4503                                         default:
4504                                                 delete transcode_video_dialog;
4505                                                 return;
4506                                 }
4507                                 delete transcode_video_dialog;
4508                         }
4509                         break;
4510                 default:
4511                 case VTL_IMPORT_NONE:
4512                         break;
4513         }
4514
4515         /* strip _session->session_directory().video_path() from video file if possible */
4516         if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4517                  path=path.substr(_session->session_directory().video_path().size());
4518                  if (path.at(0) == G_DIR_SEPARATOR) {
4519                          path=path.substr(1);
4520                  }
4521         }
4522
4523         video_timeline->set_update_session_fps(auto_set_session_fps);
4524
4525         if (video_timeline->video_file_info(path, local_file)) {
4526                 XMLNode* node = new XMLNode(X_("Videotimeline"));
4527                 node->add_property (X_("Filename"), path);
4528                 node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
4529                 node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0"));
4530                 if (orig_local_file) {
4531                         node->add_property (X_("OriginalVideoFile"), orig_path);
4532                 } else {
4533                         node->remove_property (X_("OriginalVideoFile"));
4534                 }
4535                 _session->add_extra_xml (*node);
4536                 _session->set_dirty ();
4537
4538                 if (!audio_from_video.empty() && detect_ltc) {
4539                         std::vector<LTCFileReader::LTCMap> ltc_seq;
4540
4541                         try {
4542                                 /* TODO ask user about TV standard (LTC alignment if any) */
4543                                 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4544                                 /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
4545
4546                                 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC frames to decode*/ 15);
4547
4548                                 /* TODO seek near end of file, and read LTC until end.
4549                                  * if it fails to find any LTC frames, scan complete file
4550                                  *
4551                                  * calculate drift of LTC compared to video-duration,
4552                                  * ask user for reference (timecode from start/mid/end)
4553                                  */
4554                         } catch (...) {
4555                                 // LTCFileReader will have written error messages
4556                         }
4557
4558                         ::g_unlink(audio_from_video.c_str());
4559
4560                         if (ltc_seq.size() == 0) {
4561                                 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4562                         } else {
4563                                 /* the very first TC in the file is somteimes not aligned properly */
4564                                 int i = ltc_seq.size() -1;
4565                                 ARDOUR::frameoffset_t video_start_offset =
4566                                         _session->nominal_frame_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4567                                 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4568                                 video_timeline->set_offset(video_start_offset);
4569                         }
4570                 }
4571
4572                 _session->maybe_update_session_range(
4573                         std::max(video_timeline->get_offset(), (ARDOUR::frameoffset_t) 0),
4574                         std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::frameoffset_t) 0));
4575
4576
4577                 if (add_video_dialog->launch_xjadeo() && local_file) {
4578                         editor->set_xjadeo_sensitive(true);
4579                         editor->toggle_xjadeo_proc(1);
4580                 } else {
4581                         editor->toggle_xjadeo_proc(0);
4582                 }
4583                 editor->toggle_ruler_video(true);
4584         }
4585 }
4586
4587 void
4588 ARDOUR_UI::remove_video ()
4589 {
4590         video_timeline->close_session();
4591         editor->toggle_ruler_video(false);
4592
4593         /* reset state */
4594         video_timeline->set_offset_locked(false);
4595         video_timeline->set_offset(0);
4596
4597         /* delete session state */
4598         XMLNode* node = new XMLNode(X_("Videotimeline"));
4599         _session->add_extra_xml(*node);
4600         node = new XMLNode(X_("Videomonitor"));
4601         _session->add_extra_xml(*node);
4602         node = new XMLNode(X_("Videoexport"));
4603         _session->add_extra_xml(*node);
4604         stop_video_server();
4605 }
4606
4607 void
4608 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4609 {
4610         if (localcacheonly) {
4611                 video_timeline->vmon_update();
4612         } else {
4613                 video_timeline->flush_cache();
4614         }
4615         editor->queue_visual_videotimeline_update();
4616 }
4617
4618 void
4619 ARDOUR_UI::export_video (bool range)
4620 {
4621         if (ARDOUR::Config->get_show_video_export_info()) {
4622                 ExportVideoInfobox infobox (_session);
4623                 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4624                 if (infobox.show_again()) {
4625                         ARDOUR::Config->set_show_video_export_info(false);
4626                 }
4627                 switch (rv) {
4628                         case GTK_RESPONSE_YES:
4629                                 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4630                                 break;
4631                         default:
4632                                 break;
4633                 }
4634         }
4635         export_video_dialog->set_session (_session);
4636         export_video_dialog->apply_state(editor->get_selection().time, range);
4637         export_video_dialog->run ();
4638         export_video_dialog->hide ();
4639 }
4640
4641 XMLNode*
4642 ARDOUR_UI::preferences_settings () const
4643 {
4644         XMLNode* node = 0;
4645
4646         if (_session) {
4647                 node = _session->instant_xml(X_("Preferences"));
4648         } else {
4649                 node = Config->instant_xml(X_("Preferences"));
4650         }
4651
4652         if (!node) {
4653                 node = new XMLNode (X_("Preferences"));
4654         }
4655
4656         return node;
4657 }
4658
4659 XMLNode*
4660 ARDOUR_UI::mixer_settings () const
4661 {
4662         XMLNode* node = 0;
4663
4664         if (_session) {
4665                 node = _session->instant_xml(X_("Mixer"));
4666         } else {
4667                 node = Config->instant_xml(X_("Mixer"));
4668         }
4669
4670         if (!node) {
4671                 node = new XMLNode (X_("Mixer"));
4672         }
4673
4674         return node;
4675 }
4676
4677 XMLNode*
4678 ARDOUR_UI::main_window_settings () const
4679 {
4680         XMLNode* node = 0;
4681
4682         if (_session) {
4683                 node = _session->instant_xml(X_("Main"));
4684         } else {
4685                 node = Config->instant_xml(X_("Main"));
4686         }
4687
4688         if (!node) {
4689                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4690                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4691                 }
4692         }
4693
4694         if (!node) {
4695                 node = new XMLNode (X_("Main"));
4696         }
4697
4698         return node;
4699 }
4700
4701 XMLNode*
4702 ARDOUR_UI::editor_settings () const
4703 {
4704         XMLNode* node = 0;
4705
4706         if (_session) {
4707                 node = _session->instant_xml(X_("Editor"));
4708         } else {
4709                 node = Config->instant_xml(X_("Editor"));
4710         }
4711
4712         if (!node) {
4713                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4714                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4715                 }
4716         }
4717
4718         if (!node) {
4719                 node = new XMLNode (X_("Editor"));
4720         }
4721
4722         return node;
4723 }
4724
4725 XMLNode*
4726 ARDOUR_UI::keyboard_settings () const
4727 {
4728         XMLNode* node = 0;
4729
4730         node = Config->extra_xml(X_("Keyboard"));
4731
4732         if (!node) {
4733                 node = new XMLNode (X_("Keyboard"));
4734         }
4735
4736         return node;
4737 }
4738
4739 void
4740 ARDOUR_UI::create_xrun_marker (framepos_t where)
4741 {
4742         if (_session) {
4743                 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark);
4744                 _session->locations()->add (location);
4745         }
4746 }
4747
4748 void
4749 ARDOUR_UI::halt_on_xrun_message ()
4750 {
4751         cerr << "HALT on xrun\n";
4752         MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
4753         msg.run ();
4754 }
4755
4756 void
4757 ARDOUR_UI::xrun_handler (framepos_t where)
4758 {
4759         if (!_session) {
4760                 return;
4761         }
4762
4763         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4764
4765         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4766                 create_xrun_marker(where);
4767         }
4768
4769         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4770                 halt_on_xrun_message ();
4771         }
4772 }
4773
4774 void
4775 ARDOUR_UI::disk_overrun_handler ()
4776 {
4777         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4778
4779         if (!have_disk_speed_dialog_displayed) {
4780                 have_disk_speed_dialog_displayed = true;
4781                 MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
4782 The disk system on your computer\n\
4783 was not able to keep up with %1.\n\
4784 \n\
4785 Specifically, it failed to write data to disk\n\
4786 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4787                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4788                 msg->show ();
4789         }
4790 }
4791
4792
4793 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4794 static MessageDialog *scan_dlg = NULL;
4795 static ProgressBar   *scan_pbar = NULL;
4796 static HBox          *scan_tbox = NULL;
4797 static Gtk::Button   *scan_timeout_button;
4798
4799 void
4800 ARDOUR_UI::cancel_plugin_scan ()
4801 {
4802         PluginManager::instance().cancel_plugin_scan();
4803 }
4804
4805 void
4806 ARDOUR_UI::cancel_plugin_timeout ()
4807 {
4808         PluginManager::instance().cancel_plugin_timeout();
4809         scan_timeout_button->set_sensitive (false);
4810 }
4811
4812 void
4813 ARDOUR_UI::plugin_scan_timeout (int timeout)
4814 {
4815         if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4816                 return;
4817         }
4818         if (timeout > 0) {
4819                 scan_pbar->set_sensitive (false);
4820                 scan_timeout_button->set_sensitive (true);
4821                 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
4822                 scan_tbox->show();
4823         } else {
4824                 scan_pbar->set_sensitive (false);
4825                 scan_timeout_button->set_sensitive (false);
4826         }
4827         gui_idle_handler();
4828 }
4829
4830 void
4831 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
4832 {
4833         if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
4834                 return;
4835         }
4836
4837         const bool cancelled = PluginManager::instance().cancelled();
4838         if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
4839                 if (cancelled && scan_dlg->is_mapped()) {
4840                         scan_dlg->hide();
4841                         gui_idle_handler();
4842                         return;
4843                 }
4844                 if (cancelled || !can_cancel) {
4845                         return;
4846                 }
4847         }
4848
4849         static Gtk::Button *cancel_button;
4850         if (!scan_dlg) {
4851                 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
4852                 VBox* vbox = scan_dlg->get_vbox();
4853                 vbox->set_size_request(400,-1);
4854                 scan_dlg->set_title (_("Scanning for plugins"));
4855
4856                 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
4857                 cancel_button->set_name ("EditorGTKButton");
4858                 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
4859                 cancel_button->show();
4860
4861                 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
4862
4863                 scan_tbox = manage( new HBox() );
4864
4865                 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
4866                 scan_timeout_button->set_name ("EditorGTKButton");
4867                 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
4868                 scan_timeout_button->show();
4869
4870                 scan_pbar = manage(new ProgressBar());
4871                 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
4872                 scan_pbar->set_text(_("Scan Timeout"));
4873                 scan_pbar->show();
4874
4875                 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
4876                 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
4877
4878                 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
4879         }
4880
4881         assert(scan_dlg && scan_tbox && cancel_button);
4882
4883         if (type == X_("closeme")) {
4884                 scan_tbox->hide();
4885                 scan_dlg->hide();
4886         } else {
4887                 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
4888                 scan_dlg->show();
4889         }
4890         if (!can_cancel || !cancelled) {
4891                 scan_timeout_button->set_sensitive(false);
4892         }
4893         cancel_button->set_sensitive(can_cancel && !cancelled);
4894
4895         gui_idle_handler();
4896 }
4897
4898 void
4899 ARDOUR_UI::gui_idle_handler ()
4900 {
4901         int timeout = 30;
4902         /* due to idle calls, gtk_events_pending() may always return true */
4903         while (gtk_events_pending() && --timeout) {
4904                 gtk_main_iteration ();
4905         }
4906 }
4907
4908 void
4909 ARDOUR_UI::disk_underrun_handler ()
4910 {
4911         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
4912
4913         if (!have_disk_speed_dialog_displayed) {
4914                 have_disk_speed_dialog_displayed = true;
4915                 MessageDialog* msg = new MessageDialog (
4916                         _main_window, string_compose (_("The disk system on your computer\n\
4917 was not able to keep up with %1.\n\
4918 \n\
4919 Specifically, it failed to read data from disk\n\
4920 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
4921                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4922                 msg->show ();
4923         }
4924 }
4925
4926 void
4927 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
4928 {
4929         have_disk_speed_dialog_displayed = false;
4930         delete msg;
4931 }
4932
4933 void
4934 ARDOUR_UI::session_dialog (std::string msg)
4935 {
4936         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
4937
4938         MessageDialog* d;
4939
4940         d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
4941         d->show_all ();
4942         d->run ();
4943         delete d;
4944 }
4945
4946 int
4947 ARDOUR_UI::pending_state_dialog ()
4948 {
4949         HBox* hbox = manage (new HBox());
4950         Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
4951         ArdourDialog dialog (_("Crash Recovery"), true);
4952         Label  message (string_compose (_("\
4953 This session appears to have been in the\n\
4954 middle of recording when %1 or\n\
4955 the computer was shutdown.\n\
4956 \n\
4957 %1 can recover any captured audio for\n\
4958 you, or it can ignore it. Please decide\n\
4959 what you would like to do.\n"), PROGRAM_NAME));
4960         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4961         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4962         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4963         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4964         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
4965         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
4966         dialog.set_default_response (RESPONSE_ACCEPT);
4967         dialog.set_position (WIN_POS_CENTER);
4968         message.show();
4969         image->show();
4970         hbox->show();
4971
4972         switch (dialog.run ()) {
4973         case RESPONSE_ACCEPT:
4974                 return 1;
4975         default:
4976                 return 0;
4977         }
4978 }
4979
4980 int
4981 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
4982 {
4983         HBox* hbox = new HBox();
4984         Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
4985         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
4986         Label  message (string_compose (_("\
4987 This session was created with a sample rate of %1 Hz, but\n\
4988 %2 is currently running at %3 Hz.  If you load this session,\n\
4989 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
4990
4991         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4992         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4993         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4994         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4995         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
4996         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
4997         dialog.set_default_response (RESPONSE_ACCEPT);
4998         dialog.set_position (WIN_POS_CENTER);
4999         message.show();
5000         image->show();
5001         hbox->show();
5002
5003         switch (dialog.run()) {
5004         case RESPONSE_ACCEPT:
5005                 return 0;
5006         default:
5007                 break;
5008         }
5009
5010         return 1;
5011 }
5012
5013 void
5014 ARDOUR_UI::sr_mismatch_message (framecnt_t desired, framecnt_t actual)
5015 {
5016         MessageDialog msg (string_compose (_("\
5017 This session was created with a sample rate of %1 Hz, but\n\
5018 %2 is currently running at %3 Hz.\n\
5019 Audio will be recorded and played at the wrong sample rate.\n\
5020 Re-Configure the Audio Engine in\n\
5021 Menu > Window > Audio/Midi Setup"),
5022                                 desired, PROGRAM_NAME, actual),
5023                         true,
5024                         Gtk::MESSAGE_WARNING);
5025         msg.run ();
5026 }
5027
5028 void
5029 ARDOUR_UI::use_config ()
5030 {
5031         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
5032         if (node) {
5033                 set_transport_controllable_state (*node);
5034         }
5035 }
5036
5037 void
5038 ARDOUR_UI::update_transport_clocks (framepos_t pos)
5039 {
5040         if (UIConfiguration::instance().get_primary_clock_delta_edit_cursor()) {
5041                 primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5042         } else {
5043                 primary_clock->set (pos);
5044         }
5045
5046         if (UIConfiguration::instance().get_secondary_clock_delta_edit_cursor()) {
5047                 secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5048         } else {
5049                 secondary_clock->set (pos);
5050         }
5051
5052         if (big_clock_window) {
5053                 big_clock->set (pos);
5054         }
5055         ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
5056 }
5057
5058 void
5059 ARDOUR_UI::step_edit_status_change (bool yn)
5060 {
5061         // XXX should really store pre-step edit status of things
5062         // we make insensitive
5063
5064         if (yn) {
5065                 rec_button.set_active_state (Gtkmm2ext::ImplicitActive);
5066                 rec_button.set_sensitive (false);
5067         } else {
5068                 rec_button.unset_active_state ();;
5069                 rec_button.set_sensitive (true);
5070         }
5071 }
5072
5073 void
5074 ARDOUR_UI::record_state_changed ()
5075 {
5076         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
5077
5078         if (!_session) {
5079                 /* why bother - the clock isn't visible */
5080                 return;
5081         }
5082
5083         ActionManager::set_sensitive (ActionManager::rec_sensitive_actions, !_session->actively_recording());
5084
5085         if (big_clock_window) {
5086                 if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
5087                         big_clock->set_active (true);
5088                 } else {
5089                         big_clock->set_active (false);
5090                 }
5091         }
5092
5093 }
5094
5095 bool
5096 ARDOUR_UI::first_idle ()
5097 {
5098         if (_session) {
5099                 _session->allow_auto_play (true);
5100         }
5101
5102         if (editor) {
5103                 editor->first_idle();
5104         }
5105
5106         Keyboard::set_can_save_keybindings (true);
5107         return false;
5108 }
5109
5110 void
5111 ARDOUR_UI::store_clock_modes ()
5112 {
5113         XMLNode* node = new XMLNode(X_("ClockModes"));
5114
5115         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
5116                 XMLNode* child = new XMLNode (X_("Clock"));
5117
5118                 child->add_property (X_("name"), (*x)->name());
5119                 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
5120                 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
5121
5122                 node->add_child_nocopy (*child);
5123         }
5124
5125         _session->add_extra_xml (*node);
5126         _session->set_dirty ();
5127 }
5128
5129 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
5130         : Controllable (name), ui (u), type(tp)
5131 {
5132
5133 }
5134
5135 void
5136 ARDOUR_UI::TransportControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /*group_override*/)
5137 {
5138         if (val < 0.5) {
5139                 /* do nothing: these are radio-style actions */
5140                 return;
5141         }
5142
5143         const char *action = 0;
5144
5145         switch (type) {
5146         case Roll:
5147                 action = X_("Roll");
5148                 break;
5149         case Stop:
5150                 action = X_("Stop");
5151                 break;
5152         case GotoStart:
5153                 action = X_("GotoStart");
5154                 break;
5155         case GotoEnd:
5156                 action = X_("GotoEnd");
5157                 break;
5158         case AutoLoop:
5159                 action = X_("Loop");
5160                 break;
5161         case PlaySelection:
5162                 action = X_("PlaySelection");
5163                 break;
5164         case RecordEnable:
5165                 action = X_("Record");
5166                 break;
5167         default:
5168                 break;
5169         }
5170
5171         if (action == 0) {
5172                 return;
5173         }
5174
5175         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
5176
5177         if (act) {
5178                 act->activate ();
5179         }
5180 }
5181
5182 double
5183 ARDOUR_UI::TransportControllable::get_value (void) const
5184 {
5185         float val = 0.0;
5186
5187         switch (type) {
5188         case Roll:
5189                 break;
5190         case Stop:
5191                 break;
5192         case GotoStart:
5193                 break;
5194         case GotoEnd:
5195                 break;
5196         case AutoLoop:
5197                 break;
5198         case PlaySelection:
5199                 break;
5200         case RecordEnable:
5201                 break;
5202         default:
5203                 break;
5204         }
5205
5206         return val;
5207 }
5208
5209 void
5210 ARDOUR_UI::setup_profile ()
5211 {
5212         if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
5213                 Profile->set_small_screen ();
5214         }
5215
5216         if (g_getenv ("TRX")) {
5217                 Profile->set_trx ();
5218         }
5219
5220         if (g_getenv ("MIXBUS")) {
5221                 Profile->set_mixbus ();
5222         }
5223 }
5224
5225 int
5226 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
5227 {
5228         MissingFileDialog dialog (s, str, type);
5229
5230         dialog.show ();
5231         dialog.present ();
5232
5233         int result = dialog.run ();
5234         dialog.hide ();
5235
5236         switch (result) {
5237         case RESPONSE_OK:
5238                 break;
5239         default:
5240                 return 1; // quit entire session load
5241         }
5242
5243         result = dialog.get_action ();
5244
5245         return result;
5246 }
5247
5248 int
5249 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
5250 {
5251         AmbiguousFileDialog dialog (file, hits);
5252
5253         dialog.show ();
5254         dialog.present ();
5255
5256         dialog.run ();
5257
5258         return dialog.get_which ();
5259 }
5260
5261 /** Allocate our thread-local buffers */
5262 void
5263 ARDOUR_UI::get_process_buffers ()
5264 {
5265         _process_thread->get_buffers ();
5266 }
5267
5268 /** Drop our thread-local buffers */
5269 void
5270 ARDOUR_UI::drop_process_buffers ()
5271 {
5272         _process_thread->drop_buffers ();
5273 }
5274
5275 void
5276 ARDOUR_UI::feedback_detected ()
5277 {
5278         _feedback_exists = true;
5279 }
5280
5281 void
5282 ARDOUR_UI::successful_graph_sort ()
5283 {
5284         _feedback_exists = false;
5285 }
5286
5287 void
5288 ARDOUR_UI::midi_panic ()
5289 {
5290         if (_session) {
5291                 _session->midi_panic();
5292         }
5293 }
5294
5295 void
5296 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
5297 {
5298         const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
5299         const char* end_big = "</span>";
5300         const char* start_mono = "<tt>";
5301         const char* end_mono = "</tt>";
5302
5303         MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
5304                                              "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
5305                                              "From now on, use the backup copy with older versions of %3"),
5306                                            xml_path, backup_path, PROGRAM_NAME,
5307                                            start_big, end_big,
5308                                            start_mono, end_mono), true);
5309
5310         msg.run ();
5311 }
5312
5313
5314 void
5315 ARDOUR_UI::reset_peak_display ()
5316 {
5317         if (!_session || !_session->master_out() || !editor_meter) return;
5318         editor_meter->clear_meters();
5319         editor_meter_max_peak = -INFINITY;
5320         editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
5321 }
5322
5323 void
5324 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
5325 {
5326         if (!_session || !_session->master_out()) return;
5327         if (group == _session->master_out()->route_group()) {
5328                 reset_peak_display ();
5329         }
5330 }
5331
5332 void
5333 ARDOUR_UI::reset_route_peak_display (Route* route)
5334 {
5335         if (!_session || !_session->master_out()) return;
5336         if (_session->master_out().get() == route) {
5337                 reset_peak_display ();
5338         }
5339 }
5340
5341 int
5342 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
5343 {
5344         audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
5345         audio_midi_setup->set_position (WIN_POS_CENTER);
5346
5347         if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
5348                 audio_midi_setup->try_autostart ();
5349                 if (ARDOUR::AudioEngine::instance()->running()) {
5350                         return 0;
5351                 }
5352         }
5353
5354         while (true) {
5355                 int response = audio_midi_setup->run();
5356                 printf("RESPONSE %d\n", response);
5357                 switch (response) {
5358                 case Gtk::RESPONSE_DELETE_EVENT:
5359                         return -1;
5360                 default:
5361                         if (!AudioEngine::instance()->running()) {
5362                                 continue;
5363                         }
5364                         audio_midi_setup->hide ();
5365                         return 0;
5366                 }
5367         }
5368 }
5369
5370
5371 gint
5372 ARDOUR_UI::transport_numpad_timeout ()
5373 {
5374         _numpad_locate_happening = false;
5375         if (_numpad_timeout_connection.connected() )
5376                 _numpad_timeout_connection.disconnect();
5377         return 1;
5378 }
5379
5380 void
5381 ARDOUR_UI::transport_numpad_decimal ()
5382 {
5383         _numpad_timeout_connection.disconnect();
5384
5385         if (_numpad_locate_happening) {
5386                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
5387                 _numpad_locate_happening = false;
5388         } else {
5389                 _pending_locate_num = 0;
5390                 _numpad_locate_happening = true;
5391                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
5392         }
5393 }
5394
5395 void
5396 ARDOUR_UI::transport_numpad_event (int num)
5397 {
5398         if ( _numpad_locate_happening ) {
5399                 _pending_locate_num = _pending_locate_num*10 + num;
5400         } else {
5401                 switch (num) {
5402                         case 0:  toggle_roll(false, false);             break;
5403                         case 1:  transport_rewind(1);                           break;
5404                         case 2:  transport_forward(1);                          break;
5405                         case 3:  transport_record(true);                        break;
5406                         case 4:  toggle_session_auto_loop();            break;
5407                         case 5:  transport_record(false); toggle_session_auto_loop();   break;
5408                         case 6:  toggle_punch();                                        break;
5409                         case 7:  toggle_click();                                break;
5410                         case 8:  toggle_auto_return();                  break;
5411                         case 9:  toggle_follow_edits();         break;
5412                 }
5413         }
5414 }
5415
5416 void
5417 ARDOUR_UI::set_flat_buttons ()
5418 {
5419         CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
5420 }
5421
5422 void
5423 ARDOUR_UI::audioengine_became_silent ()
5424 {
5425         MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
5426                            true,
5427                            Gtk::MESSAGE_WARNING,
5428                            Gtk::BUTTONS_NONE,
5429                            true);
5430
5431         msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5432
5433         Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5434         Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5435         Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5436         Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5437         Gtk::HBox pay_button_box;
5438         Gtk::HBox subscribe_button_box;
5439
5440         pay_button_box.pack_start (pay_button, true, false);
5441         subscribe_button_box.pack_start (subscribe_button, true, false);
5442
5443         bool (*openuri)(const char*) = PBD::open_uri; /* this forces selection of the const char* variant of PBD::open_uri(), which we need to avoid ambiguity below */
5444
5445         pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5446         subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5447
5448         msg.get_vbox()->pack_start (pay_label);
5449         msg.get_vbox()->pack_start (pay_button_box);
5450         msg.get_vbox()->pack_start (subscribe_label);
5451         msg.get_vbox()->pack_start (subscribe_button_box);
5452
5453         msg.get_vbox()->show_all ();
5454
5455         msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5456         msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5457         msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5458
5459         int r = msg.run ();
5460
5461         switch (r) {
5462         case Gtk::RESPONSE_YES:
5463                 AudioEngine::instance()->reset_silence_countdown ();
5464                 break;
5465
5466         case Gtk::RESPONSE_NO:
5467                 /* save and quit */
5468                 save_state_canfail ("");
5469                 exit (0);
5470                 break;
5471
5472         case Gtk::RESPONSE_CANCEL:
5473         default:
5474                 /* don't reset, save session and exit */
5475                 break;
5476         }
5477 }
5478
5479 void
5480 ARDOUR_UI::hide_application ()
5481 {
5482     Application::instance ()-> hide ();
5483 }
5484
5485 void
5486 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
5487 {
5488         /* icons, titles, WM stuff */
5489
5490         static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
5491
5492         if (window_icons.empty()) {
5493                 Glib::RefPtr<Gdk::Pixbuf> icon;
5494                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) {
5495                         window_icons.push_back (icon);
5496                 }
5497                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) {
5498                         window_icons.push_back (icon);
5499                 }
5500                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) {
5501                         window_icons.push_back (icon);
5502                 }
5503                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
5504                         window_icons.push_back (icon);
5505                 }
5506         }
5507
5508         if (!window_icons.empty()) {
5509                 window.set_default_icon_list (window_icons);
5510         }
5511
5512         Gtkmm2ext::WindowTitle title (Glib::get_application_name());
5513
5514         if (!name.empty()) {
5515                 title += name;
5516         }
5517
5518         window.set_title (title.get_string());
5519         window.set_wmclass (string_compose (X_("%1_%1"), downcase (PROGRAM_NAME), downcase (name)), PROGRAM_NAME);
5520
5521         window.set_flags (CAN_FOCUS);
5522         window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
5523
5524         /* This is a hack to ensure that GTK-accelerators continue to
5525          * work. Once we switch over to entirely native bindings, this will be
5526          * unnecessary and should be removed
5527          */
5528         window.add_accel_group (ActionManager::ui_manager->get_accel_group());
5529
5530         window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
5531         window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
5532         window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5533         window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5534 }
5535
5536 bool
5537 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
5538 {
5539         Gtkmm2ext::Bindings* bindings = 0;
5540         Gtk::Window* window = 0;
5541
5542         /* until we get ardour bindings working, we are not handling key
5543          * releases yet.
5544          */
5545
5546         if (ev->type != GDK_KEY_PRESS) {
5547                 return false;
5548         }
5549
5550         if (event_window == &_main_window) {
5551
5552                 window = event_window;
5553
5554                 /* find current tab contents */
5555
5556                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
5557
5558                 /* see if it uses the ardour binding system */
5559
5560                 if (w) {
5561                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
5562                 }
5563
5564                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
5565
5566         } else {
5567
5568                 window = event_window;
5569
5570                 /* see if window uses ardour binding system */
5571
5572                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
5573         }
5574
5575         /* An empty binding set is treated as if it doesn't exist */
5576
5577         if (bindings && bindings->empty()) {
5578                 bindings = 0;
5579         }
5580
5581         return key_press_focus_accelerator_handler (*window, ev, bindings);
5582 }
5583
5584 static Gtkmm2ext::Bindings*
5585 get_bindings_from_widget_heirarchy (GtkWidget** w)
5586 {
5587         void* p = NULL;
5588
5589         while (*w) {
5590                 if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) {
5591                         break;
5592                 }
5593                 *w = gtk_widget_get_parent (*w);
5594         }
5595
5596         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
5597 }
5598
5599 bool
5600 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
5601 {
5602         GtkWindow* win = window.gobj();
5603         GtkWidget* focus = gtk_window_get_focus (win);
5604         GtkWidget* binding_widget = focus;
5605         bool special_handling_of_unmodified_accelerators = false;
5606         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
5607
5608         if (focus) {
5609
5610                 /* some widget has keyboard focus */
5611
5612                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
5613
5614                         /* A particular kind of focusable widget currently has keyboard
5615                          * focus. All unmodified key events should go to that widget
5616                          * first and not be used as an accelerator by default
5617                          */
5618
5619                         special_handling_of_unmodified_accelerators = true;
5620
5621                 } else {
5622
5623                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5624                         if (focus_bindings) {
5625                                 bindings = focus_bindings;
5626                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
5627                         }
5628                 }
5629         }
5630
5631         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 [title = %9] focus = %7 (%8) Key event: code = %2  state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7 mods ? %8\n",
5632                                                           win,
5633                                                           ev->keyval,
5634                                                           Gtkmm2ext::show_gdk_event_state (ev->state),
5635                                                           special_handling_of_unmodified_accelerators,
5636                                                           Keyboard::some_magic_widget_has_focus(),
5637                                                           focus,
5638                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
5639                                                           ((ev->state & mask) ? "yes" : "no"),
5640                                                           window.get_title()));
5641
5642         /* This exists to allow us to override the way GTK handles
5643            key events. The normal sequence is:
5644
5645            a) event is delivered to a GtkWindow
5646            b) accelerators/mnemonics are activated
5647            c) if (b) didn't handle the event, propagate to
5648                the focus widget and/or focus chain
5649
5650            The problem with this is that if the accelerators include
5651            keys without modifiers, such as the space bar or the
5652            letter "e", then pressing the key while typing into
5653            a text entry widget results in the accelerator being
5654            activated, instead of the desired letter appearing
5655            in the text entry.
5656
5657            There is no good way of fixing this, but this
5658            represents a compromise. The idea is that
5659            key events involving modifiers (not Shift)
5660            get routed into the activation pathway first, then
5661            get propagated to the focus widget if necessary.
5662
5663            If the key event doesn't involve modifiers,
5664            we deliver to the focus widget first, thus allowing
5665            it to get "normal text" without interference
5666            from acceleration.
5667
5668            Of course, this can also be problematic: if there
5669            is a widget with focus, then it will swallow
5670            all "normal text" accelerators.
5671         */
5672
5673
5674         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
5675
5676                 /* no special handling or there are modifiers in effect: accelerate first */
5677
5678                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
5679                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
5680                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
5681
5682                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
5683                 KeyboardKey k (ev->state, ev->keyval);
5684
5685                 while (bindings) {
5686
5687                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
5688
5689                         if (bindings->activate (k, Bindings::Press)) {
5690                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5691                                 return true;
5692                         }
5693
5694                         if (binding_widget) {
5695                                 binding_widget = gtk_widget_get_parent (binding_widget);
5696                                 if (binding_widget) {
5697                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5698                                 } else {
5699                                         bindings = 0;
5700                                 }
5701                         } else {
5702                                 bindings = 0;
5703                         }
5704                 }
5705
5706                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5707
5708                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5709                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5710                         return true;
5711                 }
5712
5713                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
5714
5715                 if (gtk_window_propagate_key_event (win, ev)) {
5716                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
5717                         return true;
5718                 }
5719
5720         } else {
5721
5722                 /* no modifiers, propagate first */
5723
5724                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
5725
5726                 if (gtk_window_propagate_key_event (win, ev)) {
5727                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
5728                         return true;
5729                 }
5730
5731                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
5732                 KeyboardKey k (ev->state, ev->keyval);
5733
5734                 while (bindings) {
5735
5736                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
5737
5738
5739                         if (bindings->activate (k, Bindings::Press)) {
5740                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5741                                 return true;
5742                         }
5743
5744                         if (binding_widget) {
5745                                 binding_widget = gtk_widget_get_parent (binding_widget);
5746                                 if (binding_widget) {
5747                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5748                                 } else {
5749                                         bindings = 0;
5750                                 }
5751                         } else {
5752                                 bindings = 0;
5753                         }
5754                 }
5755
5756                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5757
5758                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5759                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5760                         return true;
5761                 }
5762         }
5763
5764         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
5765         return true;
5766 }
5767
5768 void
5769 ARDOUR_UI::load_bindings ()
5770 {
5771         if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
5772                 error << _("Global keybindings are missing") << endmsg;
5773         }
5774 }
5775
5776 void
5777 ARDOUR_UI::cancel_solo ()
5778 {
5779         if (_session) {
5780                 _session->cancel_all_solo ();
5781         }
5782 }
5783
5784 void
5785 ARDOUR_UI::reset_focus (Gtk::Widget* w)
5786 {
5787         /* this resets focus to the first focusable parent of the given widget,
5788          * or, if there is no focusable parent, cancels focus in the toplevel
5789          * window that the given widget is packed into (if there is one).
5790          */
5791
5792         if (!w) {
5793                 return;
5794         }
5795
5796         Gtk::Widget* top = w->get_toplevel();
5797
5798         if (!top || !top->is_toplevel()) {
5799                 return;
5800         }
5801
5802         w = w->get_parent ();
5803
5804         while (w) {
5805
5806                 if (w->is_toplevel()) {
5807                         /* Setting the focus widget to a Gtk::Window causes all
5808                          * subsequent calls to ::has_focus() on the nominal
5809                          * focus widget in that window to return
5810                          * false. Workaround: never set focus to the toplevel
5811                          * itself.
5812                          */
5813                         break;
5814                 }
5815
5816                 if (w->get_can_focus ()) {
5817                         Gtk::Window* win = dynamic_cast<Gtk::Window*> (top);
5818                         win->set_focus (*w);
5819                         return;
5820                 }
5821                 w = w->get_parent ();
5822         }
5823
5824         if (top == &_main_window) {
5825
5826         }
5827
5828         /* no focusable parent found, cancel focus in top level window.
5829            C++ API cannot be used for this. Thanks, references.
5830         */
5831
5832         gtk_window_set_focus (GTK_WINDOW(top->gobj()), 0);
5833
5834 }