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