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