Re-add template script debugging (after 7d48e80e)
[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_vca (const string& name_template, uint32_t n)
2021 {
2022         if (!_session) {
2023                 return;
2024         }
2025
2026         _session->vca_manager().create_vca (n, name_template);
2027 }
2028
2029 void
2030 ARDOUR_UI::session_add_mixed_track (
2031                 const ChanCount& input,
2032                 const ChanCount& output,
2033                 RouteGroup* route_group,
2034                 uint32_t how_many,
2035                 const string& name_template,
2036                 bool strict_io,
2037                 PluginInfoPtr instrument,
2038                 Plugin::PresetRecord* pset,
2039                 ARDOUR::PresentationInfo::order_t order)
2040 {
2041         if (_session == 0) {
2042                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
2043                 return;
2044         }
2045
2046         if (Profile->get_mixbus ()) {
2047                 strict_io = true;
2048         }
2049
2050         try {
2051                 list<boost::shared_ptr<MidiTrack> > tracks;
2052                 tracks = _session->new_midi_track (input, output, strict_io, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal);
2053
2054                 if (tracks.size() != how_many) {
2055                         error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg;
2056                 }
2057         }
2058
2059         catch (...) {
2060                 display_insufficient_ports_message ();
2061                 return;
2062         }
2063 }
2064
2065 void
2066 ARDOUR_UI::session_add_midi_bus (
2067                 RouteGroup* route_group,
2068                 uint32_t how_many,
2069                 const string& name_template,
2070                 bool strict_io,
2071                 PluginInfoPtr instrument,
2072                 Plugin::PresetRecord* pset,
2073                 ARDOUR::PresentationInfo::order_t order)
2074 {
2075         if (_session == 0) {
2076                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
2077                 return;
2078         }
2079
2080         if (Profile->get_mixbus ()) {
2081                 strict_io = true;
2082         }
2083
2084         try {
2085                 RouteList routes;
2086                 routes = _session->new_midi_route (route_group, how_many, name_template, strict_io, instrument, pset, PresentationInfo::MidiBus, order);
2087                 if (routes.size() != how_many) {
2088                         error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg;
2089                 }
2090
2091         }
2092         catch (...) {
2093                 display_insufficient_ports_message ();
2094                 return;
2095         }
2096 }
2097
2098 void
2099 ARDOUR_UI::session_add_midi_route (
2100                 bool disk,
2101                 RouteGroup* route_group,
2102                 uint32_t how_many,
2103                 const string& name_template,
2104                 bool strict_io,
2105                 PluginInfoPtr instrument,
2106                 Plugin::PresetRecord* pset,
2107                 ARDOUR::PresentationInfo::order_t order)
2108 {
2109         ChanCount one_midi_channel;
2110         one_midi_channel.set (DataType::MIDI, 1);
2111
2112         if (disk) {
2113                 session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, strict_io, instrument, pset, order);
2114         } else {
2115                 session_add_midi_bus (route_group, how_many, name_template, strict_io, instrument, pset, order);
2116         }
2117 }
2118
2119 void
2120 ARDOUR_UI::session_add_audio_route (
2121         bool track,
2122         int32_t input_channels,
2123         int32_t output_channels,
2124         ARDOUR::TrackMode mode,
2125         RouteGroup* route_group,
2126         uint32_t how_many,
2127         string const & name_template,
2128         bool strict_io,
2129         ARDOUR::PresentationInfo::order_t order)
2130 {
2131         list<boost::shared_ptr<AudioTrack> > tracks;
2132         RouteList routes;
2133
2134         if (_session == 0) {
2135                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
2136                 return;
2137         }
2138
2139         try {
2140                 if (track) {
2141                         tracks = _session->new_audio_track (input_channels, output_channels, route_group, how_many, name_template, order, mode);
2142
2143                         if (tracks.size() != how_many) {
2144                                 error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many)
2145                                       << endmsg;
2146                         }
2147
2148                 } else {
2149
2150                         routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template, PresentationInfo::AudioBus, order);
2151
2152                         if (routes.size() != how_many) {
2153                                 error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many)
2154                                       << endmsg;
2155                         }
2156                 }
2157         }
2158
2159         catch (...) {
2160                 display_insufficient_ports_message ();
2161                 return;
2162         }
2163
2164         if (strict_io) {
2165                 for (list<boost::shared_ptr<AudioTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
2166                         (*i)->set_strict_io (true);
2167                 }
2168                 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2169                         (*i)->set_strict_io (true);
2170                 }
2171         }
2172 }
2173
2174 void
2175 ARDOUR_UI::display_insufficient_ports_message ()
2176 {
2177         MessageDialog msg (_main_window,
2178                         string_compose (_("There are insufficient ports available\n\
2179 to create a new track or bus.\n\
2180 You should save %1, exit and\n\
2181 restart with more ports."), PROGRAM_NAME));
2182         pop_back_splash (msg);
2183         msg.run ();
2184 }
2185
2186 void
2187 ARDOUR_UI::transport_goto_start ()
2188 {
2189         if (_session) {
2190                 _session->goto_start();
2191
2192                 /* force displayed area in editor to start no matter
2193                    what "follow playhead" setting is.
2194                 */
2195
2196                 if (editor) {
2197                         editor->center_screen (_session->current_start_frame ());
2198                 }
2199         }
2200 }
2201
2202 void
2203 ARDOUR_UI::transport_goto_zero ()
2204 {
2205         if (_session) {
2206                 _session->request_locate (0);
2207
2208                 /* force displayed area in editor to start no matter
2209                    what "follow playhead" setting is.
2210                 */
2211
2212                 if (editor) {
2213                         editor->reset_x_origin (0);
2214                 }
2215         }
2216 }
2217
2218 void
2219 ARDOUR_UI::transport_goto_wallclock ()
2220 {
2221         if (_session && editor) {
2222
2223                 time_t now;
2224                 struct tm tmnow;
2225                 framepos_t frames;
2226
2227                 time (&now);
2228                 localtime_r (&now, &tmnow);
2229
2230                 framecnt_t frame_rate = _session->frame_rate();
2231
2232                 if (frame_rate == 0) {
2233                         /* no frame rate available */
2234                         return;
2235                 }
2236
2237                 frames = tmnow.tm_hour * (60 * 60 * frame_rate);
2238                 frames += tmnow.tm_min * (60 * frame_rate);
2239                 frames += tmnow.tm_sec * frame_rate;
2240
2241                 _session->request_locate (frames, _session->transport_rolling ());
2242
2243                 /* force displayed area in editor to start no matter
2244                    what "follow playhead" setting is.
2245                 */
2246
2247                 if (editor) {
2248                         editor->center_screen (frames);
2249                 }
2250         }
2251 }
2252
2253 void
2254 ARDOUR_UI::transport_goto_end ()
2255 {
2256         if (_session) {
2257                 framepos_t const frame = _session->current_end_frame();
2258                 _session->request_locate (frame);
2259
2260                 /* force displayed area in editor to start no matter
2261                    what "follow playhead" setting is.
2262                 */
2263
2264                 if (editor) {
2265                         editor->center_screen (frame);
2266                 }
2267         }
2268 }
2269
2270 void
2271 ARDOUR_UI::transport_stop ()
2272 {
2273         if (!_session) {
2274                 return;
2275         }
2276
2277         if (_session->is_auditioning()) {
2278                 _session->cancel_audition ();
2279                 return;
2280         }
2281
2282         _session->request_stop (false, true);
2283 }
2284
2285 /** Check if any tracks are record enabled. If none are, record enable all of them.
2286  * @return true if track record-enabled status was changed, false otherwise.
2287  */
2288 bool
2289 ARDOUR_UI::trx_record_enable_all_tracks ()
2290 {
2291         if (!_session) {
2292                 return false;
2293         }
2294
2295         boost::shared_ptr<RouteList> rl = _session->get_tracks ();
2296         bool none_record_enabled = true;
2297
2298         for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
2299                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*r);
2300                 assert (t);
2301
2302                 if (t->rec_enable_control()->get_value()) {
2303                         none_record_enabled = false;
2304                         break;
2305                 }
2306         }
2307
2308         if (none_record_enabled) {
2309                 _session->set_controls (route_list_to_control_list (rl, &Stripable::rec_enable_control), 1.0, Controllable::NoGroup);
2310         }
2311
2312         return none_record_enabled;
2313 }
2314
2315 void
2316 ARDOUR_UI::transport_record (bool roll)
2317 {
2318         if (_session) {
2319                 switch (_session->record_status()) {
2320                 case Session::Disabled:
2321                         if (_session->ntracks() == 0) {
2322                                 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."));
2323                                 msg.run ();
2324                                 return;
2325                         }
2326                         if (Profile->get_trx()) {
2327                                 roll = trx_record_enable_all_tracks ();
2328                         }
2329                         _session->maybe_enable_record ();
2330                         if (roll) {
2331                                 transport_roll ();
2332                         }
2333                         break;
2334                 case Session::Recording:
2335                         if (roll) {
2336                                 _session->request_stop();
2337                         } else {
2338                                 _session->disable_record (false, true);
2339                         }
2340                         break;
2341
2342                 case Session::Enabled:
2343                         _session->disable_record (false, true);
2344                 }
2345         }
2346 }
2347
2348 void
2349 ARDOUR_UI::transport_roll ()
2350 {
2351         if (!_session) {
2352                 return;
2353         }
2354
2355         if (_session->is_auditioning()) {
2356                 return;
2357         }
2358
2359 #if 0
2360         if (_session->config.get_external_sync()) {
2361                 switch (Config->get_sync_source()) {
2362                 case Engine:
2363                         break;
2364                 default:
2365                         /* transport controlled by the master */
2366                         return;
2367                 }
2368         }
2369 #endif
2370
2371         bool rolling = _session->transport_rolling();
2372
2373         if (_session->get_play_loop()) {
2374
2375                 /* If loop playback is not a mode, then we should cancel
2376                    it when this action is requested. If it is a mode
2377                    we just leave it in place.
2378                 */
2379
2380                 if (!Config->get_loop_is_mode()) {
2381                         /* XXX it is not possible to just leave seamless loop and keep
2382                            playing at present (nov 4th 2009)
2383                         */
2384                         if (!Config->get_seamless_loop()) {
2385                                 /* stop loop playback and stop rolling */
2386                                 _session->request_play_loop (false, true);
2387                         } else if (rolling) {
2388                                 /* stop loop playback but keep rolling */
2389                                 _session->request_play_loop (false, false);
2390                         }
2391                 }
2392
2393         } else if (_session->get_play_range () ) {
2394                 /* stop playing a range if we currently are */
2395                 _session->request_play_range (0, true);
2396         }
2397
2398         if (!rolling) {
2399                 _session->request_transport_speed (1.0f);
2400         }
2401 }
2402
2403 bool
2404 ARDOUR_UI::get_smart_mode() const
2405 {
2406         return ( editor->get_smart_mode() );
2407 }
2408
2409
2410 void
2411 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
2412 {
2413         if (!_session) {
2414                 return;
2415         }
2416
2417         if (_session->is_auditioning()) {
2418                 _session->cancel_audition ();
2419                 return;
2420         }
2421
2422         if (_session->config.get_external_sync()) {
2423                 switch (Config->get_sync_source()) {
2424                 case Engine:
2425                         break;
2426                 default:
2427                         /* transport controlled by the master */
2428                         return;
2429                 }
2430         }
2431
2432         bool rolling = _session->transport_rolling();
2433         bool affect_transport = true;
2434
2435         if (rolling && roll_out_of_bounded_mode) {
2436                 /* drop out of loop/range playback but leave transport rolling */
2437                 if (_session->get_play_loop()) {
2438                         if (_session->actively_recording()) {
2439
2440                                 /* just stop using the loop, then actually stop
2441                                  * below
2442                                  */
2443                                 _session->request_play_loop (false, affect_transport);
2444
2445                         } else {
2446                                 if (Config->get_seamless_loop()) {
2447                                         /* the disk buffers contain copies of the loop - we can't
2448                                            just keep playing, so stop the transport. the user
2449                                            can restart as they wish.
2450                                         */
2451                                         affect_transport = true;
2452                                 } else {
2453                                         /* disk buffers are normal, so we can keep playing */
2454                                         affect_transport = false;
2455                                 }
2456                                 _session->request_play_loop (false, affect_transport);
2457                         }
2458                 } else if (_session->get_play_range ()) {
2459                         affect_transport = false;
2460                         _session->request_play_range (0, true);
2461                 }
2462         }
2463
2464         if (affect_transport) {
2465                 if (rolling) {
2466                         _session->request_stop (with_abort, true);
2467
2468                 } else if (!with_abort) { /* with_abort == true means the
2469                                            * command was intended to stop
2470                                            * transport, not start.
2471                                            */
2472
2473                         /* the only external sync condition we can be in here
2474                          * would be Engine (JACK) sync, in which case we still
2475                          * want to do this.
2476                          */
2477
2478                         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
2479                                 _session->request_play_range (&editor->get_selection().time, true);
2480                                 _session->set_requested_return_frame( editor->get_selection().time.front().start );  //force an auto-return here
2481                         }
2482                         _session->request_transport_speed (1.0f);
2483                 }
2484         }
2485 }
2486
2487 void
2488 ARDOUR_UI::toggle_session_auto_loop ()
2489 {
2490         if (!_session) {
2491                 return;
2492         }
2493
2494         Location * looploc = _session->locations()->auto_loop_location();
2495
2496         if (!looploc) {
2497                 return;
2498         }
2499
2500         if (_session->get_play_loop()) {
2501
2502                 /* looping enabled, our job is to disable it */
2503
2504                 _session->request_play_loop (false);
2505
2506         } else {
2507
2508                 /* looping not enabled, our job is to enable it.
2509
2510                    loop-is-NOT-mode: this action always starts the transport rolling.
2511                    loop-IS-mode:     this action simply sets the loop play mechanism, but
2512                                         does not start transport.
2513                 */
2514                 if (Config->get_loop_is_mode()) {
2515                         _session->request_play_loop (true, false);
2516                 } else {
2517                         _session->request_play_loop (true, true);
2518                 }
2519         }
2520
2521         //show the loop markers
2522         looploc->set_hidden (false, this);
2523 }
2524
2525 void
2526 ARDOUR_UI::transport_play_selection ()
2527 {
2528         if (!_session) {
2529                 return;
2530         }
2531
2532         editor->play_selection ();
2533 }
2534
2535 void
2536 ARDOUR_UI::transport_play_preroll ()
2537 {
2538         if (!_session) {
2539                 return;
2540         }
2541         editor->play_with_preroll ();
2542 }
2543
2544 void
2545 ARDOUR_UI::transport_rec_preroll ()
2546 {
2547         if (!_session) {
2548                 return;
2549         }
2550         editor->rec_with_preroll ();
2551 }
2552
2553 void
2554 ARDOUR_UI::transport_rec_count_in ()
2555 {
2556         if (!_session) {
2557                 return;
2558         }
2559         editor->rec_with_count_in ();
2560 }
2561
2562 void
2563 ARDOUR_UI::transport_rewind (int option)
2564 {
2565         float current_transport_speed;
2566
2567         if (_session) {
2568                 current_transport_speed = _session->transport_speed();
2569
2570                 if (current_transport_speed >= 0.0f) {
2571                         switch (option) {
2572                         case 0:
2573                                 _session->request_transport_speed (-1.0f);
2574                                 break;
2575                         case 1:
2576                                 _session->request_transport_speed (-4.0f);
2577                                 break;
2578                         case -1:
2579                                 _session->request_transport_speed (-0.5f);
2580                                 break;
2581                         }
2582                 } else {
2583                         /* speed up */
2584                         _session->request_transport_speed (current_transport_speed * 1.5f);
2585                 }
2586         }
2587 }
2588
2589 void
2590 ARDOUR_UI::transport_forward (int option)
2591 {
2592         if (!_session) {
2593                 return;
2594         }
2595
2596         float current_transport_speed = _session->transport_speed();
2597
2598         if (current_transport_speed <= 0.0f) {
2599                 switch (option) {
2600                 case 0:
2601                         _session->request_transport_speed (1.0f);
2602                         break;
2603                 case 1:
2604                         _session->request_transport_speed (4.0f);
2605                         break;
2606                 case -1:
2607                         _session->request_transport_speed (0.5f);
2608                         break;
2609                 }
2610         } else {
2611                 /* speed up */
2612                 _session->request_transport_speed (current_transport_speed * 1.5f);
2613         }
2614 }
2615
2616 void
2617 ARDOUR_UI::toggle_record_enable (uint16_t rid)
2618 {
2619         if (!_session) {
2620                 return;
2621         }
2622
2623         boost::shared_ptr<Route> r;
2624
2625         if ((r = _session->get_remote_nth_route (rid)) != 0) {
2626
2627                 boost::shared_ptr<Track> t;
2628
2629                 if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
2630                         t->rec_enable_control()->set_value (!t->rec_enable_control()->get_value(), Controllable::UseGroup);
2631                 }
2632         }
2633 }
2634
2635 void
2636 ARDOUR_UI::map_transport_state ()
2637 {
2638         if (!_session) {
2639                 auto_loop_button.unset_active_state ();
2640                 play_selection_button.unset_active_state ();
2641                 roll_button.unset_active_state ();
2642                 stop_button.set_active_state (Gtkmm2ext::ExplicitActive);
2643                 layered_button.set_sensitive (false);
2644                 return;
2645         }
2646
2647         shuttle_box.map_transport_state ();
2648
2649         float sp = _session->transport_speed();
2650
2651         if (sp != 0.0f) {
2652
2653                 /* we're rolling */
2654
2655                 if (_session->get_play_range()) {
2656
2657                         play_selection_button.set_active_state (Gtkmm2ext::ExplicitActive);
2658                         roll_button.unset_active_state ();
2659                         auto_loop_button.unset_active_state ();
2660
2661                 } else if (_session->get_play_loop ()) {
2662
2663                         auto_loop_button.set_active (true);
2664                         play_selection_button.set_active (false);
2665                         if (Config->get_loop_is_mode()) {
2666                                 roll_button.set_active (true);
2667                         } else {
2668                                 roll_button.set_active (false);
2669                         }
2670
2671                 } else {
2672
2673                         roll_button.set_active (true);
2674                         play_selection_button.set_active (false);
2675                         auto_loop_button.set_active (false);
2676                 }
2677
2678                 if (UIConfiguration::instance().get_follow_edits() && !_session->config.get_external_sync()) {
2679                         /* light up both roll and play-selection if they are joined */
2680                         roll_button.set_active (true);
2681                         play_selection_button.set_active (true);
2682                 }
2683                 layered_button.set_sensitive (!_session->actively_recording ());
2684
2685                 stop_button.set_active (false);
2686
2687         } else {
2688
2689                 layered_button.set_sensitive (true);
2690                 stop_button.set_active (true);
2691                 roll_button.set_active (false);
2692                 play_selection_button.set_active (false);
2693                 if (Config->get_loop_is_mode ()) {
2694                         auto_loop_button.set_active (_session->get_play_loop());
2695                 } else {
2696                         auto_loop_button.set_active (false);
2697                 }
2698                 update_disk_space ();
2699         }
2700 }
2701
2702 void
2703 ARDOUR_UI::blink_handler (bool blink_on)
2704 {
2705         transport_rec_enable_blink (blink_on);
2706         sync_blink (blink_on);
2707
2708         if (!UIConfiguration::instance().get_blink_alert_indicators()) {
2709                 blink_on = true;
2710         }
2711         error_blink (blink_on);
2712         solo_blink (blink_on);
2713         audition_blink (blink_on);
2714         feedback_blink (blink_on);
2715 }
2716
2717 void
2718 ARDOUR_UI::update_clocks ()
2719 {
2720         if (!_session) return;
2721
2722         if (editor && !editor->dragging_playhead()) {
2723                 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD)); /* EMIT_SIGNAL */
2724         }
2725 }
2726
2727 void
2728 ARDOUR_UI::start_clocking ()
2729 {
2730         if (UIConfiguration::instance().get_super_rapid_clock_update()) {
2731                 clock_signal_connection = Timers::fps_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2732         } else {
2733                 clock_signal_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2734         }
2735 }
2736
2737 void
2738 ARDOUR_UI::stop_clocking ()
2739 {
2740         clock_signal_connection.disconnect ();
2741 }
2742
2743 bool
2744 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
2745 {
2746         char buf[256];
2747
2748         snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
2749
2750         label->set_text (buf);
2751         bar->set_fraction (fraction);
2752
2753         /* process events, redraws, etc. */
2754
2755         while (gtk_events_pending()) {
2756                 gtk_main_iteration ();
2757         }
2758
2759         return true; /* continue with save-as */
2760 }
2761
2762 void
2763 ARDOUR_UI::save_session_as ()
2764 {
2765         if (!_session) {
2766                 return;
2767         }
2768
2769         if (_session->dirty()) {
2770                 vector<string> actions;
2771                 actions.push_back (_("Abort save-as"));
2772                 actions.push_back (_("Don't save now, just save-as"));
2773                 actions.push_back (_("Save it first"));
2774                 switch (ask_about_saving_session(actions)) {
2775                         case -1:
2776                                 return;
2777                                 break;
2778                         case 1:
2779                                 if (save_state_canfail ("")) {
2780                                         MessageDialog msg (_main_window,
2781                                                         string_compose (_("\
2782 %1 was unable to save your session.\n\n\
2783 If you still wish to proceeed, please use the\n\n\
2784 \"Don't save now\" option."), PROGRAM_NAME));
2785                                         pop_back_splash(msg);
2786                                         msg.run ();
2787                                         return;
2788                                 }
2789                                 // no break
2790                         case 0:
2791                                 _session->remove_pending_capture_state ();
2792                                 break;
2793                 }
2794         }
2795
2796         if (!save_as_dialog) {
2797                 save_as_dialog = new SaveAsDialog;
2798         }
2799
2800         save_as_dialog->set_name (_session->name());
2801
2802         int response = save_as_dialog->run ();
2803
2804         save_as_dialog->hide ();
2805
2806         switch (response) {
2807         case Gtk::RESPONSE_OK:
2808                 break;
2809         default:
2810                 return;
2811         }
2812
2813
2814         Session::SaveAs sa;
2815
2816         sa.new_parent_folder = save_as_dialog->new_parent_folder ();
2817         sa.new_name = save_as_dialog->new_name ();
2818         sa.switch_to = save_as_dialog->switch_to();
2819         sa.copy_media = save_as_dialog->copy_media();
2820         sa.copy_external = save_as_dialog->copy_external();
2821         sa.include_media = save_as_dialog->include_media ();
2822
2823         /* Only bother with a progress dialog if we're going to copy
2824            media into the save-as target. Without that choice, this
2825            will be very fast because we're only talking about a few kB's to
2826            perhaps a couple of MB's of data.
2827         */
2828
2829         ArdourDialog progress_dialog (_("Save As"), true);
2830         ScopedConnection c;
2831
2832         if (sa.include_media && sa.copy_media) {
2833
2834                 Gtk::Label* label = manage (new Gtk::Label());
2835                 Gtk::ProgressBar* progress_bar = manage (new Gtk::ProgressBar ());
2836
2837                 progress_dialog.get_vbox()->pack_start (*label);
2838                 progress_dialog.get_vbox()->pack_start (*progress_bar);
2839                 label->show ();
2840                 progress_bar->show ();
2841
2842                 /* this signal will be emitted from within this, the calling thread,
2843                  * after every file is copied. It provides information on percentage
2844                  * complete (in terms of total data to copy), the number of files
2845                  * copied so far, and the total number to copy.
2846                  */
2847
2848                 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, label, progress_bar));
2849
2850                 progress_dialog.show_all ();
2851                 progress_dialog.present ();
2852         }
2853
2854         if (_session->save_as (sa)) {
2855                 /* ERROR MESSAGE */
2856                 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
2857                 msg.run ();
2858         }
2859
2860         /* the logic here may seem odd: why isn't the condition sa.switch_to ?
2861          * the trick is this: if the new session was copy with media included,
2862          * then Session::save_as() will have already done a neat trick to avoid
2863          * us having to unload and load the new state. But if the media was not
2864          * included, then this is required (it avoids us having to otherwise
2865          * drop all references to media (sources).
2866          */
2867
2868         if (!sa.include_media && sa.switch_to) {
2869                 unload_session (false);
2870                 load_session (sa.final_session_folder_name, sa.new_name);
2871         }
2872 }
2873
2874 void
2875 ARDOUR_UI::archive_session ()
2876 {
2877         if (!_session) {
2878                 return;
2879         }
2880
2881         time_t n;
2882         time (&n);
2883         Glib::DateTime gdt (Glib::DateTime::create_now_local (n));
2884
2885         SessionArchiveDialog sad;
2886         sad.set_name (_session->name() + gdt.format ("_%F_%H%M%S"));
2887         int response = sad.run ();
2888
2889         if (response != Gtk::RESPONSE_OK) {
2890                 sad.hide ();
2891                 return;
2892         }
2893
2894         if (_session->archive_session (sad.target_folder(), sad.name(), sad.encode_option (), sad.only_used_sources (), &sad)) {
2895                 MessageDialog msg (_("Session Archiving failed."));
2896                 msg.run ();
2897         }
2898 }
2899
2900 void
2901 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
2902 {
2903                 char timebuf[128];
2904                 time_t n;
2905                 struct tm local_time;
2906
2907                 time (&n);
2908                 localtime_r (&n, &local_time);
2909                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2910                 if (switch_to_it && _session->dirty ()) {
2911                         save_state_canfail ("");
2912                 }
2913
2914                 save_state (timebuf, switch_to_it);
2915 }
2916
2917
2918 bool
2919 ARDOUR_UI::process_snapshot_session_prompter (Prompter& prompter, bool switch_to_it)
2920 {
2921         string snapname;
2922
2923         prompter.get_result (snapname);
2924
2925         bool do_save = (snapname.length() != 0);
2926
2927         if (do_save) {
2928                 char illegal = Session::session_name_is_legal(snapname);
2929                 if (illegal) {
2930                         MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2931                                                              "snapshot names may not contain a '%1' character"), illegal));
2932                         msg.run ();
2933                         return false;
2934                 }
2935         }
2936
2937         vector<std::string> p;
2938         get_state_files_in_directory (_session->session_directory().root_path(), p);
2939         vector<string> n = get_file_names_no_extension (p);
2940
2941         if (find (n.begin(), n.end(), snapname) != n.end()) {
2942
2943                 do_save = overwrite_file_dialog (prompter,
2944                                                  _("Confirm Snapshot Overwrite"),
2945                                                  _("A snapshot already exists with that name. Do you want to overwrite it?"));
2946         }
2947
2948         if (do_save) {
2949                 save_state (snapname, switch_to_it);
2950         }
2951         else {
2952                 return false;
2953         }
2954
2955         return true;
2956 }
2957
2958
2959 /** Ask the user for the name of a new snapshot and then take it.
2960  */
2961
2962 void
2963 ARDOUR_UI::snapshot_session (bool switch_to_it)
2964 {
2965         if (switch_to_it && _session->dirty()) {
2966                 vector<string> actions;
2967                 actions.push_back (_("Abort saving snapshot"));
2968                 actions.push_back (_("Don't save now, just snapshot"));
2969                 actions.push_back (_("Save it first"));
2970                 switch (ask_about_saving_session(actions)) {
2971                         case -1:
2972                                 return;
2973                                 break;
2974                         case 1:
2975                                 if (save_state_canfail ("")) {
2976                                         MessageDialog msg (_main_window,
2977                                                         string_compose (_("\
2978 %1 was unable to save your session.\n\n\
2979 If you still wish to proceeed, please use the\n\n\
2980 \"Don't save now\" option."), PROGRAM_NAME));
2981                                         pop_back_splash(msg);
2982                                         msg.run ();
2983                                         return;
2984                                 }
2985                                 // no break
2986                         case 0:
2987                                 _session->remove_pending_capture_state ();
2988                                 break;
2989                 }
2990         }
2991
2992         Prompter prompter (true);
2993         prompter.set_name ("Prompter");
2994         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2995         if (switch_to_it) {
2996                 prompter.set_title (_("Snapshot and switch"));
2997                 prompter.set_prompt (_("New session name"));
2998         } else {
2999                 prompter.set_title (_("Take Snapshot"));
3000                 prompter.set_prompt (_("Name of new snapshot"));
3001         }
3002
3003         if (switch_to_it) {
3004                 prompter.set_initial_text (_session->snap_name());
3005         } else {
3006                 Glib::DateTime tm (g_date_time_new_now_local ());
3007                 prompter.set_initial_text (tm.format ("%FT%H.%M.%S"));
3008         }
3009
3010         bool finished = false;
3011         while (!finished) {
3012                 switch (prompter.run()) {
3013                 case RESPONSE_ACCEPT:
3014                 {
3015                         finished = process_snapshot_session_prompter (prompter, switch_to_it);
3016                         break;
3017                 }
3018
3019                 default:
3020                         finished = true;
3021                         break;
3022                 }
3023         }
3024 }
3025
3026 /** Ask the user for a new session name and then rename the session to it.
3027  */
3028
3029 void
3030 ARDOUR_UI::rename_session ()
3031 {
3032         if (!_session) {
3033                 return;
3034         }
3035
3036         Prompter prompter (true);
3037         string name;
3038
3039         prompter.set_name ("Prompter");
3040         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
3041         prompter.set_title (_("Rename Session"));
3042         prompter.set_prompt (_("New session name"));
3043
3044   again:
3045         switch (prompter.run()) {
3046         case RESPONSE_ACCEPT:
3047         {
3048                 prompter.get_result (name);
3049
3050                 bool do_rename = (name.length() != 0);
3051
3052                 if (do_rename) {
3053                         char illegal = Session::session_name_is_legal (name);
3054
3055                         if (illegal) {
3056                                 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
3057                                                                      "session names may not contain a '%1' character"), illegal));
3058                                 msg.run ();
3059                                 goto again;
3060                         }
3061
3062                         switch (_session->rename (name)) {
3063                         case -1: {
3064                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
3065                                 msg.set_position (WIN_POS_MOUSE);
3066                                 msg.run ();
3067                                 goto again;
3068                                 break;
3069                         }
3070                         case 0:
3071                                 break;
3072                         default: {
3073                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
3074                                 msg.set_position (WIN_POS_MOUSE);
3075                                 msg.run ();
3076                                 break;
3077                         }
3078                         }
3079                 }
3080
3081                 break;
3082         }
3083
3084         default:
3085                 break;
3086         }
3087 }
3088
3089 void
3090 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
3091 {
3092         if (!_session || _session->deletion_in_progress()) {
3093                 return;
3094         }
3095
3096         XMLNode* node = new XMLNode (X_("UI"));
3097
3098         WM::Manager::instance().add_state (*node);
3099
3100         node->add_child_nocopy (gui_object_state->get_state());
3101
3102         _session->add_extra_xml (*node);
3103
3104         if (export_video_dialog) {
3105                 _session->add_extra_xml (export_video_dialog->get_state());
3106         }
3107
3108         save_state_canfail (name, switch_to_it);
3109 }
3110
3111 int
3112 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
3113 {
3114         if (_session) {
3115                 int ret;
3116
3117                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
3118                         return ret;
3119                 }
3120         }
3121
3122         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
3123         return 0;
3124 }
3125
3126 void
3127 ARDOUR_UI::primary_clock_value_changed ()
3128 {
3129         if (_session) {
3130                 _session->request_locate (primary_clock->current_time ());
3131         }
3132 }
3133
3134 void
3135 ARDOUR_UI::big_clock_value_changed ()
3136 {
3137         if (_session) {
3138                 _session->request_locate (big_clock->current_time ());
3139         }
3140 }
3141
3142 void
3143 ARDOUR_UI::secondary_clock_value_changed ()
3144 {
3145         if (_session) {
3146                 _session->request_locate (secondary_clock->current_time ());
3147         }
3148 }
3149
3150 void
3151 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
3152 {
3153         if (_session == 0) {
3154                 return;
3155         }
3156
3157         if (_session->step_editing()) {
3158                 return;
3159         }
3160
3161         Session::RecordState const r = _session->record_status ();
3162         bool const h = _session->have_rec_enabled_track ();
3163
3164         if (r == Session::Enabled || (r == Session::Recording && !h)) {
3165                 if (onoff) {
3166                         rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
3167                 } else {
3168                         rec_button.set_active_state (Gtkmm2ext::Off);
3169                 }
3170         } else if (r == Session::Recording && h) {
3171                 rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
3172         } else {
3173                 rec_button.unset_active_state ();
3174         }
3175 }
3176
3177 bool
3178 ARDOUR_UI::process_save_template_prompter (Prompter& prompter)
3179 {
3180         string name;
3181
3182         prompter.get_result (name);
3183
3184         if (name.length()) {
3185                 int failed = _session->save_template (name);
3186
3187                 if (failed == -2) { /* file already exists. */
3188                         bool overwrite = overwrite_file_dialog (prompter,
3189                                                                 _("Confirm Template Overwrite"),
3190                                                                 _("A template already exists with that name. Do you want to overwrite it?"));
3191
3192                         if (overwrite) {
3193                                 _session->save_template (name, true);
3194                         }
3195                         else {
3196                                 return false;
3197                         }
3198                 }
3199         }
3200
3201         return true;
3202 }
3203
3204 void
3205 ARDOUR_UI::save_template ()
3206 {
3207         Prompter prompter (true);
3208
3209         if (!check_audioengine (_main_window)) {
3210                 return;
3211         }
3212
3213         prompter.set_name (X_("Prompter"));
3214         prompter.set_title (_("Save Template"));
3215         prompter.set_prompt (_("Name for template:"));
3216         prompter.set_initial_text(_session->name() + _("-template"));
3217         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
3218
3219         bool finished = false;
3220         while (!finished) {
3221                 switch (prompter.run()) {
3222                 case RESPONSE_ACCEPT:
3223                         finished = process_save_template_prompter (prompter);
3224                         break;
3225
3226                 default:
3227                         finished = true;
3228                         break;
3229                 }
3230         }
3231 }
3232
3233 void ARDOUR_UI::manage_templates ()
3234 {
3235         TemplateDialog td;
3236         td.run();
3237 }
3238
3239 void
3240 ARDOUR_UI::edit_metadata ()
3241 {
3242         SessionMetadataEditor dialog;
3243         dialog.set_session (_session);
3244         dialog.grab_focus ();
3245         dialog.run ();
3246 }
3247
3248 void
3249 ARDOUR_UI::import_metadata ()
3250 {
3251         SessionMetadataImporter dialog;
3252         dialog.set_session (_session);
3253         dialog.run ();
3254 }
3255
3256 bool
3257 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
3258 {
3259         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
3260
3261         MessageDialog msg (str,
3262                            false,
3263                            Gtk::MESSAGE_WARNING,
3264                            Gtk::BUTTONS_YES_NO,
3265                            true);
3266
3267
3268         msg.set_name (X_("OpenExistingDialog"));
3269         msg.set_title (_("Open Existing Session"));
3270         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
3271         msg.set_position (Gtk::WIN_POS_CENTER);
3272         pop_back_splash (msg);
3273
3274         switch (msg.run()) {
3275         case RESPONSE_YES:
3276                 return true;
3277                 break;
3278         }
3279         return false;
3280 }
3281
3282 int
3283 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
3284 {
3285         BusProfile bus_profile;
3286
3287         if (nsm) {
3288
3289                 bus_profile.master_out_channels = 2;
3290                 bus_profile.input_ac = AutoConnectPhysical;
3291                 bus_profile.output_ac = AutoConnectMaster;
3292                 bus_profile.requested_physical_in = 0; // use all available
3293                 bus_profile.requested_physical_out = 0; // use all available
3294
3295         } else {
3296
3297                 /* get settings from advanced section of NSD */
3298
3299                 if (sd.create_master_bus()) {
3300                         bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
3301                 } else {
3302                         bus_profile.master_out_channels = 0;
3303                 }
3304
3305                 if (sd.connect_inputs()) {
3306                         bus_profile.input_ac = AutoConnectPhysical;
3307                 } else {
3308                         bus_profile.input_ac = AutoConnectOption (0);
3309                 }
3310
3311                 bus_profile.output_ac = AutoConnectOption (0);
3312
3313                 if (sd.connect_outputs ()) {
3314                         if (sd.connect_outs_to_master()) {
3315                                 bus_profile.output_ac = AutoConnectMaster;
3316                         } else if (sd.connect_outs_to_physical()) {
3317                                 bus_profile.output_ac = AutoConnectPhysical;
3318                         }
3319                 }
3320
3321                 bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
3322                 bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
3323         }
3324
3325         if (build_session (session_path, session_name, bus_profile)) {
3326                 return -1;
3327         }
3328
3329         return 0;
3330 }
3331
3332 void
3333 ARDOUR_UI::load_from_application_api (const std::string& path)
3334 {
3335         /* OS X El Capitan (and probably later) now somehow passes the command
3336            line arguments to an app via the openFile delegate protocol. Ardour
3337            already does its own command line processing, and having both
3338            pathways active causes crashes. So, if the command line was already
3339            set, do nothing here.
3340         */
3341
3342         if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3343                 return;
3344         }
3345
3346         ARDOUR_COMMAND_LINE::session_name = path;
3347
3348         /* Cancel SessionDialog if it's visible to make OSX delegates work.
3349          *
3350          * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
3351          * race-condition:
3352          *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
3353          *    -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
3354          *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
3355          *    -> SessionDialog is not displayed
3356          */
3357
3358         if (_session_dialog) {
3359                 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3360                 std::string session_path = path;
3361                 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
3362                         session_path = Glib::path_get_dirname (session_path);
3363                 }
3364                 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
3365                 _session_dialog->set_provided_session (session_name, session_path);
3366                 _session_dialog->response (RESPONSE_NONE);
3367                 _session_dialog->hide();
3368                 return;
3369         }
3370
3371         int rv;
3372         if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
3373                 /* /path/to/foo => /path/to/foo, foo */
3374                 rv = load_session (path, basename_nosuffix (path));
3375         } else {
3376                 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
3377                 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
3378         }
3379
3380         // if load_session fails -> pop up SessionDialog.
3381         if (rv) {
3382                 ARDOUR_COMMAND_LINE::session_name = "";
3383
3384                 if (get_session_parameters (true, false)) {
3385                         exit (1);
3386                 }
3387         }
3388 }
3389
3390 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
3391 int
3392 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
3393 {
3394         string session_name;
3395         string session_path;
3396         string template_name;
3397         int ret = -1;
3398         bool likely_new = false;
3399         bool cancel_not_quit;
3400
3401         /* deal with any existing DIRTY session now, rather than later. don't
3402          * treat a non-dirty session this way, so that it stays visible
3403          * as we bring up the new session dialog.
3404          */
3405
3406         if (_session && ARDOUR_UI::instance()->video_timeline) {
3407                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
3408         }
3409
3410         /* if there is already a session, relabel the button
3411            on the SessionDialog so that we don't Quit directly
3412         */
3413         cancel_not_quit = (_session != 0) && !quit_on_cancel;
3414
3415         if (_session && _session->dirty()) {
3416                 if (unload_session (false)) {
3417                         /* unload cancelled by user */
3418                         return 0;
3419                 }
3420                 ARDOUR_COMMAND_LINE::session_name = "";
3421         }
3422
3423         if (!load_template.empty()) {
3424                 should_be_new = true;
3425                 template_name = load_template;
3426         }
3427
3428         session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3429         session_path = ARDOUR_COMMAND_LINE::session_name;
3430
3431         if (!session_path.empty()) {
3432                 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
3433                         if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
3434                                 /* session/snapshot file, change path to be dir */
3435                                 session_path = Glib::path_get_dirname (session_path);
3436                         }
3437                 }
3438         }
3439
3440         SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
3441
3442         _session_dialog = &session_dialog;
3443         while (ret != 0) {
3444
3445                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3446
3447                         /* if they named a specific statefile, use it, otherwise they are
3448                            just giving a session folder, and we want to use it as is
3449                            to find the session.
3450                         */
3451
3452                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
3453
3454                         if (suffix != string::npos) {
3455                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
3456                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
3457                                 session_name = Glib::path_get_basename (session_name);
3458                         } else {
3459                                 session_path = ARDOUR_COMMAND_LINE::session_name;
3460                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
3461                         }
3462                 } else {
3463                         session_path = "";
3464                         session_name = "";
3465                         session_dialog.clear_given ();
3466                 }
3467
3468                 if (should_be_new || session_name.empty()) {
3469                         /* need the dialog to get info from user */
3470
3471                         cerr << "run dialog\n";
3472
3473                         switch (session_dialog.run()) {
3474                         case RESPONSE_ACCEPT:
3475                                 break;
3476                         case RESPONSE_NONE:
3477                                 /* this is used for async * app->ShouldLoad(). */
3478                                 continue; // while loop
3479                                 break;
3480                         default:
3481                                 if (quit_on_cancel) {
3482                                         ARDOUR_UI::finish ();
3483                                         Gtkmm2ext::Application::instance()->cleanup();
3484                                         ARDOUR::cleanup ();
3485                                         pthread_cancel_all ();
3486                                         return -1; // caller is responsible to call exit()
3487                                 } else {
3488                                         return ret;
3489                                 }
3490                         }
3491
3492                         session_dialog.hide ();
3493                 }
3494
3495                 /* if we run the startup dialog again, offer more than just "new session" */
3496
3497                 should_be_new = false;
3498
3499                 session_name = session_dialog.session_name (likely_new);
3500                 session_path = session_dialog.session_folder ();
3501
3502                 if (nsm) {
3503                         likely_new = true;
3504                 }
3505
3506                 if (!likely_new) {
3507                         int rv = ARDOUR::inflate_session (session_name,
3508                                         Config->get_default_session_parent_dir(), session_path, session_name);
3509                         if (rv < 0) {
3510                                 MessageDialog msg (session_dialog,
3511                                         string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
3512                                 msg.run ();
3513                                 continue;
3514                         }
3515                         else if (rv == 0) {
3516                                 session_dialog.set_provided_session (session_name, session_path);
3517                         }
3518                 }
3519
3520                 // XXX check archive, inflate
3521                 string::size_type suffix = session_name.find (statefile_suffix);
3522
3523                 if (suffix != string::npos) {
3524                         session_name = session_name.substr (0, suffix);
3525                 }
3526
3527                 /* this shouldn't happen, but we catch it just in case it does */
3528
3529                 if (session_name.empty()) {
3530                         continue;
3531                 }
3532
3533                 if (session_dialog.use_session_template()) {
3534                         template_name = session_dialog.session_template_name();
3535                         _session_is_new = true;
3536                 }
3537
3538                 if (session_name[0] == G_DIR_SEPARATOR ||
3539 #ifdef PLATFORM_WINDOWS
3540                    (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3541 #else
3542                    (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3543                    (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3544 #endif
3545                 )
3546                 {
3547
3548                         /* absolute path or cwd-relative path specified for session name: infer session folder
3549                            from what was given.
3550                         */
3551
3552                         session_path = Glib::path_get_dirname (session_name);
3553                         session_name = Glib::path_get_basename (session_name);
3554
3555                 } else {
3556
3557                         session_path = session_dialog.session_folder();
3558
3559                         char illegal = Session::session_name_is_legal (session_name);
3560
3561                         if (illegal) {
3562                                 MessageDialog msg (session_dialog,
3563                                                    string_compose (_("To ensure compatibility with various systems\n"
3564                                                                      "session names may not contain a '%1' character"),
3565                                                                    illegal));
3566                                 msg.run ();
3567                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3568                                 continue;
3569                         }
3570                 }
3571
3572                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3573
3574
3575                         if (likely_new && !nsm) {
3576
3577                                 std::string existing = Glib::build_filename (session_path, session_name);
3578
3579                                 if (!ask_about_loading_existing_session (existing)) {
3580                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3581                                         continue;
3582                                 }
3583                         }
3584
3585                         _session_is_new = false;
3586
3587                 } else {
3588
3589                         if (!likely_new) {
3590                                 pop_back_splash (session_dialog);
3591                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3592                                 msg.run ();
3593                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3594                                 continue;
3595                         }
3596
3597                         char illegal = Session::session_name_is_legal(session_name);
3598
3599                         if (illegal) {
3600                                 pop_back_splash (session_dialog);
3601                                 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3602                                                                                     "session names may not contain a '%1' character"), illegal));
3603                                 msg.run ();
3604                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3605                                 continue;
3606                         }
3607
3608                         _session_is_new = true;
3609                 }
3610
3611                 if (!template_name.empty() && template_name.substr (0, 11) == "urn:ardour:") {
3612
3613                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3614                         meta_session_setup (template_name.substr (11));
3615
3616                 } else if (likely_new && template_name.empty()) {
3617
3618                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3619
3620                 } else {
3621
3622                         ret = load_session (session_path, session_name, template_name);
3623
3624                         if (ret == -2) {
3625                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3626                                 exit (1);
3627                         }
3628
3629                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3630                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3631                                 exit (1);
3632                         }
3633
3634                         /* clear this to avoid endless attempts to load the
3635                            same session.
3636                         */
3637
3638                         ARDOUR_COMMAND_LINE::session_name = "";
3639                 }
3640         }
3641
3642         _session_dialog = NULL;
3643
3644         return ret;
3645 }
3646
3647 void
3648 ARDOUR_UI::close_session()
3649 {
3650         if (!check_audioengine (_main_window)) {
3651                 return;
3652         }
3653
3654         if (unload_session (true)) {
3655                 return;
3656         }
3657
3658         ARDOUR_COMMAND_LINE::session_name = "";
3659
3660         if (get_session_parameters (true, false)) {
3661                 exit (1);
3662         }
3663 }
3664
3665 /** @param snap_name Snapshot name (without .ardour suffix).
3666  *  @return -2 if the load failed because we are not connected to the AudioEngine.
3667  */
3668 int
3669 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3670 {
3671         /* load_session calls flush_pending() which allows
3672          * GUI interaction and potentially loading another session
3673          * (that was easy via snapshot sidebar).
3674          * Recursing into load_session() from load_session() and recusive
3675          * event loops causes all kind of crashes.
3676          */
3677         assert (!session_load_in_progress);
3678         if (session_load_in_progress) {
3679                 return -1;
3680         }
3681         PBD::Unwinder<bool> lsu (session_load_in_progress, true);
3682
3683         Session *new_session;
3684         int unload_status;
3685         int retval = -1;
3686
3687         if (_session) {
3688                 unload_status = unload_session ();
3689
3690                 if (unload_status < 0) {
3691                         goto out;
3692                 } else if (unload_status > 0) {
3693                         retval = 0;
3694                         goto out;
3695                 }
3696         }
3697
3698         session_loaded = false;
3699
3700         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3701
3702         try {
3703                 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3704         }
3705
3706         /* this one is special */
3707
3708         catch (AudioEngine::PortRegistrationFailure& err) {
3709
3710                 MessageDialog msg (err.what(),
3711                                    true,
3712                                    Gtk::MESSAGE_INFO,
3713                                    Gtk::BUTTONS_CLOSE);
3714
3715                 msg.set_title (_("Port Registration Error"));
3716                 msg.set_secondary_text (_("Click the Close button to try again."));
3717                 msg.set_position (Gtk::WIN_POS_CENTER);
3718                 pop_back_splash (msg);
3719                 msg.present ();
3720
3721                 int response = msg.run ();
3722
3723                 msg.hide ();
3724
3725                 switch (response) {
3726                 case RESPONSE_CANCEL:
3727                         exit (1);
3728                 default:
3729                         break;
3730                 }
3731                 goto out;
3732         }
3733         catch (SessionException e) {
3734                 MessageDialog msg (string_compose(
3735                                            _("Session \"%1 (snapshot %2)\" did not load successfully: %3"),
3736                                            path, snap_name, e.what()),
3737                                    true,
3738                                    Gtk::MESSAGE_INFO,
3739                                    BUTTONS_OK);
3740
3741                 msg.set_title (_("Loading Error"));
3742                 msg.set_position (Gtk::WIN_POS_CENTER);
3743                 pop_back_splash (msg);
3744                 msg.present ();
3745
3746                 dump_errors (cerr);
3747
3748                 (void) msg.run ();
3749                 msg.hide ();
3750
3751                 goto out;
3752         }
3753         catch (...) {
3754
3755                 MessageDialog msg (string_compose(
3756                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
3757                                            path, snap_name),
3758                                    true,
3759                                    Gtk::MESSAGE_INFO,
3760                                    BUTTONS_OK);
3761
3762                 msg.set_title (_("Loading Error"));
3763                 msg.set_position (Gtk::WIN_POS_CENTER);
3764                 pop_back_splash (msg);
3765                 msg.present ();
3766
3767                 dump_errors (cerr);
3768
3769                 (void) msg.run ();
3770                 msg.hide ();
3771
3772                 goto out;
3773         }
3774
3775         {
3776                 list<string> const u = new_session->unknown_processors ();
3777                 if (!u.empty()) {
3778                         MissingPluginDialog d (_session, u);
3779                         d.run ();
3780                 }
3781         }
3782
3783         if (!new_session->writable()) {
3784                 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3785                                    true,
3786                                    Gtk::MESSAGE_INFO,
3787                                    BUTTONS_OK);
3788
3789                 msg.set_title (_("Read-only Session"));
3790                 msg.set_position (Gtk::WIN_POS_CENTER);
3791                 pop_back_splash (msg);
3792                 msg.present ();
3793                 (void) msg.run ();
3794                 msg.hide ();
3795         }
3796
3797
3798         /* Now the session been created, add the transport controls */
3799         new_session->add_controllable(roll_controllable);
3800         new_session->add_controllable(stop_controllable);
3801         new_session->add_controllable(goto_start_controllable);
3802         new_session->add_controllable(goto_end_controllable);
3803         new_session->add_controllable(auto_loop_controllable);
3804         new_session->add_controllable(play_selection_controllable);
3805         new_session->add_controllable(rec_controllable);
3806
3807         set_session (new_session);
3808
3809         session_loaded = true;
3810
3811         if (_session) {
3812                 _session->set_clean ();
3813         }
3814
3815 #ifdef WINDOWS_VST_SUPPORT
3816         fst_stop_threading();
3817 #endif
3818
3819         {
3820                 Timers::TimerSuspender t;
3821                 flush_pending (10);
3822         }
3823
3824 #ifdef WINDOWS_VST_SUPPORT
3825         fst_start_threading();
3826 #endif
3827         retval = 0;
3828
3829         if (!mix_template.empty ()) {
3830                 /* if mix_template is given, assume this is a new session */
3831                 string metascript = Glib::build_filename (mix_template, "template.lua");
3832                 meta_session_setup (metascript);
3833         }
3834
3835
3836   out:
3837         /* For successful session load the splash is hidden by ARDOUR_UI::first_idle,
3838          * which is queued by set_session().
3839          * If session-loading fails we hide it explicitly.
3840          * This covers both cases in a central place.
3841          */
3842         if (retval) {
3843                 hide_splash ();
3844         }
3845         return retval;
3846 }
3847
3848 int
3849 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
3850 {
3851         Session *new_session;
3852         int x;
3853
3854         session_loaded = false;
3855         x = unload_session ();
3856
3857         if (x < 0) {
3858                 return -1;
3859         } else if (x > 0) {
3860                 return 0;
3861         }
3862
3863         _session_is_new = true;
3864
3865         try {
3866                 new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
3867         }
3868
3869         catch (SessionException e) {
3870                 cerr << "Here are the errors associated with this failed session:\n";
3871                 dump_errors (cerr);
3872                 cerr << "---------\n";
3873                 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3874                 msg.set_title (_("Loading Error"));
3875                 msg.set_position (Gtk::WIN_POS_CENTER);
3876                 pop_back_splash (msg);
3877                 msg.run ();
3878                 return -1;
3879         }
3880         catch (...) {
3881                 cerr << "Here are the errors associated with this failed session:\n";
3882                 dump_errors (cerr);
3883                 cerr << "---------\n";
3884                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3885                 msg.set_title (_("Loading Error"));
3886                 msg.set_position (Gtk::WIN_POS_CENTER);
3887                 pop_back_splash (msg);
3888                 msg.run ();
3889                 return -1;
3890         }
3891
3892         /* Give the new session the default GUI state, if such things exist */
3893
3894         XMLNode* n;
3895         n = Config->instant_xml (X_("Editor"));
3896         if (n) {
3897                 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3898                 new_session->add_instant_xml (*n, false);
3899         }
3900         n = Config->instant_xml (X_("Mixer"));
3901         if (n) {
3902                 new_session->add_instant_xml (*n, false);
3903         }
3904
3905         n = Config->instant_xml (X_("Preferences"));
3906         if (n) {
3907                 new_session->add_instant_xml (*n, false);
3908         }
3909
3910         /* Put the playhead at 0 and scroll fully left */
3911         n = new_session->instant_xml (X_("Editor"));
3912         if (n) {
3913                 n->set_property (X_("playhead"), X_("0"));
3914                 n->set_property (X_("left-frame"), X_("0"));
3915         }
3916
3917         set_session (new_session);
3918
3919         session_loaded = true;
3920
3921         new_session->save_state(new_session->name());
3922
3923         return 0;
3924 }
3925
3926
3927 static void _lua_print (std::string s) {
3928 #ifndef NDEBUG
3929         std::cout << "LuaInstance: " << s << "\n";
3930 #endif
3931         PBD::info << "LuaInstance: " << s << endmsg;
3932 }
3933
3934 void
3935 ARDOUR_UI::meta_session_setup (const std::string& script_path)
3936 {
3937         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3938                 return;
3939         }
3940
3941         LuaState lua;
3942         lua.Print.connect (&_lua_print);
3943         lua.sandbox (true);
3944
3945         lua_State* L = lua.getState();
3946         LuaInstance::register_classes (L);
3947         LuaBindings::set_session (L, _session);
3948         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3949         lua_setglobal (L, "Editor");
3950
3951         lua.do_command ("function ardour () end");
3952         lua.do_file (script_path);
3953
3954         try {
3955                 luabridge::LuaRef fn = luabridge::getGlobal (L, "session_setup");
3956                 if (fn.isFunction()) {
3957                         fn ();
3958                 }
3959         } catch (luabridge::LuaException const& e) {
3960                 cerr << "LuaException:" << e.what () << endl;
3961         }
3962 }
3963
3964 void
3965 ARDOUR_UI::launch_chat ()
3966 {
3967         MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3968
3969         dialog.set_title (_("About the Chat"));
3970         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."));
3971
3972         switch (dialog.run()) {
3973         case RESPONSE_OK:
3974 #ifdef __APPLE__
3975                 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
3976 #elif defined PLATFORM_WINDOWS
3977                 open_uri("http://webchat.freenode.net/?channels=ardour-windows");
3978 #else
3979                 open_uri("http://webchat.freenode.net/?channels=ardour");
3980 #endif
3981                 break;
3982         default:
3983                 break;
3984         }
3985 }
3986
3987 void
3988 ARDOUR_UI::launch_manual ()
3989 {
3990         PBD::open_uri (Config->get_tutorial_manual_url());
3991 }
3992
3993 void
3994 ARDOUR_UI::launch_reference ()
3995 {
3996         PBD::open_uri (Config->get_reference_manual_url());
3997 }
3998
3999 void
4000 ARDOUR_UI::launch_tracker ()
4001 {
4002         PBD::open_uri ("http://tracker.ardour.org");
4003 }
4004
4005 void
4006 ARDOUR_UI::launch_subscribe ()
4007 {
4008         PBD::open_uri ("https://community.ardour.org/s/subscribe");
4009 }
4010
4011 void
4012 ARDOUR_UI::launch_cheat_sheet ()
4013 {
4014 #ifdef __APPLE__
4015         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
4016 #else
4017         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
4018 #endif
4019 }
4020
4021 void
4022 ARDOUR_UI::launch_website ()
4023 {
4024         PBD::open_uri ("http://ardour.org");
4025 }
4026
4027 void
4028 ARDOUR_UI::launch_website_dev ()
4029 {
4030         PBD::open_uri ("http://ardour.org/development.html");
4031 }
4032
4033 void
4034 ARDOUR_UI::launch_forums ()
4035 {
4036         PBD::open_uri ("https://community.ardour.org/forums");
4037 }
4038
4039 void
4040 ARDOUR_UI::launch_howto_report ()
4041 {
4042         PBD::open_uri ("http://ardour.org/reporting_bugs");
4043 }
4044
4045 void
4046 ARDOUR_UI::loading_message (const std::string& msg)
4047 {
4048         if (ARDOUR_COMMAND_LINE::no_splash) {
4049                 return;
4050         }
4051
4052         if (!splash) {
4053                 show_splash ();
4054         }
4055
4056         splash->message (msg);
4057 }
4058
4059 void
4060 ARDOUR_UI::show_splash ()
4061 {
4062         if (splash == 0) {
4063                 try {
4064                         splash = new Splash;
4065                 } catch (...) {
4066                         return;
4067                 }
4068         }
4069
4070         splash->display ();
4071 }
4072
4073 void
4074 ARDOUR_UI::hide_splash ()
4075 {
4076         delete splash;
4077         splash = 0;
4078 }
4079
4080 void
4081 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
4082 {
4083         size_t removed;
4084
4085         removed = rep.paths.size();
4086
4087         if (removed == 0) {
4088                 MessageDialog msgd (_main_window,
4089                                     _("No files were ready for clean-up"),
4090                                     true,
4091                                     Gtk::MESSAGE_INFO,
4092                                     Gtk::BUTTONS_OK);
4093                 msgd.set_title (_("Clean-up"));
4094                 msgd.set_secondary_text (_("If this seems surprising, \n\
4095 check for any existing snapshots.\n\
4096 These may still include regions that\n\
4097 require some unused files to continue to exist."));
4098
4099                 msgd.run ();
4100                 return;
4101         }
4102
4103         ArdourDialog results (_("Clean-up"), true, false);
4104
4105         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
4106                 CleanupResultsModelColumns() {
4107                         add (visible_name);
4108                         add (fullpath);
4109                 }
4110                 Gtk::TreeModelColumn<std::string> visible_name;
4111                 Gtk::TreeModelColumn<std::string> fullpath;
4112         };
4113
4114
4115         CleanupResultsModelColumns results_columns;
4116         Glib::RefPtr<Gtk::ListStore> results_model;
4117         Gtk::TreeView results_display;
4118
4119         results_model = ListStore::create (results_columns);
4120         results_display.set_model (results_model);
4121         results_display.append_column (list_title, results_columns.visible_name);
4122
4123         results_display.set_name ("CleanupResultsList");
4124         results_display.set_headers_visible (true);
4125         results_display.set_headers_clickable (false);
4126         results_display.set_reorderable (false);
4127
4128         Gtk::ScrolledWindow list_scroller;
4129         Gtk::Label txt;
4130         Gtk::VBox dvbox;
4131         Gtk::HBox dhbox;  // the hbox for the image and text
4132         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
4133         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
4134
4135         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
4136
4137         const string dead_directory = _session->session_directory().dead_path();
4138
4139         /* subst:
4140            %1 - number of files removed
4141            %2 - location of "dead"
4142            %3 - size of files affected
4143            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
4144         */
4145
4146         const char* bprefix;
4147         double space_adjusted = 0;
4148
4149         if (rep.space < 1000) {
4150                 bprefix = X_("");
4151                 space_adjusted = rep.space;
4152         } else if (rep.space < 1000000) {
4153                 bprefix = _("kilo");
4154                 space_adjusted = floorf((float)rep.space / 1000.0);
4155         } else if (rep.space < 1000000 * 1000) {
4156                 bprefix = _("mega");
4157                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
4158         } else {
4159                 bprefix = _("giga");
4160                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
4161         }
4162
4163         if (msg_delete) {
4164                 txt.set_markup (string_compose (P_("\
4165 The following file was deleted from %2,\n\
4166 releasing %3 %4bytes of disk space", "\
4167 The following %1 files were deleted from %2,\n\
4168 releasing %3 %4bytes of disk space", removed),
4169                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
4170         } else {
4171                 txt.set_markup (string_compose (P_("\
4172 The following file was not in use and \n\
4173 has been moved to: %2\n\n\
4174 After a restart of %5\n\n\
4175 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
4176 will release an additional %3 %4bytes of disk space.\n", "\
4177 The following %1 files were not in use and \n\
4178 have been moved to: %2\n\n\
4179 After a restart of %5\n\n\
4180 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
4181 will release an additional %3 %4bytes of disk space.\n", removed),
4182                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
4183         }
4184
4185         dhbox.pack_start (*dimage, true, false, 5);
4186         dhbox.pack_start (txt, true, false, 5);
4187
4188         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
4189                 TreeModel::Row row = *(results_model->append());
4190                 row[results_columns.visible_name] = *i;
4191                 row[results_columns.fullpath] = *i;
4192         }
4193
4194         list_scroller.add (results_display);
4195         list_scroller.set_size_request (-1, 150);
4196         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
4197
4198         dvbox.pack_start (dhbox, true, false, 5);
4199         dvbox.pack_start (list_scroller, true, false, 5);
4200         ddhbox.pack_start (dvbox, true, false, 5);
4201
4202         results.get_vbox()->pack_start (ddhbox, true, false, 5);
4203         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
4204         results.set_default_response (RESPONSE_CLOSE);
4205         results.set_position (Gtk::WIN_POS_MOUSE);
4206
4207         results_display.show();
4208         list_scroller.show();
4209         txt.show();
4210         dvbox.show();
4211         dhbox.show();
4212         ddhbox.show();
4213         dimage->show();
4214
4215         //results.get_vbox()->show();
4216         results.set_resizable (false);
4217
4218         results.run ();
4219
4220 }
4221
4222 void
4223 ARDOUR_UI::cleanup ()
4224 {
4225         if (_session == 0) {
4226                 /* shouldn't happen: menu item is insensitive */
4227                 return;
4228         }
4229
4230
4231         MessageDialog checker (_("Are you sure you want to clean-up?"),
4232                                 true,
4233                                 Gtk::MESSAGE_QUESTION,
4234                                 Gtk::BUTTONS_NONE);
4235
4236         checker.set_title (_("Clean-up"));
4237
4238         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
4239 ALL undo/redo information will be lost if you clean-up.\n\
4240 Clean-up will move all unused files to a \"dead\" location."));
4241
4242         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
4243         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
4244         checker.set_default_response (RESPONSE_CANCEL);
4245
4246         checker.set_name (_("CleanupDialog"));
4247         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
4248         checker.set_position (Gtk::WIN_POS_MOUSE);
4249
4250         switch (checker.run()) {
4251         case RESPONSE_ACCEPT:
4252                 break;
4253         default:
4254                 return;
4255         }
4256
4257         ARDOUR::CleanupReport rep;
4258
4259         editor->prepare_for_cleanup ();
4260
4261         /* do not allow flush until a session is reloaded */
4262
4263         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
4264         if (act) {
4265                 act->set_sensitive (false);
4266         }
4267
4268         if (_session->cleanup_sources (rep)) {
4269                 editor->finish_cleanup ();
4270                 return;
4271         }
4272
4273         editor->finish_cleanup ();
4274
4275         checker.hide();
4276         display_cleanup_results (rep, _("Cleaned Files"), false);
4277 }
4278
4279 void
4280 ARDOUR_UI::flush_trash ()
4281 {
4282         if (_session == 0) {
4283                 /* shouldn't happen: menu item is insensitive */
4284                 return;
4285         }
4286
4287         ARDOUR::CleanupReport rep;
4288
4289         if (_session->cleanup_trash_sources (rep)) {
4290                 return;
4291         }
4292
4293         display_cleanup_results (rep, _("deleted file"), true);
4294 }
4295
4296 void
4297 ARDOUR_UI::cleanup_peakfiles ()
4298 {
4299         if (_session == 0) {
4300                 /* shouldn't happen: menu item is insensitive */
4301                 return;
4302         }
4303
4304         if (! _session->can_cleanup_peakfiles ()) {
4305                 return;
4306         }
4307
4308         // get all region-views in this session
4309         RegionSelection rs;
4310         TrackViewList empty;
4311         empty.clear();
4312         editor->get_regions_after(rs, (framepos_t) 0, empty);
4313         std::list<RegionView*> views = rs.by_layer();
4314
4315         // remove displayed audio-region-views waveforms
4316         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4317                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4318                 if (!arv) { continue ; }
4319                 arv->delete_waves();
4320         }
4321
4322         // cleanup peak files:
4323         // - stop pending peakfile threads
4324         // - close peakfiles if any
4325         // - remove peak dir in session
4326         // - setup peakfiles (background thread)
4327         _session->cleanup_peakfiles ();
4328
4329         // re-add waves to ARV
4330         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4331                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4332                 if (!arv) { continue ; }
4333                 arv->create_waves();
4334         }
4335 }
4336
4337 PresentationInfo::order_t
4338 ARDOUR_UI::translate_order (RouteDialogs::InsertAt place)
4339 {
4340         if (editor->get_selection().tracks.empty()) {
4341                 return place == RouteDialogs::First ? 0 : PresentationInfo::max_order;
4342         }
4343
4344         PresentationInfo::order_t order_hint = PresentationInfo::max_order;
4345
4346         /*
4347           we want the new routes to have their order keys set starting from
4348           the highest order key in the selection + 1 (if available).
4349         */
4350
4351         if (place == RouteDialogs::AfterSelection) {
4352                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
4353                 if (rtav) {
4354                         order_hint = rtav->route()->presentation_info().order();
4355                         order_hint++;
4356                 }
4357         } else if (place == RouteDialogs::BeforeSelection) {
4358                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
4359                 if (rtav) {
4360                         order_hint = rtav->route()->presentation_info().order();
4361                 }
4362         } else if (place == RouteDialogs::First) {
4363                 order_hint = 0;
4364         } else {
4365                 /* leave order_hint at max_order */
4366         }
4367
4368         return order_hint;
4369 }
4370
4371 void
4372 ARDOUR_UI::start_duplicate_routes ()
4373 {
4374         if (!duplicate_routes_dialog) {
4375                 duplicate_routes_dialog = new DuplicateRouteDialog;
4376         }
4377
4378         if (duplicate_routes_dialog->restart (_session)) {
4379                 return;
4380         }
4381
4382         duplicate_routes_dialog->present ();
4383 }
4384
4385 void
4386 ARDOUR_UI::add_route ()
4387 {
4388         if (!add_route_dialog.get (false)) {
4389                 add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_response));
4390         }
4391
4392         if (!_session) {
4393                 return;
4394         }
4395
4396         if (add_route_dialog->is_visible()) {
4397                 /* we're already doing this */
4398                 return;
4399         }
4400
4401         add_route_dialog->set_position (WIN_POS_MOUSE);
4402         add_route_dialog->present();
4403 }
4404
4405 void
4406 ARDOUR_UI::add_route_dialog_response (int r)
4407 {
4408         int count;
4409
4410         switch (r) {
4411         case AddRouteDialog::Add:
4412                 break;
4413         case AddRouteDialog::AddAndClose:
4414                 add_route_dialog->ArdourDialog::on_response (r);
4415                 break;
4416         default:
4417                 add_route_dialog->ArdourDialog::on_response (r);
4418                 return;
4419         }
4420
4421         if ((count = add_route_dialog->count()) <= 0) {
4422                 return;
4423         }
4424
4425         PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at());
4426         string template_path = add_route_dialog->track_template();
4427         DisplaySuspender ds;
4428
4429         if (!template_path.empty()) {
4430                 if (add_route_dialog->name_template_is_default())  {
4431                         _session->new_route_from_template (count, order, template_path, string());
4432                 } else {
4433                         _session->new_route_from_template (count, order, template_path, add_route_dialog->name_template());
4434                 }
4435                 return;
4436         }
4437
4438         ChanCount input_chan= add_route_dialog->channels ();
4439         ChanCount output_chan;
4440         string name_template = add_route_dialog->name_template ();
4441         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
4442         RouteGroup* route_group = add_route_dialog->route_group ();
4443         AutoConnectOption oac = Config->get_output_auto_connect();
4444         bool strict_io = add_route_dialog->use_strict_io ();
4445
4446         if (oac & AutoConnectMaster) {
4447                 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
4448                 output_chan.set (DataType::MIDI, 0);
4449         } else {
4450                 output_chan = input_chan;
4451         }
4452
4453         /* XXX do something with name template */
4454
4455         Session::ProcessorChangeBlocker pcb (_session);
4456
4457         switch (add_route_dialog->type_wanted()) {
4458         case AddRouteDialog::AudioTrack:
4459                 session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io, order);
4460                 break;
4461         case AddRouteDialog::MidiTrack:
4462                 session_add_midi_track (route_group, count, name_template, strict_io, instrument, 0, order);
4463                 break;
4464         case AddRouteDialog::MixedTrack:
4465                 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0, order);
4466                 break;
4467         case AddRouteDialog::AudioBus:
4468                 session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template, strict_io, order);
4469                 break;
4470         case AddRouteDialog::MidiBus:
4471                 session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order);
4472                 break;
4473         case AddRouteDialog::VCAMaster:
4474                 session_add_vca (name_template, count);
4475                 break;
4476         }
4477 }
4478
4479 void
4480 ARDOUR_UI::stop_video_server (bool ask_confirm)
4481 {
4482         if (!video_server_process && ask_confirm) {
4483                 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
4484         }
4485         if (video_server_process) {
4486                 if(ask_confirm) {
4487                         ArdourDialog confirm (_("Stop Video-Server"), true);
4488                         Label m (_("Do you really want to stop the Video Server?"));
4489                         confirm.get_vbox()->pack_start (m, true, true);
4490                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
4491                         confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
4492                         confirm.show_all ();
4493                         if (confirm.run() == RESPONSE_CANCEL) {
4494                                 return;
4495                         }
4496                 }
4497                 delete video_server_process;
4498                 video_server_process =0;
4499         }
4500 }
4501
4502 void
4503 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
4504 {
4505   ARDOUR_UI::start_video_server( float_window, true);
4506 }
4507
4508 bool
4509 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
4510 {
4511         if (!_session) {
4512                 return false;
4513         }
4514         if (popup_msg) {
4515                 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
4516                         if (video_server_process) {
4517                                 popup_error(_("The Video Server is already started."));
4518                         } else {
4519                                 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
4520                         }
4521                 }
4522         }
4523
4524         int firsttime = 0;
4525         while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4526                 if (firsttime++) {
4527                         warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4528                 }
4529                 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
4530                 if (float_window) {
4531                         video_server_dialog->set_transient_for (*float_window);
4532                 }
4533
4534                 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
4535                         video_server_dialog->hide();
4536                 } else {
4537                         ResponseType r = (ResponseType) video_server_dialog->run ();
4538                         video_server_dialog->hide();
4539                         if (r != RESPONSE_ACCEPT) { return false; }
4540                         if (video_server_dialog->show_again()) {
4541                                 Config->set_show_video_server_dialog(false);
4542                         }
4543                 }
4544
4545                 std::string icsd_exec = video_server_dialog->get_exec_path();
4546                 std::string icsd_docroot = video_server_dialog->get_docroot();
4547 #ifndef PLATFORM_WINDOWS
4548                 if (icsd_docroot.empty()) {
4549                         icsd_docroot = VideoUtils::video_get_docroot (Config);
4550                 }
4551 #endif
4552
4553                 GStatBuf sb;
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 (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
4560                         warning << _("Specified docroot is not an existing directory.") << endmsg;
4561                         continue;
4562                 }
4563 #ifndef PLATFORM_WINDOWS
4564                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4565                      || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
4566                         warning << _("Given Video Server is not an executable file.") << endmsg;
4567                         continue;
4568                 }
4569 #else
4570                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4571                      || (sb.st_mode & (S_IXUSR)) == 0 ) {
4572                         warning << _("Given Video Server is not an executable file.") << endmsg;
4573                         continue;
4574                 }
4575 #endif
4576
4577                 char **argp;
4578                 argp=(char**) calloc(9,sizeof(char*));
4579                 argp[0] = strdup(icsd_exec.c_str());
4580                 argp[1] = strdup("-P");
4581                 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4582                 argp[3] = strdup("-p");
4583                 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4584                 argp[5] = strdup("-C");
4585                 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4586                 argp[7] = strdup(icsd_docroot.c_str());
4587                 argp[8] = 0;
4588                 stop_video_server();
4589
4590 #ifdef PLATFORM_WINDOWS
4591                 if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
4592                         /* OK, allow all drive letters */
4593                 } else
4594 #endif
4595                 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4596                         Config->set_video_advanced_setup(false);
4597                 } else {
4598                         std::string url_str = "http://127.0.0.1:" + to_string(video_server_dialog->get_listenport()) + "/";
4599                         Config->set_video_server_url(url_str);
4600                         Config->set_video_server_docroot(icsd_docroot);
4601                         Config->set_video_advanced_setup(true);
4602                 }
4603
4604                 if (video_server_process) {
4605                         delete video_server_process;
4606                 }
4607
4608                 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4609                 if (video_server_process->start()) {
4610                         warning << _("Cannot launch the video-server") << endmsg;
4611                         continue;
4612                 }
4613                 int timeout = 120; // 6 sec
4614                 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4615                         Glib::usleep (50000);
4616                         gui_idle_handler();
4617                         if (--timeout <= 0 || !video_server_process->is_running()) break;
4618                 }
4619                 if (timeout <= 0) {
4620                         warning << _("Video-server was started but does not respond to requests...") << endmsg;
4621                 } else {
4622                         if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4623                                 delete video_server_process;
4624                                 video_server_process = 0;
4625                         }
4626                 }
4627         }
4628         return true;
4629 }
4630
4631 void
4632 ARDOUR_UI::add_video (Gtk::Window* float_window)
4633 {
4634         if (!_session) {
4635                 return;
4636         }
4637
4638         if (!start_video_server(float_window, false)) {
4639                 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4640                 return;
4641         }
4642
4643         if (float_window) {
4644                 add_video_dialog->set_transient_for (*float_window);
4645         }
4646
4647         if (add_video_dialog->is_visible()) {
4648                 /* we're already doing this */
4649                 return;
4650         }
4651
4652         ResponseType r = (ResponseType) add_video_dialog->run ();
4653         add_video_dialog->hide();
4654         if (r != RESPONSE_ACCEPT) { return; }
4655
4656         bool local_file, orig_local_file;
4657         std::string path = add_video_dialog->file_name(local_file);
4658
4659         std::string orig_path = path;
4660         orig_local_file = local_file;
4661
4662         bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4663
4664         if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4665                 warning << string_compose(_("could not open %1"), path) << endmsg;
4666                 return;
4667         }
4668         if (!local_file && path.length() == 0) {
4669                 warning << _("no video-file selected") << endmsg;
4670                 return;
4671         }
4672
4673         std::string audio_from_video;
4674         bool detect_ltc = false;
4675
4676         switch (add_video_dialog->import_option()) {
4677                 case VTL_IMPORT_TRANSCODE:
4678                         {
4679                                 TranscodeVideoDialog *transcode_video_dialog;
4680                                 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4681                                 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4682                                 transcode_video_dialog->hide();
4683                                 if (r != RESPONSE_ACCEPT) {
4684                                         delete transcode_video_dialog;
4685                                         return;
4686                                 }
4687
4688                                 audio_from_video = transcode_video_dialog->get_audiofile();
4689
4690                                 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4691                                         detect_ltc = true;
4692                                 }
4693                                 else if (!audio_from_video.empty()) {
4694                                         editor->embed_audio_from_video(
4695                                                         audio_from_video,
4696                                                         video_timeline->get_offset(),
4697                                                         (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4698                                                         );
4699                                 }
4700                                 switch (transcode_video_dialog->import_option()) {
4701                                         case VTL_IMPORT_TRANSCODED:
4702                                                 path = transcode_video_dialog->get_filename();
4703                                                 local_file = true;
4704                                                 break;
4705                                         case VTL_IMPORT_REFERENCE:
4706                                                 break;
4707                                         default:
4708                                                 delete transcode_video_dialog;
4709                                                 return;
4710                                 }
4711                                 delete transcode_video_dialog;
4712                         }
4713                         break;
4714                 default:
4715                 case VTL_IMPORT_NONE:
4716                         break;
4717         }
4718
4719         /* strip _session->session_directory().video_path() from video file if possible */
4720         if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4721                  path=path.substr(_session->session_directory().video_path().size());
4722                  if (path.at(0) == G_DIR_SEPARATOR) {
4723                          path=path.substr(1);
4724                  }
4725         }
4726
4727         video_timeline->set_update_session_fps(auto_set_session_fps);
4728
4729         if (video_timeline->video_file_info(path, local_file)) {
4730                 XMLNode* node = new XMLNode(X_("Videotimeline"));
4731                 node->set_property (X_("Filename"), path);
4732                 node->set_property (X_("AutoFPS"), auto_set_session_fps);
4733                 node->set_property (X_("LocalFile"), local_file);
4734                 if (orig_local_file) {
4735                         node->set_property (X_("OriginalVideoFile"), orig_path);
4736                 } else {
4737                         node->remove_property (X_("OriginalVideoFile"));
4738                 }
4739                 _session->add_extra_xml (*node);
4740                 _session->set_dirty ();
4741
4742                 if (!audio_from_video.empty() && detect_ltc) {
4743                         std::vector<LTCFileReader::LTCMap> ltc_seq;
4744
4745                         try {
4746                                 /* TODO ask user about TV standard (LTC alignment if any) */
4747                                 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4748                                 /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
4749
4750                                 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC frames to decode*/ 15);
4751
4752                                 /* TODO seek near end of file, and read LTC until end.
4753                                  * if it fails to find any LTC frames, scan complete file
4754                                  *
4755                                  * calculate drift of LTC compared to video-duration,
4756                                  * ask user for reference (timecode from start/mid/end)
4757                                  */
4758                         } catch (...) {
4759                                 // LTCFileReader will have written error messages
4760                         }
4761
4762                         ::g_unlink(audio_from_video.c_str());
4763
4764                         if (ltc_seq.size() == 0) {
4765                                 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4766                         } else {
4767                                 /* the very first TC in the file is somteimes not aligned properly */
4768                                 int i = ltc_seq.size() -1;
4769                                 ARDOUR::frameoffset_t video_start_offset =
4770                                         _session->nominal_frame_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4771                                 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4772                                 video_timeline->set_offset(video_start_offset);
4773                         }
4774                 }
4775
4776                 _session->maybe_update_session_range(
4777                         std::max(video_timeline->get_offset(), (ARDOUR::frameoffset_t) 0),
4778                         std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::frameoffset_t) 0));
4779
4780
4781                 if (add_video_dialog->launch_xjadeo() && local_file) {
4782                         editor->set_xjadeo_sensitive(true);
4783                         editor->toggle_xjadeo_proc(1);
4784                 } else {
4785                         editor->toggle_xjadeo_proc(0);
4786                 }
4787                 editor->toggle_ruler_video(true);
4788         }
4789 }
4790
4791 void
4792 ARDOUR_UI::remove_video ()
4793 {
4794         video_timeline->close_session();
4795         editor->toggle_ruler_video(false);
4796
4797         /* reset state */
4798         video_timeline->set_offset_locked(false);
4799         video_timeline->set_offset(0);
4800
4801         /* delete session state */
4802         XMLNode* node = new XMLNode(X_("Videotimeline"));
4803         _session->add_extra_xml(*node);
4804         node = new XMLNode(X_("Videomonitor"));
4805         _session->add_extra_xml(*node);
4806         node = new XMLNode(X_("Videoexport"));
4807         _session->add_extra_xml(*node);
4808         stop_video_server();
4809 }
4810
4811 void
4812 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4813 {
4814         if (localcacheonly) {
4815                 video_timeline->vmon_update();
4816         } else {
4817                 video_timeline->flush_cache();
4818         }
4819         editor->queue_visual_videotimeline_update();
4820 }
4821
4822 void
4823 ARDOUR_UI::export_video (bool range)
4824 {
4825         if (ARDOUR::Config->get_show_video_export_info()) {
4826                 ExportVideoInfobox infobox (_session);
4827                 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4828                 if (infobox.show_again()) {
4829                         ARDOUR::Config->set_show_video_export_info(false);
4830                 }
4831                 switch (rv) {
4832                         case GTK_RESPONSE_YES:
4833                                 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4834                                 break;
4835                         default:
4836                                 break;
4837                 }
4838         }
4839         export_video_dialog->set_session (_session);
4840         export_video_dialog->apply_state(editor->get_selection().time, range);
4841         export_video_dialog->run ();
4842         export_video_dialog->hide ();
4843 }
4844
4845 XMLNode*
4846 ARDOUR_UI::preferences_settings () const
4847 {
4848         XMLNode* node = 0;
4849
4850         if (_session) {
4851                 node = _session->instant_xml(X_("Preferences"));
4852         } else {
4853                 node = Config->instant_xml(X_("Preferences"));
4854         }
4855
4856         if (!node) {
4857                 node = new XMLNode (X_("Preferences"));
4858         }
4859
4860         return node;
4861 }
4862
4863 XMLNode*
4864 ARDOUR_UI::mixer_settings () const
4865 {
4866         XMLNode* node = 0;
4867
4868         if (_session) {
4869                 node = _session->instant_xml(X_("Mixer"));
4870         } else {
4871                 node = Config->instant_xml(X_("Mixer"));
4872         }
4873
4874         if (!node) {
4875                 node = new XMLNode (X_("Mixer"));
4876         }
4877
4878         return node;
4879 }
4880
4881 XMLNode*
4882 ARDOUR_UI::main_window_settings () const
4883 {
4884         XMLNode* node = 0;
4885
4886         if (_session) {
4887                 node = _session->instant_xml(X_("Main"));
4888         } else {
4889                 node = Config->instant_xml(X_("Main"));
4890         }
4891
4892         if (!node) {
4893                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4894                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4895                 }
4896         }
4897
4898         if (!node) {
4899                 node = new XMLNode (X_("Main"));
4900         }
4901
4902         return node;
4903 }
4904
4905 XMLNode*
4906 ARDOUR_UI::editor_settings () const
4907 {
4908         XMLNode* node = 0;
4909
4910         if (_session) {
4911                 node = _session->instant_xml(X_("Editor"));
4912         } else {
4913                 node = Config->instant_xml(X_("Editor"));
4914         }
4915
4916         if (!node) {
4917                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4918                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4919                 }
4920         }
4921
4922         if (!node) {
4923                 node = new XMLNode (X_("Editor"));
4924         }
4925
4926         return node;
4927 }
4928
4929 XMLNode*
4930 ARDOUR_UI::keyboard_settings () const
4931 {
4932         XMLNode* node = 0;
4933
4934         node = Config->extra_xml(X_("Keyboard"));
4935
4936         if (!node) {
4937                 node = new XMLNode (X_("Keyboard"));
4938         }
4939
4940         return node;
4941 }
4942
4943 void
4944 ARDOUR_UI::create_xrun_marker (framepos_t where)
4945 {
4946         if (_session) {
4947                 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark, 0);
4948                 _session->locations()->add (location);
4949         }
4950 }
4951
4952 void
4953 ARDOUR_UI::halt_on_xrun_message ()
4954 {
4955         cerr << "HALT on xrun\n";
4956         MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
4957         msg.run ();
4958 }
4959
4960 void
4961 ARDOUR_UI::xrun_handler (framepos_t where)
4962 {
4963         if (!_session) {
4964                 return;
4965         }
4966
4967         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4968
4969         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4970                 create_xrun_marker(where);
4971         }
4972
4973         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4974                 halt_on_xrun_message ();
4975         }
4976 }
4977
4978 void
4979 ARDOUR_UI::disk_overrun_handler ()
4980 {
4981         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4982
4983         if (!have_disk_speed_dialog_displayed) {
4984                 have_disk_speed_dialog_displayed = true;
4985                 MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
4986 The disk system on your computer\n\
4987 was not able to keep up with %1.\n\
4988 \n\
4989 Specifically, it failed to write data to disk\n\
4990 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4991                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4992                 msg->show ();
4993         }
4994 }
4995
4996
4997 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4998 static MessageDialog *scan_dlg = NULL;
4999 static ProgressBar   *scan_pbar = NULL;
5000 static HBox          *scan_tbox = NULL;
5001 static Gtk::Button   *scan_timeout_button;
5002
5003 void
5004 ARDOUR_UI::cancel_plugin_scan ()
5005 {
5006         PluginManager::instance().cancel_plugin_scan();
5007 }
5008
5009 void
5010 ARDOUR_UI::cancel_plugin_timeout ()
5011 {
5012         PluginManager::instance().cancel_plugin_timeout();
5013         scan_timeout_button->set_sensitive (false);
5014 }
5015
5016 void
5017 ARDOUR_UI::plugin_scan_timeout (int timeout)
5018 {
5019         if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
5020                 return;
5021         }
5022         if (timeout > 0) {
5023                 scan_pbar->set_sensitive (false);
5024                 scan_timeout_button->set_sensitive (true);
5025                 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
5026                 scan_tbox->show();
5027         } else {
5028                 scan_pbar->set_sensitive (false);
5029                 scan_timeout_button->set_sensitive (false);
5030         }
5031         gui_idle_handler();
5032 }
5033
5034 void
5035 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
5036 {
5037         if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
5038                 return;
5039         }
5040
5041         const bool cancelled = PluginManager::instance().cancelled();
5042         if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
5043                 if (cancelled && scan_dlg->is_mapped()) {
5044                         scan_dlg->hide();
5045                         gui_idle_handler();
5046                         return;
5047                 }
5048                 if (cancelled || !can_cancel) {
5049                         return;
5050                 }
5051         }
5052
5053         static Gtk::Button *cancel_button;
5054         if (!scan_dlg) {
5055                 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
5056                 VBox* vbox = scan_dlg->get_vbox();
5057                 vbox->set_size_request(400,-1);
5058                 scan_dlg->set_title (_("Scanning for plugins"));
5059
5060                 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
5061                 cancel_button->set_name ("EditorGTKButton");
5062                 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
5063                 cancel_button->show();
5064
5065                 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
5066
5067                 scan_tbox = manage( new HBox() );
5068
5069                 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
5070                 scan_timeout_button->set_name ("EditorGTKButton");
5071                 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
5072                 scan_timeout_button->show();
5073
5074                 scan_pbar = manage(new ProgressBar());
5075                 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
5076                 scan_pbar->set_text(_("Scan Timeout"));
5077                 scan_pbar->show();
5078
5079                 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
5080                 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
5081
5082                 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
5083         }
5084
5085         assert(scan_dlg && scan_tbox && cancel_button);
5086
5087         if (type == X_("closeme")) {
5088                 scan_tbox->hide();
5089                 scan_dlg->hide();
5090         } else {
5091                 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
5092                 scan_dlg->show();
5093         }
5094         if (!can_cancel || !cancelled) {
5095                 scan_timeout_button->set_sensitive(false);
5096         }
5097         cancel_button->set_sensitive(can_cancel && !cancelled);
5098
5099         gui_idle_handler();
5100 }
5101
5102 void
5103 ARDOUR_UI::gui_idle_handler ()
5104 {
5105         int timeout = 30;
5106         /* due to idle calls, gtk_events_pending() may always return true */
5107         while (gtk_events_pending() && --timeout) {
5108                 gtk_main_iteration ();
5109         }
5110 }
5111
5112 void
5113 ARDOUR_UI::disk_underrun_handler ()
5114 {
5115         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
5116
5117         if (!have_disk_speed_dialog_displayed) {
5118                 have_disk_speed_dialog_displayed = true;
5119                 MessageDialog* msg = new MessageDialog (
5120                         _main_window, string_compose (_("The disk system on your computer\n\
5121 was not able to keep up with %1.\n\
5122 \n\
5123 Specifically, it failed to read data from disk\n\
5124 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
5125                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
5126                 msg->show ();
5127         }
5128 }
5129
5130 void
5131 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
5132 {
5133         have_disk_speed_dialog_displayed = false;
5134         delete msg;
5135 }
5136
5137 void
5138 ARDOUR_UI::session_dialog (std::string msg)
5139 {
5140         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
5141
5142         MessageDialog* d;
5143
5144         d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
5145         d->show_all ();
5146         d->run ();
5147         delete d;
5148 }
5149
5150 int
5151 ARDOUR_UI::pending_state_dialog ()
5152 {
5153         HBox* hbox = manage (new HBox());
5154         Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
5155         ArdourDialog dialog (_("Crash Recovery"), true);
5156         Label  message (string_compose (_("\
5157 This session appears to have been in the\n\
5158 middle of recording when %1 or\n\
5159 the computer was shutdown.\n\
5160 \n\
5161 %1 can recover any captured audio for\n\
5162 you, or it can ignore it. Please decide\n\
5163 what you would like to do.\n"), PROGRAM_NAME));
5164         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
5165         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
5166         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
5167         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
5168         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
5169         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
5170         dialog.set_default_response (RESPONSE_ACCEPT);
5171         dialog.set_position (WIN_POS_CENTER);
5172         message.show();
5173         image->show();
5174         hbox->show();
5175
5176         switch (dialog.run ()) {
5177         case RESPONSE_ACCEPT:
5178                 return 1;
5179         default:
5180                 return 0;
5181         }
5182 }
5183
5184 int
5185 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
5186 {
5187         HBox* hbox = new HBox();
5188         Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
5189         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
5190         Label  message (string_compose (_("\
5191 This session was created with a sample rate of %1 Hz, but\n\
5192 %2 is currently running at %3 Hz.  If you load this session,\n\
5193 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
5194
5195         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
5196         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
5197         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
5198         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
5199         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
5200         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
5201         dialog.set_default_response (RESPONSE_ACCEPT);
5202         dialog.set_position (WIN_POS_CENTER);
5203         message.show();
5204         image->show();
5205         hbox->show();
5206
5207         switch (dialog.run()) {
5208         case RESPONSE_ACCEPT:
5209                 return 0;
5210         default:
5211                 break;
5212         }
5213
5214         return 1;
5215 }
5216
5217 void
5218 ARDOUR_UI::sr_mismatch_message (framecnt_t desired, framecnt_t actual)
5219 {
5220         MessageDialog msg (string_compose (_("\
5221 This session was created with a sample rate of %1 Hz, but\n\
5222 %2 is currently running at %3 Hz.\n\
5223 Audio will be recorded and played at the wrong sample rate.\n\
5224 Re-Configure the Audio Engine in\n\
5225 Menu > Window > Audio/Midi Setup"),
5226                                 desired, PROGRAM_NAME, actual),
5227                         true,
5228                         Gtk::MESSAGE_WARNING);
5229         msg.run ();
5230 }
5231
5232 void
5233 ARDOUR_UI::use_config ()
5234 {
5235         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
5236         if (node) {
5237                 set_transport_controllable_state (*node);
5238         }
5239 }
5240
5241 void
5242 ARDOUR_UI::update_transport_clocks (framepos_t pos)
5243 {
5244         if (UIConfiguration::instance().get_primary_clock_delta_edit_cursor()) {
5245                 primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5246         } else {
5247                 primary_clock->set (pos);
5248         }
5249
5250         if (UIConfiguration::instance().get_secondary_clock_delta_edit_cursor()) {
5251                 secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5252         } else {
5253                 secondary_clock->set (pos);
5254         }
5255
5256         if (big_clock_window) {
5257                 big_clock->set (pos);
5258         }
5259         ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
5260 }
5261
5262 void
5263 ARDOUR_UI::step_edit_status_change (bool yn)
5264 {
5265         // XXX should really store pre-step edit status of things
5266         // we make insensitive
5267
5268         if (yn) {
5269                 rec_button.set_active_state (Gtkmm2ext::ImplicitActive);
5270                 rec_button.set_sensitive (false);
5271         } else {
5272                 rec_button.unset_active_state ();;
5273                 rec_button.set_sensitive (true);
5274         }
5275 }
5276
5277 void
5278 ARDOUR_UI::record_state_changed ()
5279 {
5280         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
5281
5282         if (!_session) {
5283                 /* why bother - the clock isn't visible */
5284                 return;
5285         }
5286
5287         ActionManager::set_sensitive (ActionManager::rec_sensitive_actions, !_session->actively_recording());
5288
5289         if (big_clock_window) {
5290                 if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
5291                         big_clock->set_active (true);
5292                 } else {
5293                         big_clock->set_active (false);
5294                 }
5295         }
5296
5297 }
5298
5299 bool
5300 ARDOUR_UI::first_idle ()
5301 {
5302         if (_session) {
5303                 _session->allow_auto_play (true);
5304         }
5305
5306         if (editor) {
5307                 editor->first_idle();
5308         }
5309
5310         /* in 1 second, hide the splash screen
5311          *
5312          * Consider hiding it *now*. If a user opens opens a dialog
5313          * during that one second while the splash is still visible,
5314          * the dialog will push-back the splash.
5315          * Closing the dialog later will pop it back.
5316          */
5317         Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
5318
5319         Keyboard::set_can_save_keybindings (true);
5320         return false;
5321 }
5322
5323 void
5324 ARDOUR_UI::store_clock_modes ()
5325 {
5326         XMLNode* node = new XMLNode(X_("ClockModes"));
5327
5328         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
5329                 XMLNode* child = new XMLNode (X_("Clock"));
5330
5331                 child->set_property (X_("name"), (*x)->name());
5332                 child->set_property (X_("mode"), (*x)->mode());
5333                 child->set_property (X_("on"), (*x)->on());
5334
5335                 node->add_child_nocopy (*child);
5336         }
5337
5338         _session->add_extra_xml (*node);
5339         _session->set_dirty ();
5340 }
5341
5342 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
5343         : Controllable (name), ui (u), type(tp)
5344 {
5345
5346 }
5347
5348 void
5349 ARDOUR_UI::TransportControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /*group_override*/)
5350 {
5351         if (val < 0.5) {
5352                 /* do nothing: these are radio-style actions */
5353                 return;
5354         }
5355
5356         const char *action = 0;
5357
5358         switch (type) {
5359         case Roll:
5360                 action = X_("Roll");
5361                 break;
5362         case Stop:
5363                 action = X_("Stop");
5364                 break;
5365         case GotoStart:
5366                 action = X_("GotoStart");
5367                 break;
5368         case GotoEnd:
5369                 action = X_("GotoEnd");
5370                 break;
5371         case AutoLoop:
5372                 action = X_("Loop");
5373                 break;
5374         case PlaySelection:
5375                 action = X_("PlaySelection");
5376                 break;
5377         case RecordEnable:
5378                 action = X_("Record");
5379                 break;
5380         default:
5381                 break;
5382         }
5383
5384         if (action == 0) {
5385                 return;
5386         }
5387
5388         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
5389
5390         if (act) {
5391                 act->activate ();
5392         }
5393 }
5394
5395 double
5396 ARDOUR_UI::TransportControllable::get_value (void) const
5397 {
5398         float val = 0.0;
5399
5400         switch (type) {
5401         case Roll:
5402                 break;
5403         case Stop:
5404                 break;
5405         case GotoStart:
5406                 break;
5407         case GotoEnd:
5408                 break;
5409         case AutoLoop:
5410                 break;
5411         case PlaySelection:
5412                 break;
5413         case RecordEnable:
5414                 break;
5415         default:
5416                 break;
5417         }
5418
5419         return val;
5420 }
5421
5422 void
5423 ARDOUR_UI::setup_profile ()
5424 {
5425         if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
5426                 Profile->set_small_screen ();
5427         }
5428
5429         if (g_getenv ("TRX")) {
5430                 Profile->set_trx ();
5431         }
5432
5433         if (g_getenv ("MIXBUS")) {
5434                 Profile->set_mixbus ();
5435         }
5436 }
5437
5438 int
5439 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
5440 {
5441         MissingFileDialog dialog (s, str, type);
5442
5443         dialog.show ();
5444         dialog.present ();
5445
5446         int result = dialog.run ();
5447         dialog.hide ();
5448
5449         switch (result) {
5450         case RESPONSE_OK:
5451                 break;
5452         default:
5453                 return 1; // quit entire session load
5454         }
5455
5456         result = dialog.get_action ();
5457
5458         return result;
5459 }
5460
5461 int
5462 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
5463 {
5464         AmbiguousFileDialog dialog (file, hits);
5465
5466         dialog.show ();
5467         dialog.present ();
5468
5469         dialog.run ();
5470
5471         return dialog.get_which ();
5472 }
5473
5474 /** Allocate our thread-local buffers */
5475 void
5476 ARDOUR_UI::get_process_buffers ()
5477 {
5478         _process_thread->get_buffers ();
5479 }
5480
5481 /** Drop our thread-local buffers */
5482 void
5483 ARDOUR_UI::drop_process_buffers ()
5484 {
5485         _process_thread->drop_buffers ();
5486 }
5487
5488 void
5489 ARDOUR_UI::feedback_detected ()
5490 {
5491         _feedback_exists = true;
5492 }
5493
5494 void
5495 ARDOUR_UI::successful_graph_sort ()
5496 {
5497         _feedback_exists = false;
5498 }
5499
5500 void
5501 ARDOUR_UI::midi_panic ()
5502 {
5503         if (_session) {
5504                 _session->midi_panic();
5505         }
5506 }
5507
5508 void
5509 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
5510 {
5511         const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
5512         const char* end_big = "</span>";
5513         const char* start_mono = "<tt>";
5514         const char* end_mono = "</tt>";
5515
5516         MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
5517                                              "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
5518                                              "From now on, use the backup copy with older versions of %3"),
5519                                            xml_path, backup_path, PROGRAM_NAME,
5520                                            start_big, end_big,
5521                                            start_mono, end_mono), true);
5522
5523         msg.run ();
5524 }
5525
5526 void
5527 ARDOUR_UI::add_editor_meter_type_item (Menu_Helpers::MenuList& items, RadioMenuItem::Group& group, string const & name, MeterType type)
5528 {
5529         using namespace Menu_Helpers;
5530
5531         items.push_back (RadioMenuElem (group, name, sigc::bind (sigc::mem_fun (editor_meter, &LevelMeterHBox::set_meter_type), type)));
5532         RadioMenuItem* i = dynamic_cast<RadioMenuItem *> (&items.back ());
5533         i->set_active (editor_meter->meter_type () == type);
5534 }
5535
5536 void
5537 ARDOUR_UI::popup_editor_meter_menu (GdkEventButton* ev)
5538 {
5539         using namespace Gtk::Menu_Helpers;
5540
5541         Gtk::Menu* m = manage (new Menu);
5542         MenuList& items = m->items ();
5543
5544         RadioMenuItem::Group group;
5545
5546         _suspend_editor_meter_callbacks = true;
5547         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak), MeterPeak);
5548         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak0dB), MeterPeak0dB);
5549         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterKrms),  MeterKrms);
5550         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1DIN), MeterIEC1DIN);
5551         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1NOR), MeterIEC1NOR);
5552         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2BBC), MeterIEC2BBC);
5553         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
5554         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK20), MeterK20);
5555         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK14), MeterK14);
5556         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK12), MeterK12);
5557         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterVU),  MeterVU);
5558
5559         m->popup (ev->button, ev->time);
5560         _suspend_editor_meter_callbacks = false;
5561 }
5562
5563 bool
5564 ARDOUR_UI::editor_meter_button_press (GdkEventButton* ev)
5565 {
5566         if (ev->button == 3 && editor_meter) {
5567                 popup_editor_meter_menu (ev);
5568                 return true;
5569         }
5570         return false;
5571 }
5572
5573 void
5574 ARDOUR_UI::reset_peak_display ()
5575 {
5576         if (!_session || !_session->master_out() || !editor_meter) return;
5577         editor_meter->clear_meters();
5578         editor_meter_max_peak = -INFINITY;
5579         editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
5580 }
5581
5582 void
5583 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
5584 {
5585         if (!_session || !_session->master_out()) return;
5586         if (group == _session->master_out()->route_group()) {
5587                 reset_peak_display ();
5588         }
5589 }
5590
5591 void
5592 ARDOUR_UI::reset_route_peak_display (Route* route)
5593 {
5594         if (!_session || !_session->master_out()) return;
5595         if (_session->master_out().get() == route) {
5596                 reset_peak_display ();
5597         }
5598 }
5599
5600 int
5601 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
5602 {
5603         audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
5604         audio_midi_setup->set_position (WIN_POS_CENTER);
5605
5606         if (desired_sample_rate != 0) {
5607                 if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
5608                         audio_midi_setup->try_autostart ();
5609                         if (ARDOUR::AudioEngine::instance()->running()) {
5610                                 return 0;
5611                         }
5612                 }
5613         }
5614
5615         while (true) {
5616                 int response = audio_midi_setup->run();
5617                 switch (response) {
5618                 case Gtk::RESPONSE_DELETE_EVENT:
5619                         // after latency callibration engine may run,
5620                         // Running() signal was emitted, but dialog will not
5621                         // have emitted a response. The user needs to close
5622                         // the dialog -> Gtk::RESPONSE_DELETE_EVENT
5623                         if (!AudioEngine::instance()->running()) {
5624                                 return -1;
5625                         }
5626                         // fall through
5627                 default:
5628                         if (!AudioEngine::instance()->running()) {
5629                                 continue;
5630                         }
5631                         audio_midi_setup->hide ();
5632                         return 0;
5633                 }
5634         }
5635 }
5636
5637
5638 gint
5639 ARDOUR_UI::transport_numpad_timeout ()
5640 {
5641         _numpad_locate_happening = false;
5642         if (_numpad_timeout_connection.connected() )
5643                 _numpad_timeout_connection.disconnect();
5644         return 1;
5645 }
5646
5647 void
5648 ARDOUR_UI::transport_numpad_decimal ()
5649 {
5650         _numpad_timeout_connection.disconnect();
5651
5652         if (_numpad_locate_happening) {
5653                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
5654                 _numpad_locate_happening = false;
5655         } else {
5656                 _pending_locate_num = 0;
5657                 _numpad_locate_happening = true;
5658                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
5659         }
5660 }
5661
5662 void
5663 ARDOUR_UI::transport_numpad_event (int num)
5664 {
5665         if ( _numpad_locate_happening ) {
5666                 _pending_locate_num = _pending_locate_num*10 + num;
5667         } else {
5668                 switch (num) {
5669                         case 0:  toggle_roll(false, false);             break;
5670                         case 1:  transport_rewind(1);                           break;
5671                         case 2:  transport_forward(1);                          break;
5672                         case 3:  transport_record(true);                        break;
5673                         case 4:  toggle_session_auto_loop();            break;
5674                         case 5:  transport_record(false); toggle_session_auto_loop();   break;
5675                         case 6:  toggle_punch();                                        break;
5676                         case 7:  toggle_click();                                break;
5677                         case 8:  toggle_auto_return();                  break;
5678                         case 9:  toggle_follow_edits();         break;
5679                 }
5680         }
5681 }
5682
5683 void
5684 ARDOUR_UI::set_flat_buttons ()
5685 {
5686         CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
5687 }
5688
5689 void
5690 ARDOUR_UI::audioengine_became_silent ()
5691 {
5692         MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
5693                            true,
5694                            Gtk::MESSAGE_WARNING,
5695                            Gtk::BUTTONS_NONE,
5696                            true);
5697
5698         msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5699
5700         Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5701         Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5702         Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5703         Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5704         Gtk::HBox pay_button_box;
5705         Gtk::HBox subscribe_button_box;
5706
5707         pay_button_box.pack_start (pay_button, true, false);
5708         subscribe_button_box.pack_start (subscribe_button, true, false);
5709
5710         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 */
5711
5712         pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5713         subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5714
5715         msg.get_vbox()->pack_start (pay_label);
5716         msg.get_vbox()->pack_start (pay_button_box);
5717         msg.get_vbox()->pack_start (subscribe_label);
5718         msg.get_vbox()->pack_start (subscribe_button_box);
5719
5720         msg.get_vbox()->show_all ();
5721
5722         msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5723         msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5724         msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5725
5726         int r = msg.run ();
5727
5728         switch (r) {
5729         case Gtk::RESPONSE_YES:
5730                 AudioEngine::instance()->reset_silence_countdown ();
5731                 break;
5732
5733         case Gtk::RESPONSE_NO:
5734                 /* save and quit */
5735                 save_state_canfail ("");
5736                 exit (0);
5737                 break;
5738
5739         case Gtk::RESPONSE_CANCEL:
5740         default:
5741                 /* don't reset, save session and exit */
5742                 break;
5743         }
5744 }
5745
5746 void
5747 ARDOUR_UI::hide_application ()
5748 {
5749         Application::instance ()-> hide ();
5750 }
5751
5752 void
5753 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
5754 {
5755         /* icons, titles, WM stuff */
5756
5757         static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
5758
5759         if (window_icons.empty()) {
5760                 Glib::RefPtr<Gdk::Pixbuf> icon;
5761                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) {
5762                         window_icons.push_back (icon);
5763                 }
5764                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) {
5765                         window_icons.push_back (icon);
5766                 }
5767                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) {
5768                         window_icons.push_back (icon);
5769                 }
5770                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
5771                         window_icons.push_back (icon);
5772                 }
5773         }
5774
5775         if (!window_icons.empty()) {
5776                 window.set_default_icon_list (window_icons);
5777         }
5778
5779         Gtkmm2ext::WindowTitle title (Glib::get_application_name());
5780
5781         if (!name.empty()) {
5782                 title += name;
5783         }
5784
5785         window.set_title (title.get_string());
5786         window.set_wmclass (string_compose (X_("%1_%1"), downcase (std::string(PROGRAM_NAME)), downcase (name)), PROGRAM_NAME);
5787
5788         window.set_flags (CAN_FOCUS);
5789         window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
5790
5791         /* This is a hack to ensure that GTK-accelerators continue to
5792          * work. Once we switch over to entirely native bindings, this will be
5793          * unnecessary and should be removed
5794          */
5795         window.add_accel_group (ActionManager::ui_manager->get_accel_group());
5796
5797         window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
5798         window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
5799         window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5800         window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5801 }
5802
5803 bool
5804 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
5805 {
5806         Gtkmm2ext::Bindings* bindings = 0;
5807         Gtk::Window* window = 0;
5808
5809         /* until we get ardour bindings working, we are not handling key
5810          * releases yet.
5811          */
5812
5813         if (ev->type != GDK_KEY_PRESS) {
5814                 return false;
5815         }
5816
5817         if (event_window == &_main_window) {
5818
5819                 window = event_window;
5820
5821                 /* find current tab contents */
5822
5823                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
5824
5825                 /* see if it uses the ardour binding system */
5826
5827                 if (w) {
5828                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
5829                 }
5830
5831                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
5832
5833         } else {
5834
5835                 window = event_window;
5836
5837                 /* see if window uses ardour binding system */
5838
5839                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
5840         }
5841
5842         /* An empty binding set is treated as if it doesn't exist */
5843
5844         if (bindings && bindings->empty()) {
5845                 bindings = 0;
5846         }
5847
5848         return key_press_focus_accelerator_handler (*window, ev, bindings);
5849 }
5850
5851 static Gtkmm2ext::Bindings*
5852 get_bindings_from_widget_heirarchy (GtkWidget** w)
5853 {
5854         void* p = NULL;
5855
5856         while (*w) {
5857                 if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) {
5858                         break;
5859                 }
5860                 *w = gtk_widget_get_parent (*w);
5861         }
5862
5863         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
5864 }
5865
5866 bool
5867 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
5868 {
5869         GtkWindow* win = window.gobj();
5870         GtkWidget* focus = gtk_window_get_focus (win);
5871         GtkWidget* binding_widget = focus;
5872         bool special_handling_of_unmodified_accelerators = false;
5873         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
5874
5875         if (focus) {
5876
5877                 /* some widget has keyboard focus */
5878
5879                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
5880
5881                         /* A particular kind of focusable widget currently has keyboard
5882                          * focus. All unmodified key events should go to that widget
5883                          * first and not be used as an accelerator by default
5884                          */
5885
5886                         special_handling_of_unmodified_accelerators = true;
5887
5888                 } else {
5889
5890                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5891                         if (focus_bindings) {
5892                                 bindings = focus_bindings;
5893                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
5894                         }
5895                 }
5896         }
5897
5898         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",
5899                                                           win,
5900                                                           ev->keyval,
5901                                                           Gtkmm2ext::show_gdk_event_state (ev->state),
5902                                                           special_handling_of_unmodified_accelerators,
5903                                                           Keyboard::some_magic_widget_has_focus(),
5904                                                           focus,
5905                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
5906                                                           ((ev->state & mask) ? "yes" : "no"),
5907                                                           window.get_title()));
5908
5909         /* This exists to allow us to override the way GTK handles
5910            key events. The normal sequence is:
5911
5912            a) event is delivered to a GtkWindow
5913            b) accelerators/mnemonics are activated
5914            c) if (b) didn't handle the event, propagate to
5915                the focus widget and/or focus chain
5916
5917            The problem with this is that if the accelerators include
5918            keys without modifiers, such as the space bar or the
5919            letter "e", then pressing the key while typing into
5920            a text entry widget results in the accelerator being
5921            activated, instead of the desired letter appearing
5922            in the text entry.
5923
5924            There is no good way of fixing this, but this
5925            represents a compromise. The idea is that
5926            key events involving modifiers (not Shift)
5927            get routed into the activation pathway first, then
5928            get propagated to the focus widget if necessary.
5929
5930            If the key event doesn't involve modifiers,
5931            we deliver to the focus widget first, thus allowing
5932            it to get "normal text" without interference
5933            from acceleration.
5934
5935            Of course, this can also be problematic: if there
5936            is a widget with focus, then it will swallow
5937            all "normal text" accelerators.
5938         */
5939
5940
5941         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
5942
5943                 /* no special handling or there are modifiers in effect: accelerate first */
5944
5945                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
5946                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
5947                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
5948
5949                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
5950                 KeyboardKey k (ev->state, ev->keyval);
5951
5952                 while (bindings) {
5953
5954                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
5955
5956                         if (bindings->activate (k, Bindings::Press)) {
5957                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5958                                 return true;
5959                         }
5960
5961                         if (binding_widget) {
5962                                 binding_widget = gtk_widget_get_parent (binding_widget);
5963                                 if (binding_widget) {
5964                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5965                                 } else {
5966                                         bindings = 0;
5967                                 }
5968                         } else {
5969                                 bindings = 0;
5970                         }
5971                 }
5972
5973                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5974
5975                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5976                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5977                         return true;
5978                 }
5979
5980                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
5981
5982                 if (gtk_window_propagate_key_event (win, ev)) {
5983                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
5984                         return true;
5985                 }
5986
5987         } else {
5988
5989                 /* no modifiers, propagate first */
5990
5991                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
5992
5993                 if (gtk_window_propagate_key_event (win, ev)) {
5994                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
5995                         return true;
5996                 }
5997
5998                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
5999                 KeyboardKey k (ev->state, ev->keyval);
6000
6001                 while (bindings) {
6002
6003                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
6004
6005
6006                         if (bindings->activate (k, Bindings::Press)) {
6007                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
6008                                 return true;
6009                         }
6010
6011                         if (binding_widget) {
6012                                 binding_widget = gtk_widget_get_parent (binding_widget);
6013                                 if (binding_widget) {
6014                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
6015                                 } else {
6016                                         bindings = 0;
6017                                 }
6018                         } else {
6019                                 bindings = 0;
6020                         }
6021                 }
6022
6023                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
6024
6025                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
6026                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
6027                         return true;
6028                 }
6029         }
6030
6031         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
6032         return true;
6033 }
6034
6035 void
6036 ARDOUR_UI::load_bindings ()
6037 {
6038         if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
6039                 error << _("Global keybindings are missing") << endmsg;
6040         }
6041 }
6042
6043 void
6044 ARDOUR_UI::cancel_solo ()
6045 {
6046         if (_session) {
6047                 _session->cancel_all_solo ();
6048         }
6049 }
6050
6051 void
6052 ARDOUR_UI::reset_focus (Gtk::Widget* w)
6053 {
6054         /* this resets focus to the first focusable parent of the given widget,
6055          * or, if there is no focusable parent, cancels focus in the toplevel
6056          * window that the given widget is packed into (if there is one).
6057          */
6058
6059         if (!w) {
6060                 return;
6061         }
6062
6063         Gtk::Widget* top = w->get_toplevel();
6064
6065         if (!top || !top->is_toplevel()) {
6066                 return;
6067         }
6068
6069         w = w->get_parent ();
6070
6071         while (w) {
6072
6073                 if (w->is_toplevel()) {
6074                         /* Setting the focus widget to a Gtk::Window causes all
6075                          * subsequent calls to ::has_focus() on the nominal
6076                          * focus widget in that window to return
6077                          * false. Workaround: never set focus to the toplevel
6078                          * itself.
6079                          */
6080                         break;
6081                 }
6082
6083                 if (w->get_can_focus ()) {
6084                         Gtk::Window* win = dynamic_cast<Gtk::Window*> (top);
6085                         win->set_focus (*w);
6086                         return;
6087                 }
6088                 w = w->get_parent ();
6089         }
6090
6091         if (top == &_main_window) {
6092
6093         }
6094
6095         /* no focusable parent found, cancel focus in top level window.
6096            C++ API cannot be used for this. Thanks, references.
6097         */
6098
6099         gtk_window_set_focus (GTK_WINDOW(top->gobj()), 0);
6100
6101 }