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