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