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