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