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