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