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