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