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