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