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