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