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