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