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