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