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