remove "Off" as a clock mode, make it a state instead; track editor mouse mode when...
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2007 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 #endif
23
24 #include <stdint.h>
25
26 #include <algorithm>
27 #include <cmath>
28 #include <fcntl.h>
29 #include <signal.h>
30 #include <unistd.h>
31 #include <time.h>
32 #include <cerrno>
33 #include <fstream>
34
35 #include <iostream>
36
37 #include <sys/resource.h>
38
39 #include <gtkmm/messagedialog.h>
40 #include <gtkmm/accelmap.h>
41
42 #include "pbd/error.h"
43 #include "pbd/basename.h"
44 #include "pbd/compose.h"
45 #include "pbd/failed_constructor.h"
46 #include "pbd/enumwriter.h"
47 #include "pbd/memento_command.h"
48 #include "pbd/openuri.h"
49 #include "pbd/file_utils.h"
50
51 #include "gtkmm2ext/application.h"
52 #include "gtkmm2ext/bindings.h"
53 #include "gtkmm2ext/gtk_ui.h"
54 #include "gtkmm2ext/utils.h"
55 #include "gtkmm2ext/click_box.h"
56 #include "gtkmm2ext/fastmeter.h"
57 #include "gtkmm2ext/popup.h"
58 #include "gtkmm2ext/window_title.h"
59
60 #include "midi++/manager.h"
61
62 #include "ardour/ardour.h"
63 #include "ardour/callback.h"
64 #include "ardour/profile.h"
65 #include "ardour/session_directory.h"
66 #include "ardour/session_route.h"
67 #include "ardour/session_state_utils.h"
68 #include "ardour/session_utils.h"
69 #include "ardour/port.h"
70 #include "ardour/audioengine.h"
71 #include "ardour/playlist.h"
72 #include "ardour/utils.h"
73 #include "ardour/audio_diskstream.h"
74 #include "ardour/audiofilesource.h"
75 #include "ardour/recent_sessions.h"
76 #include "ardour/port.h"
77 #include "ardour/audio_track.h"
78 #include "ardour/midi_track.h"
79 #include "ardour/filesystem_paths.h"
80 #include "ardour/filename_extensions.h"
81
82 typedef uint64_t microseconds_t;
83
84 #include "about.h"
85 #include "actions.h"
86 #include "add_route_dialog.h"
87 #include "ambiguous_file_dialog.h"
88 #include "ardour_ui.h"
89 #include "audio_clock.h"
90 #include "bundle_manager.h"
91 #include "engine_dialog.h"
92 #include "gain_meter.h"
93 #include "global_port_matrix.h"
94 #include "gui_thread.h"
95 #include "keyboard.h"
96 #include "location_ui.h"
97 #include "missing_file_dialog.h"
98 #include "missing_plugin_dialog.h"
99 #include "mixer_ui.h"
100 #include "opts.h"
101 #include "processor_box.h"
102 #include "prompter.h"
103 #include "public_editor.h"
104 #include "route_time_axis.h"
105 #include "session_metadata_dialog.h"
106 #include "shuttle_control.h"
107 #include "speaker_dialog.h"
108 #include "splash.h"
109 #include "startup.h"
110 #include "theme_manager.h"
111 #include "time_axis_view_item.h"
112 #include "utils.h"
113 #include "window_proxy.h"
114
115 #include "i18n.h"
116
117 using namespace ARDOUR;
118 using namespace PBD;
119 using namespace Gtkmm2ext;
120 using namespace Gtk;
121
122 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
123 UIConfiguration *ARDOUR_UI::ui_config = 0;
124
125 sigc::signal<void,bool> ARDOUR_UI::Blink;
126 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
127 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
128 sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock;
129
130 bool could_be_a_valid_path (const string& path);
131
132 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
133
134         : Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp)
135
136         , primary_clock (new AudioClock (X_("primary"), false, X_("TransportClockDisplay"), true, true, false, true))
137         , secondary_clock (new AudioClock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, true, false, true))
138         , preroll_clock (new AudioClock (X_("preroll"), false, X_("PreRollClock"), true, false, true))
139         , postroll_clock (new AudioClock (X_("postroll"), false, X_("PostRollClock"), true, false, true))
140
141           /* preroll stuff */
142
143         , preroll_button (_("pre\nroll"))
144         , postroll_button (_("post\nroll"))
145
146           /* big clock */
147
148         , big_clock (new AudioClock (X_("bigclock"), false, "BigClockNonRecording", true, true, false, false))
149
150           /* transport */
151
152         , roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll))
153         , stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop))
154         , goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart))
155         , goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd))
156         , auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop))
157         , play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection))
158         , rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable))
159
160         , roll_button (roll_controllable)
161         , stop_button (stop_controllable)
162         , goto_start_button (goto_start_controllable)
163         , goto_end_button (goto_end_controllable)
164         , auto_loop_button (auto_loop_controllable)
165         , play_selection_button (play_selection_controllable)
166         , rec_button (rec_controllable)
167
168         , punch_in_button (_("Punch In"))
169         , punch_out_button (_("Punch Out"))
170         , auto_return_button (_("Auto Return"))
171         , auto_play_button (_("Auto Play"))
172         , auto_input_button (_("Auto Input"))
173         , click_button (_("Click"))
174         , time_master_button (_("time\nmaster"))
175
176         , auditioning_alert_button (_("AUDITION"))
177         , solo_alert_button (_("SOLO"))
178
179         , error_log_button (_("Errors"))
180
181 {
182         using namespace Gtk::Menu_Helpers;
183
184         Gtkmm2ext::init();
185
186
187 #ifdef TOP_MENUBAR
188         // _auto_display_errors = false;
189         /*
190          * This was commented out as it wasn't defined
191          * in A3 IIRC.  If this is not needed it should
192          * be completely removed.
193          */
194 #endif
195
196         about = 0;
197         splash = 0;
198         _startup = 0;
199
200         if (theArdourUI == 0) {
201                 theArdourUI = this;
202         }
203
204         ui_config = new UIConfiguration();
205         theme_manager = new ThemeManager();
206
207         key_editor = 0;
208
209         editor = 0;
210         mixer = 0;
211         editor = 0;
212         engine = 0;
213         _session_is_new = false;
214         big_clock_window = 0;
215         big_clock_height = 0;
216         big_clock_resize_in_progress = false;
217         session_selector_window = 0;
218         last_key_press_time = 0;
219         _will_create_new_session_automatically = false;
220         add_route_dialog = 0;
221         route_params = 0;
222         bundle_manager = 0;
223         rc_option_editor = 0;
224         session_option_editor = 0;
225         location_ui = 0;
226         open_session_selector = 0;
227         have_configure_timeout = false;
228         have_disk_speed_dialog_displayed = false;
229         session_loaded = false;
230         ignore_dual_punch = false;
231         original_big_clock_width = -1;
232         original_big_clock_height = -1;
233         original_big_clock_font_size = 0;
234
235         roll_button.unset_flags (Gtk::CAN_FOCUS);
236         stop_button.unset_flags (Gtk::CAN_FOCUS);
237         goto_start_button.unset_flags (Gtk::CAN_FOCUS);
238         goto_end_button.unset_flags (Gtk::CAN_FOCUS);
239         auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
240         play_selection_button.unset_flags (Gtk::CAN_FOCUS);
241         rec_button.unset_flags (Gtk::CAN_FOCUS);
242         join_play_range_button.unset_flags (Gtk::CAN_FOCUS);
243         last_configure_time= 0;
244         last_peak_grab = 0;
245
246         ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
247         ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
248
249         /* handle dialog requests */
250
251         ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
252
253         /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
254
255         ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
256
257         /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
258
259         ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
260
261         /* handle requests to quit (coming from JACK session) */
262
263         ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::finish, this), gui_context ());
264
265         /* handle requests to deal with missing files */
266
267         ARDOUR::Session::MissingFile.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::missing_file, this, _1, _2, _3));
268
269         /* and ambiguous files */
270
271         ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2, _3));
272
273         /* lets get this party started */
274
275         try {
276                 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
277                         throw failed_constructor ();
278                 }
279
280                 setup_gtk_ardour_enums ();
281                 setup_profile ();
282
283                 GainMeter::setup_slider_pix ();
284                 RouteTimeAxisView::setup_slider_pix ();
285                 SendProcessorEntry::setup_slider_pix ();
286                 SessionEvent::create_per_thread_pool ("GUI", 512);
287
288         } catch (failed_constructor& err) {
289                 error << string_compose (_("could not initialize %1."), PROGRAM_NAME) << endmsg;
290                 // pass it on up
291                 throw;
292         }
293
294         /* we like keyboards */
295
296         keyboard = new ArdourKeyboard(*this);
297
298
299         XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
300         if (node) {
301                 keyboard->set_state (*node, Stateful::loading_state_version);
302         }
303
304         /* we don't like certain modifiers */
305         Bindings::set_ignored_state (GDK_LOCK_MASK|GDK_MOD2_MASK|GDK_MOD3_MASK);
306
307         reset_dpi();
308
309         TimeAxisViewItem::set_constant_heights ();
310
311         /* The following must happen after ARDOUR::init() so that Config is set up */
312
313         location_ui = new ActionWindowProxy<LocationUIWindow> (X_("locations"), Config->extra_xml (X_("UI")), X_("ToggleLocations"));
314         big_clock_window = new ActionWindowProxy<Gtk::Window> (X_("bigclock"), Config->extra_xml (X_("UI")), X_("ToggleBigClock"));
315         speaker_config_window = new ActionWindowProxy<SpeakerDialog> (X_("speakerconf"), Config->extra_xml (X_("UI")), X_("toggle-speaker-config"));
316
317         for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
318                 _global_port_matrix[*i] = new ActionWindowProxy<GlobalPortMatrixWindow> (
319                         string_compose ("GlobalPortMatrix-%1", (*i).to_string()),
320                         Config->extra_xml (X_("UI")),
321                         string_compose ("toggle-%1-connection-manager", (*i).to_string())
322                         );
323         }
324
325         setup_clock ();
326
327         SpeakerDialog* s = new SpeakerDialog ();
328         s->signal_unmap().connect (sigc::bind (sigc::ptr_fun (&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/toggle-speaker-config")));
329         speaker_config_window->set (s);
330
331         starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup));
332         stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown));
333 }
334
335 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
336 bool
337 ARDOUR_UI::run_startup (bool should_be_new, string load_template)
338 {
339         delete _startup;
340         _startup = new ArdourStartup ();
341
342         XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
343
344         if (audio_setup && _startup->engine_control()) {
345                 _startup->engine_control()->set_state (*audio_setup);
346         }
347
348         _startup->set_new_only (should_be_new);
349         if (!load_template.empty()) {
350                 _startup->set_load_template( load_template );
351         }
352         _startup->present ();
353
354         main().run();
355
356         _startup->hide ();
357
358         switch (_startup->response()) {
359         case RESPONSE_OK:
360                 return true;
361         default:
362                 return false;
363         }
364 }
365
366 int
367 ARDOUR_UI::create_engine ()
368 {
369         // this gets called every time by new_session()
370
371         if (engine) {
372                 return 0;
373         }
374
375         loading_message (_("Starting audio engine"));
376
377         try {
378                 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name, ARDOUR_COMMAND_LINE::jack_session_uuid);
379
380         } catch (...) {
381
382                 return -1;
383         }
384
385         engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
386         engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
387         engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
388
389         engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
390
391         ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
392
393         post_engine ();
394
395         return 0;
396 }
397
398 void
399 ARDOUR_UI::post_engine ()
400 {
401         /* Things to be done once we create the AudioEngine
402          */
403
404         ARDOUR::init_post_engine ();
405
406         ActionManager::init ();
407         _tooltips.enable();
408
409         if (setup_windows ()) {
410                 throw failed_constructor ();
411         }
412
413         check_memory_locking();
414
415         /* this is the first point at which all the keybindings are available */
416
417         if (ARDOUR_COMMAND_LINE::show_key_actions) {
418                 vector<string> names;
419                 vector<string> paths;
420                 vector<string> tooltips;
421                 vector<string> keys;
422                 vector<AccelKey> bindings;
423
424                 ActionManager::get_all_actions (names, paths, tooltips, keys, bindings);
425
426                 vector<string>::iterator n;
427                 vector<string>::iterator k;
428                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
429                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
430                 }
431
432                 exit (0);
433         }
434
435         blink_timeout_tag = -1;
436
437         /* this being a GUI and all, we want peakfiles */
438
439         AudioFileSource::set_build_peakfiles (true);
440         AudioFileSource::set_build_missing_peakfiles (true);
441
442         /* set default clock modes */
443
444         if (Profile->get_sae()) {
445                 primary_clock->set_mode (AudioClock::BBT);
446                 secondary_clock->set_mode (AudioClock::MinSec);
447         }  else {
448                 primary_clock->set_mode (AudioClock::Timecode);
449                 secondary_clock->set_mode (AudioClock::BBT);
450         }
451
452         /* start the time-of-day-clock */
453
454 #ifndef GTKOSX
455         /* OS X provides a nearly-always visible wallclock, so don't be stupid */
456         update_wall_clock ();
457         Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
458 #endif
459
460         update_disk_space ();
461         update_cpu_load ();
462         update_sample_rate (engine->frame_rate());
463
464         Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
465         boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
466         Config->map_parameters (pc);
467
468         /* now start and maybe save state */
469
470         if (do_engine_start () == 0) {
471                 if (_session && _session_is_new) {
472                         /* we need to retain initial visual
473                            settings for a new session
474                         */
475                         _session->save_state ("");
476                 }
477         }
478 }
479
480 ARDOUR_UI::~ARDOUR_UI ()
481 {
482         delete keyboard;
483         delete editor;
484         delete mixer;
485         delete add_route_dialog;
486 }
487
488 void
489 ARDOUR_UI::pop_back_splash ()
490 {
491         if (Splash::instance()) {
492                 // Splash::instance()->pop_back();
493                 Splash::instance()->hide ();
494         }
495 }
496
497 gint
498 ARDOUR_UI::configure_timeout ()
499 {
500         if (last_configure_time == 0) {
501                 /* no configure events yet */
502                 return true;
503         }
504
505         /* force a gap of 0.5 seconds since the last configure event
506          */
507
508         if (get_microseconds() - last_configure_time < 500000) {
509                 return true;
510         } else {
511                 have_configure_timeout = false;
512                 cerr << "config event-driven save\n";
513                 save_ardour_state ();
514                 return false;
515         }
516 }
517
518 gboolean
519 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
520 {
521         if (have_configure_timeout) {
522                 last_configure_time = get_microseconds();
523         } else {
524                 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
525                 have_configure_timeout = true;
526         }
527
528         return FALSE;
529 }
530
531 void
532 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
533 {
534         const XMLProperty* prop;
535
536         if ((prop = node.property ("roll")) != 0) {
537                 roll_controllable->set_id (prop->value());
538         }
539         if ((prop = node.property ("stop")) != 0) {
540                 stop_controllable->set_id (prop->value());
541         }
542         if ((prop = node.property ("goto-start")) != 0) {
543                 goto_start_controllable->set_id (prop->value());
544         }
545         if ((prop = node.property ("goto-end")) != 0) {
546                 goto_end_controllable->set_id (prop->value());
547         }
548         if ((prop = node.property ("auto-loop")) != 0) {
549                 auto_loop_controllable->set_id (prop->value());
550         }
551         if ((prop = node.property ("play-selection")) != 0) {
552                 play_selection_controllable->set_id (prop->value());
553         }
554         if ((prop = node.property ("rec")) != 0) {
555                 rec_controllable->set_id (prop->value());
556         }
557         if ((prop = node.property ("shuttle")) != 0) {
558                 shuttle_box->controllable()->set_id (prop->value());
559         }
560
561 }
562
563 XMLNode&
564 ARDOUR_UI::get_transport_controllable_state ()
565 {
566         XMLNode* node = new XMLNode(X_("TransportControllables"));
567         char buf[64];
568
569         roll_controllable->id().print (buf, sizeof (buf));
570         node->add_property (X_("roll"), buf);
571         stop_controllable->id().print (buf, sizeof (buf));
572         node->add_property (X_("stop"), buf);
573         goto_start_controllable->id().print (buf, sizeof (buf));
574         node->add_property (X_("goto_start"), buf);
575         goto_end_controllable->id().print (buf, sizeof (buf));
576         node->add_property (X_("goto_end"), buf);
577         auto_loop_controllable->id().print (buf, sizeof (buf));
578         node->add_property (X_("auto_loop"), buf);
579         play_selection_controllable->id().print (buf, sizeof (buf));
580         node->add_property (X_("play_selection"), buf);
581         rec_controllable->id().print (buf, sizeof (buf));
582         node->add_property (X_("rec"), buf);
583         shuttle_box->controllable()->id().print (buf, sizeof (buf));
584         node->add_property (X_("shuttle"), buf);
585
586         return *node;
587 }
588
589
590 gint
591 ARDOUR_UI::autosave_session ()
592 {
593         if (g_main_depth() > 1) {
594                 /* inside a recursive main loop,
595                    give up because we may not be able to
596                    take a lock.
597                 */
598                 return 1;
599         }
600
601         if (!Config->get_periodic_safety_backups()) {
602                 return 1;
603         }
604
605         if (_session) {
606                 _session->maybe_write_autosave();
607         }
608
609         return 1;
610 }
611
612 void
613 ARDOUR_UI::update_autosave ()
614 {
615         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_autosave)
616
617         if (_session && _session->dirty()) {
618                 if (_autosave_connection.connected()) {
619                         _autosave_connection.disconnect();
620                 }
621
622                 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
623                                 Config->get_periodic_safety_backup_interval() * 1000);
624
625         } else {
626                 if (_autosave_connection.connected()) {
627                         _autosave_connection.disconnect();
628                 }
629         }
630 }
631
632 void
633 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
634 {
635         string title;
636         if (we_set_params) {
637                 title = string_compose (_("%1 could not start JACK"), PROGRAM_NAME);
638         } else {
639                 title = string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME);
640         }
641
642         MessageDialog win (title,
643                            false,
644                            Gtk::MESSAGE_INFO,
645                            Gtk::BUTTONS_NONE);
646
647         if (we_set_params) {
648                 win.set_secondary_text(_("There are several possible reasons:\n\
649 \n\
650 1) You requested audio parameters that are not supported..\n\
651 2) JACK is running as another user.\n\
652 \n\
653 Please consider the possibilities, and perhaps try different parameters."));
654         } else {
655                 win.set_secondary_text(_("There are several possible reasons:\n\
656 \n\
657 1) JACK is not running.\n\
658 2) JACK is running as another user, perhaps root.\n\
659 3) There is already another client called \"ardour\".\n\
660 \n\
661 Please consider the possibilities, and perhaps (re)start JACK."));
662         }
663
664         if (toplevel) {
665                 win.set_transient_for (*toplevel);
666         }
667
668         if (we_set_params) {
669                 win.add_button (Stock::OK, RESPONSE_CLOSE);
670         } else {
671                 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
672         }
673
674         win.set_default_response (RESPONSE_CLOSE);
675
676         win.show_all ();
677         win.set_position (Gtk::WIN_POS_CENTER);
678         pop_back_splash ();
679
680         /* we just don't care about the result, but we want to block */
681
682         win.run ();
683 }
684
685 void
686 ARDOUR_UI::startup ()
687 {
688         Application* app = Application::instance ();
689
690         app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
691         app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_load));
692
693 #ifdef PHONE_HOME
694         call_the_mothership (VERSIONSTRING);
695 #endif
696
697         app->ready ();
698
699         if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) {
700                 exit (1);
701         }
702
703         use_config ();
704
705         goto_editor_window ();
706
707         /* Add the window proxies here; their addition may cause windows to be opened, and we want them
708            to be opened on top of the editor window that goto_editor_window() just opened.
709         */
710         add_window_proxy (location_ui);
711         add_window_proxy (big_clock_window);
712         for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
713                 add_window_proxy (_global_port_matrix[*i]);
714         }
715
716         BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
717 }
718
719 void
720 ARDOUR_UI::no_memory_warning ()
721 {
722         XMLNode node (X_("no-memory-warning"));
723         Config->add_instant_xml (node);
724 }
725
726 void
727 ARDOUR_UI::check_memory_locking ()
728 {
729 #ifdef __APPLE__
730         /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
731         return;
732 #else // !__APPLE__
733
734         XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
735
736         if (engine->is_realtime() && memory_warning_node == 0) {
737
738                 struct rlimit limits;
739                 int64_t ram;
740                 long pages, page_size;
741
742                 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
743                         ram = 0;
744                 } else {
745                         ram = (int64_t) pages * (int64_t) page_size;
746                 }
747
748                 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
749                         return;
750                 }
751
752                 if (limits.rlim_cur != RLIM_INFINITY) {
753
754                         if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
755
756                                 MessageDialog msg (
757                                         string_compose (
758                                                 _("WARNING: Your system has a limit for maximum amount of locked memory. "
759                                                   "This might cause %1 to run out of memory before your system "
760                                                   "runs out of memory. \n\n"
761                                                   "You can view the memory limit with 'ulimit -l', "
762                                                   "and it is normally controlled by /etc/security/limits.conf"),
763                                                 PROGRAM_NAME).c_str());
764
765                                 VBox* vbox = msg.get_vbox();
766                                 HBox hbox;
767                                 CheckButton cb (_("Do not show this window again"));
768
769                                 cb.signal_toggled().connect (sigc::mem_fun (*this, &ARDOUR_UI::no_memory_warning));
770
771                                 hbox.pack_start (cb, true, false);
772                                 vbox->pack_start (hbox);
773                                 cb.show();
774                                 vbox->show();
775                                 hbox.show ();
776
777                                 pop_back_splash ();
778
779                                 editor->ensure_float (msg);
780                                 msg.run ();
781                         }
782                 }
783         }
784 #endif // !__APPLE__
785 }
786
787
788 void
789 ARDOUR_UI::queue_finish ()
790 {
791         Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::idle_finish));
792 }
793
794 bool
795 ARDOUR_UI::idle_finish ()
796 {
797         finish ();
798         return false; /* do not call again */
799 }
800
801 void
802 ARDOUR_UI::finish()
803 {
804         if (_session) {
805                 int tries = 0;
806
807                 if (_session->transport_rolling() && (++tries < 8)) {
808                         _session->request_stop (false, true);
809                         usleep (10000);
810                 }
811
812                 if (_session->dirty()) {
813                         vector<string> actions;
814                         actions.push_back (_("Don't quit"));
815                         actions.push_back (_("Just quit"));
816                         actions.push_back (_("Save and quit"));
817                         switch (ask_about_saving_session(actions)) {
818                         case -1:
819                                 return;
820                                 break;
821                         case 1:
822                                 /* use the default name */
823                                 if (save_state_canfail ("")) {
824                                         /* failed - don't quit */
825                                         MessageDialog msg (*editor,
826                                                            _("\
827 Ardour was unable to save your session.\n\n\
828 If you still wish to quit, please use the\n\n\
829 \"Just quit\" option."));
830                                         pop_back_splash();
831                                         msg.run ();
832                                         return;
833                                 }
834                                 break;
835                         case 0:
836                                 break;
837                         }
838                 }
839
840                 second_connection.disconnect ();
841                 point_one_second_connection.disconnect ();
842                 point_oh_five_second_connection.disconnect ();
843                 point_zero_one_second_connection.disconnect();
844         }
845
846         /* Save state before deleting the session, as that causes some
847            windows to be destroyed before their visible state can be
848            saved.
849         */
850         save_ardour_state ();
851
852         if (_session) {
853                 // _session->set_deletion_in_progress ();
854                 _session->set_clean ();
855                 _session->remove_pending_capture_state ();
856                 delete _session;
857                 _session = 0;
858         }
859
860         ArdourDialog::close_all_dialogs ();
861         engine->stop (true);
862         quit ();
863 }
864
865 int
866 ARDOUR_UI::ask_about_saving_session (const vector<string>& actions)
867 {
868         ArdourDialog window (_("Unsaved Session"));
869         Gtk::HBox dhbox;  // the hbox for the image and text
870         Gtk::Label  prompt_label;
871         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
872
873         string msg;
874
875         assert (actions.size() >= 3);
876
877         window.add_button (actions[0], RESPONSE_REJECT);
878         window.add_button (actions[1], RESPONSE_APPLY);
879         window.add_button (actions[2], RESPONSE_ACCEPT);
880
881         window.set_default_response (RESPONSE_ACCEPT);
882
883         Gtk::Button noquit_button (msg);
884         noquit_button.set_name ("EditorGTKButton");
885
886         string prompt;
887
888         if (_session->snap_name() == _session->name()) {
889                 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?"),
890                                         _session->snap_name());
891         } else {
892                 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?"),
893                                         _session->snap_name());
894         }
895
896         prompt_label.set_text (prompt);
897         prompt_label.set_name (X_("PrompterLabel"));
898         prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
899
900         dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
901         dhbox.set_homogeneous (false);
902         dhbox.pack_start (*dimage, false, false, 5);
903         dhbox.pack_start (prompt_label, true, false, 5);
904         window.get_vbox()->pack_start (dhbox);
905
906         window.set_name (_("Prompter"));
907         window.set_position (Gtk::WIN_POS_MOUSE);
908         window.set_modal (true);
909         window.set_resizable (false);
910
911         dhbox.show();
912         prompt_label.show();
913         dimage->show();
914         window.show();
915         window.set_keep_above (true);
916         window.present ();
917
918         ResponseType r = (ResponseType) window.run();
919
920         window.hide ();
921
922         switch (r) {
923         case RESPONSE_ACCEPT: // save and get out of here
924                 return 1;
925         case RESPONSE_APPLY:  // get out of here
926                 return 0;
927         default:
928                 break;
929         }
930
931         return -1;
932 }
933
934 gint
935 ARDOUR_UI::every_second ()
936 {
937         update_cpu_load ();
938         update_buffer_load ();
939         update_disk_space ();
940         return TRUE;
941 }
942
943 gint
944 ARDOUR_UI::every_point_one_seconds ()
945 {
946         shuttle_box->update_speed_display ();
947         RapidScreenUpdate(); /* EMIT_SIGNAL */
948         return TRUE;
949 }
950
951 gint
952 ARDOUR_UI::every_point_zero_one_seconds ()
953 {
954         // august 2007: actual update frequency: 40Hz, not 100Hz
955
956         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
957         return TRUE;
958 }
959
960 void
961 ARDOUR_UI::update_sample_rate (framecnt_t)
962 {
963         char buf[32];
964
965         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
966
967         if (!engine->connected()) {
968
969                 snprintf (buf, sizeof (buf), _("disconnected"));
970
971         } else {
972
973                 framecnt_t rate = engine->frame_rate();
974
975                 if (fmod (rate, 1000.0) != 0.0) {
976                         snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
977                                   (float) rate/1000.0f,
978                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
979                 } else {
980                         snprintf (buf, sizeof (buf), _("%" PRId64 " kHz / %4.1f ms"),
981                                   rate/1000,
982                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
983                 }
984         }
985
986         sample_rate_label.set_text (buf);
987 }
988
989 void
990 ARDOUR_UI::update_cpu_load ()
991 {
992         char buf[32];
993         snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
994         cpu_load_label.set_text (buf);
995 }
996
997 void
998 ARDOUR_UI::update_buffer_load ()
999 {
1000         char buf[64];
1001         uint32_t c, p;
1002
1003         if (_session) {
1004                 c = _session->capture_load ();
1005                 p = _session->playback_load ();
1006
1007                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
1008                           _session->playback_load(), _session->capture_load());
1009                 buffer_load_label.set_text (buf);
1010         } else {
1011                 buffer_load_label.set_text ("");
1012         }
1013 }
1014
1015 void
1016 ARDOUR_UI::count_recenabled_streams (Route& route)
1017 {
1018         Track* track = dynamic_cast<Track*>(&route);
1019         if (track && track->record_enabled()) {
1020                 rec_enabled_streams += track->n_inputs().n_total();
1021         }
1022 }
1023
1024 void
1025 ARDOUR_UI::update_disk_space()
1026 {
1027         if (_session == 0) {
1028                 return;
1029         }
1030
1031         framecnt_t frames = _session->available_capture_duration();
1032         char buf[64];
1033         framecnt_t fr = _session->frame_rate();
1034
1035         if (frames == max_framecnt) {
1036                 strcpy (buf, _("Disk: 24hrs+"));
1037         } else {
1038                 rec_enabled_streams = 0;
1039                 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
1040
1041                 if (rec_enabled_streams) {
1042                         frames /= rec_enabled_streams;
1043                 }
1044
1045                 int hrs;
1046                 int mins;
1047                 int secs;
1048
1049                 hrs  = frames / (fr * 3600);
1050                 frames -= hrs * fr * 3600;
1051                 mins = frames / (fr * 60);
1052                 frames -= mins * fr * 60;
1053                 secs = frames / fr;
1054
1055                 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
1056         }
1057
1058         disk_space_label.set_text (buf);
1059
1060         // An attempt to make the disk space label flash red when space has run out.
1061
1062         if (frames < fr * 60 * 5) {
1063         /*      disk_space_box.style ("disk_space_label_empty"); */
1064         } else {
1065         /*      disk_space_box.style ("disk_space_label"); */
1066         }
1067
1068 }
1069
1070 gint
1071 ARDOUR_UI::update_wall_clock ()
1072 {
1073         time_t now;
1074         struct tm *tm_now;
1075         char buf[16];
1076
1077         time (&now);
1078         tm_now = localtime (&now);
1079
1080         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1081         wall_clock_label.set_text (buf);
1082
1083         return TRUE;
1084 }
1085
1086 gint
1087 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1088 {
1089         session_popup_menu->popup (0, 0);
1090         return TRUE;
1091 }
1092
1093 void
1094 ARDOUR_UI::redisplay_recent_sessions ()
1095 {
1096         std::vector<sys::path> session_directories;
1097         RecentSessionsSorter cmp;
1098
1099         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1100         recent_session_model->clear ();
1101
1102         ARDOUR::RecentSessions rs;
1103         ARDOUR::read_recent_sessions (rs);
1104
1105         if (rs.empty()) {
1106                 recent_session_display.set_model (recent_session_model);
1107                 return;
1108         }
1109         //
1110         // sort them alphabetically
1111         sort (rs.begin(), rs.end(), cmp);
1112
1113         for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1114                 session_directories.push_back ((*i).second);
1115         }
1116
1117         for (vector<sys::path>::const_iterator i = session_directories.begin();
1118                         i != session_directories.end(); ++i)
1119         {
1120                 std::vector<sys::path> state_file_paths;
1121
1122                 // now get available states for this session
1123
1124                 get_state_files_in_directory (*i, state_file_paths);
1125
1126                 vector<string*>* states;
1127                 vector<const gchar*> item;
1128                 string fullpath = (*i).to_string();
1129
1130                 /* remove any trailing / */
1131
1132                 if (fullpath[fullpath.length()-1] == '/') {
1133                         fullpath = fullpath.substr (0, fullpath.length()-1);
1134                 }
1135
1136                 /* check whether session still exists */
1137                 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1138                         /* session doesn't exist */
1139                         cerr << "skipping non-existent session " << fullpath << endl;
1140                         continue;
1141                 }
1142
1143                 /* now get available states for this session */
1144
1145                 if ((states = Session::possible_states (fullpath)) == 0) {
1146                         /* no state file? */
1147                         continue;
1148                 }
1149
1150                 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1151
1152                 Gtk::TreeModel::Row row = *(recent_session_model->append());
1153
1154                 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1155                 row[recent_session_columns.fullpath] = fullpath;
1156
1157                 if (state_file_names.size() > 1) {
1158
1159                         // add the children
1160
1161                         for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1162                                         i2 != state_file_names.end(); ++i2)
1163                         {
1164
1165                                 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1166
1167                                 child_row[recent_session_columns.visible_name] = *i2;
1168                                 child_row[recent_session_columns.fullpath] = fullpath;
1169                         }
1170                 }
1171         }
1172
1173         recent_session_display.set_model (recent_session_model);
1174 }
1175
1176 void
1177 ARDOUR_UI::build_session_selector ()
1178 {
1179         session_selector_window = new ArdourDialog (_("Recent Sessions"));
1180
1181         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1182
1183         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1184         session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1185         session_selector_window->set_default_response (RESPONSE_ACCEPT);
1186         recent_session_model = TreeStore::create (recent_session_columns);
1187         recent_session_display.set_model (recent_session_model);
1188         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1189         recent_session_display.set_headers_visible (false);
1190         recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1191         recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1192
1193         scroller->add (recent_session_display);
1194         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1195
1196         session_selector_window->set_name ("SessionSelectorWindow");
1197         session_selector_window->set_size_request (200, 400);
1198         session_selector_window->get_vbox()->pack_start (*scroller);
1199
1200         recent_session_display.show();
1201         scroller->show();
1202         //session_selector_window->get_vbox()->show();
1203 }
1204
1205 void
1206 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1207 {
1208         session_selector_window->response (RESPONSE_ACCEPT);
1209 }
1210
1211 void
1212 ARDOUR_UI::open_recent_session ()
1213 {
1214         bool can_return = (_session != 0);
1215
1216         if (session_selector_window == 0) {
1217                 build_session_selector ();
1218         }
1219
1220         redisplay_recent_sessions ();
1221
1222         while (true) {
1223
1224                 session_selector_window->set_position (WIN_POS_MOUSE);
1225
1226                 ResponseType r = (ResponseType) session_selector_window->run ();
1227
1228                 switch (r) {
1229                 case RESPONSE_ACCEPT:
1230                         break;
1231                 default:
1232                         if (can_return) {
1233                                 session_selector_window->hide();
1234                                 return;
1235                         } else {
1236                                 exit (1);
1237                         }
1238                 }
1239
1240                 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1241                         continue;
1242                 }
1243
1244                 session_selector_window->hide();
1245
1246                 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1247
1248                 if (i == recent_session_model->children().end()) {
1249                         return;
1250                 }
1251
1252                 std::string path = (*i)[recent_session_columns.fullpath];
1253                 std::string state = (*i)[recent_session_columns.visible_name];
1254
1255                 _session_is_new = false;
1256
1257                 if (load_session (path, state) == 0) {
1258                         break;
1259                 }
1260
1261                 can_return = false;
1262         }
1263 }
1264
1265 bool
1266 ARDOUR_UI::check_audioengine ()
1267 {
1268         if (engine) {
1269                 if (!engine->connected()) {
1270                         MessageDialog msg (string_compose (
1271                                                    _("%1 is not connected to JACK\n"
1272                                                      "You cannot open or close sessions in this condition"),
1273                                                    PROGRAM_NAME));
1274                         pop_back_splash ();
1275                         msg.run ();
1276                         return false;
1277                 }
1278                 return true;
1279         } else {
1280                 return false;
1281         }
1282 }
1283
1284 void
1285 ARDOUR_UI::open_session ()
1286 {
1287         if (!check_audioengine()) {
1288                 return;
1289
1290         }
1291
1292         /* popup selector window */
1293
1294         if (open_session_selector == 0) {
1295
1296                 /* ardour sessions are folders */
1297
1298                 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1299                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1300                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1301                 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1302
1303                 FileFilter session_filter;
1304                 session_filter.add_pattern ("*.ardour");
1305                 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1306                 open_session_selector->add_filter (session_filter);
1307                 open_session_selector->set_filter (session_filter);
1308         }
1309
1310         int response = open_session_selector->run();
1311         open_session_selector->hide ();
1312
1313         switch (response) {
1314         case RESPONSE_ACCEPT:
1315                 break;
1316         default:
1317                 open_session_selector->hide();
1318                 return;
1319         }
1320
1321         open_session_selector->hide();
1322         string session_path = open_session_selector->get_filename();
1323         string path, name;
1324         bool isnew;
1325
1326         if (session_path.length() > 0) {
1327                 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1328                         _session_is_new = isnew;
1329                         load_session (path, name);
1330                 }
1331         }
1332 }
1333
1334
1335 void
1336 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many, string const & name_template)
1337 {
1338         list<boost::shared_ptr<MidiTrack> > tracks;
1339
1340         if (_session == 0) {
1341                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1342                 return;
1343         }
1344
1345         try {
1346                 if (disk) {
1347
1348                         tracks = _session->new_midi_track (ARDOUR::Normal, route_group, how_many, name_template);
1349
1350                         if (tracks.size() != how_many) {
1351                                 if (how_many == 1) {
1352                                         error << _("could not create a new midi track") << endmsg;
1353                                 } else {
1354                                         error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1355                                 }
1356                         }
1357                 } /*else {
1358                         if ((route = _session->new_midi_route ()) == 0) {
1359                                 error << _("could not create new midi bus") << endmsg;
1360                         }
1361                 }*/
1362         }
1363
1364         catch (...) {
1365                 MessageDialog msg (*editor,
1366                                    string_compose (_("There are insufficient JACK ports available\n\
1367 to create a new track or bus.\n\
1368 You should save %1, exit and\n\
1369 restart JACK with more ports."), PROGRAM_NAME));
1370                 msg.run ();
1371         }
1372 }
1373
1374
1375 void
1376 ARDOUR_UI::session_add_audio_route (
1377         bool track,
1378         int32_t input_channels,
1379         int32_t output_channels,
1380         ARDOUR::TrackMode mode,
1381         RouteGroup* route_group,
1382         uint32_t how_many,
1383         string const & name_template
1384         )
1385 {
1386         list<boost::shared_ptr<AudioTrack> > tracks;
1387         RouteList routes;
1388
1389         if (_session == 0) {
1390                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1391                 return;
1392         }
1393
1394         try {
1395                 if (track) {
1396                         tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many, name_template);
1397
1398                         if (tracks.size() != how_many) {
1399                                 if (how_many == 1) {
1400                                         error << _("could not create a new audio track") << endmsg;
1401                                 } else {
1402                                         error << string_compose (_("could only create %1 of %2 new audio %3"),
1403                                                                  tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1404                                 }
1405                         }
1406
1407                 } else {
1408
1409                         routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template);
1410
1411                         if (routes.size() != how_many) {
1412                                 if (how_many == 1) {
1413                                         error << _("could not create a new audio track") << endmsg;
1414                                 } else {
1415                                         error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1416                                 }
1417                         }
1418                 }
1419         }
1420
1421         catch (...) {
1422                 MessageDialog msg (*editor,
1423                                    string_compose (_("There are insufficient JACK ports available\n\
1424 to create a new track or bus.\n\
1425 You should save %1, exit and\n\
1426 restart JACK with more ports."), PROGRAM_NAME));
1427                 pop_back_splash ();
1428                 msg.run ();
1429         }
1430 }
1431
1432 void
1433 ARDOUR_UI::do_transport_locate (framepos_t new_position, bool with_roll)
1434 {
1435         framecnt_t _preroll = 0;
1436
1437         if (_session) {
1438                 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1439                 // _preroll = _session->convert_to_frames_at (new_position, Config->get_preroll());
1440
1441                 if (new_position > _preroll) {
1442                         new_position -= _preroll;
1443                 } else {
1444                         new_position = 0;
1445                 }
1446
1447                 _session->request_locate (new_position, with_roll);
1448         }
1449 }
1450
1451 void
1452 ARDOUR_UI::transport_goto_start ()
1453 {
1454         if (_session) {
1455                 _session->goto_start();
1456
1457                 /* force displayed area in editor to start no matter
1458                    what "follow playhead" setting is.
1459                 */
1460
1461                 if (editor) {
1462                         editor->center_screen (_session->current_start_frame ());
1463                 }
1464         }
1465 }
1466
1467 void
1468 ARDOUR_UI::transport_goto_zero ()
1469 {
1470         if (_session) {
1471                 _session->request_locate (0);
1472
1473                 /* force displayed area in editor to start no matter
1474                    what "follow playhead" setting is.
1475                 */
1476
1477                 if (editor) {
1478                         editor->reset_x_origin (0);
1479                 }
1480         }
1481 }
1482
1483 void
1484 ARDOUR_UI::transport_goto_wallclock ()
1485 {
1486         if (_session && editor) {
1487
1488                 time_t now;
1489                 struct tm tmnow;
1490                 framepos_t frames;
1491
1492                 time (&now);
1493                 localtime_r (&now, &tmnow);
1494
1495                 frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate());
1496                 frames += tmnow.tm_min * (60 * _session->frame_rate());
1497                 frames += tmnow.tm_sec * _session->frame_rate();
1498
1499                 _session->request_locate (frames, _session->transport_rolling ());
1500
1501                 /* force displayed area in editor to start no matter
1502                    what "follow playhead" setting is.
1503                 */
1504
1505                 if (editor) {
1506                         editor->center_screen (frames);
1507                 }
1508         }
1509 }
1510
1511 void
1512 ARDOUR_UI::transport_goto_end ()
1513 {
1514         if (_session) {
1515                 framepos_t const frame = _session->current_end_frame();
1516                 _session->request_locate (frame);
1517
1518                 /* force displayed area in editor to start no matter
1519                    what "follow playhead" setting is.
1520                 */
1521
1522                 if (editor) {
1523                         editor->center_screen (frame);
1524                 }
1525         }
1526 }
1527
1528 void
1529 ARDOUR_UI::transport_stop ()
1530 {
1531         if (!_session) {
1532                 return;
1533         }
1534
1535         if (_session->is_auditioning()) {
1536                 _session->cancel_audition ();
1537                 return;
1538         }
1539
1540         _session->request_stop (false, true);
1541 }
1542
1543 void
1544 ARDOUR_UI::transport_stop_and_forget_capture ()
1545 {
1546         if (_session) {
1547                 _session->request_stop (true, true);
1548         }
1549 }
1550
1551 void
1552 ARDOUR_UI::remove_last_capture()
1553 {
1554         if (editor) {
1555                 editor->remove_last_capture();
1556         }
1557 }
1558
1559 void
1560 ARDOUR_UI::transport_record (bool roll)
1561 {
1562
1563         if (_session) {
1564                 switch (_session->record_status()) {
1565                 case Session::Disabled:
1566                         if (_session->ntracks() == 0) {
1567                                 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1568                                 msg.run ();
1569                                 return;
1570                         }
1571                         _session->maybe_enable_record ();
1572                         if (roll) {
1573                                 transport_roll ();
1574                         }
1575                         break;
1576                 case Session::Recording:
1577                         if (roll) {
1578                                 _session->request_stop();
1579                         } else {
1580                                 _session->disable_record (false, true);
1581                         }
1582                         break;
1583
1584                 case Session::Enabled:
1585                         _session->disable_record (false, true);
1586                 }
1587         }
1588         //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " _session->record_status() = " << _session->record_status() << endl;
1589 }
1590
1591 void
1592 ARDOUR_UI::transport_roll ()
1593 {
1594         if (!_session) {
1595                 return;
1596         }
1597
1598         if (_session->is_auditioning()) {
1599                 return;
1600         }
1601
1602 #if 0
1603         if (_session->config.get_external_sync()) {
1604                 switch (_session->config.get_sync_source()) {
1605                 case JACK:
1606                         break;
1607                 default:
1608                         /* transport controlled by the master */
1609                         return;
1610                 }
1611         }
1612 #endif
1613
1614         bool rolling = _session->transport_rolling();
1615
1616         if (_session->get_play_loop()) {
1617                 /* XXX it is not possible to just leave seamless loop and keep
1618                    playing at present (nov 4th 2009)
1619                 */
1620                 if (!Config->get_seamless_loop()) {
1621                         _session->request_play_loop (false, true);
1622                 }
1623         } else if (_session->get_play_range () && !join_play_range_button.get_active()) {
1624                 /* stop playing a range if we currently are */
1625                 _session->request_play_range (0, true);
1626         }
1627
1628         if (join_play_range_button.get_active()) {
1629                 _session->request_play_range (&editor->get_selection().time, true);
1630         }
1631
1632         if (!rolling) {
1633                 _session->request_transport_speed (1.0f);
1634         }
1635 }
1636
1637 void
1638 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1639 {
1640
1641         if (!_session) {
1642                 return;
1643         }
1644
1645         if (_session->is_auditioning()) {
1646                 _session->cancel_audition ();
1647                 return;
1648         }
1649
1650         if (_session->config.get_external_sync()) {
1651                 switch (_session->config.get_sync_source()) {
1652                 case JACK:
1653                         break;
1654                 default:
1655                         /* transport controlled by the master */
1656                         return;
1657                 }
1658         }
1659
1660         bool rolling = _session->transport_rolling();
1661         bool affect_transport = true;
1662
1663         if (rolling && roll_out_of_bounded_mode) {
1664                 /* drop out of loop/range playback but leave transport rolling */
1665                 if (_session->get_play_loop()) {
1666                         if (Config->get_seamless_loop()) {
1667                                 /* the disk buffers contain copies of the loop - we can't
1668                                    just keep playing, so stop the transport. the user
1669                                    can restart as they wish.
1670                                 */
1671                                 affect_transport = true;
1672                         } else {
1673                                 /* disk buffers are normal, so we can keep playing */
1674                                 affect_transport = false;
1675                         }
1676                         _session->request_play_loop (false, true);
1677                 } else if (_session->get_play_range ()) {
1678                         affect_transport = false;
1679                         _session->request_play_range (0, true);
1680                 }
1681         }
1682
1683         if (affect_transport) {
1684                 if (rolling) {
1685                         _session->request_stop (with_abort, true);
1686                 } else {
1687                         if (join_play_range_button.get_active()) {
1688                                 _session->request_play_range (&editor->get_selection().time, true);
1689                         }
1690
1691                         _session->request_transport_speed (1.0f);
1692                 }
1693         }
1694 }
1695
1696 void
1697 ARDOUR_UI::toggle_session_auto_loop ()
1698 {
1699         if (!_session) {
1700                 return;
1701         }
1702
1703         if (_session->get_play_loop()) {
1704
1705                 if (_session->transport_rolling()) {
1706
1707                         Location * looploc = _session->locations()->auto_loop_location();
1708
1709                         if (looploc) {
1710                                 _session->request_locate (looploc->start(), true);
1711                                 _session->request_play_loop (false);
1712                         }
1713
1714                 } else {
1715                         _session->request_play_loop (false);
1716                 }
1717         } else {
1718
1719           Location * looploc = _session->locations()->auto_loop_location();
1720
1721                 if (looploc) {
1722                         _session->request_play_loop (true);
1723                 }
1724         }
1725 }
1726
1727 void
1728 ARDOUR_UI::transport_play_selection ()
1729 {
1730         if (!_session) {
1731                 return;
1732         }
1733
1734         editor->play_selection ();
1735 }
1736
1737 void
1738 ARDOUR_UI::transport_rewind (int option)
1739 {
1740         float current_transport_speed;
1741
1742         if (_session) {
1743                 current_transport_speed = _session->transport_speed();
1744
1745                 if (current_transport_speed >= 0.0f) {
1746                         switch (option) {
1747                         case 0:
1748                                 _session->request_transport_speed (-1.0f);
1749                                 break;
1750                         case 1:
1751                                 _session->request_transport_speed (-4.0f);
1752                                 break;
1753                         case -1:
1754                                 _session->request_transport_speed (-0.5f);
1755                                 break;
1756                         }
1757                 } else {
1758                         /* speed up */
1759                         _session->request_transport_speed (current_transport_speed * 1.5f);
1760                 }
1761         }
1762 }
1763
1764 void
1765 ARDOUR_UI::transport_forward (int option)
1766 {
1767         float current_transport_speed;
1768
1769         if (_session) {
1770                 current_transport_speed = _session->transport_speed();
1771
1772                 if (current_transport_speed <= 0.0f) {
1773                         switch (option) {
1774                         case 0:
1775                                 _session->request_transport_speed (1.0f);
1776                                 break;
1777                         case 1:
1778                                 _session->request_transport_speed (4.0f);
1779                                 break;
1780                         case -1:
1781                                 _session->request_transport_speed (0.5f);
1782                                 break;
1783                         }
1784                 } else {
1785                         /* speed up */
1786                         _session->request_transport_speed (current_transport_speed * 1.5f);
1787                 }
1788
1789         }
1790 }
1791
1792 void
1793 ARDOUR_UI::toggle_record_enable (uint32_t rid)
1794 {
1795         if (_session == 0) {
1796                 return;
1797         }
1798
1799         boost::shared_ptr<Route> r;
1800
1801         if ((r = _session->route_by_remote_id (rid)) != 0) {
1802
1803                 Track* t;
1804
1805                 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1806                         t->set_record_enabled (!t->record_enabled(), this);
1807                 }
1808         }
1809         if (_session == 0) {
1810                 return;
1811         }
1812 }
1813
1814 void
1815 ARDOUR_UI::map_transport_state ()
1816 {
1817         if (!_session) {
1818                 auto_loop_button.set_visual_state (0);
1819                 play_selection_button.set_visual_state (0);
1820                 roll_button.set_visual_state (0);
1821                 stop_button.set_visual_state (1);
1822                 return;
1823         }
1824
1825         shuttle_box->map_transport_state ();
1826
1827         float sp = _session->transport_speed();
1828
1829         if (sp != 0.0f) {
1830
1831                 /* we're rolling */
1832
1833                 if (_session->get_play_range()) {
1834
1835                         play_selection_button.set_visual_state (1);
1836                         roll_button.set_visual_state (0);
1837                         auto_loop_button.set_visual_state (0);
1838
1839                 } else if (_session->get_play_loop ()) {
1840
1841                         auto_loop_button.set_visual_state (1);
1842                         play_selection_button.set_visual_state (0);
1843                         roll_button.set_visual_state (0);
1844
1845                 } else {
1846
1847                         roll_button.set_visual_state (1);
1848                         play_selection_button.set_visual_state (0);
1849                         auto_loop_button.set_visual_state (0);
1850                 }
1851
1852                 if (join_play_range_button.get_active()) {
1853                         /* light up both roll and play-selection if they are joined */
1854                         roll_button.set_visual_state (1);
1855                         play_selection_button.set_visual_state (1);
1856                 }
1857
1858                 stop_button.set_visual_state (0);
1859
1860         } else {
1861
1862                 stop_button.set_visual_state (1);
1863                 roll_button.set_visual_state (0);
1864                 play_selection_button.set_visual_state (0);
1865                 auto_loop_button.set_visual_state (0);
1866                 update_disk_space ();
1867         }
1868 }
1869
1870 void
1871 ARDOUR_UI::engine_stopped ()
1872 {
1873         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
1874         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1875         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1876 }
1877
1878 void
1879 ARDOUR_UI::engine_running ()
1880 {
1881         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
1882         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1883         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1884
1885         Glib::RefPtr<Action> action;
1886         const char* action_name = 0;
1887
1888         switch (engine->frames_per_cycle()) {
1889         case 32:
1890                 action_name = X_("JACKLatency32");
1891                 break;
1892         case 64:
1893                 action_name = X_("JACKLatency64");
1894                 break;
1895         case 128:
1896                 action_name = X_("JACKLatency128");
1897                 break;
1898         case 512:
1899                 action_name = X_("JACKLatency512");
1900                 break;
1901         case 1024:
1902                 action_name = X_("JACKLatency1024");
1903                 break;
1904         case 2048:
1905                 action_name = X_("JACKLatency2048");
1906                 break;
1907         case 4096:
1908                 action_name = X_("JACKLatency4096");
1909                 break;
1910         case 8192:
1911                 action_name = X_("JACKLatency8192");
1912                 break;
1913         default:
1914                 /* XXX can we do anything useful ? */
1915                 break;
1916         }
1917
1918         if (action_name) {
1919
1920                 action = ActionManager::get_action (X_("JACK"), action_name);
1921
1922                 if (action) {
1923                         Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1924                         ract->set_active ();
1925                 }
1926         }
1927 }
1928
1929 void
1930 ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
1931 {
1932         if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
1933                 /* we can't rely on the original string continuing to exist when we are called
1934                    again in the GUI thread, so make a copy and note that we need to
1935                    free it later.
1936                 */
1937                 char *copy = strdup (reason);
1938                 Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
1939                 return;
1940         }
1941
1942         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1943         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1944
1945         update_sample_rate (0);
1946
1947         string msgstr;
1948
1949         /* if the reason is a non-empty string, it means that the backend was shutdown
1950            rather than just Ardour.
1951         */
1952
1953         if (strlen (reason)) {
1954                 msgstr = string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason);
1955         } else {
1956                 msgstr = string_compose (_("\
1957 JACK has either been shutdown or it\n\
1958 disconnected %1 because %1\n\
1959 was not fast enough. Try to restart\n\
1960 JACK, reconnect and save the session."), PROGRAM_NAME);
1961         }
1962
1963         MessageDialog msg (*editor, msgstr);
1964         pop_back_splash ();
1965         msg.run ();
1966
1967         if (free_reason) {
1968                 free ((char*) reason);
1969         }
1970 }
1971
1972 int32_t
1973 ARDOUR_UI::do_engine_start ()
1974 {
1975         try {
1976                 engine->start();
1977         }
1978
1979         catch (...) {
1980                 engine->stop ();
1981                 error << _("Unable to start the session running")
1982                       << endmsg;
1983                 unload_session ();
1984                 return -2;
1985         }
1986
1987         return 0;
1988 }
1989
1990 void
1991 ARDOUR_UI::setup_theme ()
1992 {
1993         theme_manager->setup_theme();
1994 }
1995
1996 void
1997 ARDOUR_UI::update_clocks ()
1998 {
1999         if (!editor || !editor->dragging_playhead()) {
2000                 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
2001         }
2002 }
2003
2004 void
2005 ARDOUR_UI::start_clocking ()
2006 {
2007         clock_signal_connection = RapidScreenUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2008 }
2009
2010 void
2011 ARDOUR_UI::stop_clocking ()
2012 {
2013         clock_signal_connection.disconnect ();
2014 }
2015
2016 void
2017 ARDOUR_UI::toggle_clocking ()
2018 {
2019 #if 0
2020         if (clock_button.get_active()) {
2021                 start_clocking ();
2022         } else {
2023                 stop_clocking ();
2024         }
2025 #endif
2026 }
2027
2028 gint
2029 ARDOUR_UI::_blink (void *arg)
2030
2031 {
2032         ((ARDOUR_UI *) arg)->blink ();
2033         return TRUE;
2034 }
2035
2036 void
2037 ARDOUR_UI::blink ()
2038 {
2039         Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2040 }
2041
2042 void
2043 ARDOUR_UI::start_blinking ()
2044 {
2045         /* Start the blink signal. Everybody with a blinking widget
2046            uses Blink to drive the widget's state.
2047         */
2048
2049         if (blink_timeout_tag < 0) {
2050                 blink_on = false;
2051                 blink_timeout_tag = g_timeout_add (240, _blink, this);
2052         }
2053 }
2054
2055 void
2056 ARDOUR_UI::stop_blinking ()
2057 {
2058         if (blink_timeout_tag >= 0) {
2059                 g_source_remove (blink_timeout_tag);
2060                 blink_timeout_tag = -1;
2061         }
2062 }
2063
2064
2065 /** Ask the user for the name of a new shapshot and then take it.
2066  */
2067
2068 void
2069 ARDOUR_UI::snapshot_session (bool switch_to_it)
2070 {
2071         ArdourPrompter prompter (true);
2072         string snapname;
2073
2074         prompter.set_name ("Prompter");
2075         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2076         prompter.set_title (_("Take Snapshot"));
2077         prompter.set_title (_("Take Snapshot"));
2078         prompter.set_prompt (_("Name of new snapshot"));
2079
2080         if (!switch_to_it) {
2081                 char timebuf[128];
2082                 time_t n;
2083                 struct tm local_time;
2084
2085                 time (&n);
2086                 localtime_r (&n, &local_time);
2087                 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
2088                 prompter.set_initial_text (timebuf);
2089         }
2090
2091   again:
2092         switch (prompter.run()) {
2093         case RESPONSE_ACCEPT:
2094         {
2095                 prompter.get_result (snapname);
2096
2097                 bool do_save = (snapname.length() != 0);
2098
2099                 if (do_save) {
2100                         if (snapname.find ('/') != string::npos) {
2101                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
2102                                                      "snapshot names may not contain a '/' character"));
2103                                 msg.run ();
2104                                 goto again;
2105                         }
2106                         if (snapname.find ('\\') != string::npos) {
2107                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
2108                                                      "snapshot names may not contain a '\\' character"));
2109                                 msg.run ();
2110                                 goto again;
2111                         }
2112                 }
2113
2114                 vector<sys::path> p;
2115                 get_state_files_in_directory (_session->session_directory().root_path(), p);
2116                 vector<string> n = get_file_names_no_extension (p);
2117                 if (find (n.begin(), n.end(), snapname) != n.end()) {
2118
2119                         ArdourDialog confirm (_("Confirm Snapshot Overwrite"), true);
2120                         Label m (_("A snapshot already exists with that name.  Do you want to overwrite it?"));
2121                         confirm.get_vbox()->pack_start (m, true, true);
2122                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
2123                         confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
2124                         confirm.show_all ();
2125                         switch (confirm.run()) {
2126                         case RESPONSE_CANCEL:
2127                                 do_save = false;
2128                         }
2129                 }
2130
2131                 if (do_save) {
2132                         save_state (snapname, switch_to_it);
2133                 }
2134                 break;
2135         }
2136
2137         default:
2138                 break;
2139         }
2140 }
2141
2142 void
2143 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2144 {
2145         XMLNode* node = new XMLNode (X_("UI"));
2146
2147         for (list<WindowProxyBase*>::iterator i = _window_proxies.begin(); i != _window_proxies.end(); ++i) {
2148                 if (!(*i)->rc_configured()) {
2149                         node->add_child_nocopy (*((*i)->get_state ()));
2150                 }
2151         }
2152
2153         _session->add_extra_xml (*node);
2154
2155         save_state_canfail (name, switch_to_it);
2156 }
2157
2158 int
2159 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2160 {
2161         if (_session) {
2162                 int ret;
2163
2164                 if (name.length() == 0) {
2165                         name = _session->snap_name();
2166                 }
2167
2168                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2169                         return ret;
2170                 }
2171         }
2172
2173         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2174         return 0;
2175 }
2176
2177 void
2178 ARDOUR_UI::primary_clock_value_changed ()
2179 {
2180         if (_session) {
2181                 _session->request_locate (primary_clock->current_time ());
2182         }
2183 }
2184
2185 void
2186 ARDOUR_UI::big_clock_value_changed ()
2187 {
2188         if (_session) {
2189                 _session->request_locate (big_clock->current_time ());
2190         }
2191 }
2192
2193 void
2194 ARDOUR_UI::secondary_clock_value_changed ()
2195 {
2196         if (_session) {
2197                 _session->request_locate (secondary_clock->current_time ());
2198         }
2199 }
2200
2201 void
2202 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2203 {
2204         if (_session == 0) {
2205                 return;
2206         }
2207
2208         if (_session->step_editing()) {
2209                 return;
2210         }
2211
2212         Session::RecordState const r = _session->record_status ();
2213         bool const h = _session->have_rec_enabled_track ();
2214
2215         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2216                 if (onoff) {
2217                         rec_button.set_visual_state (2);
2218                 } else {
2219                         rec_button.set_visual_state (0);
2220                 }
2221         } else if (r == Session::Recording && h) {
2222                 rec_button.set_visual_state (1);
2223         } else {
2224                 rec_button.set_visual_state (0);
2225         }
2226 }
2227
2228 void
2229 ARDOUR_UI::save_template ()
2230 {
2231         ArdourPrompter prompter (true);
2232         string name;
2233
2234         if (!check_audioengine()) {
2235                 return;
2236         }
2237
2238         prompter.set_name (X_("Prompter"));
2239         prompter.set_title (_("Save Template"));
2240         prompter.set_prompt (_("Name for template:"));
2241         prompter.set_initial_text(_session->name() + _("-template"));
2242         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2243
2244         switch (prompter.run()) {
2245         case RESPONSE_ACCEPT:
2246                 prompter.get_result (name);
2247
2248                 if (name.length()) {
2249                         _session->save_template (name);
2250                 }
2251                 break;
2252
2253         default:
2254                 break;
2255         }
2256 }
2257
2258 void
2259 ARDOUR_UI::edit_metadata ()
2260 {
2261         SessionMetadataEditor dialog;
2262         dialog.set_session (_session);
2263         editor->ensure_float (dialog);
2264         dialog.run ();
2265 }
2266
2267 void
2268 ARDOUR_UI::import_metadata ()
2269 {
2270         SessionMetadataImporter dialog;
2271         dialog.set_session (_session);
2272         editor->ensure_float (dialog);
2273         dialog.run ();
2274 }
2275
2276 bool
2277 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
2278 {
2279         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2280
2281         MessageDialog msg (str,
2282                            false,
2283                            Gtk::MESSAGE_WARNING,
2284                            Gtk::BUTTONS_YES_NO,
2285                            true);
2286
2287
2288         msg.set_name (X_("OpenExistingDialog"));
2289         msg.set_title (_("Open Existing Session"));
2290         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
2291         msg.set_position (Gtk::WIN_POS_MOUSE);
2292         pop_back_splash ();
2293
2294         switch (msg.run()) {
2295         case RESPONSE_YES:
2296                 return true;
2297                 break;
2298         }
2299         return false;
2300 }
2301
2302 int
2303 ARDOUR_UI::build_session_from_nsd (const std::string& session_path, const std::string& session_name)
2304 {
2305         BusProfile bus_profile;
2306
2307         if (Profile->get_sae()) {
2308
2309                 bus_profile.master_out_channels = 2;
2310                 bus_profile.input_ac = AutoConnectPhysical;
2311                 bus_profile.output_ac = AutoConnectMaster;
2312                 bus_profile.requested_physical_in = 0; // use all available
2313                 bus_profile.requested_physical_out = 0; // use all available
2314
2315         } else {
2316
2317                 /* get settings from advanced section of NSD */
2318
2319                 if (_startup->create_master_bus()) {
2320                         bus_profile.master_out_channels = (uint32_t) _startup->master_channel_count();
2321                 } else {
2322                         bus_profile.master_out_channels = 0;
2323                 }
2324
2325                 if (_startup->connect_inputs()) {
2326                         bus_profile.input_ac = AutoConnectPhysical;
2327                 } else {
2328                         bus_profile.input_ac = AutoConnectOption (0);
2329                 }
2330
2331                 /// @todo some minor tweaks.
2332
2333                 bus_profile.output_ac = AutoConnectOption (0);
2334
2335                 if (_startup->connect_outputs ()) {
2336                         if (_startup->connect_outs_to_master()) {
2337                                 bus_profile.output_ac = AutoConnectMaster;
2338                         } else if (_startup->connect_outs_to_physical()) {
2339                                 bus_profile.output_ac = AutoConnectPhysical;
2340                         }
2341                 }
2342
2343                 bus_profile.requested_physical_in = (uint32_t) _startup->input_limit_count();
2344                 bus_profile.requested_physical_out = (uint32_t) _startup->output_limit_count();
2345         }
2346
2347         if (build_session (session_path, session_name, bus_profile)) {
2348                 return -1;
2349         }
2350
2351         return 0;
2352 }
2353
2354 void
2355 ARDOUR_UI::idle_load (const std::string& path)
2356 {
2357         if (_session) {
2358                 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2359                         /* /path/to/foo => /path/to/foo, foo */
2360                         load_session (path, basename_nosuffix (path));
2361                 } else {
2362                         /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2363                         load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2364                 }
2365         } else {
2366
2367                 ARDOUR_COMMAND_LINE::session_name = path;
2368
2369                 /*
2370                  * new_session_dialog doens't exist in A3
2371                  * Try to remove all references to it to
2372                  * see if it will compile.  NOTE: this will
2373                  * likely cause a runtime issue is my somewhat
2374                  * uneducated guess.
2375                  */
2376
2377                 //if (new_session_dialog) {
2378
2379
2380                         /* make it break out of Dialog::run() and
2381                            start again.
2382                          */
2383
2384                         //new_session_dialog->response (1);
2385                 //}
2386         }
2387 }
2388
2389 void
2390 ARDOUR_UI::end_loading_messages ()
2391 {
2392         // hide_splash ();
2393 }
2394
2395 void
2396 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2397 {
2398         // show_splash ();
2399         // splash->message (msg);
2400         flush_pending ();
2401 }
2402
2403 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2404 int
2405 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
2406 {
2407         string session_name;
2408         string session_path;
2409         string template_name;
2410         int ret = -1;
2411         bool likely_new = false;
2412
2413         if (!load_template.empty()) {
2414                 should_be_new = true;
2415                 template_name = load_template;
2416         }
2417
2418         while (ret != 0) {
2419
2420                 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2421
2422                         /* if they named a specific statefile, use it, otherwise they are
2423                            just giving a session folder, and we want to use it as is
2424                            to find the session.
2425                         */
2426
2427                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
2428
2429                         if (suffix != string::npos) {
2430                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2431                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
2432                                 session_name = Glib::path_get_basename (session_name);
2433                         } else {
2434                                 session_path = ARDOUR_COMMAND_LINE::session_name;
2435                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2436                         }
2437
2438                 } else {
2439
2440                         bool const apply = run_startup (should_be_new, load_template);
2441
2442                         if (!apply) {
2443                                 if (quit_on_cancel) {
2444                                         exit (1);
2445                                 } else {
2446                                         return ret;
2447                                 }
2448                         }
2449
2450                         /* if we run the startup dialog again, offer more than just "new session" */
2451
2452                         should_be_new = false;
2453
2454                         session_name = _startup->session_name (likely_new);
2455
2456                         /* this shouldn't happen, but we catch it just in case it does */
2457
2458                         if (session_name.empty()) {
2459                                 continue;
2460                         }
2461
2462                         if (_startup->use_session_template()) {
2463                                 template_name = _startup->session_template_name();
2464                                 _session_is_new = true;
2465                         }
2466
2467                         if (session_name[0] == G_DIR_SEPARATOR ||
2468                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
2469                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)) {
2470
2471                                 /* absolute path or cwd-relative path specified for session name: infer session folder
2472                                    from what was given.
2473                                 */
2474
2475                                 session_path = Glib::path_get_dirname (session_name);
2476                                 session_name = Glib::path_get_basename (session_name);
2477
2478                         } else {
2479
2480                                 session_path = _startup->session_folder();
2481
2482                                 if (session_name.find ('/') != string::npos) {
2483                                         MessageDialog msg (*_startup,
2484                                                            _("To ensure compatibility with various systems\n"
2485                                                              "session names may not contain a '/' character"));
2486                                         msg.run ();
2487                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2488                                         continue;
2489                                 }
2490
2491                                 if (session_name.find ('\\') != string::npos) {
2492                                         MessageDialog msg (*_startup,
2493                                                            _("To ensure compatibility with various systems\n"
2494                                                              "session names may not contain a '\\' character"));
2495                                         msg.run ();
2496                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2497                                         continue;
2498                                 }
2499                         }
2500                 }
2501
2502                 if (create_engine ()) {
2503                         break;
2504                 }
2505
2506                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2507
2508                         if (likely_new) {
2509
2510                                 std::string existing = Glib::build_filename (session_path, session_name);
2511
2512                                 if (!ask_about_loading_existing_session (existing)) {
2513                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2514                                         continue;
2515                                 }
2516                         }
2517
2518                         _session_is_new = false;
2519
2520                 } else {
2521
2522                         if (!likely_new) {
2523                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2524                                 msg.run ();
2525                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2526                                 continue;
2527                         }
2528
2529                         if (session_name.find ('/') != std::string::npos) {
2530                                 MessageDialog msg (*_startup,
2531                                                    _("To ensure compatibility with various systems\n"
2532                                                      "session names may not contain a '/' character"));
2533                                 msg.run ();
2534                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2535                                 continue;
2536                         }
2537
2538                         if (session_name.find ('\\') != std::string::npos) {
2539                                 MessageDialog msg (*_startup,
2540                                                    _("To ensure compatibility with various systems\n"
2541                                                      "session names may not contain a '\\' character"));
2542                                 msg.run ();
2543                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2544                                 continue;
2545                         }
2546
2547                         _session_is_new = true;
2548                 }
2549
2550                 if (likely_new && template_name.empty()) {
2551
2552                         ret = build_session_from_nsd (session_path, session_name);
2553
2554                 } else {
2555
2556                         ret = load_session (session_path, session_name, template_name);
2557
2558                         if (ret == -2) {
2559                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
2560                                 exit (1);
2561                         }
2562
2563                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2564                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2565                                 exit (1);
2566                         }
2567                 }
2568         }
2569
2570         return ret;
2571 }
2572
2573 void
2574 ARDOUR_UI::close_session()
2575 {
2576         if (!check_audioengine()) {
2577                 return;
2578         }
2579
2580         if (unload_session (true)) {
2581                 return;
2582         }
2583
2584         ARDOUR_COMMAND_LINE::session_name = "";
2585
2586         if (get_session_parameters (true, false)) {
2587                 exit (1);
2588         }
2589
2590         goto_editor_window ();
2591 }
2592
2593 /** @param snap_name Snapshot name (without .ardour suffix).
2594  *  @return -2 if the load failed because we are not connected to the AudioEngine.
2595  */
2596 int
2597 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
2598 {
2599         Session *new_session;
2600         int unload_status;
2601         int retval = -1;
2602
2603         session_loaded = false;
2604
2605         if (!check_audioengine()) {
2606                 return -2;
2607         }
2608
2609         unload_status = unload_session ();
2610
2611         if (unload_status < 0) {
2612                 goto out;
2613         } else if (unload_status > 0) {
2614                 retval = 0;
2615                 goto out;
2616         }
2617
2618         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
2619
2620         try {
2621                 new_session = new Session (*engine, path, snap_name, 0, mix_template);
2622         }
2623
2624         /* this one is special */
2625
2626         catch (AudioEngine::PortRegistrationFailure& err) {
2627
2628                 MessageDialog msg (err.what(),
2629                                    true,
2630                                    Gtk::MESSAGE_INFO,
2631                                    Gtk::BUTTONS_CLOSE);
2632
2633                 msg.set_title (_("Port Registration Error"));
2634                 msg.set_secondary_text (_("Click the Close button to try again."));
2635                 msg.set_position (Gtk::WIN_POS_CENTER);
2636                 pop_back_splash ();
2637                 msg.present ();
2638
2639                 int response = msg.run ();
2640
2641                 msg.hide ();
2642
2643                 switch (response) {
2644                 case RESPONSE_CANCEL:
2645                         exit (1);
2646                 default:
2647                         break;
2648                 }
2649                 goto out;
2650         }
2651
2652         catch (...) {
2653
2654                 MessageDialog msg (string_compose(
2655                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
2656                                            path, snap_name),
2657                                    true,
2658                                    Gtk::MESSAGE_INFO,
2659                                    BUTTONS_OK);
2660
2661                 msg.set_title (_("Loading Error"));
2662                 msg.set_secondary_text (_("Click the Refresh button to try again."));
2663                 msg.add_button (Stock::REFRESH, 1);
2664                 msg.set_position (Gtk::WIN_POS_CENTER);
2665                 pop_back_splash ();
2666                 msg.present ();
2667
2668                 int response = msg.run ();
2669
2670                 switch (response) {
2671                 case 1:
2672                         break;
2673                 default:
2674                         exit (1);
2675                 }
2676
2677                 msg.hide ();
2678
2679                 goto out;
2680         }
2681
2682         {
2683                 list<string> const u = new_session->unknown_processors ();
2684                 if (!u.empty()) {
2685                         MissingPluginDialog d (_session, u);
2686                         d.run ();
2687                 }
2688         }
2689
2690         /* Now the session been created, add the transport controls */
2691         new_session->add_controllable(roll_controllable);
2692         new_session->add_controllable(stop_controllable);
2693         new_session->add_controllable(goto_start_controllable);
2694         new_session->add_controllable(goto_end_controllable);
2695         new_session->add_controllable(auto_loop_controllable);
2696         new_session->add_controllable(play_selection_controllable);
2697         new_session->add_controllable(rec_controllable);
2698
2699         set_session (new_session);
2700
2701         session_loaded = true;
2702
2703         goto_editor_window ();
2704
2705         if (_session) {
2706                 _session->set_clean ();
2707         }
2708
2709         flush_pending ();
2710         retval = 0;
2711
2712   out:
2713         return retval;
2714 }
2715
2716 int
2717 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
2718 {
2719         Session *new_session;
2720         int x;
2721
2722         if (!check_audioengine()) {
2723                 return -1;
2724         }
2725
2726         session_loaded = false;
2727
2728         x = unload_session ();
2729
2730         if (x < 0) {
2731                 return -1;
2732         } else if (x > 0) {
2733                 return 0;
2734         }
2735
2736         _session_is_new = true;
2737
2738         try {
2739                 new_session = new Session (*engine, path, snap_name, &bus_profile);
2740         }
2741
2742         catch (...) {
2743
2744                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2745                 pop_back_splash ();
2746                 msg.run ();
2747                 return -1;
2748         }
2749
2750         /* Give the new session the default GUI state, if such things exist */
2751
2752         XMLNode* n;
2753         n = Config->instant_xml (X_("Editor"));
2754         if (n) {
2755                 new_session->add_instant_xml (*n, false);
2756         }
2757         n = Config->instant_xml (X_("Mixer"));
2758         if (n) {
2759                 new_session->add_instant_xml (*n, false);
2760         }
2761
2762         /* Put the playhead at 0 and scroll fully left */
2763         n = new_session->instant_xml (X_("Editor"));
2764         if (n) {
2765                 n->add_property (X_("playhead"), X_("0"));
2766                 n->add_property (X_("left-frame"), X_("0"));
2767         }
2768
2769         set_session (new_session);
2770
2771         session_loaded = true;
2772
2773         new_session->save_state(new_session->name());
2774
2775         return 0;
2776 }
2777
2778 void
2779 ARDOUR_UI::launch_chat ()
2780 {
2781 #ifdef __APPLE__
2782         open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2783 #else
2784         open_uri("http://webchat.freenode.net/?channels=ardour");
2785 #endif
2786 }
2787
2788 void
2789 ARDOUR_UI::show_about ()
2790 {
2791         if (about == 0) {
2792                 about = new About;
2793                 about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2794         }
2795
2796         about->set_transient_for(*editor);
2797         about->show_all ();
2798 }
2799
2800 void
2801 ARDOUR_UI::launch_manual ()
2802 {
2803         PBD::open_uri("http://ardour.org/flossmanual");
2804 }
2805
2806 void
2807 ARDOUR_UI::launch_reference ()
2808 {
2809         PBD::open_uri("http://ardour.org/refmanual");
2810 }
2811
2812 void
2813 ARDOUR_UI::hide_about ()
2814 {
2815         if (about) {
2816                 about->get_window()->set_cursor ();
2817                 about->hide ();
2818         }
2819 }
2820
2821 void
2822 ARDOUR_UI::about_signal_response (int /*response*/)
2823 {
2824         hide_about();
2825 }
2826
2827 void
2828 ARDOUR_UI::show_splash ()
2829 {
2830         if (splash == 0) {
2831                 try {
2832                         splash = new Splash;
2833                 } catch (...) {
2834                         return;
2835                 }
2836         }
2837
2838         splash->show ();
2839         splash->present ();
2840         splash->queue_draw ();
2841         splash->get_window()->process_updates (true);
2842         flush_pending ();
2843 }
2844
2845 void
2846 ARDOUR_UI::hide_splash ()
2847 {
2848         if (splash) {
2849                 splash->hide();
2850         }
2851 }
2852
2853 void
2854 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
2855                                     const string& plural_msg, const string& singular_msg)
2856 {
2857         size_t removed;
2858
2859         removed = rep.paths.size();
2860
2861         if (removed == 0) {
2862                 MessageDialog msgd (*editor,
2863                                     _("No files were ready for clean-up"),
2864                                     true,
2865                                     Gtk::MESSAGE_INFO,
2866                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2867                 msgd.set_title (_("Clean-up"));
2868                 msgd.set_secondary_text (_("If this seems suprising, \n\
2869 check for any existing snapshots.\n\
2870 These may still include regions that\n\
2871 require some unused files to continue to exist."));
2872
2873                 msgd.run ();
2874                 return;
2875         }
2876
2877         ArdourDialog results (_("Clean-up"), true, false);
2878
2879         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2880             CleanupResultsModelColumns() {
2881                     add (visible_name);
2882                     add (fullpath);
2883             }
2884             Gtk::TreeModelColumn<std::string> visible_name;
2885             Gtk::TreeModelColumn<std::string> fullpath;
2886         };
2887
2888
2889         CleanupResultsModelColumns results_columns;
2890         Glib::RefPtr<Gtk::ListStore> results_model;
2891         Gtk::TreeView results_display;
2892
2893         results_model = ListStore::create (results_columns);
2894         results_display.set_model (results_model);
2895         results_display.append_column (list_title, results_columns.visible_name);
2896
2897         results_display.set_name ("CleanupResultsList");
2898         results_display.set_headers_visible (true);
2899         results_display.set_headers_clickable (false);
2900         results_display.set_reorderable (false);
2901
2902         Gtk::ScrolledWindow list_scroller;
2903         Gtk::Label txt;
2904         Gtk::VBox dvbox;
2905         Gtk::HBox dhbox;  // the hbox for the image and text
2906         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2907         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2908
2909         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2910
2911         const string dead_directory = _session->session_directory().dead_path().to_string();
2912
2913         /* subst:
2914            %1 - number of files removed
2915            %2 - location of "dead"
2916            %3 - size of files affected
2917            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2918         */
2919
2920         const char* bprefix;
2921         double space_adjusted = 0;
2922
2923         if (rep.space < 1000) {
2924                 bprefix = X_("");
2925                 space_adjusted = rep.space;
2926         } else if (rep.space < 1000000) {
2927                 bprefix = X_("kilo");
2928                 space_adjusted = truncf((float)rep.space / 1000.0);
2929         } else if (rep.space < 1000000 * 1000) {
2930                 bprefix = X_("mega");
2931                 space_adjusted = truncf((float)rep.space / (1000.0 * 1000.0));
2932         } else {
2933                 bprefix = X_("giga");
2934                 space_adjusted = truncf((float)rep.space / (1000.0 * 1000 * 1000.0));
2935         }
2936
2937         if (removed > 1) {
2938                 txt.set_text (string_compose (plural_msg, removed, dead_directory, space_adjusted, bprefix));
2939         } else {
2940                 txt.set_text (string_compose (singular_msg, removed, dead_directory, space_adjusted, bprefix));
2941         }
2942
2943         dhbox.pack_start (*dimage, true, false, 5);
2944         dhbox.pack_start (txt, true, false, 5);
2945
2946         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2947                 TreeModel::Row row = *(results_model->append());
2948                 row[results_columns.visible_name] = *i;
2949                 row[results_columns.fullpath] = *i;
2950         }
2951
2952         list_scroller.add (results_display);
2953         list_scroller.set_size_request (-1, 150);
2954         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2955
2956         dvbox.pack_start (dhbox, true, false, 5);
2957         dvbox.pack_start (list_scroller, true, false, 5);
2958         ddhbox.pack_start (dvbox, true, false, 5);
2959
2960         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2961         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2962         results.set_default_response (RESPONSE_CLOSE);
2963         results.set_position (Gtk::WIN_POS_MOUSE);
2964
2965         results_display.show();
2966         list_scroller.show();
2967         txt.show();
2968         dvbox.show();
2969         dhbox.show();
2970         ddhbox.show();
2971         dimage->show();
2972
2973         //results.get_vbox()->show();
2974         results.set_resizable (false);
2975
2976         results.run ();
2977
2978 }
2979
2980 void
2981 ARDOUR_UI::cleanup ()
2982 {
2983         if (_session == 0) {
2984                 /* shouldn't happen: menu item is insensitive */
2985                 return;
2986         }
2987
2988
2989         MessageDialog checker (_("Are you sure you want to clean-up?"),
2990                                 true,
2991                                 Gtk::MESSAGE_QUESTION,
2992                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2993
2994         checker.set_title (_("Clean-up"));
2995
2996         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
2997 ALL undo/redo information will be lost if you clean-up.\n\
2998 Clean-up will move all unused files to a \"dead\" location."));
2999
3000         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3001         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3002         checker.set_default_response (RESPONSE_CANCEL);
3003
3004         checker.set_name (_("CleanupDialog"));
3005         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3006         checker.set_position (Gtk::WIN_POS_MOUSE);
3007
3008         switch (checker.run()) {
3009         case RESPONSE_ACCEPT:
3010                 break;
3011         default:
3012                 return;
3013         }
3014
3015         ARDOUR::CleanupReport rep;
3016
3017         editor->prepare_for_cleanup ();
3018
3019         /* do not allow flush until a session is reloaded */
3020
3021         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3022         if (act) {
3023                 act->set_sensitive (false);
3024         }
3025
3026         if (_session->cleanup_sources (rep)) {
3027                 editor->finish_cleanup ();
3028                 return;
3029         }
3030
3031         editor->finish_cleanup ();
3032
3033         checker.hide();
3034         display_cleanup_results (rep,
3035                                  _("Cleaned Files"),
3036                                  _("\
3037 The following %1 files were not in use and \n\
3038 have been moved to:\n\n\
3039 %2\n\n\
3040 After a restart of Ardour,\n\n\
3041 Session -> Clean-up -> Flush Wastebasket\n\n\
3042 will release an additional\n\
3043 %3 %4bytes of disk space.\n"),
3044                                  _("\
3045 The following file was not in use and \n\
3046 has been moved to:\n                            \
3047 %2\n\n\
3048 After a restart of Ardour,\n\n\
3049 Session -> Clean-up -> Flush Wastebasket\n\n\
3050 will release an additional\n\
3051 %3 %4bytes of disk space.\n"
3052                                          ));
3053
3054 }
3055
3056 void
3057 ARDOUR_UI::flush_trash ()
3058 {
3059         if (_session == 0) {
3060                 /* shouldn't happen: menu item is insensitive */
3061                 return;
3062         }
3063
3064         ARDOUR::CleanupReport rep;
3065
3066         if (_session->cleanup_trash_sources (rep)) {
3067                 return;
3068         }
3069
3070         display_cleanup_results (rep,
3071                                  _("deleted file"),
3072                                  _("The following %1 files were deleted from\n\
3073 %2,\n\
3074 releasing %3 %4bytes of disk space"),
3075                                  _("The following file was deleted from\n\
3076 %2,\n\
3077 releasing %3 %4bytes of disk space"));
3078 }
3079
3080 void
3081 ARDOUR_UI::add_route (Gtk::Window* float_window)
3082 {
3083         int count;
3084
3085         if (!_session) {
3086                 return;
3087         }
3088
3089         if (add_route_dialog == 0) {
3090                 add_route_dialog = new AddRouteDialog (_session);
3091                 if (float_window) {
3092                         add_route_dialog->set_transient_for (*float_window);
3093                 }
3094         }
3095
3096         if (add_route_dialog->is_visible()) {
3097                 /* we're already doing this */
3098                 return;
3099         }
3100
3101         ResponseType r = (ResponseType) add_route_dialog->run ();
3102
3103         add_route_dialog->hide();
3104
3105         switch (r) {
3106                 case RESPONSE_ACCEPT:
3107                         break;
3108                 default:
3109                         return;
3110                         break;
3111         }
3112
3113         if ((count = add_route_dialog->count()) <= 0) {
3114                 return;
3115         }
3116
3117         string template_path = add_route_dialog->track_template();
3118
3119         if (!template_path.empty()) {
3120                 _session->new_route_from_template (count, template_path);
3121                 return;
3122         }
3123
3124         uint32_t input_chan = add_route_dialog->channels ();
3125         uint32_t output_chan;
3126         string name_template = add_route_dialog->name_template ();
3127         bool track = add_route_dialog->track ();
3128         RouteGroup* route_group = add_route_dialog->route_group ();
3129
3130         AutoConnectOption oac = Config->get_output_auto_connect();
3131
3132         if (oac & AutoConnectMaster) {
3133                 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
3134         } else {
3135                 output_chan = input_chan;
3136         }
3137
3138         /* XXX do something with name template */
3139
3140         if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3141                 if (track) {
3142                         session_add_midi_track (route_group, count, name_template);
3143                 } else  {
3144                         MessageDialog msg (*editor,
3145                                         _("Sorry, MIDI Busses are not supported at this time."));
3146                         msg.run ();
3147                         //session_add_midi_bus();
3148                 }
3149         } else {
3150                 if (track) {
3151                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count, name_template);
3152                 } else {
3153                         session_add_audio_bus (input_chan, output_chan, route_group, count, name_template);
3154                 }
3155         }
3156 }
3157
3158 XMLNode*
3159 ARDOUR_UI::mixer_settings () const
3160 {
3161         XMLNode* node = 0;
3162
3163         if (_session) {
3164                 node = _session->instant_xml(X_("Mixer"));
3165         } else {
3166                 node = Config->instant_xml(X_("Mixer"));
3167         }
3168
3169         if (!node) {
3170                 node = new XMLNode (X_("Mixer"));
3171         }
3172
3173         return node;
3174 }
3175
3176 XMLNode*
3177 ARDOUR_UI::editor_settings () const
3178 {
3179         XMLNode* node = 0;
3180
3181         if (_session) {
3182                 node = _session->instant_xml(X_("Editor"));
3183         } else {
3184                 node = Config->instant_xml(X_("Editor"));
3185         }
3186
3187         if (!node) {
3188                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3189                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3190                 }
3191         }
3192
3193         if (!node) {
3194                 node = new XMLNode (X_("Editor"));
3195         }
3196
3197         return node;
3198 }
3199
3200 XMLNode*
3201 ARDOUR_UI::keyboard_settings () const
3202 {
3203         XMLNode* node = 0;
3204
3205         node = Config->extra_xml(X_("Keyboard"));
3206
3207         if (!node) {
3208                 node = new XMLNode (X_("Keyboard"));
3209         }
3210
3211         return node;
3212 }
3213
3214 void
3215 ARDOUR_UI::create_xrun_marker (framepos_t where)
3216 {
3217         editor->mouse_add_new_marker (where, false, true);
3218 }
3219
3220 void
3221 ARDOUR_UI::halt_on_xrun_message ()
3222 {
3223         MessageDialog msg (*editor,
3224                            _("Recording was stopped because your system could not keep up."));
3225         msg.run ();
3226 }
3227
3228 void
3229 ARDOUR_UI::xrun_handler (framepos_t where)
3230 {
3231         if (!_session) {
3232                 return;
3233         }
3234
3235         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
3236
3237         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
3238                 create_xrun_marker(where);
3239         }
3240
3241         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
3242                 halt_on_xrun_message ();
3243         }
3244 }
3245
3246 void
3247 ARDOUR_UI::disk_overrun_handler ()
3248 {
3249         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
3250
3251         if (!have_disk_speed_dialog_displayed) {
3252                 have_disk_speed_dialog_displayed = true;
3253                 MessageDialog* msg = new MessageDialog (*editor, string_compose (_("\
3254 The disk system on your computer\n\
3255 was not able to keep up with %1.\n\
3256 \n\
3257 Specifically, it failed to write data to disk\n\
3258 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
3259                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3260                 msg->show ();
3261         }
3262 }
3263
3264 void
3265 ARDOUR_UI::disk_underrun_handler ()
3266 {
3267         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
3268
3269         if (!have_disk_speed_dialog_displayed) {
3270                 have_disk_speed_dialog_displayed = true;
3271                 MessageDialog* msg = new MessageDialog (
3272                         *editor, string_compose (_("The disk system on your computer\n\
3273 was not able to keep up with %1.\n\
3274 \n\
3275 Specifically, it failed to read data from disk\n\
3276 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
3277                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3278                 msg->show ();
3279         }
3280 }
3281
3282 void
3283 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3284 {
3285         have_disk_speed_dialog_displayed = false;
3286         delete msg;
3287 }
3288
3289 void
3290 ARDOUR_UI::session_dialog (std::string msg)
3291 {
3292         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
3293
3294         MessageDialog* d;
3295
3296         if (editor) {
3297                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3298         } else {
3299                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3300         }
3301
3302         d->show_all ();
3303         d->run ();
3304         delete d;
3305 }
3306
3307 int
3308 ARDOUR_UI::pending_state_dialog ()
3309 {
3310         HBox* hbox = new HBox();
3311         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3312         ArdourDialog dialog (_("Crash Recovery"), true);
3313         Label  message (_("\
3314 This session appears to have been in\n\
3315 middle of recording when ardour or\n\
3316 the computer was shutdown.\n\
3317 \n\
3318 Ardour can recover any captured audio for\n\
3319 you, or it can ignore it. Please decide\n\
3320 what you would like to do.\n"));
3321         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3322         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3323         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3324         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3325         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3326         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3327         dialog.set_default_response (RESPONSE_ACCEPT);
3328         dialog.set_position (WIN_POS_CENTER);
3329         message.show();
3330         image->show();
3331         hbox->show();
3332
3333         switch (dialog.run ()) {
3334         case RESPONSE_ACCEPT:
3335                 return 1;
3336         default:
3337                 return 0;
3338         }
3339 }
3340
3341 int
3342 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
3343 {
3344         HBox* hbox = new HBox();
3345         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3346         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3347         Label  message (string_compose (_("\
3348 This session was created with a sample rate of %1 Hz\n\
3349 \n\
3350 The audioengine is currently running at %2 Hz\n"), desired, actual));
3351
3352         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3353         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3354         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3355         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3356         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3357         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3358         dialog.set_default_response (RESPONSE_ACCEPT);
3359         dialog.set_position (WIN_POS_CENTER);
3360         message.show();
3361         image->show();
3362         hbox->show();
3363
3364         switch (dialog.run ()) {
3365         case RESPONSE_ACCEPT:
3366                 return 0;
3367         default:
3368                 return 1;
3369         }
3370 }
3371
3372
3373 void
3374 ARDOUR_UI::disconnect_from_jack ()
3375 {
3376         if (engine) {
3377                 if( engine->disconnect_from_jack ()) {
3378                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3379                         msg.run ();
3380                 }
3381
3382                 update_sample_rate (0);
3383         }
3384 }
3385
3386 void
3387 ARDOUR_UI::reconnect_to_jack ()
3388 {
3389         if (engine) {
3390                 if (engine->reconnect_to_jack ()) {
3391                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3392                         msg.run ();
3393                 }
3394
3395                 update_sample_rate (0);
3396         }
3397 }
3398
3399 void
3400 ARDOUR_UI::use_config ()
3401 {
3402         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3403         if (node) {
3404                 set_transport_controllable_state (*node);
3405         }
3406 }
3407
3408 void
3409 ARDOUR_UI::update_transport_clocks (framepos_t pos)
3410 {
3411         if (Config->get_primary_clock_delta_edit_cursor()) {
3412                 primary_clock->set (pos, false, editor->get_preferred_edit_position(), 1);
3413         } else {
3414                 primary_clock->set (pos, 0, true);
3415         }
3416
3417         if (Config->get_secondary_clock_delta_edit_cursor()) {
3418                 secondary_clock->set (pos, false, editor->get_preferred_edit_position(), 2);
3419         } else {
3420                 secondary_clock->set (pos);
3421         }
3422
3423         if (big_clock_window->get()) {
3424                 big_clock->set (pos);
3425         }
3426 }
3427
3428
3429 void
3430 ARDOUR_UI::step_edit_status_change (bool yn)
3431 {
3432         // XXX should really store pre-step edit status of things
3433         // we make insensitive
3434
3435         if (yn) {
3436                 rec_button.set_visual_state (3);
3437                 rec_button.set_sensitive (false);
3438         } else {
3439                 rec_button.set_visual_state (0);
3440                 rec_button.set_sensitive (true);
3441         }
3442 }
3443
3444 void
3445 ARDOUR_UI::record_state_changed ()
3446 {
3447         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
3448
3449         if (!_session || !big_clock_window->get()) {
3450                 /* why bother - the clock isn't visible */
3451                 return;
3452         }
3453
3454         Session::RecordState const r = _session->record_status ();
3455         bool const h = _session->have_rec_enabled_track ();
3456
3457         if (r == Session::Recording && h)  {
3458                 big_clock->set_widget_name ("BigClockRecording");
3459         } else {
3460                 big_clock->set_widget_name ("BigClockNonRecording");
3461         }
3462 }
3463
3464 bool
3465 ARDOUR_UI::first_idle ()
3466 {
3467         if (_session) {
3468                 _session->allow_auto_play (true);
3469         }
3470
3471         if (editor) {
3472                 editor->first_idle();
3473         }
3474
3475         Keyboard::set_can_save_keybindings (true);
3476         return false;
3477 }
3478
3479 void
3480 ARDOUR_UI::store_clock_modes ()
3481 {
3482         XMLNode* node = new XMLNode(X_("ClockModes"));
3483
3484         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3485                 XMLNode* child = new XMLNode (X_("Clock"));
3486                 
3487                 child->add_property (X_("name"), (*x)->name());
3488                 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
3489                 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
3490
3491                 node->add_child_nocopy (*child);
3492         }
3493
3494         _session->add_extra_xml (*node);
3495         _session->set_dirty ();
3496 }
3497
3498 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3499         : Controllable (name), ui (u), type(tp)
3500 {
3501
3502 }
3503
3504 void
3505 ARDOUR_UI::TransportControllable::set_value (double val)
3506 {
3507         if (val < 0.5) {
3508                 /* do nothing: these are radio-style actions */
3509                 return;
3510         }
3511
3512         const char *action = 0;
3513
3514         switch (type) {
3515         case Roll:
3516                 action = X_("Roll");
3517                 break;
3518         case Stop:
3519                 action = X_("Stop");
3520                 break;
3521         case GotoStart:
3522                 action = X_("Goto Start");
3523                 break;
3524         case GotoEnd:
3525                 action = X_("Goto End");
3526                 break;
3527         case AutoLoop:
3528                 action = X_("Loop");
3529                 break;
3530         case PlaySelection:
3531                 action = X_("Play Selection");
3532                 break;
3533         case RecordEnable:
3534                 action = X_("Record");
3535                 break;
3536         default:
3537                 break;
3538         }
3539
3540         if (action == 0) {
3541                 return;
3542         }
3543
3544         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3545
3546         if (act) {
3547                 act->activate ();
3548         }
3549 }
3550
3551 double
3552 ARDOUR_UI::TransportControllable::get_value (void) const
3553 {
3554         float val = 0.0;
3555
3556         switch (type) {
3557         case Roll:
3558                 break;
3559         case Stop:
3560                 break;
3561         case GotoStart:
3562                 break;
3563         case GotoEnd:
3564                 break;
3565         case AutoLoop:
3566                 break;
3567         case PlaySelection:
3568                 break;
3569         case RecordEnable:
3570                 break;
3571         default:
3572                 break;
3573         }
3574
3575         return val;
3576 }
3577
3578 void
3579 ARDOUR_UI::TransportControllable::set_id (const string& str)
3580 {
3581         _id = str;
3582 }
3583
3584 void
3585 ARDOUR_UI::setup_profile ()
3586 {
3587         if (gdk_screen_width() < 1200) {
3588                 Profile->set_small_screen ();
3589         }
3590
3591
3592         if (getenv ("ARDOUR_SAE")) {
3593                 Profile->set_sae ();
3594                 Profile->set_single_package ();
3595         }
3596 }
3597
3598 void
3599 ARDOUR_UI::toggle_translations ()
3600 {
3601         using namespace Glib;
3602
3603         RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("EnableTranslation"));
3604         if (act) {
3605                 RefPtr<ToggleAction> ract = RefPtr<ToggleAction>::cast_dynamic (act);
3606                 if (ract) {
3607
3608                         string i18n_killer = ARDOUR::translation_kill_path();
3609
3610                         bool already_enabled = !ARDOUR::translations_are_disabled ();
3611
3612                         if (ract->get_active ()) {
3613 /* we don't care about errors */
3614                                 int fd = ::open (i18n_killer.c_str(), O_RDONLY|O_CREAT, 0644);
3615                                 close (fd);
3616                         } else {
3617 /* we don't care about errors */
3618                                 unlink (i18n_killer.c_str());
3619                         }
3620
3621                         if (already_enabled != ract->get_active()) {
3622                                 MessageDialog win (already_enabled ? _("Translations disabled") : _("Translations enabled"),
3623                                                    false,
3624                                                    Gtk::MESSAGE_WARNING,
3625                                                    Gtk::BUTTONS_OK);
3626                                 win.set_secondary_text (string_compose (_("You must restart %1 for this to take effect."), PROGRAM_NAME));
3627                                 win.set_position (Gtk::WIN_POS_CENTER);
3628                                 win.present ();
3629                                 win.run ();
3630                         }
3631                 }
3632         }
3633 }
3634
3635 /** Add a window proxy to our list, so that its state will be saved.
3636  *  This call also causes the window to be created and opened if its
3637  *  state was saved as `visible'.
3638  */
3639 void
3640 ARDOUR_UI::add_window_proxy (WindowProxyBase* p)
3641 {
3642         _window_proxies.push_back (p);
3643         p->maybe_show ();
3644 }
3645
3646 /** Remove a window proxy from our list.  Must be called if a WindowProxy
3647  *  is deleted, to prevent hanging pointers.
3648  */
3649 void
3650 ARDOUR_UI::remove_window_proxy (WindowProxyBase* p)
3651 {
3652         _window_proxies.remove (p);
3653 }
3654
3655 int
3656 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
3657 {
3658         MissingFileDialog dialog (s, str, type);
3659
3660         dialog.show ();
3661         dialog.present ();
3662
3663         int result = dialog.run ();
3664         dialog.hide ();
3665
3666         switch (result) {
3667         case RESPONSE_OK:
3668                 break;
3669         default:
3670                 return 1; // quit entire session load
3671         }
3672
3673         result = dialog.get_action ();
3674
3675         return result;
3676 }
3677
3678 int
3679 ARDOUR_UI::ambiguous_file (std::string file, std::string path, std::vector<std::string> hits)
3680 {
3681         AmbiguousFileDialog dialog (file, hits);
3682
3683         dialog.show ();
3684         dialog.present ();
3685
3686         dialog.run ();
3687         return dialog.get_which ();
3688 }