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