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