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