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