even more fixes for the new session dialog and its use
[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                 new_session_dialog->set_session_folder (session_path);
2072                 new_session_dialog->set_modal (true);
2073
2074                 if (existing_session) {
2075
2076                         if (session_name.length() == 0 || session_path.length() == 0) {
2077                                 error << string_compose (_("Ardour cannot understand \"%1\" as a session name"), predetermined_path) << endmsg;
2078                                 return false;
2079                         }
2080                         
2081                         if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
2082                                 Glib::ustring predicted_session_file;
2083                                 
2084                                 predicted_session_file = predetermined_path;
2085                                 predicted_session_file += '/';
2086                                 predicted_session_file += session_name;
2087                                 predicted_session_file += Session::statefile_suffix();
2088                                 
2089                                 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2090                                         existing_session = true;
2091                                 }
2092                                 
2093                         } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_EXISTS)) {
2094                                 
2095                                 if (predetermined_path.find (Session::statefile_suffix()) == predetermined_path.length() - 7) {
2096                                         /* existing .ardour file */
2097                                         existing_session = true;
2098                                 }
2099                         } else {
2100                                 existing_session = false;
2101                         }
2102                         
2103                         if (existing_session && have_engine) {
2104                                 /* lets just try to load it */
2105                                 
2106                                 loading_dialog->set_message (_("Starting audio engine"));
2107                                 loading_dialog->show_all ();
2108                                 flush_pending ();
2109                                 
2110                                 if (create_engine ()) {
2111                                         backend_audio_error (!have_engine, new_session_dialog);
2112                                         loading_dialog->hide ();
2113                                         return false;
2114                                 }
2115                                 
2116                                 if (load_session (session_path, session_name) == 0) {
2117                                         goto done;
2118                                 }
2119                         }
2120                 }
2121         }
2122
2123         /* loading failed, or we need the NSD for something */
2124
2125         new_session_dialog->set_position (WIN_POS_CENTER);
2126         new_session_dialog->set_current_page (0);
2127         new_session_dialog->set_existing_session (existing_session);
2128         new_session_dialog->reset_recent();
2129
2130         do {
2131                 new_session_dialog->set_have_engine (have_engine);
2132                 new_session_dialog->present ();
2133                 response = new_session_dialog->run ();
2134                 loading_dialog->hide ();
2135                 
2136                 _session_is_new = false;
2137                 
2138                 /* handle possible negative responses */
2139
2140                 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
2141                         
2142                         if (!session) {
2143                                 quit();
2144                         }
2145                         new_session_dialog->hide ();
2146                         return false;
2147                         
2148                 } else if (response == Gtk::RESPONSE_NONE) {
2149                         /* "Clear" was pressed */
2150                         
2151                         goto try_again;
2152                 }
2153
2154                 fontconfig_dialog();
2155
2156                 /* if we're here to help set up audio parameters this is where want to do that.
2157                 */
2158
2159                 if (!have_engine) {
2160                         if (new_session_dialog->engine_control.setup_engine ()) {
2161                                 new_session_dialog->hide ();
2162                                 return false;
2163                         } 
2164
2165                         loading_dialog->set_message (_("Starting audio engine"));
2166                         loading_dialog->show_all ();
2167                         flush_pending ();
2168                 }
2169
2170                 if (create_engine ()) {
2171                         backend_audio_error (!have_engine, new_session_dialog);
2172                         loading_dialog->hide ();
2173                         flush_pending ();
2174                         /* audio setup page */
2175                         new_session_dialog->set_existing_session (false);
2176                         new_session_dialog->set_current_page (2);
2177                         response = Gtk::RESPONSE_NONE;
2178                         goto try_again;
2179                 }
2180
2181                 loading_dialog->hide ();
2182                 have_engine = true;             
2183                         
2184                 /* now handle possible affirmative responses */
2185
2186                 if (response == Gtk::RESPONSE_YES) {
2187
2188                         /* YES == OPEN from the session selector */
2189
2190                         session_name = new_session_dialog->session_name();
2191                         
2192                         if (session_name.empty()) {
2193                                 response = Gtk::RESPONSE_NONE;
2194                                 goto try_again;
2195                         } 
2196
2197                         if (session_name[0] == '/' || 
2198                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2199                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2200                                 if (load_session (Glib::path_get_dirname (session_name), session_name)) {
2201                                         response = Gtk::RESPONSE_NONE;
2202                                         goto try_again;
2203                                 }
2204                         } else {
2205                                 session_path = new_session_dialog->session_folder();
2206                                 if (load_session (session_path, session_name)) {
2207                                         response = Gtk::RESPONSE_NONE;
2208                                         goto try_again;
2209                                 }
2210                         }
2211                         
2212                 } else if (response == Gtk::RESPONSE_OK) {
2213
2214                         /* OK == OPEN button */
2215
2216                         session_name = new_session_dialog->session_name();
2217                 
2218                         if (session_name.empty()) {
2219                                 response = Gtk::RESPONSE_NONE;
2220                                 goto try_again;
2221                         } 
2222
2223                         switch (new_session_dialog->which_page()) {
2224                         case NewSessionDialog::OpenPage: 
2225                         case NewSessionDialog::EnginePage:
2226
2227                                 if (session_name[0] == '/' || 
2228                                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2229                                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2230                                         if (load_session (Glib::path_get_dirname (session_name), session_name)) {
2231                                                 response = Gtk::RESPONSE_NONE;
2232                                                 goto try_again;
2233                                         }
2234
2235                                 } else {
2236                                         session_path = new_session_dialog->session_folder();
2237                                         if (load_session (session_path, session_name)) {
2238                                                 response = Gtk::RESPONSE_NONE;
2239                                                 goto try_again;
2240                                         }
2241                                 }
2242                                 break;
2243
2244                         case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2245
2246                                 cerr << "on page zero\n";
2247
2248                                 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2249                                         should_be_new = true;
2250                                 }
2251
2252                                 /* handle what appear to be paths rather than just a name */
2253
2254                                 if (session_name[0] == '/' || 
2255                                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2256                                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2257
2258                                         session_path = Glib::path_get_dirname (session_name);
2259                                         session_name = Glib::path_get_basename (session_name);
2260
2261                                 } else {
2262
2263                                         session_path = new_session_dialog->session_folder();
2264
2265                                 }
2266
2267                                 //XXX This is needed because session constructor wants a 
2268                                 //non-existant path. hopefully this will be fixed at some point.
2269                                 
2270                                 session_path = Glib::build_filename (session_path, session_name);
2271
2272                                 if (!should_be_new) {
2273
2274                                         if (load_session (session_path, session_name)) {
2275                                                 response = Gtk::RESPONSE_NONE;
2276                                                 goto try_again;
2277                                         }
2278
2279                                         continue; /* leaves while() loop because response != NONE */
2280
2281                                 } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2282
2283                                         Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2284
2285                                         MessageDialog msg (str,
2286                                                            false,
2287                                                            Gtk::MESSAGE_WARNING,
2288                                                            Gtk::BUTTONS_YES_NO,
2289                                                            true);
2290
2291
2292                                         msg.set_name (X_("CleanupDialog"));
2293                                         msg.set_wmclass (X_("existing_session"), "Ardour");
2294                                         msg.set_position (Gtk::WIN_POS_MOUSE);
2295                                         
2296                                         switch (msg.run()) {
2297                                         case RESPONSE_YES:
2298                                                 new_session_dialog->hide ();
2299                                                 goto_editor_window ();
2300                                                 flush_pending ();
2301                                                 if (load_session (session_path, session_name)) {
2302                                                         response = Gtk::RESPONSE_NONE;
2303                                                         goto try_again;
2304                                                 }
2305                                                 goto done;
2306                                                 break;
2307                                         default:
2308                                                 response = RESPONSE_NONE;
2309                                                 new_session_dialog->reset ();
2310                                                 new_session_dialog->set_existing_session (false);
2311                                                 loading_dialog->hide ();
2312                                                 continue;
2313                                         }
2314                                 } 
2315
2316                                 _session_is_new = true;
2317                                                 
2318                                 if (new_session_dialog->use_session_template()) {
2319
2320                                         template_name = new_session_dialog->session_template_name();
2321
2322                                         new_session_dialog->hide ();
2323                                         goto_editor_window ();
2324                                         flush_pending ();
2325
2326                                         if (load_session (session_path, session_name, template_name)) {
2327                                                 response = Gtk::RESPONSE_NONE;
2328                                                 goto try_again;
2329                                         }
2330
2331                           
2332                                 } else {
2333
2334                                         uint32_t cchns;
2335                                         uint32_t mchns;
2336                                         AutoConnectOption iconnect;
2337                                         AutoConnectOption oconnect;
2338                                         uint32_t nphysin;
2339                                         uint32_t nphysout;
2340                                         
2341                                         if (Profile->get_sae()) {
2342
2343                                                 cchns = 0;
2344                                                 mchns = 2;
2345                                                 iconnect = AutoConnectPhysical;
2346                                                 oconnect = AutoConnectMaster;
2347                                                 nphysin = 0; // use all available
2348                                                 nphysout = 0; // use all available
2349
2350                                         } else {
2351
2352                                                 /* get settings from advanced section of NSD */
2353                                                 
2354                                                 if (new_session_dialog->create_control_bus()) {
2355                                                         cchns = (uint32_t) new_session_dialog->control_channel_count();
2356                                                 } else {
2357                                                         cchns = 0;
2358                                                 }
2359                                                 
2360                                                 if (new_session_dialog->create_master_bus()) {
2361                                                         mchns = (uint32_t) new_session_dialog->master_channel_count();
2362                                                 } else {
2363                                                         mchns = 0;
2364                                                 }
2365                                                 
2366                                                 if (new_session_dialog->connect_inputs()) {
2367                                                         iconnect = AutoConnectPhysical;
2368                                                 } else {
2369                                                         iconnect = AutoConnectOption (0);
2370                                                 }
2371                                                 
2372                                                 /// @todo some minor tweaks.
2373                                                 
2374                                                 if (new_session_dialog->connect_outs_to_master()) {
2375                                                         oconnect = AutoConnectMaster;
2376                                                 } else if (new_session_dialog->connect_outs_to_physical()) {
2377                                                         oconnect = AutoConnectPhysical;
2378                                                 } else {
2379                                                         oconnect = AutoConnectOption (0);
2380                                                 } 
2381                                                 
2382                                                 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2383                                                 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2384                                         }
2385
2386                                         if (build_session (session_path,
2387                                                            session_name,
2388                                                            cchns,
2389                                                            mchns,
2390                                                            iconnect,
2391                                                            oconnect,
2392                                                            nphysin,
2393                                                            nphysout, 
2394                                                            engine->frame_rate() * 60 * 5)) {
2395                                                 
2396                                                 response = Gtk::RESPONSE_NONE;
2397                                                 goto try_again;
2398                                         }
2399
2400                                         new_session_dialog->hide ();
2401                                         goto_editor_window ();
2402                                         flush_pending ();
2403                                 }
2404                                 break;
2405
2406                         default:
2407                                 break;
2408                         }
2409                 }
2410
2411           try_again:
2412                 if (response == Gtk::RESPONSE_NONE) {
2413                         loading_dialog->hide ();
2414                         new_session_dialog->set_existing_session (false);
2415                         new_session_dialog->reset ();
2416                 }
2417                 
2418         } while (response == Gtk::RESPONSE_NONE);
2419
2420   done:
2421         show();
2422         loading_dialog->hide ();
2423         new_session_dialog->hide();
2424         return true;
2425 }
2426
2427 void
2428 ARDOUR_UI::close_session ()
2429 {
2430         if (!check_audioengine()) {
2431                 return;
2432         }
2433
2434         unload_session (true);
2435         
2436         get_session_parameters ("", true, false);
2437 }
2438
2439 int
2440 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2441 {
2442         Session *new_session;
2443         int unload_status;
2444         int retval = -1;
2445
2446         session_loaded = false;
2447
2448         if (!check_audioengine()) {
2449                 return -1;
2450         }
2451
2452         unload_status = unload_session ();
2453
2454         if (unload_status < 0) {
2455                 goto out;
2456         } else if (unload_status > 0) {
2457                 retval = 0;
2458                 goto out;
2459         }
2460
2461         /* if it already exists, we must have write access */
2462
2463         if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2464                 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2465                                               "This prevents the session from being loaded."));
2466                 msg.run ();
2467                 goto out;
2468         }
2469
2470         if (loading_dialog) {
2471                 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2472                 flush_pending ();
2473         }
2474
2475         disable_screen_updates ();
2476
2477         try {
2478                 new_session = new Session (*engine, path, snap_name, mix_template);
2479         }
2480
2481         /* this one is special */
2482
2483         catch (AudioEngine::PortRegistrationFailure& err) {
2484
2485                 MessageDialog msg (err.what(),
2486                                    true,
2487                                    Gtk::MESSAGE_INFO,
2488                                    Gtk::BUTTONS_OK_CANCEL);
2489                 
2490                 msg.set_title (_("Loading Error"));
2491                 msg.set_secondary_text (_("Click the OK button to try again."));
2492                 msg.set_position (Gtk::WIN_POS_CENTER);
2493                 msg.present ();
2494
2495                 int response = msg.run ();
2496
2497                 msg.hide ();
2498
2499                 switch (response) {
2500                 case RESPONSE_CANCEL:
2501                         exit (1);
2502                 default:
2503                         break;
2504                 }
2505                 goto out;
2506         }
2507
2508         catch (...) {
2509
2510                 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2511                                    true,
2512                                    Gtk::MESSAGE_INFO,
2513                                    Gtk::BUTTONS_OK_CANCEL);
2514                 
2515                 msg.set_title (_("Loading Error"));
2516                 msg.set_secondary_text (_("Click the OK button to try again."));
2517                 msg.set_position (Gtk::WIN_POS_CENTER);
2518                 msg.present ();
2519
2520                 int response = msg.run ();
2521
2522                 msg.hide ();
2523
2524                 switch (response) {
2525                 case RESPONSE_CANCEL:
2526                         exit (1);
2527                 default:
2528                         break;
2529                 }
2530                 goto out;
2531         }
2532
2533         connect_to_session (new_session);
2534
2535         Config->set_current_owner (ConfigVariableBase::Interface);
2536
2537         session_loaded = true;
2538         
2539         goto_editor_window ();
2540
2541         if (session) {
2542                 session->set_clean ();
2543         }
2544
2545         enable_screen_updates ();
2546         flush_pending ();
2547         retval = 0;
2548
2549   out:
2550         return retval;
2551 }
2552
2553 int
2554 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name, 
2555                           uint32_t control_channels,
2556                           uint32_t master_channels, 
2557                           AutoConnectOption input_connect,
2558                           AutoConnectOption output_connect,
2559                           uint32_t nphysin,
2560                           uint32_t nphysout,
2561                           nframes_t initial_length)
2562 {
2563         Session *new_session;
2564         int x;
2565
2566         if (!check_audioengine()) {
2567                 return -1;
2568         }
2569
2570         session_loaded = false;
2571
2572         x = unload_session ();
2573
2574         if (x < 0) {
2575                 return -1;
2576         } else if (x > 0) {
2577                 return 0;
2578         }
2579         
2580         _session_is_new = true;
2581
2582         try {
2583                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2584                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2585         }
2586
2587         catch (...) {
2588
2589                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2590                 msg.run ();
2591                 return -1;
2592         }
2593
2594         connect_to_session (new_session);
2595
2596         session_loaded = true;
2597         return 0;
2598 }
2599
2600 void
2601 ARDOUR_UI::show ()
2602 {
2603         if (editor) {
2604                 editor->show_window ();
2605                 
2606                 if (!shown_flag) {
2607                         editor->present ();
2608                 }
2609
2610                 shown_flag = true;
2611         }
2612 }
2613
2614 void
2615 ARDOUR_UI::show_splash ()
2616 {
2617         if (about == 0) {
2618                 about = new About();
2619                 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2620         }
2621         about->present();
2622         flush_pending ();
2623 }
2624
2625 void
2626 ARDOUR_UI::about_signal_response(int response)
2627 {
2628         hide_splash();
2629 }
2630
2631 void
2632 ARDOUR_UI::hide_splash ()
2633 {
2634         if (about) {
2635                 about->get_window()->set_cursor ();
2636                 about->hide();
2637         }
2638 }
2639
2640 void
2641 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2642 {
2643         size_t removed;
2644
2645         removed = rep.paths.size();
2646
2647         if (removed == 0) {
2648                 MessageDialog msgd (*editor,
2649                                     _("No audio files were ready for cleanup"), 
2650                                     true,
2651                                     Gtk::MESSAGE_INFO,
2652                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2653                 msgd.set_secondary_text (_("If this seems suprising, \n\
2654 check for any existing snapshots.\n\
2655 These may still include regions that\n\
2656 require some unused files to continue to exist."));
2657         
2658                 msgd.run ();
2659                 return;
2660         } 
2661
2662         ArdourDialog results (_("ardour: cleanup"), true, false);
2663         
2664         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2665             CleanupResultsModelColumns() { 
2666                     add (visible_name);
2667                     add (fullpath);
2668             }
2669             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2670             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2671         };
2672
2673         
2674         CleanupResultsModelColumns results_columns;
2675         Glib::RefPtr<Gtk::ListStore> results_model;
2676         Gtk::TreeView results_display;
2677         
2678         results_model = ListStore::create (results_columns);
2679         results_display.set_model (results_model);
2680         results_display.append_column (list_title, results_columns.visible_name);
2681
2682         results_display.set_name ("CleanupResultsList");
2683         results_display.set_headers_visible (true);
2684         results_display.set_headers_clickable (false);
2685         results_display.set_reorderable (false);
2686
2687         Gtk::ScrolledWindow list_scroller;
2688         Gtk::Label txt;
2689         Gtk::VBox dvbox;
2690         Gtk::HBox dhbox;  // the hbox for the image and text
2691         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2692         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2693
2694         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2695
2696         if (rep.space < 1048576.0f) {
2697                 if (removed > 1) {
2698                   txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2699                 } else {
2700                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2701                 }
2702         } else {
2703                 if (removed > 1) {
2704                         txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2705                 } else {
2706                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2707                 }
2708         }
2709
2710         dhbox.pack_start (*dimage, true, false, 5);
2711         dhbox.pack_start (txt, true, false, 5);
2712
2713         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2714                 TreeModel::Row row = *(results_model->append());
2715                 row[results_columns.visible_name] = *i;
2716                 row[results_columns.fullpath] = *i;
2717         }
2718         
2719         list_scroller.add (results_display);
2720         list_scroller.set_size_request (-1, 150);
2721         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2722
2723         dvbox.pack_start (dhbox, true, false, 5);
2724         dvbox.pack_start (list_scroller, true, false, 5);
2725         ddhbox.pack_start (dvbox, true, false, 5);
2726
2727         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2728         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2729         results.set_default_response (RESPONSE_CLOSE);
2730         results.set_position (Gtk::WIN_POS_MOUSE);
2731         results.show_all_children ();
2732         results.set_resizable (false);
2733
2734         results.run ();
2735
2736 }
2737
2738 void
2739 ARDOUR_UI::cleanup ()
2740 {
2741         if (session == 0) {
2742                 /* shouldn't happen: menu item is insensitive */
2743                 return;
2744         }
2745
2746
2747         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2748                                 true,
2749                                 Gtk::MESSAGE_QUESTION,
2750                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2751
2752         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2753 ALL undo/redo information will be lost if you cleanup.\n\
2754 After cleanup, unused audio files will be moved to a \
2755 \"dead sounds\" location."));
2756         
2757         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2758         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2759         checker.set_default_response (RESPONSE_CANCEL);
2760
2761         checker.set_name (_("CleanupDialog"));
2762         checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2763         checker.set_position (Gtk::WIN_POS_MOUSE);
2764
2765         switch (checker.run()) {
2766         case RESPONSE_ACCEPT:
2767                 break;
2768         default:
2769                 return;
2770         }
2771
2772         Session::cleanup_report rep;
2773
2774         editor->prepare_for_cleanup ();
2775
2776         /* do not allow flush until a session is reloaded */
2777
2778         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2779         if (act) {
2780                 act->set_sensitive (false);
2781         }
2782
2783         if (session->cleanup_sources (rep)) {
2784                 return;
2785         }
2786
2787         checker.hide();
2788         display_cleanup_results (rep, 
2789                                  _("cleaned files"),
2790                                  _("\
2791 The following %1 %2 not in use and \n\
2792 have been moved to:\n\
2793 %3. \n\n\
2794 Flushing the wastebasket will \n\
2795 release an additional\n\
2796 %4 %5bytes of disk space.\n"
2797                                          ));
2798
2799
2800
2801 }
2802
2803 void
2804 ARDOUR_UI::flush_trash ()
2805 {
2806         if (session == 0) {
2807                 /* shouldn't happen: menu item is insensitive */
2808                 return;
2809         }
2810
2811         Session::cleanup_report rep;
2812
2813         if (session->cleanup_trash_sources (rep)) {
2814                 return;
2815         }
2816
2817         display_cleanup_results (rep, 
2818                                  _("deleted file"),
2819                                  _("The following %1 %2 deleted from\n\
2820 %3,\n\
2821 releasing %4 %5bytes of disk space"));
2822 }
2823
2824 void
2825 ARDOUR_UI::add_route (Gtk::Window* float_window)
2826 {
2827         int count;
2828
2829         if (!session) {
2830                 return;
2831         }
2832
2833         if (add_route_dialog == 0) {
2834                 add_route_dialog = new AddRouteDialog;
2835                 if (float_window) {
2836                         add_route_dialog->set_transient_for (*float_window);
2837                 }
2838         }
2839
2840         if (add_route_dialog->is_visible()) {
2841                 /* we're already doing this */
2842                 return;
2843         }
2844
2845         ResponseType r = (ResponseType) add_route_dialog->run ();
2846         
2847         add_route_dialog->hide();
2848
2849         switch (r) {
2850         case RESPONSE_ACCEPT:
2851                 break;
2852         default:
2853                 return;
2854                 break;
2855         }
2856
2857         if ((count = add_route_dialog->count()) <= 0) {
2858                 return;
2859         }
2860
2861         uint32_t input_chan = add_route_dialog->channels ();
2862         uint32_t output_chan;
2863         string name_template = add_route_dialog->name_template ();
2864         bool track = add_route_dialog->track ();
2865
2866         AutoConnectOption oac = Config->get_output_auto_connect();
2867
2868         if (oac & AutoConnectMaster) {
2869                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2870         } else {
2871                 output_chan = input_chan;
2872         }
2873
2874         /* XXX do something with name template */
2875
2876         if (track) {
2877                 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2878         } else {
2879                 session_add_audio_bus (input_chan, output_chan, count);
2880         }
2881 }
2882
2883 XMLNode*
2884 ARDOUR_UI::mixer_settings () const
2885 {
2886         XMLNode* node = 0;
2887
2888         if (session) {
2889                 node = session->instant_xml(X_("Mixer"), session->path());
2890         } else {
2891                 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2892         }
2893
2894         if (!node) {
2895                 node = new XMLNode (X_("Mixer"));
2896         }
2897
2898         return node;
2899 }
2900
2901 XMLNode*
2902 ARDOUR_UI::editor_settings () const
2903 {
2904         XMLNode* node = 0;
2905
2906         if (session) {
2907                 node = session->instant_xml(X_("Editor"), session->path());
2908         } else {
2909                 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2910         }
2911
2912         if (!node) {
2913                 node = new XMLNode (X_("Editor"));
2914         }
2915         return node;
2916 }
2917
2918 XMLNode*
2919 ARDOUR_UI::keyboard_settings () const
2920 {
2921         XMLNode* node = 0;
2922
2923         node = Config->extra_xml(X_("Keyboard"));
2924         
2925         if (!node) {
2926                 node = new XMLNode (X_("Keyboard"));
2927         }
2928         return node;
2929 }
2930
2931 void
2932 ARDOUR_UI::halt_on_xrun_message ()
2933 {
2934         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2935
2936         MessageDialog msg (*editor,
2937                            _("Recording was stopped because your system could not keep up."));
2938         msg.run ();
2939 }
2940
2941 void
2942 ARDOUR_UI::disk_overrun_handler ()
2943 {
2944         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2945
2946         if (!have_disk_speed_dialog_displayed) {
2947                 have_disk_speed_dialog_displayed = true;
2948                 MessageDialog* msg = new MessageDialog (*editor, _("\
2949 The disk system on your computer\n\
2950 was not able to keep up with Ardour.\n\
2951 \n\
2952 Specifically, it failed to write data to disk\n\
2953 quickly enough to keep up with recording.\n"));
2954                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2955                 msg->show_all ();
2956         }
2957 }
2958
2959 void
2960 ARDOUR_UI::disk_underrun_handler ()
2961 {
2962         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2963
2964         if (!have_disk_speed_dialog_displayed) {
2965                 have_disk_speed_dialog_displayed = true;
2966                 MessageDialog* msg = new MessageDialog (*editor,
2967                                    _("The disk system on your computer\n\
2968 was not able to keep up with Ardour.\n\
2969 \n\
2970 Specifically, it failed to read data from disk\n\
2971 quickly enough to keep up with playback.\n"));
2972                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2973                 msg->show_all ();
2974         } 
2975 }
2976
2977 void
2978 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2979 {
2980         have_disk_speed_dialog_displayed = false;
2981         delete msg;
2982 }
2983
2984 int
2985 ARDOUR_UI::pending_state_dialog ()
2986 {
2987         HBox* hbox = new HBox();
2988         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2989         ArdourDialog dialog (_("Crash Recovery"), true);
2990         Label  message (_("\
2991 This session appears to have been in\n\
2992 middle of recording when ardour or\n\
2993 the computer was shutdown.\n\
2994 \n\
2995 Ardour can recover any captured audio for\n\
2996 you, or it can ignore it. Please decide\n\
2997 what you would like to do.\n"));
2998         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
2999         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3000         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3001         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3002         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3003         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3004         dialog.set_default_response (RESPONSE_ACCEPT);
3005         dialog.set_position (WIN_POS_CENTER);
3006         message.show();
3007         image->show();
3008         hbox->show();
3009
3010         switch (dialog.run ()) {
3011         case RESPONSE_ACCEPT:
3012                 return 1;
3013         default:
3014                 return 0;
3015         }
3016 }
3017         
3018 void
3019 ARDOUR_UI::disconnect_from_jack ()
3020 {
3021         if (engine) {
3022                 if( engine->disconnect_from_jack ()) {
3023                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3024                         msg.run ();
3025                 }
3026
3027                 update_sample_rate (0);
3028         }
3029 }
3030
3031 void
3032 ARDOUR_UI::reconnect_to_jack ()
3033 {
3034         if (engine) {
3035                 if (engine->reconnect_to_jack ()) {
3036                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3037                         msg.run ();
3038                 }
3039
3040                 update_sample_rate (0);
3041         }
3042 }
3043
3044 int
3045 ARDOUR_UI::cmdline_new_session (string path)
3046 {
3047         if (path[0] != '/') {
3048                 char buf[PATH_MAX+1];
3049                 string str;
3050
3051                 getcwd (buf, sizeof (buf));
3052                 str = buf;
3053                 str += '/';
3054                 str += path;
3055                 path = str;
3056         }
3057
3058         get_session_parameters (path, false, true);
3059
3060         _will_create_new_session_automatically = false; /* done it */
3061         return FALSE; /* don't call it again */
3062 }
3063
3064 void
3065 ARDOUR_UI::use_config ()
3066 {
3067         Glib::RefPtr<Action> act;
3068
3069         switch (Config->get_native_file_data_format ()) {
3070         case FormatFloat:
3071                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3072                 break;
3073         case FormatInt24:
3074                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3075                 break;
3076         case FormatInt16:
3077                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3078                 break;
3079         }
3080
3081         if (act) {
3082                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3083                 ract->set_active ();
3084         }       
3085
3086         switch (Config->get_native_file_header_format ()) {
3087         case BWF:
3088                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3089                 break;
3090         case WAVE:
3091                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3092                 break;
3093         case WAVE64:
3094                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3095                 break;
3096         case iXML:
3097                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3098                 break;
3099         case RF64:
3100                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3101                 break;
3102         case CAF:
3103                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3104                 break;
3105         case AIFF:
3106                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3107                 break;
3108         }
3109
3110         if (act) {
3111                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3112                 ract->set_active ();
3113         }       
3114
3115         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3116         if (node) {
3117                 set_transport_controllable_state (*node);
3118         }
3119 }
3120
3121 void
3122 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3123 {
3124         if (Config->get_primary_clock_delta_edit_cursor()) {
3125                 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3126         } else {
3127                 primary_clock.set (pos, 0, true);
3128         }
3129
3130         if (Config->get_secondary_clock_delta_edit_cursor()) {
3131                 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3132         } else {
3133                 secondary_clock.set (pos);
3134         }
3135
3136         if (big_clock_window) {
3137                 big_clock.set (pos);
3138         }
3139 }
3140
3141 void
3142 ARDOUR_UI::record_state_changed ()
3143 {
3144         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3145
3146         if (!session || !big_clock_window) {
3147                 /* why bother - the clock isn't visible */
3148                 return;
3149         }
3150
3151         switch (session->record_status()) {
3152         case Session::Recording:
3153                 big_clock.set_widget_name ("BigClockRecording");
3154                 break;
3155         default:
3156                 big_clock.set_widget_name ("BigClockNonRecording");
3157                 break;
3158         }
3159 }
3160
3161 void
3162 ARDOUR_UI::set_keybindings_path (string path)
3163 {
3164         keybindings_path = path;
3165 }
3166
3167 void
3168 ARDOUR_UI::save_keybindings ()
3169 {
3170         if (can_save_keybindings) {
3171                 AccelMap::save (user_keybindings_path);
3172         } 
3173 }
3174
3175 bool
3176 ARDOUR_UI::first_idle ()
3177 {
3178         if (session) {
3179                 session->allow_auto_play (true);
3180         }
3181         can_save_keybindings = true;
3182         return false;
3183 }
3184
3185 void
3186 ARDOUR_UI::store_clock_modes ()
3187 {
3188         XMLNode* node = new XMLNode(X_("ClockModes"));
3189
3190         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3191                 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3192         }
3193
3194         session->add_extra_xml (*node);
3195         session->set_dirty ();
3196 }
3197
3198
3199                 
3200 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3201         : Controllable (name), ui (u), type(tp)
3202 {
3203         
3204 }
3205
3206 void
3207 ARDOUR_UI::TransportControllable::set_value (float val)
3208 {
3209         if (type == ShuttleControl) {
3210                 double fract;
3211
3212                 if (val == 0.5f) {
3213                         fract = 0.0;
3214                 } else {
3215                         if (val < 0.5f) {
3216                                 fract = -((0.5f - val)/0.5f);
3217                         } else {
3218                                 fract = ((val - 0.5f)/0.5f);
3219                         }
3220                 }
3221                 
3222                 ui.set_shuttle_fract (fract);
3223                 return;
3224         }
3225
3226         if (val < 0.5f) {
3227                 /* do nothing: these are radio-style actions */
3228                 return;
3229         }
3230
3231         char *action = 0;
3232
3233         switch (type) {
3234         case Roll:
3235                 action = X_("Roll");
3236                 break;
3237         case Stop:
3238                 action = X_("Stop");
3239                 break;
3240         case GotoStart:
3241                 action = X_("Goto Start");
3242                 break;
3243         case GotoEnd:
3244                 action = X_("Goto End");
3245                 break;
3246         case AutoLoop:
3247                 action = X_("Loop");
3248                 break;
3249         case PlaySelection:
3250                 action = X_("Play Selection");
3251                 break;
3252         case RecordEnable:
3253                 action = X_("Record");
3254                 break;
3255         default:
3256                 break;
3257         }
3258
3259         if (action == 0) {
3260                 return;
3261         }
3262
3263         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3264
3265         if (act) {
3266                 act->activate ();
3267         }
3268 }
3269
3270 float
3271 ARDOUR_UI::TransportControllable::get_value (void) const
3272 {
3273         float val = 0.0f;
3274         
3275         switch (type) {
3276         case Roll:
3277                 break;
3278         case Stop:
3279                 break;
3280         case GotoStart:
3281                 break;
3282         case GotoEnd:
3283                 break;
3284         case AutoLoop:
3285                 break;
3286         case PlaySelection:
3287                 break;
3288         case RecordEnable:
3289                 break;
3290         case ShuttleControl:
3291                 break;
3292         default:
3293                 break;
3294         }
3295
3296         return val;
3297 }
3298
3299 void
3300 ARDOUR_UI::TransportControllable::set_id (const string& str)
3301 {
3302         _id = str;
3303 }
3304
3305 void
3306 ARDOUR_UI::setup_profile ()
3307 {
3308         if (gdk_screen_width() < 1200) {
3309                 Profile->set_small_screen ();
3310         }
3311
3312         if (getenv ("ARDOUR_SAE")) {
3313                 Profile->set_sae ();
3314                 Profile->set_single_package ();
3315         }
3316 }
3317