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