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