Fix a bug when formatting time strings
[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                 Glib::DateTime tm (g_date_time_new_now_local ());
2737                 prompter.set_initial_text (tm.format ("%FT%H.%M.%S"));
2738         }
2739
2740         bool finished = false;
2741         while (!finished) {
2742                 switch (prompter.run()) {
2743                 case RESPONSE_ACCEPT:
2744                 {
2745                         finished = process_snapshot_session_prompter (prompter, switch_to_it);
2746                         break;
2747                 }
2748
2749                 default:
2750                         finished = true;
2751                         break;
2752                 }
2753         }
2754 }
2755
2756 /** Ask the user for a new session name and then rename the session to it.
2757  */
2758
2759 void
2760 ARDOUR_UI::rename_session ()
2761 {
2762         if (!_session) {
2763                 return;
2764         }
2765
2766         ArdourPrompter prompter (true);
2767         string name;
2768
2769         prompter.set_name ("Prompter");
2770         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2771         prompter.set_title (_("Rename Session"));
2772         prompter.set_prompt (_("New session name"));
2773
2774   again:
2775         switch (prompter.run()) {
2776         case RESPONSE_ACCEPT:
2777         {
2778                 prompter.get_result (name);
2779
2780                 bool do_rename = (name.length() != 0);
2781
2782                 if (do_rename) {
2783                         char illegal = Session::session_name_is_legal (name);
2784
2785                         if (illegal) {
2786                                 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2787                                                                      "session names may not contain a '%1' character"), illegal));
2788                                 msg.run ();
2789                                 goto again;
2790                         }
2791
2792                         switch (_session->rename (name)) {
2793                         case -1: {
2794                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2795                                 msg.set_position (WIN_POS_MOUSE);
2796                                 msg.run ();
2797                                 goto again;
2798                                 break;
2799                         }
2800                         case 0:
2801                                 break;
2802                         default: {
2803                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2804                                 msg.set_position (WIN_POS_MOUSE);
2805                                 msg.run ();
2806                                 break;
2807                         }
2808                         }
2809                 }
2810
2811                 break;
2812         }
2813
2814         default:
2815                 break;
2816         }
2817 }
2818
2819 void
2820 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2821 {
2822         if (!_session || _session->deletion_in_progress()) {
2823                 return;
2824         }
2825
2826         XMLNode* node = new XMLNode (X_("UI"));
2827
2828         WM::Manager::instance().add_state (*node);
2829
2830         node->add_child_nocopy (gui_object_state->get_state());
2831
2832         _session->add_extra_xml (*node);
2833
2834         if (export_video_dialog) {
2835                 _session->add_extra_xml (export_video_dialog->get_state());
2836         }
2837
2838         save_state_canfail (name, switch_to_it);
2839 }
2840
2841 int
2842 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2843 {
2844         if (_session) {
2845                 int ret;
2846
2847                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2848                         return ret;
2849                 }
2850         }
2851
2852         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2853         return 0;
2854 }
2855
2856 void
2857 ARDOUR_UI::primary_clock_value_changed ()
2858 {
2859         if (_session) {
2860                 _session->request_locate (primary_clock->current_time ());
2861         }
2862 }
2863
2864 void
2865 ARDOUR_UI::big_clock_value_changed ()
2866 {
2867         if (_session) {
2868                 _session->request_locate (big_clock->current_time ());
2869         }
2870 }
2871
2872 void
2873 ARDOUR_UI::secondary_clock_value_changed ()
2874 {
2875         if (_session) {
2876                 _session->request_locate (secondary_clock->current_time ());
2877         }
2878 }
2879
2880 void
2881 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2882 {
2883         if (_session == 0) {
2884                 return;
2885         }
2886
2887         if (_session->step_editing()) {
2888                 return;
2889         }
2890
2891         Session::RecordState const r = _session->record_status ();
2892         bool const h = _session->have_rec_enabled_track ();
2893
2894         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2895                 if (onoff) {
2896                         rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2897                 } else {
2898                         rec_button.set_active_state (Gtkmm2ext::Off);
2899                 }
2900         } else if (r == Session::Recording && h) {
2901                 rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2902         } else {
2903                 rec_button.unset_active_state ();
2904         }
2905 }
2906
2907 bool
2908 ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
2909 {
2910         string name;
2911
2912         prompter.get_result (name);
2913
2914         if (name.length()) {
2915                 int failed = _session->save_template (name);
2916
2917                 if (failed == -2) { /* file already exists. */
2918                         bool overwrite = overwrite_file_dialog (prompter,
2919                                                                 _("Confirm Template Overwrite"),
2920                                                                 _("A template already exists with that name. Do you want to overwrite it?"));
2921
2922                         if (overwrite) {
2923                                 _session->save_template (name, true);
2924                         }
2925                         else {
2926                                 return false;
2927                         }
2928                 }
2929         }
2930
2931         return true;
2932 }
2933
2934 void
2935 ARDOUR_UI::save_template ()
2936 {
2937         ArdourPrompter prompter (true);
2938
2939         if (!check_audioengine (_main_window)) {
2940                 return;
2941         }
2942
2943         prompter.set_name (X_("Prompter"));
2944         prompter.set_title (_("Save Template"));
2945         prompter.set_prompt (_("Name for template:"));
2946         prompter.set_initial_text(_session->name() + _("-template"));
2947         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2948
2949         bool finished = false;
2950         while (!finished) {
2951                 switch (prompter.run()) {
2952                 case RESPONSE_ACCEPT:
2953                         finished = process_save_template_prompter (prompter);
2954                         break;
2955
2956                 default:
2957                         finished = true;
2958                         break;
2959                 }
2960         }
2961 }
2962
2963 void
2964 ARDOUR_UI::edit_metadata ()
2965 {
2966         SessionMetadataEditor dialog;
2967         dialog.set_session (_session);
2968         dialog.grab_focus ();
2969         dialog.run ();
2970 }
2971
2972 void
2973 ARDOUR_UI::import_metadata ()
2974 {
2975         SessionMetadataImporter dialog;
2976         dialog.set_session (_session);
2977         dialog.run ();
2978 }
2979
2980 bool
2981 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
2982 {
2983         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2984
2985         MessageDialog msg (str,
2986                            false,
2987                            Gtk::MESSAGE_WARNING,
2988                            Gtk::BUTTONS_YES_NO,
2989                            true);
2990
2991
2992         msg.set_name (X_("OpenExistingDialog"));
2993         msg.set_title (_("Open Existing Session"));
2994         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
2995         msg.set_position (Gtk::WIN_POS_CENTER);
2996         pop_back_splash (msg);
2997
2998         switch (msg.run()) {
2999         case RESPONSE_YES:
3000                 return true;
3001                 break;
3002         }
3003         return false;
3004 }
3005
3006 int
3007 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
3008 {
3009         BusProfile bus_profile;
3010
3011         if (nsm) {
3012
3013                 bus_profile.master_out_channels = 2;
3014                 bus_profile.input_ac = AutoConnectPhysical;
3015                 bus_profile.output_ac = AutoConnectMaster;
3016                 bus_profile.requested_physical_in = 0; // use all available
3017                 bus_profile.requested_physical_out = 0; // use all available
3018
3019         } else {
3020
3021                 /* get settings from advanced section of NSD */
3022
3023                 if (sd.create_master_bus()) {
3024                         bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
3025                 } else {
3026                         bus_profile.master_out_channels = 0;
3027                 }
3028
3029                 if (sd.connect_inputs()) {
3030                         bus_profile.input_ac = AutoConnectPhysical;
3031                 } else {
3032                         bus_profile.input_ac = AutoConnectOption (0);
3033                 }
3034
3035                 bus_profile.output_ac = AutoConnectOption (0);
3036
3037                 if (sd.connect_outputs ()) {
3038                         if (sd.connect_outs_to_master()) {
3039                                 bus_profile.output_ac = AutoConnectMaster;
3040                         } else if (sd.connect_outs_to_physical()) {
3041                                 bus_profile.output_ac = AutoConnectPhysical;
3042                         }
3043                 }
3044
3045                 bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
3046                 bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
3047         }
3048
3049         if (build_session (session_path, session_name, bus_profile)) {
3050                 return -1;
3051         }
3052
3053         return 0;
3054 }
3055
3056 void
3057 ARDOUR_UI::load_from_application_api (const std::string& path)
3058 {
3059         ARDOUR_COMMAND_LINE::session_name = path;
3060         /* Cancel SessionDialog if it's visible to make OSX delegates work.
3061          *
3062          * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
3063          * race-condition:
3064          *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
3065          *    -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
3066          *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
3067          *    -> SessionDialog is not displayed
3068          */
3069
3070         if (_session_dialog) {
3071                 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3072                 std::string session_path = path;
3073                 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
3074                         session_path = Glib::path_get_dirname (session_path);
3075                 }
3076                 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
3077                 _session_dialog->set_provided_session (session_name, session_path);
3078                 _session_dialog->response (RESPONSE_NONE);
3079                 _session_dialog->hide();
3080                 return;
3081         }
3082
3083         int rv;
3084         if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
3085                 /* /path/to/foo => /path/to/foo, foo */
3086                 rv = load_session (path, basename_nosuffix (path));
3087         } else {
3088                 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
3089                 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
3090         }
3091
3092         // if load_session fails -> pop up SessionDialog.
3093         if (rv) {
3094                 ARDOUR_COMMAND_LINE::session_name = "";
3095
3096                 if (get_session_parameters (true, false)) {
3097                         exit (1);
3098                 }
3099         }
3100 }
3101
3102 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
3103 int
3104 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
3105 {
3106         string session_name;
3107         string session_path;
3108         string template_name;
3109         int ret = -1;
3110         bool likely_new = false;
3111         bool cancel_not_quit;
3112
3113         /* deal with any existing DIRTY session now, rather than later. don't
3114          * treat a non-dirty session this way, so that it stays visible
3115          * as we bring up the new session dialog.
3116          */
3117
3118         if (_session && ARDOUR_UI::instance()->video_timeline) {
3119                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
3120         }
3121
3122         /* if there is already a session, relabel the button
3123            on the SessionDialog so that we don't Quit directly
3124         */
3125         cancel_not_quit = (_session != 0);
3126
3127         if (_session && _session->dirty()) {
3128                 if (unload_session (false)) {
3129                         /* unload cancelled by user */
3130                         return 0;
3131                 }
3132                 ARDOUR_COMMAND_LINE::session_name = "";
3133         }
3134
3135         if (!load_template.empty()) {
3136                 should_be_new = true;
3137                 template_name = load_template;
3138         }
3139
3140         session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3141         session_path = ARDOUR_COMMAND_LINE::session_name;
3142
3143         if (!session_path.empty()) {
3144                 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
3145                         if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
3146                                 /* session/snapshot file, change path to be dir */
3147                                 session_path = Glib::path_get_dirname (session_path);
3148                         }
3149                 }
3150         }
3151
3152         SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
3153
3154         _session_dialog = &session_dialog;
3155         while (ret != 0) {
3156
3157                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3158
3159                         /* if they named a specific statefile, use it, otherwise they are
3160                            just giving a session folder, and we want to use it as is
3161                            to find the session.
3162                         */
3163
3164                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
3165
3166                         if (suffix != string::npos) {
3167                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
3168                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
3169                                 session_name = Glib::path_get_basename (session_name);
3170                         } else {
3171                                 session_path = ARDOUR_COMMAND_LINE::session_name;
3172                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
3173                         }
3174                 } else {
3175                         session_path = "";
3176                         session_name = "";
3177                         session_dialog.clear_given ();
3178                 }
3179
3180                 if (should_be_new || session_name.empty()) {
3181                         /* need the dialog to get info from user */
3182
3183                         cerr << "run dialog\n";
3184
3185                         switch (session_dialog.run()) {
3186                         case RESPONSE_ACCEPT:
3187                                 break;
3188                         case RESPONSE_NONE:
3189                                 /* this is used for async * app->ShouldLoad(). */
3190                                 continue; // while loop
3191                                 break;
3192                         default:
3193                                 if (quit_on_cancel) {
3194                                         // JE - Currently (July 2014) this section can only get reached if the
3195                                         // user quits from the main 'Session Setup' dialog (i.e. reaching this
3196                                         // point does NOT indicate an abnormal termination). Therefore, let's
3197                                         // behave gracefully (i.e. let's do some cleanup) before we call exit()
3198                                         ARDOUR::cleanup ();
3199                                         pthread_cancel_all ();
3200
3201                                         exit (1);
3202                                 } else {
3203                                         return ret;
3204                                 }
3205                         }
3206
3207                         session_dialog.hide ();
3208                 }
3209
3210                 /* if we run the startup dialog again, offer more than just "new session" */
3211
3212                 should_be_new = false;
3213
3214                 session_name = session_dialog.session_name (likely_new);
3215                 session_path = session_dialog.session_folder ();
3216
3217                 if (nsm) {
3218                         likely_new = true;
3219                 }
3220
3221                 string::size_type suffix = session_name.find (statefile_suffix);
3222
3223                 if (suffix != string::npos) {
3224                         session_name = session_name.substr (0, suffix);
3225                 }
3226
3227                 /* this shouldn't happen, but we catch it just in case it does */
3228
3229                 if (session_name.empty()) {
3230                         continue;
3231                 }
3232
3233                 if (session_dialog.use_session_template()) {
3234                         template_name = session_dialog.session_template_name();
3235                         _session_is_new = true;
3236                 }
3237
3238                 if (session_name[0] == G_DIR_SEPARATOR ||
3239 #ifdef PLATFORM_WINDOWS
3240                     (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3241 #else
3242                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3243                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3244 #endif
3245                          )
3246                 {
3247
3248                         /* absolute path or cwd-relative path specified for session name: infer session folder
3249                            from what was given.
3250                         */
3251
3252                         session_path = Glib::path_get_dirname (session_name);
3253                         session_name = Glib::path_get_basename (session_name);
3254
3255                 } else {
3256
3257                         session_path = session_dialog.session_folder();
3258
3259                         char illegal = Session::session_name_is_legal (session_name);
3260
3261                         if (illegal) {
3262                                 MessageDialog msg (session_dialog,
3263                                                    string_compose (_("To ensure compatibility with various systems\n"
3264                                                                      "session names may not contain a '%1' character"),
3265                                                                    illegal));
3266                                 msg.run ();
3267                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3268                                 continue;
3269                         }
3270                 }
3271
3272                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3273
3274
3275                         if (likely_new && !nsm) {
3276
3277                                 std::string existing = Glib::build_filename (session_path, session_name);
3278
3279                                 if (!ask_about_loading_existing_session (existing)) {
3280                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3281                                         continue;
3282                                 }
3283                         }
3284
3285                         _session_is_new = false;
3286
3287                 } else {
3288
3289                         if (!likely_new) {
3290                                 pop_back_splash (session_dialog);
3291                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3292                                 msg.run ();
3293                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3294                                 continue;
3295                         }
3296
3297                         char illegal = Session::session_name_is_legal(session_name);
3298
3299                         if (illegal) {
3300                                 pop_back_splash (session_dialog);
3301                                 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3302                                                                                     "session names may not contain a '%1' character"), illegal));
3303                                 msg.run ();
3304                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3305                                 continue;
3306                         }
3307
3308                         _session_is_new = true;
3309                 }
3310
3311                 if (likely_new && template_name.empty()) {
3312
3313                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3314
3315                 } else {
3316
3317                         ret = load_session (session_path, session_name, template_name);
3318
3319                         if (ret == -2) {
3320                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3321                                 exit (1);
3322                         }
3323
3324                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3325                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3326                                 exit (1);
3327                         }
3328
3329                         /* clear this to avoid endless attempts to load the
3330                            same session.
3331                         */
3332
3333                         ARDOUR_COMMAND_LINE::session_name = "";
3334                 }
3335         }
3336
3337         _session_dialog = NULL;
3338
3339         return ret;
3340 }
3341
3342 void
3343 ARDOUR_UI::close_session()
3344 {
3345         if (!check_audioengine (_main_window)) {
3346                 return;
3347         }
3348
3349         if (unload_session (true)) {
3350                 return;
3351         }
3352
3353         ARDOUR_COMMAND_LINE::session_name = "";
3354
3355         if (get_session_parameters (true, false)) {
3356                 exit (1);
3357         }
3358         if (splash && splash->is_visible()) {
3359                 // in 1 second, hide the splash screen
3360                 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
3361         }
3362 }
3363
3364 /** @param snap_name Snapshot name (without .ardour suffix).
3365  *  @return -2 if the load failed because we are not connected to the AudioEngine.
3366  */
3367 int
3368 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3369 {
3370         Session *new_session;
3371         int unload_status;
3372         int retval = -1;
3373
3374         if (_session) {
3375                 unload_status = unload_session ();
3376
3377                 if (unload_status < 0) {
3378                         goto out;
3379                 } else if (unload_status > 0) {
3380                         retval = 0;
3381                         goto out;
3382                 }
3383         }
3384
3385         session_loaded = false;
3386
3387         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3388
3389         try {
3390                 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3391         }
3392
3393         /* this one is special */
3394
3395         catch (AudioEngine::PortRegistrationFailure& err) {
3396
3397                 MessageDialog msg (err.what(),
3398                                    true,
3399                                    Gtk::MESSAGE_INFO,
3400                                    Gtk::BUTTONS_CLOSE);
3401
3402                 msg.set_title (_("Port Registration Error"));
3403                 msg.set_secondary_text (_("Click the Close button to try again."));
3404                 msg.set_position (Gtk::WIN_POS_CENTER);
3405                 pop_back_splash (msg);
3406                 msg.present ();
3407
3408                 int response = msg.run ();
3409
3410                 msg.hide ();
3411
3412                 switch (response) {
3413                 case RESPONSE_CANCEL:
3414                         exit (1);
3415                 default:
3416                         break;
3417                 }
3418                 goto out;
3419         }
3420         catch (SessionException e) {
3421                 MessageDialog msg (string_compose(
3422                                            _("Session \"%1 (snapshot %2)\" did not load successfully: %3"),
3423                                            path, snap_name, e.what()),
3424                                    true,
3425                                    Gtk::MESSAGE_INFO,
3426                                    BUTTONS_OK);
3427
3428                 msg.set_title (_("Loading Error"));
3429                 msg.set_position (Gtk::WIN_POS_CENTER);
3430                 pop_back_splash (msg);
3431                 msg.present ();
3432
3433                 dump_errors (cerr);
3434
3435                 (void) msg.run ();
3436                 msg.hide ();
3437
3438                 goto out;
3439         }
3440         catch (...) {
3441
3442                 MessageDialog msg (string_compose(
3443                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
3444                                            path, snap_name),
3445                                    true,
3446                                    Gtk::MESSAGE_INFO,
3447                                    BUTTONS_OK);
3448
3449                 msg.set_title (_("Loading Error"));
3450                 msg.set_position (Gtk::WIN_POS_CENTER);
3451                 pop_back_splash (msg);
3452                 msg.present ();
3453
3454                 dump_errors (cerr);
3455
3456                 (void) msg.run ();
3457                 msg.hide ();
3458
3459                 goto out;
3460         }
3461
3462         {
3463                 list<string> const u = new_session->unknown_processors ();
3464                 if (!u.empty()) {
3465                         MissingPluginDialog d (_session, u);
3466                         d.run ();
3467                 }
3468         }
3469
3470         if (!new_session->writable()) {
3471                 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3472                                    true,
3473                                    Gtk::MESSAGE_INFO,
3474                                    BUTTONS_OK);
3475
3476                 msg.set_title (_("Read-only Session"));
3477                 msg.set_position (Gtk::WIN_POS_CENTER);
3478                 pop_back_splash (msg);
3479                 msg.present ();
3480                 (void) msg.run ();
3481                 msg.hide ();
3482         }
3483
3484
3485         /* Now the session been created, add the transport controls */
3486         new_session->add_controllable(roll_controllable);
3487         new_session->add_controllable(stop_controllable);
3488         new_session->add_controllable(goto_start_controllable);
3489         new_session->add_controllable(goto_end_controllable);
3490         new_session->add_controllable(auto_loop_controllable);
3491         new_session->add_controllable(play_selection_controllable);
3492         new_session->add_controllable(rec_controllable);
3493
3494         set_session (new_session);
3495
3496         session_loaded = true;
3497
3498         if (_session) {
3499                 _session->set_clean ();
3500         }
3501
3502 #ifdef WINDOWS_VST_SUPPORT
3503         fst_stop_threading();
3504 #endif
3505
3506         {
3507                 Timers::TimerSuspender t;
3508                 flush_pending (10);
3509         }
3510
3511 #ifdef WINDOWS_VST_SUPPORT
3512         fst_start_threading();
3513 #endif
3514         retval = 0;
3515
3516   out:
3517         return retval;
3518 }
3519
3520 int
3521 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
3522 {
3523         Session *new_session;
3524         int x;
3525
3526         session_loaded = false;
3527         x = unload_session ();
3528
3529         if (x < 0) {
3530                 return -1;
3531         } else if (x > 0) {
3532                 return 0;
3533         }
3534
3535         _session_is_new = true;
3536
3537         try {
3538                 new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
3539         }
3540
3541         catch (SessionException e) {
3542                 dump_errors (cerr);
3543                 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3544                 msg.set_title (_("Loading Error"));
3545                 msg.set_position (Gtk::WIN_POS_CENTER);
3546                 pop_back_splash (msg);
3547                 msg.run ();
3548                 return -1;
3549         }
3550         catch (...) {
3551                 dump_errors (cerr);
3552                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3553                 msg.set_title (_("Loading Error"));
3554                 msg.set_position (Gtk::WIN_POS_CENTER);
3555                 pop_back_splash (msg);
3556                 msg.run ();
3557                 return -1;
3558         }
3559
3560         /* Give the new session the default GUI state, if such things exist */
3561
3562         XMLNode* n;
3563         n = Config->instant_xml (X_("Editor"));
3564         if (n) {
3565                 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3566                 new_session->add_instant_xml (*n, false);
3567         }
3568         n = Config->instant_xml (X_("Mixer"));
3569         if (n) {
3570                 new_session->add_instant_xml (*n, false);
3571         }
3572
3573         n = Config->instant_xml (X_("Preferences"));
3574         if (n) {
3575                 new_session->add_instant_xml (*n, false);
3576         }
3577
3578         /* Put the playhead at 0 and scroll fully left */
3579         n = new_session->instant_xml (X_("Editor"));
3580         if (n) {
3581                 n->add_property (X_("playhead"), X_("0"));
3582                 n->add_property (X_("left-frame"), X_("0"));
3583         }
3584
3585         set_session (new_session);
3586
3587         session_loaded = true;
3588
3589         new_session->save_state(new_session->name());
3590
3591         return 0;
3592 }
3593
3594 void
3595 ARDOUR_UI::launch_chat ()
3596 {
3597         MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3598
3599         dialog.set_title (_("About the Chat"));
3600         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."));
3601
3602         switch (dialog.run()) {
3603         case RESPONSE_OK:
3604 #ifdef __APPLE__
3605                 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
3606 #elif defined PLATFORM_WINDOWS
3607                 open_uri("http://webchat.freenode.net/?channels=ardour-windows");
3608 #else
3609                 open_uri("http://webchat.freenode.net/?channels=ardour");
3610 #endif
3611                 break;
3612         default:
3613                 break;
3614         }
3615 }
3616
3617 void
3618 ARDOUR_UI::launch_manual ()
3619 {
3620         PBD::open_uri (Config->get_tutorial_manual_url());
3621 }
3622
3623 void
3624 ARDOUR_UI::launch_reference ()
3625 {
3626         PBD::open_uri (Config->get_reference_manual_url());
3627 }
3628
3629 void
3630 ARDOUR_UI::launch_tracker ()
3631 {
3632         PBD::open_uri ("http://tracker.ardour.org");
3633 }
3634
3635 void
3636 ARDOUR_UI::launch_subscribe ()
3637 {
3638         PBD::open_uri ("https://community.ardour.org/s/subscribe");
3639 }
3640
3641 void
3642 ARDOUR_UI::launch_cheat_sheet ()
3643 {
3644 #ifdef __APPLE__
3645         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
3646 #else
3647         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
3648 #endif
3649 }
3650
3651 void
3652 ARDOUR_UI::launch_website ()
3653 {
3654         PBD::open_uri ("http://ardour.org");
3655 }
3656
3657 void
3658 ARDOUR_UI::launch_website_dev ()
3659 {
3660         PBD::open_uri ("http://ardour.org/development.html");
3661 }
3662
3663 void
3664 ARDOUR_UI::launch_forums ()
3665 {
3666         PBD::open_uri ("https://community.ardour.org/forums");
3667 }
3668
3669 void
3670 ARDOUR_UI::launch_howto_report ()
3671 {
3672         PBD::open_uri ("http://ardour.org/reporting_bugs");
3673 }
3674
3675 void
3676 ARDOUR_UI::loading_message (const std::string& msg)
3677 {
3678         if (ARDOUR_COMMAND_LINE::no_splash) {
3679                 return;
3680         }
3681
3682         if (!splash) {
3683                 show_splash ();
3684         }
3685
3686         splash->message (msg);
3687 }
3688
3689 void
3690 ARDOUR_UI::show_splash ()
3691 {
3692         if (splash == 0) {
3693                 try {
3694                         splash = new Splash;
3695                 } catch (...) {
3696                         return;
3697                 }
3698         }
3699
3700         splash->display ();
3701 }
3702
3703 void
3704 ARDOUR_UI::hide_splash ()
3705 {
3706         delete splash;
3707         splash = 0;
3708 }
3709
3710 void
3711 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
3712 {
3713         size_t removed;
3714
3715         removed = rep.paths.size();
3716
3717         if (removed == 0) {
3718                 MessageDialog msgd (_main_window,
3719                                     _("No files were ready for clean-up"),
3720                                     true,
3721                                     Gtk::MESSAGE_INFO,
3722                                     Gtk::BUTTONS_OK);
3723                 msgd.set_title (_("Clean-up"));
3724                 msgd.set_secondary_text (_("If this seems suprising, \n\
3725 check for any existing snapshots.\n\
3726 These may still include regions that\n\
3727 require some unused files to continue to exist."));
3728
3729                 msgd.run ();
3730                 return;
3731         }
3732
3733         ArdourDialog results (_("Clean-up"), true, false);
3734
3735         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3736             CleanupResultsModelColumns() {
3737                     add (visible_name);
3738                     add (fullpath);
3739             }
3740             Gtk::TreeModelColumn<std::string> visible_name;
3741             Gtk::TreeModelColumn<std::string> fullpath;
3742         };
3743
3744
3745         CleanupResultsModelColumns results_columns;
3746         Glib::RefPtr<Gtk::ListStore> results_model;
3747         Gtk::TreeView results_display;
3748
3749         results_model = ListStore::create (results_columns);
3750         results_display.set_model (results_model);
3751         results_display.append_column (list_title, results_columns.visible_name);
3752
3753         results_display.set_name ("CleanupResultsList");
3754         results_display.set_headers_visible (true);
3755         results_display.set_headers_clickable (false);
3756         results_display.set_reorderable (false);
3757
3758         Gtk::ScrolledWindow list_scroller;
3759         Gtk::Label txt;
3760         Gtk::VBox dvbox;
3761         Gtk::HBox dhbox;  // the hbox for the image and text
3762         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3763         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
3764
3765         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3766
3767         const string dead_directory = _session->session_directory().dead_path();
3768
3769         /* subst:
3770            %1 - number of files removed
3771            %2 - location of "dead"
3772            %3 - size of files affected
3773            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3774         */
3775
3776         const char* bprefix;
3777         double space_adjusted = 0;
3778
3779         if (rep.space < 1000) {
3780                 bprefix = X_("");
3781                 space_adjusted = rep.space;
3782         } else if (rep.space < 1000000) {
3783                 bprefix = _("kilo");
3784                 space_adjusted = floorf((float)rep.space / 1000.0);
3785         } else if (rep.space < 1000000 * 1000) {
3786                 bprefix = _("mega");
3787                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
3788         } else {
3789                 bprefix = _("giga");
3790                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
3791         }
3792
3793         if (msg_delete) {
3794                 txt.set_markup (string_compose (P_("\
3795 The following file was deleted from %2,\n\
3796 releasing %3 %4bytes of disk space", "\
3797 The following %1 files were deleted from %2,\n\
3798 releasing %3 %4bytes of disk space", removed),
3799                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3800         } else {
3801                 txt.set_markup (string_compose (P_("\
3802 The following file was not in use and \n\
3803 has been moved to: %2\n\n\
3804 After a restart of %5\n\n\
3805 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3806 will release an additional %3 %4bytes of disk space.\n", "\
3807 The following %1 files were not in use and \n\
3808 have been moved to: %2\n\n\
3809 After a restart of %5\n\n\
3810 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3811 will release an additional %3 %4bytes of disk space.\n", removed),
3812                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3813         }
3814
3815         dhbox.pack_start (*dimage, true, false, 5);
3816         dhbox.pack_start (txt, true, false, 5);
3817
3818         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3819                 TreeModel::Row row = *(results_model->append());
3820                 row[results_columns.visible_name] = *i;
3821                 row[results_columns.fullpath] = *i;
3822         }
3823
3824         list_scroller.add (results_display);
3825         list_scroller.set_size_request (-1, 150);
3826         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3827
3828         dvbox.pack_start (dhbox, true, false, 5);
3829         dvbox.pack_start (list_scroller, true, false, 5);
3830         ddhbox.pack_start (dvbox, true, false, 5);
3831
3832         results.get_vbox()->pack_start (ddhbox, true, false, 5);
3833         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3834         results.set_default_response (RESPONSE_CLOSE);
3835         results.set_position (Gtk::WIN_POS_MOUSE);
3836
3837         results_display.show();
3838         list_scroller.show();
3839         txt.show();
3840         dvbox.show();
3841         dhbox.show();
3842         ddhbox.show();
3843         dimage->show();
3844
3845         //results.get_vbox()->show();
3846         results.set_resizable (false);
3847
3848         results.run ();
3849
3850 }
3851
3852 void
3853 ARDOUR_UI::cleanup ()
3854 {
3855         if (_session == 0) {
3856                 /* shouldn't happen: menu item is insensitive */
3857                 return;
3858         }
3859
3860
3861         MessageDialog checker (_("Are you sure you want to clean-up?"),
3862                                 true,
3863                                 Gtk::MESSAGE_QUESTION,
3864                                 Gtk::BUTTONS_NONE);
3865
3866         checker.set_title (_("Clean-up"));
3867
3868         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3869 ALL undo/redo information will be lost if you clean-up.\n\
3870 Clean-up will move all unused files to a \"dead\" location."));
3871
3872         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3873         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3874         checker.set_default_response (RESPONSE_CANCEL);
3875
3876         checker.set_name (_("CleanupDialog"));
3877         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3878         checker.set_position (Gtk::WIN_POS_MOUSE);
3879
3880         switch (checker.run()) {
3881         case RESPONSE_ACCEPT:
3882                 break;
3883         default:
3884                 return;
3885         }
3886
3887         ARDOUR::CleanupReport rep;
3888
3889         editor->prepare_for_cleanup ();
3890
3891         /* do not allow flush until a session is reloaded */
3892
3893         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3894         if (act) {
3895                 act->set_sensitive (false);
3896         }
3897
3898         if (_session->cleanup_sources (rep)) {
3899                 editor->finish_cleanup ();
3900                 return;
3901         }
3902
3903         editor->finish_cleanup ();
3904
3905         checker.hide();
3906         display_cleanup_results (rep, _("Cleaned Files"), false);
3907 }
3908
3909 void
3910 ARDOUR_UI::flush_trash ()
3911 {
3912         if (_session == 0) {
3913                 /* shouldn't happen: menu item is insensitive */
3914                 return;
3915         }
3916
3917         ARDOUR::CleanupReport rep;
3918
3919         if (_session->cleanup_trash_sources (rep)) {
3920                 return;
3921         }
3922
3923         display_cleanup_results (rep, _("deleted file"), true);
3924 }
3925
3926 void
3927 ARDOUR_UI::cleanup_peakfiles ()
3928 {
3929         if (_session == 0) {
3930                 /* shouldn't happen: menu item is insensitive */
3931                 return;
3932         }
3933
3934         if (! _session->can_cleanup_peakfiles ()) {
3935                 return;
3936         }
3937
3938         // get all region-views in this session
3939         RegionSelection rs;
3940         TrackViewList empty;
3941         empty.clear();
3942         editor->get_regions_after(rs, (framepos_t) 0, empty);
3943         std::list<RegionView*> views = rs.by_layer();
3944
3945         // remove displayed audio-region-views waveforms
3946         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3947                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3948                 if (!arv) { continue ; }
3949                 arv->delete_waves();
3950         }
3951
3952         // cleanup peak files:
3953         // - stop pending peakfile threads
3954         // - close peakfiles if any
3955         // - remove peak dir in session
3956         // - setup peakfiles (background thread)
3957         _session->cleanup_peakfiles ();
3958
3959         // re-add waves to ARV
3960         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3961                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3962                 if (!arv) { continue ; }
3963                 arv->create_waves();
3964         }
3965 }
3966
3967 PresentationInfo::order_t
3968 ARDOUR_UI::translate_order (RouteDialogs::InsertAt place)
3969 {
3970         if (editor->get_selection().tracks.empty()) {
3971                 return PresentationInfo::max_order;
3972         }
3973
3974         PresentationInfo::order_t order_hint = PresentationInfo::max_order;
3975
3976         /*
3977           we want the new routes to have their order keys set starting from
3978           the highest order key in the selection + 1 (if available).
3979         */
3980
3981         if (place == RouteDialogs::AfterSelection) {
3982                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
3983                 if (rtav) {
3984                         order_hint = rtav->route()->presentation_info().order();
3985                         order_hint++;
3986                 }
3987         } else if (place == RouteDialogs::BeforeSelection) {
3988                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
3989                 if (rtav) {
3990                         order_hint = rtav->route()->presentation_info().order();
3991                 }
3992         } else if (place == RouteDialogs::First) {
3993                 order_hint = 0;
3994         } else {
3995                 /* leave order_hint at max_order */
3996         }
3997
3998         return order_hint;
3999 }
4000
4001 void
4002 ARDOUR_UI::start_duplicate_routes ()
4003 {
4004         if (!duplicate_routes_dialog) {
4005                 duplicate_routes_dialog = new DuplicateRouteDialog;
4006         }
4007
4008         if (duplicate_routes_dialog->restart (_session)) {
4009                 return;
4010         }
4011
4012         duplicate_routes_dialog->present ();
4013 }
4014
4015 void
4016 ARDOUR_UI::add_route ()
4017 {
4018         if (!add_route_dialog.get (false)) {
4019                 add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_finished));
4020         }
4021
4022         if (!_session) {
4023                 return;
4024         }
4025
4026         if (add_route_dialog->is_visible()) {
4027                 /* we're already doing this */
4028                 return;
4029         }
4030
4031         add_route_dialog->set_position (WIN_POS_MOUSE);
4032         add_route_dialog->present();
4033 }
4034
4035 void
4036 ARDOUR_UI::add_route_dialog_finished (int r)
4037 {
4038         int count;
4039
4040         add_route_dialog->hide();
4041
4042         switch (r) {
4043                 case RESPONSE_ACCEPT:
4044                         break;
4045                 default:
4046                         return;
4047                         break;
4048         }
4049
4050         if ((count = add_route_dialog->count()) <= 0) {
4051                 return;
4052         }
4053
4054         PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at());
4055         string template_path = add_route_dialog->track_template();
4056         DisplaySuspender ds;
4057
4058         if (!template_path.empty()) {
4059                 if (add_route_dialog->name_template_is_default())  {
4060                         _session->new_route_from_template (count, order, template_path, string());
4061                 } else {
4062                         _session->new_route_from_template (count, order, template_path, add_route_dialog->name_template());
4063                 }
4064                 return;
4065         }
4066
4067         ChanCount input_chan= add_route_dialog->channels ();
4068         ChanCount output_chan;
4069         string name_template = add_route_dialog->name_template ();
4070         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
4071         RouteGroup* route_group = add_route_dialog->route_group ();
4072         AutoConnectOption oac = Config->get_output_auto_connect();
4073         bool strict_io = add_route_dialog->use_strict_io ();
4074
4075         if (oac & AutoConnectMaster) {
4076                 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
4077                 output_chan.set (DataType::MIDI, 0);
4078         } else {
4079                 output_chan = input_chan;
4080         }
4081
4082         /* XXX do something with name template */
4083
4084         switch (add_route_dialog->type_wanted()) {
4085         case AddRouteDialog::AudioTrack:
4086                 session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io, order);
4087                 break;
4088         case AddRouteDialog::MidiTrack:
4089                 session_add_midi_track (route_group, count, name_template, strict_io, instrument, 0, order);
4090                 break;
4091         case AddRouteDialog::MixedTrack:
4092                 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0, order);
4093                 break;
4094         case AddRouteDialog::AudioBus:
4095                 session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template, strict_io, order);
4096                 break;
4097         case AddRouteDialog::MidiBus:
4098                 session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order);
4099                 break;
4100         case AddRouteDialog::VCAMaster:
4101                 session_add_vca (name_template, count);
4102                 break;
4103         }
4104 }
4105
4106 void
4107 ARDOUR_UI::add_lua_script ()
4108 {
4109         if (!_session) {
4110                 return;
4111         }
4112
4113         LuaScriptInfoPtr spi;
4114         ScriptSelector ss ("Add Lua Session Script", LuaScriptInfo::Session);
4115         switch (ss.run ()) {
4116                 case Gtk::RESPONSE_ACCEPT:
4117                         spi = ss.script();
4118                         break;
4119                 default:
4120                         return;
4121         }
4122         ss.hide();
4123
4124         std::string script = "";
4125
4126         try {
4127                 script = Glib::file_get_contents (spi->path);
4128         } catch (Glib::FileError e) {
4129                 string msg = string_compose (_("Cannot read session script '%1': %2"), spi->path, e.what());
4130                 MessageDialog am (msg);
4131                 am.run ();
4132                 return;
4133         }
4134
4135         LuaScriptParamList lsp = LuaScriptParams::script_params (spi, "sess_params");
4136         std::vector<std::string> reg = _session->registered_lua_functions ();
4137
4138         ScriptParameterDialog spd (_("Set Script Parameters"), spi, reg, lsp);
4139         switch (spd.run ()) {
4140                 case Gtk::RESPONSE_ACCEPT:
4141                         break;
4142                 default:
4143                         return;
4144         }
4145
4146         try {
4147                 _session->register_lua_function (spd.name(), script, lsp);
4148         } catch (luabridge::LuaException const& e) {
4149                 string msg = string_compose (_("Session script '%1' instantiation failed: %2"), spd.name(), e.what ());
4150                 MessageDialog am (msg);
4151                 am.run ();
4152         } catch (SessionException e) {
4153                 string msg = string_compose (_("Loading Session script '%1' failed: %2"), spd.name(), e.what ());
4154                 MessageDialog am (msg);
4155                 am.run ();
4156         }
4157 }
4158
4159 void
4160 ARDOUR_UI::remove_lua_script ()
4161 {
4162         if (!_session) {
4163                 return;
4164         }
4165         if (_session->registered_lua_function_count () ==  0) {
4166                 string msg = _("There are no active Lua session scripts present in this session.");
4167                 MessageDialog am (msg);
4168                 am.run ();
4169                 return;
4170         }
4171
4172         std::vector<std::string> reg = _session->registered_lua_functions ();
4173         SessionScriptManager sm ("Remove Lua Session Script", reg);
4174         switch (sm.run ()) {
4175                 case Gtk::RESPONSE_ACCEPT:
4176                         break;
4177                 default:
4178                         return;
4179         }
4180         try {
4181                 _session->unregister_lua_function (sm.name());
4182         } catch (luabridge::LuaException const& e) {
4183                 string msg = string_compose (_("Session script '%1' removal failed: %2"), sm.name(), e.what ());
4184                 MessageDialog am (msg);
4185                 am.run ();
4186         }
4187 }
4188
4189 void
4190 ARDOUR_UI::stop_video_server (bool ask_confirm)
4191 {
4192         if (!video_server_process && ask_confirm) {
4193                 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
4194         }
4195         if (video_server_process) {
4196                 if(ask_confirm) {
4197                         ArdourDialog confirm (_("Stop Video-Server"), true);
4198                         Label m (_("Do you really want to stop the Video Server?"));
4199                         confirm.get_vbox()->pack_start (m, true, true);
4200                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
4201                         confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
4202                         confirm.show_all ();
4203                         if (confirm.run() == RESPONSE_CANCEL) {
4204                                 return;
4205                         }
4206                 }
4207                 delete video_server_process;
4208                 video_server_process =0;
4209         }
4210 }
4211
4212 void
4213 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
4214 {
4215   ARDOUR_UI::start_video_server( float_window, true);
4216 }
4217
4218 bool
4219 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
4220 {
4221         if (!_session) {
4222                 return false;
4223         }
4224         if (popup_msg) {
4225                 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
4226                         if (video_server_process) {
4227                                 popup_error(_("The Video Server is already started."));
4228                         } else {
4229                                 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
4230                         }
4231                 }
4232         }
4233
4234         int firsttime = 0;
4235         while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4236                 if (firsttime++) {
4237                         warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4238                 }
4239                 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
4240                 if (float_window) {
4241                         video_server_dialog->set_transient_for (*float_window);
4242                 }
4243
4244                 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
4245                         video_server_dialog->hide();
4246                 } else {
4247                         ResponseType r = (ResponseType) video_server_dialog->run ();
4248                         video_server_dialog->hide();
4249                         if (r != RESPONSE_ACCEPT) { return false; }
4250                         if (video_server_dialog->show_again()) {
4251                                 Config->set_show_video_server_dialog(false);
4252                         }
4253                 }
4254
4255                 std::string icsd_exec = video_server_dialog->get_exec_path();
4256                 std::string icsd_docroot = video_server_dialog->get_docroot();
4257                 if (icsd_docroot.empty()) {
4258 #ifndef PLATFORM_WINDOWS
4259                         icsd_docroot = X_("/");
4260 #else
4261                         icsd_docroot = X_("C:\\");
4262 #endif
4263                 }
4264
4265                 GStatBuf sb;
4266                 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
4267                         warning << _("Specified docroot is not an existing directory.") << endmsg;
4268                         continue;
4269                 }
4270 #ifndef PLATFORM_WINDOWS
4271                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4272                      || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
4273                         warning << _("Given Video Server is not an executable file.") << endmsg;
4274                         continue;
4275                 }
4276 #else
4277                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4278                      || (sb.st_mode & (S_IXUSR)) == 0 ) {
4279                         warning << _("Given Video Server is not an executable file.") << endmsg;
4280                         continue;
4281                 }
4282 #endif
4283
4284                 char **argp;
4285                 argp=(char**) calloc(9,sizeof(char*));
4286                 argp[0] = strdup(icsd_exec.c_str());
4287                 argp[1] = strdup("-P");
4288                 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4289                 argp[3] = strdup("-p");
4290                 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4291                 argp[5] = strdup("-C");
4292                 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4293                 argp[7] = strdup(icsd_docroot.c_str());
4294                 argp[8] = 0;
4295                 stop_video_server();
4296
4297                 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4298                         Config->set_video_advanced_setup(false);
4299                 } else {
4300                         std::ostringstream osstream;
4301                         osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/";
4302                         Config->set_video_server_url(osstream.str());
4303                         Config->set_video_server_docroot(icsd_docroot);
4304                         Config->set_video_advanced_setup(true);
4305                 }
4306
4307                 if (video_server_process) {
4308                         delete video_server_process;
4309                 }
4310
4311                 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4312                 if (video_server_process->start()) {
4313                         warning << _("Cannot launch the video-server") << endmsg;
4314                         continue;
4315                 }
4316                 int timeout = 120; // 6 sec
4317                 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4318                         Glib::usleep (50000);
4319                         gui_idle_handler();
4320                         if (--timeout <= 0 || !video_server_process->is_running()) break;
4321                 }
4322                 if (timeout <= 0) {
4323                         warning << _("Video-server was started but does not respond to requests...") << endmsg;
4324                 } else {
4325                         if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4326                                 delete video_server_process;
4327                                 video_server_process = 0;
4328                         }
4329                 }
4330         }
4331         return true;
4332 }
4333
4334 void
4335 ARDOUR_UI::add_video (Gtk::Window* float_window)
4336 {
4337         if (!_session) {
4338                 return;
4339         }
4340
4341         if (!start_video_server(float_window, false)) {
4342                 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4343                 return;
4344         }
4345
4346         if (float_window) {
4347                 add_video_dialog->set_transient_for (*float_window);
4348         }
4349
4350         if (add_video_dialog->is_visible()) {
4351                 /* we're already doing this */
4352                 return;
4353         }
4354
4355         ResponseType r = (ResponseType) add_video_dialog->run ();
4356         add_video_dialog->hide();
4357         if (r != RESPONSE_ACCEPT) { return; }
4358
4359         bool local_file, orig_local_file;
4360         std::string path = add_video_dialog->file_name(local_file);
4361
4362         std::string orig_path = path;
4363         orig_local_file = local_file;
4364
4365         bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4366
4367         if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4368                 warning << string_compose(_("could not open %1"), path) << endmsg;
4369                 return;
4370         }
4371         if (!local_file && path.length() == 0) {
4372                 warning << _("no video-file selected") << endmsg;
4373                 return;
4374         }
4375
4376         std::string audio_from_video;
4377         bool detect_ltc = false;
4378
4379         switch (add_video_dialog->import_option()) {
4380                 case VTL_IMPORT_TRANSCODE:
4381                         {
4382                                 TranscodeVideoDialog *transcode_video_dialog;
4383                                 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4384                                 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4385                                 transcode_video_dialog->hide();
4386                                 if (r != RESPONSE_ACCEPT) {
4387                                         delete transcode_video_dialog;
4388                                         return;
4389                                 }
4390
4391                                 audio_from_video = transcode_video_dialog->get_audiofile();
4392
4393                                 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4394                                         detect_ltc = true;
4395                                 }
4396                                 else if (!audio_from_video.empty()) {
4397                                         editor->embed_audio_from_video(
4398                                                         audio_from_video,
4399                                                         video_timeline->get_offset(),
4400                                                         (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4401                                                         );
4402                                 }
4403                                 switch (transcode_video_dialog->import_option()) {
4404                                         case VTL_IMPORT_TRANSCODED:
4405                                                 path = transcode_video_dialog->get_filename();
4406                                                 local_file = true;
4407                                                 break;
4408                                         case VTL_IMPORT_REFERENCE:
4409                                                 break;
4410                                         default:
4411                                                 delete transcode_video_dialog;
4412                                                 return;
4413                                 }
4414                                 delete transcode_video_dialog;
4415                         }
4416                         break;
4417                 default:
4418                 case VTL_IMPORT_NONE:
4419                         break;
4420         }
4421
4422         /* strip _session->session_directory().video_path() from video file if possible */
4423         if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4424                  path=path.substr(_session->session_directory().video_path().size());
4425                  if (path.at(0) == G_DIR_SEPARATOR) {
4426                          path=path.substr(1);
4427                  }
4428         }
4429
4430         video_timeline->set_update_session_fps(auto_set_session_fps);
4431
4432         if (video_timeline->video_file_info(path, local_file)) {
4433                 XMLNode* node = new XMLNode(X_("Videotimeline"));
4434                 node->add_property (X_("Filename"), path);
4435                 node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
4436                 node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0"));
4437                 if (orig_local_file) {
4438                         node->add_property (X_("OriginalVideoFile"), orig_path);
4439                 } else {
4440                         node->remove_property (X_("OriginalVideoFile"));
4441                 }
4442                 _session->add_extra_xml (*node);
4443                 _session->set_dirty ();
4444
4445                 if (!audio_from_video.empty() && detect_ltc) {
4446                         std::vector<LTCFileReader::LTCMap> ltc_seq;
4447
4448                         try {
4449                                 /* TODO ask user about TV standard (LTC alignment if any) */
4450                                 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4451                                 /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
4452
4453                                 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC frames to decode*/ 15);
4454
4455                                 /* TODO seek near end of file, and read LTC until end.
4456                                  * if it fails to find any LTC frames, scan complete file
4457                                  *
4458                                  * calculate drift of LTC compared to video-duration,
4459                                  * ask user for reference (timecode from start/mid/end)
4460                                  */
4461                         } catch (...) {
4462                                 // LTCFileReader will have written error messages
4463                         }
4464
4465                         ::g_unlink(audio_from_video.c_str());
4466
4467                         if (ltc_seq.size() == 0) {
4468                                 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4469                         } else {
4470                                 /* the very first TC in the file is somteimes not aligned properly */
4471                                 int i = ltc_seq.size() -1;
4472                                 ARDOUR::frameoffset_t video_start_offset =
4473                                         _session->nominal_frame_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4474                                 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4475                                 video_timeline->set_offset(video_start_offset);
4476                         }
4477                 }
4478
4479                 _session->maybe_update_session_range(
4480                         std::max(video_timeline->get_offset(), (ARDOUR::frameoffset_t) 0),
4481                         std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::frameoffset_t) 0));
4482
4483
4484                 if (add_video_dialog->launch_xjadeo() && local_file) {
4485                         editor->set_xjadeo_sensitive(true);
4486                         editor->toggle_xjadeo_proc(1);
4487                 } else {
4488                         editor->toggle_xjadeo_proc(0);
4489                 }
4490                 editor->toggle_ruler_video(true);
4491         }
4492 }
4493
4494 void
4495 ARDOUR_UI::remove_video ()
4496 {
4497         video_timeline->close_session();
4498         editor->toggle_ruler_video(false);
4499
4500         /* reset state */
4501         video_timeline->set_offset_locked(false);
4502         video_timeline->set_offset(0);
4503
4504         /* delete session state */
4505         XMLNode* node = new XMLNode(X_("Videotimeline"));
4506         _session->add_extra_xml(*node);
4507         node = new XMLNode(X_("Videomonitor"));
4508         _session->add_extra_xml(*node);
4509         node = new XMLNode(X_("Videoexport"));
4510         _session->add_extra_xml(*node);
4511         stop_video_server();
4512 }
4513
4514 void
4515 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4516 {
4517         if (localcacheonly) {
4518                 video_timeline->vmon_update();
4519         } else {
4520                 video_timeline->flush_cache();
4521         }
4522         editor->queue_visual_videotimeline_update();
4523 }
4524
4525 void
4526 ARDOUR_UI::export_video (bool range)
4527 {
4528         if (ARDOUR::Config->get_show_video_export_info()) {
4529                 ExportVideoInfobox infobox (_session);
4530                 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4531                 if (infobox.show_again()) {
4532                         ARDOUR::Config->set_show_video_export_info(false);
4533                 }
4534                 switch (rv) {
4535                         case GTK_RESPONSE_YES:
4536                                 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4537                                 break;
4538                         default:
4539                                 break;
4540                 }
4541         }
4542         export_video_dialog->set_session (_session);
4543         export_video_dialog->apply_state(editor->get_selection().time, range);
4544         export_video_dialog->run ();
4545         export_video_dialog->hide ();
4546 }
4547
4548 XMLNode*
4549 ARDOUR_UI::preferences_settings () const
4550 {
4551         XMLNode* node = 0;
4552
4553         if (_session) {
4554                 node = _session->instant_xml(X_("Preferences"));
4555         } else {
4556                 node = Config->instant_xml(X_("Preferences"));
4557         }
4558
4559         if (!node) {
4560                 node = new XMLNode (X_("Preferences"));
4561         }
4562
4563         return node;
4564 }
4565
4566 XMLNode*
4567 ARDOUR_UI::mixer_settings () const
4568 {
4569         XMLNode* node = 0;
4570
4571         if (_session) {
4572                 node = _session->instant_xml(X_("Mixer"));
4573         } else {
4574                 node = Config->instant_xml(X_("Mixer"));
4575         }
4576
4577         if (!node) {
4578                 node = new XMLNode (X_("Mixer"));
4579         }
4580
4581         return node;
4582 }
4583
4584 XMLNode*
4585 ARDOUR_UI::main_window_settings () const
4586 {
4587         XMLNode* node = 0;
4588
4589         if (_session) {
4590                 node = _session->instant_xml(X_("Main"));
4591         } else {
4592                 node = Config->instant_xml(X_("Main"));
4593         }
4594
4595         if (!node) {
4596                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4597                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4598                 }
4599         }
4600
4601         if (!node) {
4602                 node = new XMLNode (X_("Main"));
4603         }
4604
4605         return node;
4606 }
4607
4608 XMLNode*
4609 ARDOUR_UI::editor_settings () const
4610 {
4611         XMLNode* node = 0;
4612
4613         if (_session) {
4614                 node = _session->instant_xml(X_("Editor"));
4615         } else {
4616                 node = Config->instant_xml(X_("Editor"));
4617         }
4618
4619         if (!node) {
4620                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4621                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4622                 }
4623         }
4624
4625         if (!node) {
4626                 node = new XMLNode (X_("Editor"));
4627         }
4628
4629         return node;
4630 }
4631
4632 XMLNode*
4633 ARDOUR_UI::keyboard_settings () const
4634 {
4635         XMLNode* node = 0;
4636
4637         node = Config->extra_xml(X_("Keyboard"));
4638
4639         if (!node) {
4640                 node = new XMLNode (X_("Keyboard"));
4641         }
4642
4643         return node;
4644 }
4645
4646 void
4647 ARDOUR_UI::create_xrun_marker (framepos_t where)
4648 {
4649         if (_session) {
4650                 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark);
4651                 _session->locations()->add (location);
4652         }
4653 }
4654
4655 void
4656 ARDOUR_UI::halt_on_xrun_message ()
4657 {
4658         cerr << "HALT on xrun\n";
4659         MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
4660         msg.run ();
4661 }
4662
4663 void
4664 ARDOUR_UI::xrun_handler (framepos_t where)
4665 {
4666         if (!_session) {
4667                 return;
4668         }
4669
4670         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4671
4672         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4673                 create_xrun_marker(where);
4674         }
4675
4676         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4677                 halt_on_xrun_message ();
4678         }
4679 }
4680
4681 void
4682 ARDOUR_UI::disk_overrun_handler ()
4683 {
4684         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4685
4686         if (!have_disk_speed_dialog_displayed) {
4687                 have_disk_speed_dialog_displayed = true;
4688                 MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
4689 The disk system on your computer\n\
4690 was not able to keep up with %1.\n\
4691 \n\
4692 Specifically, it failed to write data to disk\n\
4693 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4694                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4695                 msg->show ();
4696         }
4697 }
4698
4699
4700 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4701 static MessageDialog *scan_dlg = NULL;
4702 static ProgressBar   *scan_pbar = NULL;
4703 static HBox          *scan_tbox = NULL;
4704 static Gtk::Button   *scan_timeout_button;
4705
4706 void
4707 ARDOUR_UI::cancel_plugin_scan ()
4708 {
4709         PluginManager::instance().cancel_plugin_scan();
4710 }
4711
4712 void
4713 ARDOUR_UI::cancel_plugin_timeout ()
4714 {
4715         PluginManager::instance().cancel_plugin_timeout();
4716         scan_timeout_button->set_sensitive (false);
4717 }
4718
4719 void
4720 ARDOUR_UI::plugin_scan_timeout (int timeout)
4721 {
4722         if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4723                 return;
4724         }
4725         if (timeout > 0) {
4726                 scan_pbar->set_sensitive (false);
4727                 scan_timeout_button->set_sensitive (true);
4728                 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
4729                 scan_tbox->show();
4730         } else {
4731                 scan_pbar->set_sensitive (false);
4732                 scan_timeout_button->set_sensitive (false);
4733         }
4734         gui_idle_handler();
4735 }
4736
4737 void
4738 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
4739 {
4740         if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
4741                 return;
4742         }
4743
4744         const bool cancelled = PluginManager::instance().cancelled();
4745         if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
4746                 if (cancelled && scan_dlg->is_mapped()) {
4747                         scan_dlg->hide();
4748                         gui_idle_handler();
4749                         return;
4750                 }
4751                 if (cancelled || !can_cancel) {
4752                         return;
4753                 }
4754         }
4755
4756         static Gtk::Button *cancel_button;
4757         if (!scan_dlg) {
4758                 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
4759                 VBox* vbox = scan_dlg->get_vbox();
4760                 vbox->set_size_request(400,-1);
4761                 scan_dlg->set_title (_("Scanning for plugins"));
4762
4763                 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
4764                 cancel_button->set_name ("EditorGTKButton");
4765                 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
4766                 cancel_button->show();
4767
4768                 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
4769
4770                 scan_tbox = manage( new HBox() );
4771
4772                 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
4773                 scan_timeout_button->set_name ("EditorGTKButton");
4774                 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
4775                 scan_timeout_button->show();
4776
4777                 scan_pbar = manage(new ProgressBar());
4778                 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
4779                 scan_pbar->set_text(_("Scan Timeout"));
4780                 scan_pbar->show();
4781
4782                 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
4783                 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
4784
4785                 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
4786         }
4787
4788         assert(scan_dlg && scan_tbox && cancel_button);
4789
4790         if (type == X_("closeme")) {
4791                 scan_tbox->hide();
4792                 scan_dlg->hide();
4793         } else {
4794                 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
4795                 scan_dlg->show();
4796         }
4797         if (!can_cancel || !cancelled) {
4798                 scan_timeout_button->set_sensitive(false);
4799         }
4800         cancel_button->set_sensitive(can_cancel && !cancelled);
4801
4802         gui_idle_handler();
4803 }
4804
4805 void
4806 ARDOUR_UI::gui_idle_handler ()
4807 {
4808         int timeout = 30;
4809         /* due to idle calls, gtk_events_pending() may always return true */
4810         while (gtk_events_pending() && --timeout) {
4811                 gtk_main_iteration ();
4812         }
4813 }
4814
4815 void
4816 ARDOUR_UI::disk_underrun_handler ()
4817 {
4818         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
4819
4820         if (!have_disk_speed_dialog_displayed) {
4821                 have_disk_speed_dialog_displayed = true;
4822                 MessageDialog* msg = new MessageDialog (
4823                         _main_window, string_compose (_("The disk system on your computer\n\
4824 was not able to keep up with %1.\n\
4825 \n\
4826 Specifically, it failed to read data from disk\n\
4827 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
4828                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4829                 msg->show ();
4830         }
4831 }
4832
4833 void
4834 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
4835 {
4836         have_disk_speed_dialog_displayed = false;
4837         delete msg;
4838 }
4839
4840 void
4841 ARDOUR_UI::session_dialog (std::string msg)
4842 {
4843         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
4844
4845         MessageDialog* d;
4846
4847         d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
4848         d->show_all ();
4849         d->run ();
4850         delete d;
4851 }
4852
4853 int
4854 ARDOUR_UI::pending_state_dialog ()
4855 {
4856         HBox* hbox = manage (new HBox());
4857         Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
4858         ArdourDialog dialog (_("Crash Recovery"), true);
4859         Label  message (string_compose (_("\
4860 This session appears to have been in the\n\
4861 middle of recording when %1 or\n\
4862 the computer was shutdown.\n\
4863 \n\
4864 %1 can recover any captured audio for\n\
4865 you, or it can ignore it. Please decide\n\
4866 what you would like to do.\n"), PROGRAM_NAME));
4867         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4868         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4869         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4870         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4871         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
4872         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
4873         dialog.set_default_response (RESPONSE_ACCEPT);
4874         dialog.set_position (WIN_POS_CENTER);
4875         message.show();
4876         image->show();
4877         hbox->show();
4878
4879         switch (dialog.run ()) {
4880         case RESPONSE_ACCEPT:
4881                 return 1;
4882         default:
4883                 return 0;
4884         }
4885 }
4886
4887 int
4888 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
4889 {
4890         HBox* hbox = new HBox();
4891         Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
4892         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
4893         Label  message (string_compose (_("\
4894 This session was created with a sample rate of %1 Hz, but\n\
4895 %2 is currently running at %3 Hz.  If you load this session,\n\
4896 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
4897
4898         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4899         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4900         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4901         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4902         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
4903         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
4904         dialog.set_default_response (RESPONSE_ACCEPT);
4905         dialog.set_position (WIN_POS_CENTER);
4906         message.show();
4907         image->show();
4908         hbox->show();
4909
4910         switch (dialog.run()) {
4911         case RESPONSE_ACCEPT:
4912                 return 0;
4913         default:
4914                 break;
4915         }
4916
4917         return 1;
4918 }
4919
4920 void
4921 ARDOUR_UI::sr_mismatch_message (framecnt_t desired, framecnt_t actual)
4922 {
4923         MessageDialog msg (string_compose (_("\
4924 This session was created with a sample rate of %1 Hz, but\n\
4925 %2 is currently running at %3 Hz.\n\
4926 Audio will be recorded and played at the wrong sample rate.\n\
4927 Re-Configure the Audio Engine in\n\
4928 Menu > Window > Audio/Midi Setup"),
4929                                 desired, PROGRAM_NAME, actual),
4930                         true,
4931                         Gtk::MESSAGE_WARNING);
4932         msg.run ();
4933 }
4934
4935 void
4936 ARDOUR_UI::use_config ()
4937 {
4938         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
4939         if (node) {
4940                 set_transport_controllable_state (*node);
4941         }
4942 }
4943
4944 void
4945 ARDOUR_UI::update_transport_clocks (framepos_t pos)
4946 {
4947         if (UIConfiguration::instance().get_primary_clock_delta_edit_cursor()) {
4948                 primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4949         } else {
4950                 primary_clock->set (pos);
4951         }
4952
4953         if (UIConfiguration::instance().get_secondary_clock_delta_edit_cursor()) {
4954                 secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4955         } else {
4956                 secondary_clock->set (pos);
4957         }
4958
4959         if (big_clock_window) {
4960                 big_clock->set (pos);
4961         }
4962         ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
4963 }
4964
4965 void
4966 ARDOUR_UI::step_edit_status_change (bool yn)
4967 {
4968         // XXX should really store pre-step edit status of things
4969         // we make insensitive
4970
4971         if (yn) {
4972                 rec_button.set_active_state (Gtkmm2ext::ImplicitActive);
4973                 rec_button.set_sensitive (false);
4974         } else {
4975                 rec_button.unset_active_state ();;
4976                 rec_button.set_sensitive (true);
4977         }
4978 }
4979
4980 void
4981 ARDOUR_UI::record_state_changed ()
4982 {
4983         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
4984
4985         if (!_session || !big_clock_window) {
4986                 /* why bother - the clock isn't visible */
4987                 return;
4988         }
4989
4990         if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
4991                 big_clock->set_active (true);
4992         } else {
4993                 big_clock->set_active (false);
4994         }
4995 }
4996
4997 bool
4998 ARDOUR_UI::first_idle ()
4999 {
5000         if (_session) {
5001                 _session->allow_auto_play (true);
5002         }
5003
5004         if (editor) {
5005                 editor->first_idle();
5006         }
5007
5008         Keyboard::set_can_save_keybindings (true);
5009         return false;
5010 }
5011
5012 void
5013 ARDOUR_UI::store_clock_modes ()
5014 {
5015         XMLNode* node = new XMLNode(X_("ClockModes"));
5016
5017         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
5018                 XMLNode* child = new XMLNode (X_("Clock"));
5019
5020                 child->add_property (X_("name"), (*x)->name());
5021                 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
5022                 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
5023
5024                 node->add_child_nocopy (*child);
5025         }
5026
5027         _session->add_extra_xml (*node);
5028         _session->set_dirty ();
5029 }
5030
5031 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
5032         : Controllable (name), ui (u), type(tp)
5033 {
5034
5035 }
5036
5037 void
5038 ARDOUR_UI::TransportControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /*group_override*/)
5039 {
5040         if (val < 0.5) {
5041                 /* do nothing: these are radio-style actions */
5042                 return;
5043         }
5044
5045         const char *action = 0;
5046
5047         switch (type) {
5048         case Roll:
5049                 action = X_("Roll");
5050                 break;
5051         case Stop:
5052                 action = X_("Stop");
5053                 break;
5054         case GotoStart:
5055                 action = X_("GotoStart");
5056                 break;
5057         case GotoEnd:
5058                 action = X_("GotoEnd");
5059                 break;
5060         case AutoLoop:
5061                 action = X_("Loop");
5062                 break;
5063         case PlaySelection:
5064                 action = X_("PlaySelection");
5065                 break;
5066         case RecordEnable:
5067                 action = X_("Record");
5068                 break;
5069         default:
5070                 break;
5071         }
5072
5073         if (action == 0) {
5074                 return;
5075         }
5076
5077         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
5078
5079         if (act) {
5080                 act->activate ();
5081         }
5082 }
5083
5084 double
5085 ARDOUR_UI::TransportControllable::get_value (void) const
5086 {
5087         float val = 0.0;
5088
5089         switch (type) {
5090         case Roll:
5091                 break;
5092         case Stop:
5093                 break;
5094         case GotoStart:
5095                 break;
5096         case GotoEnd:
5097                 break;
5098         case AutoLoop:
5099                 break;
5100         case PlaySelection:
5101                 break;
5102         case RecordEnable:
5103                 break;
5104         default:
5105                 break;
5106         }
5107
5108         return val;
5109 }
5110
5111 void
5112 ARDOUR_UI::setup_profile ()
5113 {
5114         if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
5115                 Profile->set_small_screen ();
5116         }
5117
5118         if (g_getenv ("TRX")) {
5119                 Profile->set_trx ();
5120         }
5121
5122         if (g_getenv ("MIXBUS")) {
5123                 Profile->set_mixbus ();
5124         }
5125 }
5126
5127 int
5128 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
5129 {
5130         MissingFileDialog dialog (s, str, type);
5131
5132         dialog.show ();
5133         dialog.present ();
5134
5135         int result = dialog.run ();
5136         dialog.hide ();
5137
5138         switch (result) {
5139         case RESPONSE_OK:
5140                 break;
5141         default:
5142                 return 1; // quit entire session load
5143         }
5144
5145         result = dialog.get_action ();
5146
5147         return result;
5148 }
5149
5150 int
5151 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
5152 {
5153         AmbiguousFileDialog dialog (file, hits);
5154
5155         dialog.show ();
5156         dialog.present ();
5157
5158         dialog.run ();
5159
5160         return dialog.get_which ();
5161 }
5162
5163 /** Allocate our thread-local buffers */
5164 void
5165 ARDOUR_UI::get_process_buffers ()
5166 {
5167         _process_thread->get_buffers ();
5168 }
5169
5170 /** Drop our thread-local buffers */
5171 void
5172 ARDOUR_UI::drop_process_buffers ()
5173 {
5174         _process_thread->drop_buffers ();
5175 }
5176
5177 void
5178 ARDOUR_UI::feedback_detected ()
5179 {
5180         _feedback_exists = true;
5181 }
5182
5183 void
5184 ARDOUR_UI::successful_graph_sort ()
5185 {
5186         _feedback_exists = false;
5187 }
5188
5189 void
5190 ARDOUR_UI::midi_panic ()
5191 {
5192         if (_session) {
5193                 _session->midi_panic();
5194         }
5195 }
5196
5197 void
5198 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
5199 {
5200         const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
5201         const char* end_big = "</span>";
5202         const char* start_mono = "<tt>";
5203         const char* end_mono = "</tt>";
5204
5205         MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
5206                                              "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
5207                                              "From now on, use the backup copy with older versions of %3"),
5208                                            xml_path, backup_path, PROGRAM_NAME,
5209                                            start_big, end_big,
5210                                            start_mono, end_mono), true);
5211
5212         msg.run ();
5213 }
5214
5215
5216 void
5217 ARDOUR_UI::reset_peak_display ()
5218 {
5219         if (!_session || !_session->master_out() || !editor_meter) return;
5220         editor_meter->clear_meters();
5221         editor_meter_max_peak = -INFINITY;
5222         editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
5223 }
5224
5225 void
5226 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
5227 {
5228         if (!_session || !_session->master_out()) return;
5229         if (group == _session->master_out()->route_group()) {
5230                 reset_peak_display ();
5231         }
5232 }
5233
5234 void
5235 ARDOUR_UI::reset_route_peak_display (Route* route)
5236 {
5237         if (!_session || !_session->master_out()) return;
5238         if (_session->master_out().get() == route) {
5239                 reset_peak_display ();
5240         }
5241 }
5242
5243 int
5244 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
5245 {
5246         audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
5247         audio_midi_setup->set_position (WIN_POS_CENTER);
5248
5249         if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
5250                 audio_midi_setup->try_autostart ();
5251                 if (ARDOUR::AudioEngine::instance()->running()) {
5252                         return 0;
5253                 }
5254         }
5255
5256         while (true) {
5257                 int response = audio_midi_setup->run();
5258                 switch (response) {
5259                 case Gtk::RESPONSE_OK:
5260                         if (!AudioEngine::instance()->running()) {
5261                                 continue;
5262                         } else {
5263                                 return 0;
5264                         }
5265                         return 0;
5266                 default:
5267                         return -1;
5268                 }
5269         }
5270 }
5271
5272
5273 gint
5274 ARDOUR_UI::transport_numpad_timeout ()
5275 {
5276         _numpad_locate_happening = false;
5277         if (_numpad_timeout_connection.connected() )
5278                 _numpad_timeout_connection.disconnect();
5279         return 1;
5280 }
5281
5282 void
5283 ARDOUR_UI::transport_numpad_decimal ()
5284 {
5285         _numpad_timeout_connection.disconnect();
5286
5287         if (_numpad_locate_happening) {
5288                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
5289                 _numpad_locate_happening = false;
5290         } else {
5291                 _pending_locate_num = 0;
5292                 _numpad_locate_happening = true;
5293                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
5294         }
5295 }
5296
5297 void
5298 ARDOUR_UI::transport_numpad_event (int num)
5299 {
5300         if ( _numpad_locate_happening ) {
5301                 _pending_locate_num = _pending_locate_num*10 + num;
5302         } else {
5303                 switch (num) {
5304                         case 0:  toggle_roll(false, false);             break;
5305                         case 1:  transport_rewind(1);                           break;
5306                         case 2:  transport_forward(1);                          break;
5307                         case 3:  transport_record(true);                        break;
5308                         case 4:  toggle_session_auto_loop();            break;
5309                         case 5:  transport_record(false); toggle_session_auto_loop();   break;
5310                         case 6:  toggle_punch();                                        break;
5311                         case 7:  toggle_click();                                break;
5312                         case 8:  toggle_auto_return();                  break;
5313                         case 9:  toggle_follow_edits();         break;
5314                 }
5315         }
5316 }
5317
5318 void
5319 ARDOUR_UI::set_flat_buttons ()
5320 {
5321         CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
5322 }
5323
5324 void
5325 ARDOUR_UI::audioengine_became_silent ()
5326 {
5327         MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
5328                            true,
5329                            Gtk::MESSAGE_WARNING,
5330                            Gtk::BUTTONS_NONE,
5331                            true);
5332
5333         msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5334
5335         Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5336         Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5337         Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5338         Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5339         Gtk::HBox pay_button_box;
5340         Gtk::HBox subscribe_button_box;
5341
5342         pay_button_box.pack_start (pay_button, true, false);
5343         subscribe_button_box.pack_start (subscribe_button, true, false);
5344
5345         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 */
5346
5347         pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5348         subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5349
5350         msg.get_vbox()->pack_start (pay_label);
5351         msg.get_vbox()->pack_start (pay_button_box);
5352         msg.get_vbox()->pack_start (subscribe_label);
5353         msg.get_vbox()->pack_start (subscribe_button_box);
5354
5355         msg.get_vbox()->show_all ();
5356
5357         msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5358         msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5359         msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5360
5361         int r = msg.run ();
5362
5363         switch (r) {
5364         case Gtk::RESPONSE_YES:
5365                 AudioEngine::instance()->reset_silence_countdown ();
5366                 break;
5367
5368         case Gtk::RESPONSE_NO:
5369                 /* save and quit */
5370                 save_state_canfail ("");
5371                 exit (0);
5372                 break;
5373
5374         case Gtk::RESPONSE_CANCEL:
5375         default:
5376                 /* don't reset, save session and exit */
5377                 break;
5378         }
5379 }
5380
5381 void
5382 ARDOUR_UI::hide_application ()
5383 {
5384     Application::instance ()-> hide ();
5385 }
5386
5387 void
5388 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
5389 {
5390         /* icons, titles, WM stuff */
5391
5392         static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
5393
5394         if (window_icons.empty()) {
5395                 Glib::RefPtr<Gdk::Pixbuf> icon;
5396                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) {
5397                         window_icons.push_back (icon);
5398                 }
5399                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) {
5400                         window_icons.push_back (icon);
5401                 }
5402                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) {
5403                         window_icons.push_back (icon);
5404                 }
5405                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
5406                         window_icons.push_back (icon);
5407                 }
5408         }
5409
5410         if (!window_icons.empty()) {
5411                 window.set_default_icon_list (window_icons);
5412         }
5413
5414         Gtkmm2ext::WindowTitle title (Glib::get_application_name());
5415
5416         if (!name.empty()) {
5417                 title += name;
5418         }
5419
5420         window.set_title (title.get_string());
5421         window.set_wmclass (string_compose (X_("%1_%1"), downcase (PROGRAM_NAME), downcase (name)), PROGRAM_NAME);
5422
5423         window.set_flags (CAN_FOCUS);
5424         window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
5425
5426         /* This is a hack to ensure that GTK-accelerators continue to
5427          * work. Once we switch over to entirely native bindings, this will be
5428          * unnecessary and should be removed
5429          */
5430         window.add_accel_group (ActionManager::ui_manager->get_accel_group());
5431
5432         window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
5433         window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
5434         window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5435         window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5436 }
5437
5438 bool
5439 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
5440 {
5441         Gtkmm2ext::Bindings* bindings = 0;
5442         Gtk::Window* window = 0;
5443
5444         /* until we get ardour bindings working, we are not handling key
5445          * releases yet.
5446          */
5447
5448         if (ev->type != GDK_KEY_PRESS) {
5449                 return false;
5450         }
5451
5452         if (event_window == &_main_window) {
5453
5454                 window = event_window;
5455
5456                 /* find current tab contents */
5457
5458                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
5459
5460                 /* see if it uses the ardour binding system */
5461
5462                 if (w) {
5463                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
5464                 }
5465
5466                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
5467
5468         } else {
5469
5470                 window = event_window;
5471
5472                 /* see if window uses ardour binding system */
5473
5474                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
5475         }
5476
5477         /* An empty binding set is treated as if it doesn't exist */
5478
5479         if (bindings && bindings->empty()) {
5480                 bindings = 0;
5481         }
5482
5483         return key_press_focus_accelerator_handler (*window, ev, bindings);
5484 }
5485
5486 static Gtkmm2ext::Bindings*
5487 get_bindings_from_widget_heirarchy (GtkWidget* w)
5488 {
5489         void* p = NULL;
5490
5491         while (w) {
5492                 if ((p = g_object_get_data (G_OBJECT(w), "ardour-bindings")) != 0) {
5493                         break;
5494                 }
5495                 w = gtk_widget_get_parent (w);
5496         }
5497
5498         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
5499 }
5500
5501 bool
5502 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
5503 {
5504         GtkWindow* win = window.gobj();
5505         GtkWidget* focus = gtk_window_get_focus (win);
5506         bool special_handling_of_unmodified_accelerators = false;
5507         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
5508
5509         if (focus) {
5510
5511                 /* some widget has keyboard focus */
5512
5513                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
5514
5515                         /* A particular kind of focusable widget currently has keyboard
5516                          * focus. All unmodified key events should go to that widget
5517                          * first and not be used as an accelerator by default
5518                          */
5519
5520                         special_handling_of_unmodified_accelerators = true;
5521
5522                 } else {
5523
5524                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (focus);
5525                         if (focus_bindings) {
5526                                 bindings = focus_bindings;
5527                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
5528                         }
5529                 }
5530         }
5531
5532         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",
5533                                                           win,
5534                                                           ev->keyval,
5535                                                           Gtkmm2ext::show_gdk_event_state (ev->state),
5536                                                           special_handling_of_unmodified_accelerators,
5537                                                           Keyboard::some_magic_widget_has_focus(),
5538                                                           focus,
5539                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
5540                                                           ((ev->state & mask) ? "yes" : "no"),
5541                                                           window.get_title()));
5542
5543         /* This exists to allow us to override the way GTK handles
5544            key events. The normal sequence is:
5545
5546            a) event is delivered to a GtkWindow
5547            b) accelerators/mnemonics are activated
5548            c) if (b) didn't handle the event, propagate to
5549                the focus widget and/or focus chain
5550
5551            The problem with this is that if the accelerators include
5552            keys without modifiers, such as the space bar or the
5553            letter "e", then pressing the key while typing into
5554            a text entry widget results in the accelerator being
5555            activated, instead of the desired letter appearing
5556            in the text entry.
5557
5558            There is no good way of fixing this, but this
5559            represents a compromise. The idea is that
5560            key events involving modifiers (not Shift)
5561            get routed into the activation pathway first, then
5562            get propagated to the focus widget if necessary.
5563
5564            If the key event doesn't involve modifiers,
5565            we deliver to the focus widget first, thus allowing
5566            it to get "normal text" without interference
5567            from acceleration.
5568
5569            Of course, this can also be problematic: if there
5570            is a widget with focus, then it will swallow
5571            all "normal text" accelerators.
5572         */
5573
5574
5575         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
5576
5577                 /* no special handling or there are modifiers in effect: accelerate first */
5578
5579                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
5580                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
5581                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
5582
5583                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
5584                 KeyboardKey k (ev->state, ev->keyval);
5585
5586                 if (bindings) {
5587
5588                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
5589
5590                         if (bindings->activate (k, Bindings::Press)) {
5591                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5592                                 return true;
5593                         }
5594                 }
5595
5596                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5597
5598                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5599                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5600                         return true;
5601                 }
5602
5603                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
5604
5605                 if (gtk_window_propagate_key_event (win, ev)) {
5606                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
5607                         return true;
5608                 }
5609
5610         } else {
5611
5612                 /* no modifiers, propagate first */
5613
5614                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
5615
5616                 if (gtk_window_propagate_key_event (win, ev)) {
5617                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
5618                         return true;
5619                 }
5620
5621                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
5622                 KeyboardKey k (ev->state, ev->keyval);
5623
5624                 if (bindings) {
5625
5626                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
5627
5628
5629                         if (bindings->activate (k, Bindings::Press)) {
5630                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5631                                 return true;
5632                         }
5633
5634                 }
5635
5636                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5637
5638                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5639                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5640                         return true;
5641                 }
5642         }
5643
5644         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
5645         return true;
5646 }
5647
5648 void
5649 ARDOUR_UI::load_bindings ()
5650 {
5651         if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
5652                 error << _("Global keybindings are missing") << endmsg;
5653         }
5654 }
5655
5656 void
5657 ARDOUR_UI::cancel_solo ()
5658 {
5659         if (_session) {
5660                 _session->cancel_all_solo ();
5661         }
5662 }