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