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