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