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