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