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