add destructive outlines, more action usage and state fixups in GUI
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2002 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     $Id$
19 */
20
21 #include <algorithm>
22 #include <cmath>
23 #include <fcntl.h>
24 #include <signal.h>
25 #include <unistd.h>
26 #include <cerrno>
27 #include <fstream>
28
29 #include <iostream>
30
31 #include <pbd/error.h>
32 #include <pbd/compose.h>
33 #include <pbd/basename.h>
34 #include <pbd/pathscanner.h>
35 #include <pbd/failed_constructor.h>
36 #include <gtkmm2ext/gtk_ui.h>
37 #include <gtkmm2ext/pix.h>
38 #include <gtkmm2ext/utils.h>
39 #include <gtkmm2ext/click_box.h>
40 #include <gtkmm2ext/fastmeter.h>
41 #include <gtkmm2ext/stop_signal.h>
42 #include <gtkmm2ext/popup.h>
43
44 #include <midi++/port.h>
45 #include <midi++/mmc.h>
46
47 #include <ardour/ardour.h>
48 #include <ardour/port.h>
49 #include <ardour/audioengine.h>
50 #include <ardour/playlist.h>
51 #include <ardour/utils.h>
52 #include <ardour/diskstream.h>
53 #include <ardour/filesource.h>
54 #include <ardour/recent_sessions.h>
55 #include <ardour/session_diskstream.h>
56 #include <ardour/port.h>
57 #include <ardour/audio_track.h>
58
59 #include "actions.h"
60 #include "ardour_ui.h"
61 #include "ardour_message.h"
62 #include "public_editor.h"
63 #include "audio_clock.h"
64 #include "keyboard.h"
65 #include "mixer_ui.h"
66 #include "prompter.h"
67 #include "opts.h"
68 #include "keyboard_target.h"
69 #include "add_route_dialog.h"
70 #include "new_session_dialog.h"
71 #include "about.h"
72 #include "utils.h"
73 #include "gui_thread.h"
74 #include "meter_xpms.h"
75
76 #include "i18n.h"
77
78 using namespace ARDOUR;
79 using namespace Gtkmm2ext;
80 using namespace Gtk;
81 using namespace sigc;
82
83 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
84
85 sigc::signal<void,bool> ARDOUR_UI::Blink;
86 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
87 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
88 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
89
90 static const char* channel_setup_names[] = {
91         "mono",
92         "stereo",
93         "3 channels",
94         "4 channels",
95         "5 channels",
96         "8 channels",
97         "manual setup",
98         0
99 };
100
101 vector<string> channel_combo_strings;
102
103 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
104
105         : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
106           
107           primary_clock (X_("TransportClockDisplay"), true, false, true),
108           secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
109           preroll_clock (X_("PreRollClock"), true, true),
110           postroll_clock (X_("PostRollClock"), true, true),
111
112           /* adjuster table */
113
114           adjuster_table (3, 3),
115
116           /* preroll stuff */
117
118           preroll_button (_("pre\nroll")),
119           postroll_button (_("post\nroll")),
120
121           /* big clock */
122
123           big_clock ("BigClockDisplay", true),
124
125           /* transport */
126
127           time_master_button (_("time\nmaster")),
128
129           shuttle_units_button (_("% ")),
130
131           punch_in_button (_("punch\nin")),
132           punch_out_button (_("punch\nout")),
133           auto_return_button (_("auto\nreturn")),
134           auto_play_button (_("auto\nplay")),
135           auto_input_button (_("auto\ninput")),
136           click_button (_("click")),
137           auditioning_alert_button (_("AUDITIONING")),
138           solo_alert_button (_("SOLO")),
139           shown_flag (false)
140
141 {
142         using namespace Gtk::Menu_Helpers;
143
144         Gtkmm2ext::init();
145
146         /* actually, its already loaded, but ... */
147
148         cerr << "Loading UI configuration file " << rcfile << endl;
149
150         about = 0;
151
152         if (theArdourUI == 0) {
153                 theArdourUI = this;
154         }
155
156         ActionManager::init ();
157         
158         m_new_session_dialog = 0;
159         m_new_session_dialog_ref = NewSessionDialogFactory::create();
160         m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
161         editor = 0;
162         mixer = 0;
163         session = 0;
164         _session_is_new = false;
165         big_clock_window = 0;
166         session_selector_window = 0;
167         last_key_press_time = 0;
168         connection_editor = 0;
169         add_route_dialog = 0;
170         route_params = 0;
171         option_editor = 0;
172         location_ui = 0;
173         sfdb = 0;
174         open_session_selector = 0;
175         have_configure_timeout = false;
176         have_disk_overrun_displayed = false;
177         have_disk_underrun_displayed = false;
178         _will_create_new_session_automatically = false;
179         session_loaded = false;
180         last_speed_displayed = -1.0f;
181
182         last_configure_time.tv_sec = 0;
183         last_configure_time.tv_usec = 0;
184
185         shuttle_grabbed = false;
186         shuttle_fract = 0.0;
187
188         set_shuttle_units (Percentage);
189         set_shuttle_behaviour (Sprung);
190
191         shuttle_style_menu = 0;
192         shuttle_unit_menu = 0;
193
194         gettimeofday (&last_peak_grab, 0);
195         gettimeofday (&last_shuttle_request, 0);
196
197         ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
198         ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
199         ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
200         ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
201
202         /* handle pending state with a dialog */
203
204         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
205
206         channel_combo_strings = internationalize (channel_setup_names);
207         
208         /* have to wait for AudioEngine and Configuration before proceeding */
209 }
210
211 void
212 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
213 {
214         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
215         
216         string msg = string_compose (_("\
217 You cannot record-enable\n\
218 track %1\n\
219 because it has no input connections.\n\
220 You would be wasting space recording silence."),
221                               ds->name());
222
223         ArdourMessage message (editor, X_("cannotrecord"), msg);
224 }
225
226 void
227 ARDOUR_UI::set_engine (AudioEngine& e)
228 {
229         engine = &e;
230
231         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
232         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
233         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
234         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
235
236         _tooltips.enable();
237
238         keyboard = new Keyboard;
239         install_keybindings ();
240
241         FastMeter::set_vertical_xpm (v_meter_strip_xpm);
242         FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
243
244         if (setup_windows ()) {
245                 throw failed_constructor ();
246         }
247
248         if (GTK_ARDOUR::show_key_actions) {
249                 vector<string> names;
250                 vector<string> paths;
251                 vector<string> keys;
252                 vector<AccelKey> bindings;
253
254                 ActionManager::get_all_actions (names, paths, keys, bindings);
255
256                 vector<string>::iterator n;
257                 vector<string>::iterator k;
258                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
259                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
260                 }
261
262                 exit (0);
263         }
264
265         /* start with timecode, metering enabled
266         */
267         
268         blink_timeout_tag = -1;
269
270         /* this being a GUI and all, we want peakfiles */
271
272         FileSource::set_build_peakfiles (true);
273         FileSource::set_build_missing_peakfiles (true);
274
275         if (Source::start_peak_thread ()) {
276                 throw failed_constructor();
277         }
278
279         /* start the time-of-day-clock */
280         
281         update_wall_clock ();
282         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
283
284         update_disk_space ();
285         update_cpu_load ();
286         update_sample_rate (engine->frame_rate());
287
288         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
289         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
290 }
291
292 ARDOUR_UI::~ARDOUR_UI ()
293 {
294         save_ardour_state ();
295
296         if (keyboard) {
297                 delete keyboard;
298         }
299
300         if (editor) {
301                 delete editor;
302         }
303
304         if (mixer) {
305                 delete mixer;
306         }
307
308         if (add_route_dialog) {
309                 delete add_route_dialog;
310         }
311
312         Source::stop_peak_thread ();
313 }
314
315 gint
316 ARDOUR_UI::configure_timeout ()
317 {
318         struct timeval now;
319         struct timeval diff;
320
321         if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
322                 /* no configure events yet */
323                 return TRUE;
324         }
325
326         gettimeofday (&now, 0);
327         timersub (&now, &last_configure_time, &diff);
328
329         /* force a gap of 0.5 seconds since the last configure event
330          */
331
332         if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
333                 return TRUE;
334         } else {
335                 have_configure_timeout = false;
336                 save_ardour_state ();
337                 return FALSE;
338         }
339 }
340
341 gboolean
342 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
343 {
344         if (have_configure_timeout) {
345                 gettimeofday (&last_configure_time, 0);
346         } else {
347                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
348                 have_configure_timeout = true;
349         }
350                 
351         return FALSE;
352 }
353
354 void
355 ARDOUR_UI::save_ardour_state ()
356 {
357         if (!keyboard || !mixer || !editor) {
358                 return;
359         }
360         
361         /* XXX this is all a bit dubious. add_extra_xml() uses
362            a different lifetime model from add_instant_xml().
363         */
364
365         XMLNode* node = new XMLNode (keyboard->get_state());
366         Config->add_extra_xml (*node);
367         Config->save_state();
368
369         XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
370         XMLNode& mnode (mixer->get_state());
371
372         if (session) {
373                 session->add_instant_xml(enode, session->path());
374                 session->add_instant_xml(mnode, session->path());
375         } else {
376                 Config->add_instant_xml(enode, Config->get_user_ardour_path());
377                 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
378         }
379 }
380
381 void
382 ARDOUR_UI::startup ()
383 {
384         /* Once the UI is up and running, start the audio engine. Doing
385            this before the UI is up and running can cause problems
386            when not running with SCHED_FIFO, because the amount of
387            CPU and disk work needed to get the UI started can interfere
388            with the scheduling of the audio thread.
389         */
390
391         Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
392 }
393
394 void
395 ARDOUR_UI::finish()
396 {
397         if (session && session->dirty()) {
398                 switch (ask_about_saving_session(_("quit"))) {
399                 case -1:
400                         return;
401                         break;
402                 case 1:
403                         /* use the default name */
404                         if (save_state_canfail ("")) {
405                                 /* failed - don't quit */
406                                 ArdourMessage (editor, X_("badsave dialog"),
407                                                _("\
408 Ardour was unable to save your session.\n\n\
409 If you still wish to quit, please use the\n\n\
410 \"Just quit\" option."));
411                                 return;
412                         }
413                         break;
414                 case 0:
415                         break;
416                 }
417         }
418
419         quit ();
420 }
421
422 int
423 ARDOUR_UI::ask_about_saving_session (const string & what)
424 {
425         ArdourDialog window (_("ardour: save session?"));
426         Gtk::Label  prompt_label;
427         string msg;
428
429         msg = string_compose(_("Save and %1"), what);
430         window.add_button (msg, RESPONSE_ACCEPT);
431         msg = string_compose(_("Just %1"), what);
432         window.add_button (msg, RESPONSE_APPLY);
433         msg = string_compose(_("Don't %1"), what);
434         window.add_button (msg, RESPONSE_REJECT);
435
436         Gtk::Button noquit_button (msg);
437         noquit_button.set_name ("EditorGTKButton");
438
439         string prompt;
440         string type;
441
442         if (session->snap_name() == session->name()) {
443                 type = _("session");
444         } else {
445                 type = _("snapshot");
446         }
447         prompt = string_compose(_("The %1\n\"%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?"), 
448                          type, session->snap_name());
449         
450         prompt_label.set_text (prompt);
451         prompt_label.set_alignment (0.5, 0.5);
452         prompt_label.set_name (X_("PrompterLabel"));
453         
454         window.get_vbox()->pack_start (prompt_label);
455
456         window.set_name (_("Prompter"));
457         window.set_position (Gtk::WIN_POS_MOUSE);
458         window.set_modal (true);
459         window.show_all ();
460
461         save_the_session = 0;
462
463         editor->ensure_float (window);
464
465         ResponseType r = (ResponseType) window.run();
466
467         window.hide ();
468
469         switch (r) {
470         case RESPONSE_ACCEPT: // save and get out of here
471                 return 1;
472         case RESPONSE_APPLY:  // get out of here
473                 return 0;
474         default:
475                 break;
476         }
477
478         return -1;
479 }
480         
481 gint
482 ARDOUR_UI::every_second ()
483 {
484         update_cpu_load ();
485         update_buffer_load ();
486         update_disk_space ();
487         // update_disk_rate ();
488         return TRUE;
489 }
490
491 gint
492 ARDOUR_UI::every_point_one_seconds ()
493 {
494         struct timeval now;
495         struct timeval diff;
496         
497         /* do not attempt to grab peak power more than once per cycle.
498          */
499
500         gettimeofday (&now, 0);
501         timersub (&now, &last_peak_grab, &diff);
502
503         if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
504                 IO::GrabPeakPower(); /* EMIT_SIGNAL */
505                 last_peak_grab = now;
506         } 
507
508         update_speed_display ();
509         RapidScreenUpdate(); /* EMIT_SIGNAL */
510         return TRUE;
511 }
512
513 gint
514 ARDOUR_UI::every_point_zero_one_seconds ()
515 {
516         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
517         return TRUE;
518 }
519
520 void
521 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
522 {
523         char buf[32];
524
525         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
526
527         if (!engine->connected()) {
528
529                 snprintf (buf, sizeof (buf), _("disconnected"));
530
531         } else {
532
533                 jack_nframes_t rate = engine->frame_rate();
534                 
535                 if (fmod (rate, 1000.0) != 0.0) {
536                         snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), 
537                                   (float) rate/1000.0f,
538                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
539                 } else {
540                         snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), 
541                                   rate/1000,
542                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
543                 }
544         }
545
546         sample_rate_label.set_text (buf);
547 }
548
549 void
550 ARDOUR_UI::update_cpu_load ()
551 {
552         char buf[32];
553         snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
554         cpu_load_label.set_text (buf);
555 }
556
557 void
558 ARDOUR_UI::update_disk_rate ()
559 {
560         char buf[64];
561
562         if (session) {
563                 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"), 
564                           session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
565                 disk_rate_label.set_text (buf);
566         } else {
567                 disk_rate_label.set_text ("");
568         }
569 }
570
571 void
572 ARDOUR_UI::update_buffer_load ()
573 {
574         char buf[64];
575
576         if (session) {
577                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
578                           session->playback_load(), session->capture_load());
579                 buffer_load_label.set_text (buf);
580         } else {
581                 buffer_load_label.set_text ("");
582         }
583 }
584
585 void
586 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
587 {
588         if (ds.record_enabled()) {
589                 rec_enabled_diskstreams++;
590         }
591 }
592
593 void
594 ARDOUR_UI::update_disk_space()
595 {
596         if (session == 0) {
597                 return;
598         }
599
600         jack_nframes_t frames = session->available_capture_duration();
601         char buf[64];
602
603         if (frames == max_frames) {
604                 strcpy (buf, _("space: 24hrs+"));
605         } else {
606                 int hrs;
607                 int mins;
608                 int secs;
609                 jack_nframes_t fr = session->frame_rate();
610                 
611                 if (session->actively_recording()){
612                         
613                         rec_enabled_diskstreams = 0;
614                         session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
615                         
616                         if (rec_enabled_diskstreams) {
617                                 frames /= rec_enabled_diskstreams;
618                         }
619                         
620                 } else {
621                         
622                         /* hmmm. shall we divide by the route count? or the diskstream count?
623                            or what? for now, do nothing ...
624                         */
625                         
626                 }
627                 
628                 hrs  = frames / (fr * 3600);
629                 frames -= hrs * fr * 3600;
630                 mins = frames / (fr * 60);
631                 frames -= mins * fr * 60;
632                 secs = frames / fr;
633                 
634                 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
635         }
636
637         disk_space_label.set_text (buf);
638 }                 
639
640 gint
641 ARDOUR_UI::update_wall_clock ()
642 {
643         time_t now;
644         struct tm *tm_now;
645         char buf[16];
646
647         time (&now);
648         tm_now = localtime (&now);
649
650         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
651         wall_clock_label.set_text (buf);
652
653         return TRUE;
654 }
655 void
656 ARDOUR_UI::control_methods_adjusted ()
657
658 {
659         int which_method;
660
661         which_method = (int) online_control_button->adjustment.get_value();
662         switch (which_method) {
663         case 0:
664                 allow_mmc_and_local ();
665                 break;
666         case 1:
667                 allow_mmc_only ();
668                 break;
669         case 2:
670                 allow_local_only ();
671                 break;
672         default:
673                 fatal << _("programming error: impossible control method") << endmsg;
674         }
675 }
676         
677
678 void
679 ARDOUR_UI::mmc_device_id_adjusted ()
680
681 {
682 #if 0
683         if (mmc) {
684                 int dev_id = (int) mmc_id_button->adjustment.get_value();
685                 mmc->set_device_id (dev_id);
686         }
687 #endif
688 }
689
690 void
691 ARDOUR_UI::map_some_session_state (ToggleButton& button,
692                                    bool (Session::*get)() const)
693         
694 {
695         bool x;
696
697         if (session == 0) {
698                 return;
699         }
700         
701         if (button.get_active() != (x = (session->*get)())) {
702                 button.set_active (x);
703         }
704 }
705
706 gint
707 ARDOUR_UI::session_menu (GdkEventButton *ev)
708 {
709         session_popup_menu->popup (0, 0);
710         return TRUE;
711 }
712
713 void
714 ARDOUR_UI::redisplay_recent_sessions ()
715 {
716         vector<string *> *sessions;
717         vector<string *>::iterator i;
718         RecentSessionsSorter cmp;
719         
720         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
721         recent_session_model->clear ();
722
723         RecentSessions rs;
724         ARDOUR::read_recent_sessions (rs);
725
726         if (rs.empty()) {
727                 recent_session_display.set_model (recent_session_model);
728                 return;
729         }
730
731         /* sort them alphabetically */
732         sort (rs.begin(), rs.end(), cmp);
733         sessions = new vector<string*>;
734
735         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
736                 sessions->push_back (new string ((*i).second));
737         }
738
739         for (i = sessions->begin(); i != sessions->end(); ++i) {
740
741                 vector<string*>* states;
742                 vector<const gchar*> item;
743                 string fullpath = *(*i);
744                 
745                 /* remove any trailing / */
746
747                 if (fullpath[fullpath.length()-1] == '/') {
748                         fullpath = fullpath.substr (0, fullpath.length()-1);
749                 }
750
751                 /* now get available states for this session */
752
753                 if ((states = Session::possible_states (fullpath)) == 0) {
754                         /* no state file? */
755                         continue;
756                 }
757
758                 TreeModel::Row row = *(recent_session_model->append());
759
760                 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
761                 row[recent_session_columns.fullpath] = fullpath;
762
763                 if (states->size() > 1) {
764
765                         /* add the children */
766                         
767                         for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
768                                 
769                                 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
770
771                                 child_row[recent_session_columns.visible_name] = **i2;
772                                 child_row[recent_session_columns.fullpath] = fullpath;
773
774                                 delete *i2;
775                         }
776                 }
777
778                 delete states;
779         }
780
781         recent_session_display.set_model (recent_session_model);
782         delete sessions;
783 }
784
785 void
786 ARDOUR_UI::build_session_selector ()
787 {
788         session_selector_window = new ArdourDialog ("session selector");
789         
790         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
791         
792         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
793         session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
794
795         recent_session_model = TreeStore::create (recent_session_columns);
796         recent_session_display.set_model (recent_session_model);
797         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
798         recent_session_display.set_headers_visible (false);
799
800         scroller->add (recent_session_display);
801         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
802
803         session_selector_window->set_name ("SessionSelectorWindow");
804         session_selector_window->set_size_request (200, 400);
805         session_selector_window->get_vbox()->pack_start (*scroller);
806         session_selector_window->show_all_children();
807 }
808
809 void
810 ARDOUR_UI::open_recent_session ()
811 {
812         /* popup selector window */
813
814         if (session_selector_window == 0) {
815                 build_session_selector ();
816         }
817
818         redisplay_recent_sessions ();
819
820         ResponseType r = (ResponseType) session_selector_window->run ();
821
822         session_selector_window->hide();
823
824         switch (r) {
825         case RESPONSE_ACCEPT:
826                 break;
827         default:
828                 return;
829         }
830
831         Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
832
833         if (i == recent_session_model->children().end()) {
834                 return;
835         }
836         
837         Glib::ustring path = (*i)[recent_session_columns.fullpath];
838         Glib::ustring state = (*i)[recent_session_columns.visible_name];
839
840         _session_is_new = false;
841
842         load_session (path, state);
843 }
844
845 bool
846 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) 
847 {
848         struct stat statbuf;
849
850         if (stat (info.filename.c_str(), &statbuf) != 0) {
851                 return false;
852         }
853
854         if (!S_ISDIR(statbuf.st_mode)) {
855                 return false;
856         }
857
858         string session_file = info.filename;
859         session_file += '/';
860         session_file += PBD::basename (info.filename);
861         session_file += ".ardour";
862         
863         if (stat (session_file.c_str(), &statbuf) != 0) {
864                 return false;
865         }
866
867         return S_ISREG (statbuf.st_mode);
868 }
869
870 void
871 ARDOUR_UI::open_session ()
872 {
873         /* popup selector window */
874
875         if (open_session_selector == 0) {
876
877                 /* ardour sessions are folders */
878
879                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
880                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
881                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
882
883                 FileFilter session_filter;
884                 session_filter.add_pattern ("*.ardour");
885                 session_filter.set_name (_("Ardour sessions"));
886                 open_session_selector->add_filter (session_filter);
887                 open_session_selector->set_filter (session_filter);
888         }
889
890         int response = open_session_selector->run();
891         open_session_selector->hide ();
892
893         switch (response) {
894         case RESPONSE_ACCEPT:
895                 break;
896         default:
897                 open_session_selector->hide();
898                 return;
899         }
900
901         open_session_selector->hide();
902         string session_path = open_session_selector->get_filename();
903         string path, name;
904         bool isnew;
905
906         if (session_path.length() > 0) {
907                 if (Session::find_session (session_path, path, name, isnew) == 0) {
908                         _session_is_new = isnew;
909                         load_session (path, name);
910                 }
911         }
912 }
913
914
915 void
916 ARDOUR_UI::session_add_midi_track ()
917 {
918         cerr << _("Patience is a virtue.\n");
919 }
920
921 void
922 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
923 {
924         Route* route;
925
926         if (session == 0) {
927                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
928                 return;
929         }
930
931         try { 
932                 if (disk) {
933                         if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
934                                 error << _("could not create new audio track") << endmsg;
935                         }
936                 } else {
937                         if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
938                                 error << _("could not create new audio bus") << endmsg;
939                         }
940                 }
941                 
942 #if CONTROLOUTS
943                 if (need_control_room_outs) {
944                         pan_t pans[2];
945                         
946                         pans[0] = 0.5;
947                         pans[1] = 0.5;
948                         
949                         route->set_stereo_control_outs (control_lr_channels);
950                         route->control_outs()->set_stereo_pan (pans, this);
951                 }
952 #endif /* CONTROLOUTS */
953         }
954
955         catch (...) {
956                 ArdourMessage msg (editor, X_("noport dialog"),
957                                    _("There are insufficient JACK ports available\n\
958 to create a new track or bus.\n\
959 You should save Ardour, exit and\n\
960 restart JACK with more ports."));
961         }
962 }
963
964 void
965 ARDOUR_UI::diskstream_added (DiskStream* ds)
966 {
967 }
968
969 void
970 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
971 {
972         jack_nframes_t _preroll;
973
974         if (session) {
975                 _preroll = session->convert_to_frames_at (new_position, session->preroll);
976
977                 if (new_position > _preroll) {
978                         new_position -= _preroll;
979                 } else {
980                         new_position = 0;
981                 }
982
983                 session->request_locate (new_position);
984         }
985 }
986
987 void
988 ARDOUR_UI::transport_goto_start ()
989 {
990         if (session) {
991                 session->request_locate (0);
992
993                 
994                 /* force displayed area in editor to start no matter
995                    what "follow playhead" setting is.
996                 */
997                 
998                 if (editor) {
999                         editor->reposition_x_origin (0);
1000                 }
1001         }
1002 }
1003
1004 void
1005 ARDOUR_UI::transport_goto_end ()
1006 {
1007         if (session) {
1008                 jack_nframes_t frame = session->current_end_frame();
1009                 session->request_locate (frame);
1010
1011                 /* force displayed area in editor to start no matter
1012                    what "follow playhead" setting is.
1013                 */
1014                 
1015                 if (editor) {
1016                         editor->reposition_x_origin (frame);
1017                 }
1018         }
1019 }
1020
1021 void
1022 ARDOUR_UI::transport_stop ()
1023 {
1024         if (!session) {
1025                 return;
1026         }
1027
1028         if (session->is_auditioning()) {
1029                 session->cancel_audition ();
1030                 return;
1031         }
1032         
1033         if (session->get_auto_loop()) {
1034                 session->request_auto_loop (false);
1035         }
1036         
1037         session->request_stop ();
1038 }
1039
1040 void
1041 ARDOUR_UI::transport_stop_and_forget_capture ()
1042 {
1043         if (session) {
1044                 session->request_stop (true);
1045         }
1046 }
1047
1048 void
1049 ARDOUR_UI::remove_last_capture()
1050 {
1051         if (editor) {
1052                 editor->remove_last_capture();
1053         }
1054 }
1055
1056 void
1057 ARDOUR_UI::transport_record ()
1058 {
1059         if (session) {
1060                 switch (session->record_status()) {
1061                 case Session::Disabled:
1062                         if (session->ntracks() == 0) {
1063                                 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1064                                 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1065                                 return;
1066                         }
1067                         session->maybe_enable_record ();
1068                         break;
1069                 case Session::Recording:
1070                 case Session::Enabled:
1071                         session->disable_record ();
1072                 }
1073         }
1074 }
1075
1076 void
1077 ARDOUR_UI::transport_roll ()
1078 {
1079         bool rolling;
1080
1081         if (!session) {
1082                 return;
1083         }
1084
1085         rolling = session->transport_rolling ();
1086
1087         if (session->get_auto_loop()) {
1088                 session->request_auto_loop (false);
1089                 auto_loop_button.set_active (false);
1090                 roll_button.set_active (true);
1091         } else if (session->get_play_range ()) {
1092                 session->request_play_range (false);
1093                 play_selection_button.set_active (false);
1094         } else if (rolling) {
1095                 session->request_locate (session->last_transport_start(), true);
1096         }
1097
1098         session->request_transport_speed (1.0f);
1099 }
1100
1101 void
1102 ARDOUR_UI::transport_loop()
1103 {
1104         if (session) {
1105                 if (session->get_auto_loop()) {
1106                         if (session->transport_rolling()) {
1107                                 Location * looploc = session->locations()->auto_loop_location();
1108                                 if (looploc) {
1109                                         session->request_locate (looploc->start(), true);
1110                                 }
1111                         }
1112                 }
1113                 else {
1114                         session->request_auto_loop (true);
1115                 }
1116         }
1117 }
1118
1119 void
1120 ARDOUR_UI::transport_play_selection ()
1121 {
1122         if (!session) {
1123                 return;
1124         }
1125
1126         if (!session->get_play_range()) {
1127                 session->request_stop ();
1128         }
1129
1130         editor->play_selection ();
1131 }
1132
1133 void
1134 ARDOUR_UI::transport_rewind (int option)
1135 {
1136         float current_transport_speed;
1137  
1138         if (session) {
1139                 current_transport_speed = session->transport_speed();
1140                 
1141                 if (current_transport_speed >= 0.0f) {
1142                         switch (option) {
1143                         case 0:
1144                                 session->request_transport_speed (-1.0f);
1145                                 break;
1146                         case 1:
1147                                 session->request_transport_speed (-4.0f);
1148                                 break;
1149                         case -1:
1150                                 session->request_transport_speed (-0.5f);
1151                                 break;
1152                         }
1153                 } else {
1154                         /* speed up */
1155                         session->request_transport_speed (current_transport_speed * 1.5f);
1156                 }
1157         }
1158 }
1159
1160 void
1161 ARDOUR_UI::transport_forward (int option)
1162 {
1163         float current_transport_speed;
1164         
1165         if (session) {
1166                 current_transport_speed = session->transport_speed();
1167                 
1168                 if (current_transport_speed <= 0.0f) {
1169                         switch (option) {
1170                         case 0:
1171                                 session->request_transport_speed (1.0f);
1172                                 break;
1173                         case 1:
1174                                 session->request_transport_speed (4.0f);
1175                                 break;
1176                         case -1:
1177                                 session->request_transport_speed (0.5f);
1178                                 break;
1179                         }
1180                 } else {
1181                         /* speed up */
1182                         session->request_transport_speed (current_transport_speed * 1.5f);
1183                 }
1184         }
1185 }
1186
1187 void
1188 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
1189 {
1190         if (session == 0) {
1191                 return;
1192         }
1193
1194         DiskStream *ds;
1195
1196         if ((ds = session->diskstream_by_id (dstream)) != 0) {
1197                 Port *port = ds->io()->input (0);
1198                 port->request_monitor_input (!port->monitoring_input());
1199         }
1200 }
1201
1202 void
1203 ARDOUR_UI::toggle_record_enable (guint32 dstream)
1204 {
1205         if (session == 0) {
1206                 return;
1207         }
1208
1209         DiskStream *ds;
1210
1211         if ((ds = session->diskstream_by_id (dstream)) != 0) {
1212                 ds->set_record_enabled (!ds->record_enabled(), this);
1213         }
1214 }
1215
1216 void
1217 ARDOUR_UI::queue_transport_change ()
1218 {
1219         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1220 }
1221
1222 void
1223 ARDOUR_UI::map_transport_state ()
1224 {
1225         float sp = session->transport_speed();
1226
1227         if (sp == 1.0f) {
1228                 transport_rolling ();
1229         } else if (sp < 0.0f) {
1230                 transport_rewinding ();
1231         } else if (sp > 0.0f) {
1232                 transport_forwarding ();
1233         } else {
1234                 transport_stopped ();
1235         }
1236 }
1237
1238 void
1239 ARDOUR_UI::send_all_midi_feedback ()
1240 {
1241         if (session) {
1242                 session->send_all_midi_feedback();
1243         }
1244 }
1245
1246 void
1247 ARDOUR_UI::allow_local_only ()
1248 {
1249
1250 }
1251
1252 void
1253 ARDOUR_UI::allow_mmc_only ()
1254 {
1255
1256 }
1257
1258 void
1259 ARDOUR_UI::allow_mmc_and_local ()
1260 {
1261
1262 }
1263
1264 void
1265 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1266 {
1267         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1268                 (int) adj.get_value()].c_str());
1269 }
1270
1271 void
1272 ARDOUR_UI::engine_stopped ()
1273 {
1274         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1275         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1276         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1277 }
1278
1279
1280 void
1281 ARDOUR_UI::engine_running ()
1282 {
1283         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1284         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1285         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1286 }
1287
1288 void
1289 ARDOUR_UI::engine_halted ()
1290 {
1291         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1292
1293         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1294         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1295
1296         update_sample_rate (0);
1297
1298         ArdourMessage msg (editor, X_("halted"),
1299                            _("\
1300 JACK has either been shutdown or it\n\
1301 disconnected Ardour because Ardour\n\
1302 was not fast enough. You can save the\n\
1303 session and/or try to reconnect to JACK ."));
1304 }
1305
1306 int32_t
1307 ARDOUR_UI::do_engine_start ()
1308 {
1309         try { 
1310                 engine->start();
1311         }
1312
1313         catch (AudioEngine::PortRegistrationFailure& err) {
1314                 engine->stop ();
1315                 error << _("Unable to create all required ports")
1316                       << endmsg;
1317                 unload_session ();
1318                 return -1;
1319         }
1320
1321         catch (...) {
1322                 engine->stop ();
1323                 error << _("Unable to start the session running")
1324                       << endmsg;
1325                 unload_session ();
1326                 return -2;
1327         }
1328         
1329         return 0;
1330 }
1331
1332 gint
1333 ARDOUR_UI::start_engine ()
1334 {
1335         if (do_engine_start () == 0) {
1336                 if (session && _session_is_new) {
1337                         /* we need to retain initial visual 
1338                            settings for a new session 
1339                         */
1340                         session->save_state ("");
1341                 }
1342
1343                 /* there is too much going on, in too many threads, for us to 
1344                    end up with a clean session. So wait 1 second after loading,
1345                    and fix it up. its ugly, but until i come across a better
1346                    solution, its what we have.
1347                 */
1348
1349                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
1350         }
1351
1352         return FALSE;
1353 }
1354
1355 void
1356 ARDOUR_UI::update_clocks ()
1357 {
1358          Clock (session->audible_frame()); /* EMIT_SIGNAL */
1359 }
1360
1361 void
1362 ARDOUR_UI::start_clocking ()
1363 {
1364         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1365 }
1366
1367 void
1368 ARDOUR_UI::stop_clocking ()
1369 {
1370         clock_signal_connection.disconnect ();
1371 }
1372         
1373 void
1374 ARDOUR_UI::toggle_clocking ()
1375 {
1376 #if 0
1377         if (clock_button.get_active()) {
1378                 start_clocking ();
1379         } else {
1380                 stop_clocking ();
1381         }
1382 #endif
1383 }
1384
1385 gint
1386 ARDOUR_UI::_blink (void *arg)
1387
1388 {
1389         ((ARDOUR_UI *) arg)->blink ();
1390         return TRUE;
1391 }
1392
1393 void
1394 ARDOUR_UI::blink ()
1395 {
1396          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1397 }
1398
1399 void
1400 ARDOUR_UI::start_blinking ()
1401 {
1402         /* Start the blink signal. Everybody with a blinking widget
1403            uses Blink to drive the widget's state.
1404         */
1405
1406         if (blink_timeout_tag < 0) {
1407                 blink_on = false;       
1408                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
1409         }
1410 }
1411
1412 void
1413 ARDOUR_UI::stop_blinking ()
1414 {
1415         if (blink_timeout_tag >= 0) {
1416                 gtk_timeout_remove (blink_timeout_tag);
1417                 blink_timeout_tag = -1;
1418         }
1419 }
1420
1421
1422 void
1423 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
1424 {
1425         using namespace Gtk;
1426         using namespace Menu_Helpers;
1427
1428         if (dstream.hidden()) {
1429                 return;
1430         }
1431
1432         MenuList& items = diskstream_menu->items();
1433         items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
1434 }
1435         
1436 void
1437 ARDOUR_UI::diskstream_selected (gint32 id)
1438 {
1439         selected_dstream = id;
1440         Main::quit ();
1441 }
1442
1443 gint32
1444 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
1445 {
1446         using namespace Gtk;
1447         using namespace Menu_Helpers;
1448
1449         if (session == 0) {
1450                 return -1;
1451         }
1452
1453         diskstream_menu = new Menu();
1454         diskstream_menu->set_name ("ArdourContextMenu");
1455         using namespace Gtk;
1456         using namespace Menu_Helpers;
1457
1458         MenuList& items = diskstream_menu->items();
1459         items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
1460
1461         session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
1462
1463         if (ev) {
1464                 diskstream_menu->popup (ev->button, ev->time);
1465         } else {
1466                 diskstream_menu->popup (0, 0);
1467         }
1468
1469         selected_dstream = -1;
1470
1471         Main::run ();
1472
1473         delete diskstream_menu;
1474
1475         return selected_dstream;
1476 }
1477
1478 void
1479 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
1480                           string& buf,
1481                           IO& io,
1482                           bool in)
1483 {
1484         if (in) {
1485                 if (io.n_inputs() == 0) {
1486                         buf = _("none");
1487                         return;
1488                 }
1489                 
1490                 /* XXX we're not handling multiple ports yet. */
1491
1492                 const char **connections = io.input(0)->get_connections();
1493                 
1494                 if (connections == 0 || connections[0] == '\0') {
1495                         buf = _("off");
1496                 } else {
1497                         buf = connections[0];
1498                 }
1499
1500                 free (connections);
1501
1502         } else {
1503
1504                 if (io.n_outputs() == 0) {
1505                         buf = _("none");
1506                         return;
1507                 }
1508                 
1509                 /* XXX we're not handling multiple ports yet. */
1510
1511                 const char **connections = io.output(0)->get_connections();
1512                 
1513                 if (connections == 0 || connections[0] == '\0') {
1514                         buf = _("off");
1515                 } else {
1516                         buf = connections[0];
1517                 }
1518
1519                 free (connections);
1520         }
1521 }
1522
1523 void
1524 ARDOUR_UI::snapshot_session ()
1525 {
1526         ArdourPrompter prompter (true);
1527         string snapname;
1528         string now;
1529         time_t n;
1530
1531         time (&n);
1532         now = ctime (&n);
1533         now = now.substr (0, now.length() - 1);
1534
1535         prompter.set_name ("Prompter");
1536         prompter.set_prompt (_("Name for snapshot"));
1537         prompter.set_initial_text (now);
1538         
1539         switch (prompter.run()) {
1540         case RESPONSE_ACCEPT:
1541                 prompter.get_result (snapname);
1542                 if (snapname.length()){
1543                         save_state (snapname);
1544                 }
1545                 break;
1546
1547         default:
1548                 break;
1549         }
1550 }
1551
1552 void
1553 ARDOUR_UI::save_state (const string & name)
1554 {
1555         (void) save_state_canfail (name);
1556 }
1557                 
1558 int
1559 ARDOUR_UI::save_state_canfail (string name)
1560 {
1561         if (session) {
1562                 int ret;
1563
1564                 if (name.length() == 0) {
1565                         name = session->snap_name();
1566                 }
1567
1568                 if ((ret = session->save_state (name)) != 0) {
1569                         return ret;
1570                 }
1571         }
1572         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1573         return 0;
1574 }
1575
1576 void
1577 ARDOUR_UI::restore_state (string name)
1578 {
1579         if (session) {
1580                 if (name.length() == 0) {
1581                         name = session->name();
1582                 }
1583                 session->restore_state (name);
1584         }
1585 }
1586
1587 void
1588 ARDOUR_UI::primary_clock_value_changed ()
1589 {
1590         if (session) {
1591                 session->request_locate (primary_clock.current_time ());
1592         }
1593 }
1594
1595 void
1596 ARDOUR_UI::secondary_clock_value_changed ()
1597 {
1598         if (session) {
1599                 session->request_locate (secondary_clock.current_time ());
1600         }
1601 }
1602
1603 void
1604 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
1605 {
1606         if (session && dstream && dstream->record_enabled()) {
1607
1608                 Session::RecordState rs;
1609                 
1610                 rs = session->record_status ();
1611
1612                 switch (rs) {
1613                 case Session::Disabled:
1614                 case Session::Enabled:
1615                         if (w->get_state() != STATE_SELECTED) {
1616                                 w->set_state (STATE_SELECTED);
1617                         }
1618                         break;
1619
1620                 case Session::Recording:
1621                         if (w->get_state() != STATE_ACTIVE) {
1622                                 w->set_state (STATE_ACTIVE);
1623                         }
1624                         break;
1625                 }
1626
1627         } else {
1628                 if (w->get_state() != STATE_NORMAL) {
1629                         w->set_state (STATE_NORMAL);
1630                 }
1631         }
1632 }
1633
1634 void
1635 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
1636 {
1637         if (session == 0) {
1638                 return;
1639         }
1640         
1641         switch (session->record_status()) {
1642         case Session::Enabled:
1643                 if (onoff) {
1644                         rec_button.set_state (1);
1645                 } else {
1646                         rec_button.set_state (0);
1647                 }
1648                 break;
1649
1650         case Session::Recording:
1651                 rec_button.set_state (2);
1652                 break;
1653
1654         default:
1655                 rec_button.set_state (0);
1656                 break;
1657         }
1658 }
1659
1660 gint
1661 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1662 {
1663         window->hide();
1664         Gtk::Main::quit ();
1665         return TRUE;
1666 }
1667
1668 void
1669 ARDOUR_UI::start_keyboard_prefix ()
1670 {
1671         keyboard->start_prefix();
1672 }
1673
1674 void
1675 ARDOUR_UI::save_template ()
1676
1677 {
1678         ArdourPrompter prompter (true);
1679         string name;
1680
1681         prompter.set_name (X_("Prompter"));
1682         prompter.set_prompt (_("Name for mix template:"));
1683         prompter.set_initial_text(session->name() + _("-template"));
1684         
1685         switch (prompter.run()) {
1686         case RESPONSE_ACCEPT:
1687                 prompter.get_result (name);
1688                 
1689                 if (name.length()) {
1690                         session->save_template (name);
1691                 }
1692                 break;
1693
1694         default:
1695                 break;
1696         }
1697 }
1698
1699 void
1700 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1701 {
1702         m_new_session_dialog->show_all();
1703         m_new_session_dialog->set_transient_for(*editor);
1704         m_new_session_dialog->set_name(predetermined_path);
1705
1706         int response = Gtk::RESPONSE_CANCEL;
1707
1708         do {
1709                 response = m_new_session_dialog->run ();
1710         
1711                 if(response == Gtk::RESPONSE_OK) {
1712
1713                         _session_is_new = true;
1714                         
1715                         std::string session_name = m_new_session_dialog->session_name();
1716                         std::string session_path = m_new_session_dialog->session_folder();
1717                         
1718                         /*
1719                           XXX This is needed because session constructor wants a 
1720                           non-existant path. hopefully this will be fixed at some point.
1721                         */
1722                         session_path = Glib::build_filename(session_path, session_name);
1723                         
1724                         std::string template_name = m_new_session_dialog->session_template_name();
1725                         
1726                         if (m_new_session_dialog->use_session_template()) {
1727                                 
1728                                 load_session (session_path, session_name, &template_name);
1729                                 
1730                         } else {
1731                                 
1732                                 uint32_t cchns;
1733                                 uint32_t mchns;
1734                                 Session::AutoConnectOption iconnect;
1735                                 Session::AutoConnectOption oconnect;
1736                                 
1737                                 if (m_new_session_dialog->create_control_bus()) {
1738                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1739                                 } else {
1740                                         cchns = 0;
1741                                 }
1742                                 
1743                                 if (m_new_session_dialog->create_master_bus()) {
1744                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1745                                 } else {
1746                                         mchns = 0;
1747                                 }
1748                                 
1749                                 if (m_new_session_dialog->connect_inputs()) {
1750                                         iconnect = Session::AutoConnectPhysical;
1751                                 } else {
1752                                         iconnect = Session::AutoConnectOption (0);
1753                                 }
1754                                 
1755                                 /// @todo some minor tweaks.
1756
1757                                 if (m_new_session_dialog->connect_outs_to_master()) {
1758                                         oconnect = Session::AutoConnectMaster;
1759                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1760                                         oconnect = Session::AutoConnectPhysical;
1761                                 } else {
1762                                         oconnect = Session::AutoConnectOption (0);
1763                                 } 
1764                                 
1765                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1766                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1767                                 
1768                                 build_session (session_path,
1769                                                session_name,
1770                                                cchns,
1771                                                mchns,
1772                                                iconnect,
1773                                                oconnect,
1774                                                nphysin,
1775                                                nphysout, 
1776                                                engine->frame_rate() * 60 * 5);
1777                         }               
1778                 }
1779
1780         } while(response == Gtk::RESPONSE_HELP);
1781         m_new_session_dialog->hide_all();
1782 }
1783
1784 int
1785 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1786 {
1787         Session *new_session;
1788         int x;
1789         session_loaded = false;
1790         x = unload_session ();
1791
1792         if (x < 0) {
1793                 return -1;
1794         } else if (x > 0) {
1795                 return 0;
1796         }
1797
1798         /* if it already exists, we must have write access */
1799
1800         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1801                 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
1802 You do not have write access to this session.\n\
1803 This prevents the session from being loaded."));
1804                 return -1;
1805         }
1806
1807         try {
1808                 new_session = new Session (*engine, path, snap_name, mix_template);
1809         }
1810
1811         catch (...) {
1812
1813                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1814                 return -1;
1815         }
1816
1817         connect_to_session (new_session);
1818
1819         //if (engine->running()) {
1820         //mixer->show_window();
1821         //}
1822         session_loaded = true;
1823         return 0;
1824 }
1825
1826 int
1827 ARDOUR_UI::make_session_clean ()
1828 {
1829         if (session) {
1830                 session->set_clean ();
1831         }
1832
1833         return FALSE;
1834 }
1835
1836 int
1837 ARDOUR_UI::build_session (const string & path, const string & snap_name, 
1838                           uint32_t control_channels,
1839                           uint32_t master_channels, 
1840                           Session::AutoConnectOption input_connect,
1841                           Session::AutoConnectOption output_connect,
1842                           uint32_t nphysin,
1843                           uint32_t nphysout,
1844                           jack_nframes_t initial_length)
1845 {
1846         Session *new_session;
1847         int x;
1848
1849         session_loaded = false;
1850         x = unload_session ();
1851         if (x < 0) {
1852                 return -1;
1853         } else if (x > 0) {
1854                 return 0;
1855         }
1856         
1857         _session_is_new = true;
1858
1859         try {
1860                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1861                                            control_channels, master_channels, nphysin, nphysout, initial_length);
1862         }
1863
1864         catch (...) {
1865
1866                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1867                 return -1;
1868         }
1869
1870         connect_to_session (new_session);
1871
1872         //if (engine->running()) {
1873         //mixer->show_window();
1874         //}
1875         session_loaded = true;
1876         return 0;
1877 }
1878
1879 void
1880 ARDOUR_UI::show ()
1881 {
1882         if (editor) {
1883                 editor->show_window ();
1884                 shown_flag = true;
1885         }
1886
1887         if (session && mixer) {
1888                 // mixer->show_window ();
1889         }
1890         
1891         if (about) {
1892                 about->present ();
1893         }
1894 }
1895
1896 void
1897 ARDOUR_UI::show_splash ()
1898 {
1899         if (about == 0) {
1900                 about = new About();
1901         }
1902         about->present();
1903 }
1904
1905 void
1906 ARDOUR_UI::hide_splash ()
1907 {
1908         if (about) {
1909                 // about->hide();
1910         }
1911 }
1912
1913 void
1914 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1915 {
1916         size_t removed;
1917
1918         removed = rep.paths.size();
1919
1920         if (removed == 0) {
1921                 ArdourMessage msg (editor, X_("cleanupresults"),
1922                                    _("\
1923 No audio files were ready for cleanup\n\n\
1924 If this seems suprising, check for any existing\n\
1925 snapshots. These may still include regions that\n\
1926 require some unused files to continue to exist."));
1927                 return;
1928         } 
1929
1930         ArdourDialog results (_("ardour: cleanup"), true);
1931         
1932         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1933             CleanupResultsModelColumns() { 
1934                     add (visible_name);
1935                     add (fullpath);
1936             }
1937             Gtk::TreeModelColumn<Glib::ustring> visible_name;
1938             Gtk::TreeModelColumn<Glib::ustring> fullpath;
1939         };
1940
1941         
1942         Glib::RefPtr<Gtk::ListStore> results_model;
1943         CleanupResultsModelColumns results_columns;
1944         Gtk::TreeView results_display;
1945         
1946         results_model = ListStore::create (results_columns);
1947         results_display.set_model (results_model);
1948         results_display.append_column (list_title, results_columns.visible_name);
1949         results_display.set_headers_visible (true);
1950
1951         Gtk::ScrolledWindow list_scroller;
1952         Gtk::Label txt;
1953
1954         if (rep.space < 1048576.0f) {
1955                 if (removed > 1) {
1956                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
1957                 } else {
1958                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
1959                 }
1960         } else {
1961                 if (removed > 1) {
1962                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
1963                 } else {
1964                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
1965                 }
1966         }
1967
1968         results.get_vbox()->pack_start (txt, false, false);
1969         
1970         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1971                 TreeModel::Row row = *(results_model->append());
1972                 row[results_columns.visible_name] = *i;
1973                 row[results_columns.fullpath] = *i;
1974         }
1975         
1976         list_scroller.add (results_display);
1977         list_scroller.set_size_request (-1, 250);
1978         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1979         
1980         results.get_vbox()->pack_start (list_scroller, true, true);
1981         results.add_button (Stock::OK, RESPONSE_ACCEPT);
1982         results.set_position (Gtk::WIN_POS_MOUSE);
1983
1984         results.run ();
1985 }
1986
1987 void
1988 ARDOUR_UI::cleanup ()
1989 {
1990         if (session == 0) {
1991                 /* shouldn't happen: menu item is insensitive */
1992                 return;
1993         }
1994
1995         ArdourDialog checker (_("ardour cleanup"));
1996         Gtk::Label label (_("\
1997 Cleanup is a destructive operation.\n\
1998 ALL undo/redo information will be lost if you cleanup.\n\
1999 Unused audio files will be moved to a \"dead sounds\" location."));
2000         
2001         checker.get_vbox()->pack_start (label, false, false);
2002         checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2003         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2004
2005         checker.set_name (_("CleanupDialog"));
2006         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2007         checker.set_position (Gtk::WIN_POS_MOUSE);
2008
2009         switch (checker.run()) {
2010         case RESPONSE_ACCEPT:
2011                 break;
2012         default:
2013                 return;
2014         }
2015
2016         Session::cleanup_report rep;
2017
2018         editor->prepare_for_cleanup ();
2019
2020         if (session->cleanup_sources (rep)) {
2021                 return;
2022         }
2023
2024         display_cleanup_results (rep, 
2025                                  _("cleaned files"),
2026                                  _("\
2027 The following %1 %2 were not in use.\n\
2028 The next time you flush the wastebasket\n\
2029 it will release an additional %3 %4bytes\n\
2030 of disk space"
2031                                          ));
2032 }
2033
2034 void
2035 ARDOUR_UI::flush_trash ()
2036 {
2037         if (session == 0) {
2038                 /* shouldn't happen: menu item is insensitive */
2039                 return;
2040         }
2041
2042         Session::cleanup_report rep;
2043
2044         if (session->cleanup_trash_sources (rep)) {
2045                 return;
2046         }
2047
2048         display_cleanup_results (rep, 
2049                                  _("deleted file"),
2050                                  _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2051 }
2052
2053 void
2054 ARDOUR_UI::add_route ()
2055 {
2056         int count;
2057
2058         if (!session) {
2059                 return;
2060         }
2061
2062         if (add_route_dialog == 0) {
2063                 add_route_dialog = new AddRouteDialog;
2064                 editor->ensure_float (*add_route_dialog);
2065         }
2066
2067         if (add_route_dialog->is_visible()) {
2068                 /* we're already doing this */
2069                 return;
2070         }
2071
2072         ResponseType r = (ResponseType) add_route_dialog->run ();
2073         
2074         add_route_dialog->hide();
2075
2076         switch (r) {
2077         case RESPONSE_ACCEPT:
2078                 break;
2079         default:
2080                 return;
2081                 break;
2082         }
2083
2084         if ((count = add_route_dialog->count()) <= 0) {
2085                 return;
2086         }
2087
2088         uint32_t input_chan = add_route_dialog->channels ();
2089         uint32_t output_chan;
2090         string name_template = add_route_dialog->name_template ();
2091         bool track = add_route_dialog->track ();
2092
2093         Session::AutoConnectOption oac = session->get_output_auto_connect();
2094
2095         if (oac & Session::AutoConnectMaster) {
2096                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2097         } else {
2098                 output_chan = input_chan;
2099         }
2100
2101         /* XXX do something with name template */
2102
2103         while (count) {
2104                 if (track) {
2105                         session_add_audio_track (input_chan, output_chan);
2106                 } else {
2107                         session_add_audio_bus (input_chan, output_chan);
2108                 }
2109                 --count;
2110                 
2111                 while (Main::events_pending()) {
2112                         Main::iteration ();
2113                 }
2114         }
2115 }
2116
2117 XMLNode*
2118 ARDOUR_UI::mixer_settings () const
2119 {
2120         XMLNode* node = 0;
2121
2122         if (session) {
2123                 node = session->instant_xml(X_("Mixer"), session->path());
2124         } else {
2125                 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
2126         }
2127
2128         if (!node) {
2129                 node = new XMLNode (X_("Mixer"));
2130         }
2131
2132         return node;
2133 }
2134
2135 XMLNode*
2136 ARDOUR_UI::editor_settings () const
2137 {
2138         XMLNode* node = 0;
2139
2140         if (session) {
2141                 node = session->instant_xml(X_("Editor"), session->path());
2142         } else {
2143                 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
2144         }
2145
2146         if (!node) {
2147                 node = new XMLNode (X_("Editor"));
2148         }
2149         return node;
2150 }
2151
2152 XMLNode*
2153 ARDOUR_UI::keyboard_settings () const
2154 {
2155         XMLNode* node = 0;
2156
2157         node = Config->extra_xml(X_("Keyboard"));
2158         
2159         if (!node) {
2160                 node = new XMLNode (X_("Keyboard"));
2161         }
2162         return node;
2163 }
2164
2165 void
2166 ARDOUR_UI::halt_on_xrun_message ()
2167 {
2168         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2169
2170         ArdourMessage msg (editor, X_("haltonxrun"),
2171                            _("Recording was stopped because your system could not keep up."));
2172 }
2173
2174 void 
2175 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
2176 {
2177         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2178
2179         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2180                 delete *i;
2181         }
2182
2183         delete deletion_list;
2184 }
2185
2186 void
2187 ARDOUR_UI::disk_overrun_handler ()
2188 {
2189         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2190
2191         if (!have_disk_overrun_displayed) {
2192                 have_disk_overrun_displayed = true;
2193                 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
2194 The disk system on your computer\n\
2195 was not able to keep up with Ardour.\n\
2196 \n\
2197 Specifically, it failed to write data to disk\n\
2198 quickly enough to keep up with recording.\n"));
2199                 have_disk_overrun_displayed = false;
2200         }
2201 }
2202
2203 void
2204 ARDOUR_UI::disk_underrun_handler ()
2205 {
2206         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2207
2208         if (!have_disk_underrun_displayed) {
2209                 have_disk_underrun_displayed = true;
2210                 ArdourMessage msg (editor, X_("diskrate2 dialog"),
2211                         (_("The disk system on your computer\n\
2212 was not able to keep up with Ardour.\n\
2213 \n\
2214 Specifically, it failed to read data from disk\n\
2215 quickly enough to keep up with playback.\n")));
2216                 have_disk_underrun_displayed = false;
2217         } 
2218 }
2219
2220 void
2221 ARDOUR_UI::disk_underrun_message_gone ()
2222 {
2223         have_disk_underrun_displayed = false;
2224 }
2225
2226 void
2227 ARDOUR_UI::disk_overrun_message_gone ()
2228 {
2229         have_disk_underrun_displayed = false;
2230 }
2231
2232 int
2233 ARDOUR_UI::pending_state_dialog ()
2234 {
2235         ArdourDialog dialog ("pending state dialog");
2236         Label  message (_("\
2237 This session appears to have been in\n\
2238 middle of recording when ardour or\n\
2239 the computer was shutdown.\n\
2240 \n\
2241 Ardour can recover any captured audio for\n\
2242 you, or it can ignore it. Please decide\n\
2243 what you would like to do.\n"));
2244
2245         dialog.get_vbox()->pack_start (message);
2246         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2247         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2248
2249         dialog.set_position (WIN_POS_CENTER);
2250         dialog.show_all ();
2251         
2252         switch (dialog.run ()) {
2253         case RESPONSE_ACCEPT:
2254                 break;
2255         default:
2256                 return 1;
2257         }
2258
2259         return 0;
2260 }
2261         
2262         
2263 void
2264 ARDOUR_UI::disconnect_from_jack ()
2265 {
2266         if (engine) {
2267                 if( engine->disconnect_from_jack ()) {
2268                         ArdourMessage msg (editor, X_("nojack dialog"),
2269                                            _("Could not disconnect from JACK"));
2270                 }
2271
2272                 update_sample_rate (0);
2273         }
2274 }
2275
2276 void
2277 ARDOUR_UI::reconnect_to_jack ()
2278 {
2279         if (engine) {
2280                 if (engine->reconnect_to_jack ()) {
2281                         ArdourMessage msg (editor, X_("nojack dialog"),
2282                                            _("Could not reconnect to JACK"));
2283                 }
2284
2285                 update_sample_rate (0);
2286         }
2287 }
2288
2289 void
2290 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2291 {
2292         engine->request_buffer_size (nframes);
2293         update_sample_rate (0);
2294 }
2295
2296 int
2297 ARDOUR_UI::cmdline_new_session (string path)
2298 {
2299         if (path[0] != '/') {
2300                 char buf[PATH_MAX+1];
2301                 string str;
2302
2303                 getcwd (buf, sizeof (buf));
2304                 str = buf;
2305                 str += '/';
2306                 str += path;
2307                 path = str;
2308         }
2309
2310         new_session (false, path);
2311
2312         _will_create_new_session_automatically = false; /* done it */
2313         return FALSE; /* don't call it again */
2314 }