732c829a3858a59c97247bb473f22b83b7d61b09
[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/port.h>
50 #include <ardour/audioengine.h>
51 #include <ardour/playlist.h>
52 #include <ardour/utils.h>
53 #include <ardour/audio_diskstream.h>
54 #include <ardour/audiofilesource.h>
55 #include <ardour/recent_sessions.h>
56 #include <ardour/session_diskstream.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::AudioDiskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
190         ARDOUR::AudioDiskstream::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 (AudioDiskstream& ds)
547 {
548         if (ds.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, _("space: 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_audio_diskstream (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), _("space: %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         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::diskstream_added (AudioDiskstream* ds)
922 {
923 }
924
925 void
926 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
927 {
928         jack_nframes_t _preroll;
929
930         if (session) {
931                 _preroll = session->convert_to_frames_at (new_position, session->preroll);
932
933                 if (new_position > _preroll) {
934                         new_position -= _preroll;
935                 } else {
936                         new_position = 0;
937                 }
938
939                 session->request_locate (new_position);
940         }
941 }
942
943 void
944 ARDOUR_UI::transport_goto_start ()
945 {
946         if (session) {
947                 session->goto_start();
948
949                 
950                 /* force displayed area in editor to start no matter
951                    what "follow playhead" setting is.
952                 */
953                 
954                 if (editor) {
955                         editor->reposition_x_origin (session->current_start_frame());
956                 }
957         }
958 }
959
960 void
961 ARDOUR_UI::transport_goto_zero ()
962 {
963         if (session) {
964                 session->request_locate (0);
965
966                 
967                 /* force displayed area in editor to start no matter
968                    what "follow playhead" setting is.
969                 */
970                 
971                 if (editor) {
972                         editor->reposition_x_origin (0);
973                 }
974         }
975 }
976
977 void
978 ARDOUR_UI::transport_goto_end ()
979 {
980         if (session) {
981                 jack_nframes_t frame = session->current_end_frame();
982                 session->request_locate (frame);
983
984                 /* force displayed area in editor to start no matter
985                    what "follow playhead" setting is.
986                 */
987                 
988                 if (editor) {
989                         editor->reposition_x_origin (frame);
990                 }
991         }
992 }
993
994 void
995 ARDOUR_UI::transport_stop ()
996 {
997         if (!session) {
998                 return;
999         }
1000
1001         if (session->is_auditioning()) {
1002                 session->cancel_audition ();
1003                 return;
1004         }
1005         
1006         if (session->get_auto_loop()) {
1007                 session->request_auto_loop (false);
1008         }
1009         
1010         session->request_stop ();
1011 }
1012
1013 void
1014 ARDOUR_UI::transport_stop_and_forget_capture ()
1015 {
1016         if (session) {
1017                 session->request_stop (true);
1018         }
1019 }
1020
1021 void
1022 ARDOUR_UI::remove_last_capture()
1023 {
1024         if (editor) {
1025                 editor->remove_last_capture();
1026         }
1027 }
1028
1029 void
1030 ARDOUR_UI::transport_record ()
1031 {
1032         if (session) {
1033                 switch (session->record_status()) {
1034                 case Session::Disabled:
1035                         if (session->ntracks() == 0) {
1036                                 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1037                                 MessageDialog msg (*editor, txt);
1038                                 msg.run ();
1039                                 return;
1040                         }
1041                         session->maybe_enable_record ();
1042                         break;
1043                 case Session::Recording:
1044                 case Session::Enabled:
1045                         session->disable_record (true);
1046                 }
1047         }
1048 }
1049
1050 void
1051 ARDOUR_UI::transport_roll ()
1052 {
1053         bool rolling;
1054
1055         if (!session) {
1056                 return;
1057         }
1058
1059         rolling = session->transport_rolling ();
1060
1061         if (session->get_auto_loop()) {
1062                 session->request_auto_loop (false);
1063                 auto_loop_button.set_active (false);
1064                 roll_button.set_active (true);
1065         } else if (session->get_play_range ()) {
1066                 session->request_play_range (false);
1067                 play_selection_button.set_active (false);
1068         } else if (rolling) {
1069                 session->request_locate (session->last_transport_start(), true);
1070         }
1071
1072         session->request_transport_speed (1.0f);
1073 }
1074
1075 void
1076 ARDOUR_UI::transport_loop()
1077 {
1078         if (session) {
1079                 if (session->get_auto_loop()) {
1080                         if (session->transport_rolling()) {
1081                                 Location * looploc = session->locations()->auto_loop_location();
1082                                 if (looploc) {
1083                                         session->request_locate (looploc->start(), true);
1084                                 }
1085                         }
1086                 }
1087                 else {
1088                         session->request_auto_loop (true);
1089                 }
1090         }
1091 }
1092
1093 void
1094 ARDOUR_UI::transport_play_selection ()
1095 {
1096         if (!session) {
1097                 return;
1098         }
1099
1100         if (!session->get_play_range()) {
1101                 session->request_stop ();
1102         }
1103
1104         editor->play_selection ();
1105 }
1106
1107 void
1108 ARDOUR_UI::transport_rewind (int option)
1109 {
1110         float current_transport_speed;
1111  
1112         if (session) {
1113                 current_transport_speed = session->transport_speed();
1114                 
1115                 if (current_transport_speed >= 0.0f) {
1116                         switch (option) {
1117                         case 0:
1118                                 session->request_transport_speed (-1.0f);
1119                                 break;
1120                         case 1:
1121                                 session->request_transport_speed (-4.0f);
1122                                 break;
1123                         case -1:
1124                                 session->request_transport_speed (-0.5f);
1125                                 break;
1126                         }
1127                 } else {
1128                         /* speed up */
1129                         session->request_transport_speed (current_transport_speed * 1.5f);
1130                 }
1131         }
1132 }
1133
1134 void
1135 ARDOUR_UI::transport_forward (int option)
1136 {
1137         float current_transport_speed;
1138         
1139         if (session) {
1140                 current_transport_speed = session->transport_speed();
1141                 
1142                 if (current_transport_speed <= 0.0f) {
1143                         switch (option) {
1144                         case 0:
1145                                 session->request_transport_speed (1.0f);
1146                                 break;
1147                         case 1:
1148                                 session->request_transport_speed (4.0f);
1149                                 break;
1150                         case -1:
1151                                 session->request_transport_speed (0.5f);
1152                                 break;
1153                         }
1154                 } else {
1155                         /* speed up */
1156                         session->request_transport_speed (current_transport_speed * 1.5f);
1157                 }
1158         }
1159 }
1160
1161 void
1162 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1163 {
1164         if (session == 0) {
1165                 return;
1166         }
1167
1168         Route* r;
1169         
1170         if ((r = session->route_by_remote_id (dstream)) != 0) {
1171
1172                 AudioTrack* at;
1173
1174                 if ((at = dynamic_cast<AudioTrack*>(r)) != 0) {
1175                         at->disk_stream().set_record_enabled (!at->disk_stream().record_enabled(), this);
1176                 }
1177         }
1178 }
1179
1180 void
1181 ARDOUR_UI::queue_transport_change ()
1182 {
1183         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1184 }
1185
1186 void
1187 ARDOUR_UI::map_transport_state ()
1188 {
1189         float sp = session->transport_speed();
1190
1191         if (sp == 1.0f) {
1192                 transport_rolling ();
1193         } else if (sp < 0.0f) {
1194                 transport_rewinding ();
1195         } else if (sp > 0.0f) {
1196                 transport_forwarding ();
1197         } else {
1198                 transport_stopped ();
1199         }
1200 }
1201
1202 void
1203 ARDOUR_UI::allow_local_only ()
1204 {
1205
1206 }
1207
1208 void
1209 ARDOUR_UI::allow_mmc_only ()
1210 {
1211
1212 }
1213
1214 void
1215 ARDOUR_UI::allow_mmc_and_local ()
1216 {
1217
1218 }
1219
1220 void
1221 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1222 {
1223         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1224                 (int) adj.get_value()].c_str());
1225 }
1226
1227 void
1228 ARDOUR_UI::engine_stopped ()
1229 {
1230         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1231         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1232         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1233 }
1234
1235
1236 void
1237 ARDOUR_UI::engine_running ()
1238 {
1239         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1240         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1241         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1242 }
1243
1244 void
1245 ARDOUR_UI::engine_halted ()
1246 {
1247         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1248
1249         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1250         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1251
1252         update_sample_rate (0);
1253
1254         MessageDialog msg (*editor, 
1255                            _("\
1256 JACK has either been shutdown or it\n\
1257 disconnected Ardour because Ardour\n\
1258 was not fast enough. You can save the\n\
1259 session and/or try to reconnect to JACK ."));
1260         msg.run ();
1261 }
1262
1263 int32_t
1264 ARDOUR_UI::do_engine_start ()
1265 {
1266         try { 
1267                 engine->start();
1268         }
1269
1270         catch (AudioEngine::PortRegistrationFailure& err) {
1271                 engine->stop ();
1272                 error << _("Unable to create all required ports")
1273                       << endmsg;
1274                 unload_session ();
1275                 return -1;
1276         }
1277
1278         catch (...) {
1279                 engine->stop ();
1280                 error << _("Unable to start the session running")
1281                       << endmsg;
1282                 unload_session ();
1283                 return -2;
1284         }
1285         
1286         return 0;
1287 }
1288
1289 gint
1290 ARDOUR_UI::start_engine ()
1291 {
1292         if (do_engine_start () == 0) {
1293                 if (session && _session_is_new) {
1294                         /* we need to retain initial visual 
1295                            settings for a new session 
1296                         */
1297                         session->save_state ("");
1298                 }
1299
1300                 /* there is too much going on, in too many threads, for us to 
1301                    end up with a clean session. So wait 1 second after loading,
1302                    and fix it up. its ugly, but until i come across a better
1303                    solution, its what we have.
1304                 */
1305
1306                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
1307         }
1308
1309         return FALSE;
1310 }
1311
1312 void
1313 ARDOUR_UI::update_clocks ()
1314 {
1315          Clock (session->audible_frame()); /* EMIT_SIGNAL */
1316 }
1317
1318 void
1319 ARDOUR_UI::start_clocking ()
1320 {
1321         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1322 }
1323
1324 void
1325 ARDOUR_UI::stop_clocking ()
1326 {
1327         clock_signal_connection.disconnect ();
1328 }
1329         
1330 void
1331 ARDOUR_UI::toggle_clocking ()
1332 {
1333 #if 0
1334         if (clock_button.get_active()) {
1335                 start_clocking ();
1336         } else {
1337                 stop_clocking ();
1338         }
1339 #endif
1340 }
1341
1342 gint
1343 ARDOUR_UI::_blink (void *arg)
1344
1345 {
1346         ((ARDOUR_UI *) arg)->blink ();
1347         return TRUE;
1348 }
1349
1350 void
1351 ARDOUR_UI::blink ()
1352 {
1353          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1354 }
1355
1356 void
1357 ARDOUR_UI::start_blinking ()
1358 {
1359         /* Start the blink signal. Everybody with a blinking widget
1360            uses Blink to drive the widget's state.
1361         */
1362
1363         if (blink_timeout_tag < 0) {
1364                 blink_on = false;       
1365                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
1366         }
1367 }
1368
1369 void
1370 ARDOUR_UI::stop_blinking ()
1371 {
1372         if (blink_timeout_tag >= 0) {
1373                 gtk_timeout_remove (blink_timeout_tag);
1374                 blink_timeout_tag = -1;
1375         }
1376 }
1377
1378 void
1379 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
1380                           string& buf,
1381                           IO& io,
1382                           bool in)
1383 {
1384         if (in) {
1385                 if (io.n_inputs() == 0) {
1386                         buf = _("none");
1387                         return;
1388                 }
1389                 
1390                 /* XXX we're not handling multiple ports yet. */
1391
1392                 const char **connections = io.input(0)->get_connections();
1393                 
1394                 if (connections == 0 || connections[0] == '\0') {
1395                         buf = _("off");
1396                 } else {
1397                         buf = connections[0];
1398                 }
1399
1400                 free (connections);
1401
1402         } else {
1403
1404                 if (io.n_outputs() == 0) {
1405                         buf = _("none");
1406                         return;
1407                 }
1408                 
1409                 /* XXX we're not handling multiple ports yet. */
1410
1411                 const char **connections = io.output(0)->get_connections();
1412                 
1413                 if (connections == 0 || connections[0] == '\0') {
1414                         buf = _("off");
1415                 } else {
1416                         buf = connections[0];
1417                 }
1418
1419                 free (connections);
1420         }
1421 }
1422
1423 void
1424 ARDOUR_UI::snapshot_session ()
1425 {
1426         ArdourPrompter prompter (true);
1427         string snapname;
1428         string now;
1429         time_t n;
1430
1431         time (&n);
1432         now = ctime (&n);
1433         now = now.substr (20, 4) + now.substr (3, 16) + " (" + now.substr (0, 3) + ")";
1434
1435         prompter.set_name ("Prompter");
1436         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1437         prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1438         prompter.set_prompt (_("Name of New Snapshot"));
1439         prompter.set_initial_text (now);
1440         
1441         switch (prompter.run()) {
1442         case RESPONSE_ACCEPT:
1443                 prompter.get_result (snapname);
1444                 if (snapname.length()){
1445                         save_state (snapname);
1446                 }
1447                 break;
1448
1449         default:
1450                 break;
1451         }
1452 }
1453
1454 void
1455 ARDOUR_UI::save_state (const string & name)
1456 {
1457         (void) save_state_canfail (name);
1458 }
1459                 
1460 int
1461 ARDOUR_UI::save_state_canfail (string name)
1462 {
1463         if (session) {
1464                 int ret;
1465
1466                 if (name.length() == 0) {
1467                         name = session->snap_name();
1468                 }
1469
1470                 if ((ret = session->save_state (name)) != 0) {
1471                         return ret;
1472                 }
1473         }
1474         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1475         return 0;
1476 }
1477
1478 void
1479 ARDOUR_UI::restore_state (string name)
1480 {
1481         if (session) {
1482                 if (name.length() == 0) {
1483                         name = session->name();
1484                 }
1485                 session->restore_state (name);
1486         }
1487 }
1488
1489 void
1490 ARDOUR_UI::primary_clock_value_changed ()
1491 {
1492         if (session) {
1493                 session->request_locate (primary_clock.current_time ());
1494         }
1495 }
1496
1497 void
1498 ARDOUR_UI::secondary_clock_value_changed ()
1499 {
1500         if (session) {
1501                 session->request_locate (secondary_clock.current_time ());
1502         }
1503 }
1504
1505 void
1506 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1507 {
1508         if (session && dstream && dstream->record_enabled()) {
1509
1510                 Session::RecordState rs;
1511                 
1512                 rs = session->record_status ();
1513
1514                 switch (rs) {
1515                 case Session::Disabled:
1516                 case Session::Enabled:
1517                         if (w->get_state() != STATE_SELECTED) {
1518                                 w->set_state (STATE_SELECTED);
1519                         }
1520                         break;
1521
1522                 case Session::Recording:
1523                         if (w->get_state() != STATE_ACTIVE) {
1524                                 w->set_state (STATE_ACTIVE);
1525                         }
1526                         break;
1527                 }
1528
1529         } else {
1530                 if (w->get_state() != STATE_NORMAL) {
1531                         w->set_state (STATE_NORMAL);
1532                 }
1533         }
1534 }
1535
1536 void
1537 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
1538 {
1539         if (session == 0) {
1540                 return;
1541         }
1542         
1543         switch (session->record_status()) {
1544         case Session::Enabled:
1545                 if (onoff) {
1546                         rec_button.set_state (1);
1547                 } else {
1548                         rec_button.set_state (0);
1549                 }
1550                 break;
1551
1552         case Session::Recording:
1553                 rec_button.set_state (2);
1554                 break;
1555
1556         default:
1557                 rec_button.set_state (0);
1558                 break;
1559         }
1560 }
1561
1562 gint
1563 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1564 {
1565         window->hide();
1566         Gtk::Main::quit ();
1567         return TRUE;
1568 }
1569
1570 void
1571 ARDOUR_UI::start_keyboard_prefix ()
1572 {
1573         keyboard->start_prefix();
1574 }
1575
1576 void
1577 ARDOUR_UI::save_template ()
1578
1579 {
1580         ArdourPrompter prompter (true);
1581         string name;
1582
1583         prompter.set_name (X_("Prompter"));
1584         prompter.set_prompt (_("Name for mix template:"));
1585         prompter.set_initial_text(session->name() + _("-template"));
1586         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1587         prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1588
1589         switch (prompter.run()) {
1590         case RESPONSE_ACCEPT:
1591                 prompter.get_result (name);
1592                 
1593                 if (name.length()) {
1594                         session->save_template (name);
1595                 }
1596                 break;
1597
1598         default:
1599                 break;
1600         }
1601 }
1602
1603 void
1604 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1605 {
1606         m_new_session_dialog->show();
1607         m_new_session_dialog->set_modal(true);
1608         m_new_session_dialog->set_name(predetermined_path);
1609         m_new_session_dialog->reset_recent();
1610
1611         int response = Gtk::RESPONSE_CANCEL;
1612
1613         do {
1614                 response = m_new_session_dialog->run ();
1615                 if(response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1616                   quit();
1617                   return;
1618
1619                 } else if (response == Gtk::RESPONSE_NONE) {
1620                   /* Clear was pressed */
1621                   m_new_session_dialog->reset();
1622
1623                 } else if (response == Gtk::RESPONSE_YES) {
1624                   /* YES  == OPEN, but there's no enum for that */
1625                   std::string session_name = m_new_session_dialog->session_name();
1626                   std::string session_path = m_new_session_dialog->session_folder();
1627                   load_session (session_path, session_name);
1628
1629
1630                 } else if (response == Gtk::RESPONSE_OK) {
1631                   if (m_new_session_dialog->get_current_page() == 1) {
1632
1633                     /* XXX this is a bit of a hack.. 
1634                        i really want the new sesion dialog to return RESPONSE_YES
1635                        if we're on page 1 (the load page)
1636                        Unfortunately i can't see how atm.. 
1637                     */
1638                         std::string session_name = m_new_session_dialog->session_name();
1639                         std::string session_path = m_new_session_dialog->session_folder();
1640                         load_session (session_path, session_name);
1641
1642                   } else {
1643
1644                         _session_is_new = true;
1645                         
1646                         std::string session_name = m_new_session_dialog->session_name();
1647                         std::string session_path = m_new_session_dialog->session_folder();
1648                         
1649
1650                           //XXX This is needed because session constructor wants a 
1651                           //non-existant path. hopefully this will be fixed at some point.
1652                         
1653                         session_path = Glib::build_filename(session_path, session_name);
1654                         
1655                         std::string template_name = m_new_session_dialog->session_template_name();
1656                         
1657                         if (m_new_session_dialog->use_session_template()) {
1658                                 
1659                                 load_session (session_path, session_name, &template_name);
1660                                 
1661                         } else {
1662                                 
1663                                 uint32_t cchns;
1664                                 uint32_t mchns;
1665                                 Session::AutoConnectOption iconnect;
1666                                 Session::AutoConnectOption oconnect;
1667                                 
1668                                 if (m_new_session_dialog->create_control_bus()) {
1669                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1670                                 } else {
1671                                         cchns = 0;
1672                                 }
1673                                 
1674                                 if (m_new_session_dialog->create_master_bus()) {
1675                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1676                                 } else {
1677                                         mchns = 0;
1678                                 }
1679                                 
1680                                 if (m_new_session_dialog->connect_inputs()) {
1681                                         iconnect = Session::AutoConnectPhysical;
1682                                 } else {
1683                                         iconnect = Session::AutoConnectOption (0);
1684                                 }
1685                                 
1686                                 /// @todo some minor tweaks.
1687
1688                                 if (m_new_session_dialog->connect_outs_to_master()) {
1689                                         oconnect = Session::AutoConnectMaster;
1690                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1691                                         oconnect = Session::AutoConnectPhysical;
1692                                 } else {
1693                                         oconnect = Session::AutoConnectOption (0);
1694                                 } 
1695                                 
1696                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1697                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1698                                 
1699                                 build_session (session_path,
1700                                                session_name,
1701                                                cchns,
1702                                                mchns,
1703                                                iconnect,
1704                                                oconnect,
1705                                                nphysin,
1706                                                nphysout, 
1707                                                engine->frame_rate() * 60 * 5);
1708                         }
1709                   }     
1710                 }
1711                 
1712         } while (response == Gtk::RESPONSE_NONE);
1713         m_new_session_dialog->hide();
1714         show();
1715
1716 }
1717
1718 void
1719 ARDOUR_UI::close_session()
1720 {
1721   unload_session();
1722   new_session ();
1723 }
1724
1725 int
1726 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1727 {
1728         Session *new_session;
1729         int x;
1730         session_loaded = false;
1731         x = unload_session ();
1732
1733         if (x < 0) {
1734                 return -1;
1735         } else if (x > 0) {
1736                 return 0;
1737         }
1738
1739         /* if it already exists, we must have write access */
1740
1741         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1742                 MessageDialog msg (*editor, _("\
1743 You do not have write access to this session.\n\
1744 This prevents the session from being loaded."));
1745                 msg.run ();
1746                 return -1;
1747         }
1748
1749         try {
1750                 new_session = new Session (*engine, path, snap_name, mix_template);
1751         }
1752
1753         catch (...) {
1754
1755                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1756                 return -1;
1757         }
1758
1759         connect_to_session (new_session);
1760
1761         //if (engine->running()) {
1762         //mixer->show_window();
1763         //}
1764         session_loaded = true;
1765         return 0;
1766 }
1767
1768 int
1769 ARDOUR_UI::make_session_clean ()
1770 {
1771         if (session) {
1772                 session->set_clean ();
1773         }
1774
1775         show ();
1776
1777         return FALSE;
1778 }
1779
1780 int
1781 ARDOUR_UI::build_session (const string & path, const string & snap_name, 
1782                           uint32_t control_channels,
1783                           uint32_t master_channels, 
1784                           Session::AutoConnectOption input_connect,
1785                           Session::AutoConnectOption output_connect,
1786                           uint32_t nphysin,
1787                           uint32_t nphysout,
1788                           jack_nframes_t initial_length)
1789 {
1790         Session *new_session;
1791         int x;
1792
1793         session_loaded = false;
1794         x = unload_session ();
1795         if (x < 0) {
1796                 return -1;
1797         } else if (x > 0) {
1798                 return 0;
1799         }
1800         
1801         _session_is_new = true;
1802
1803         try {
1804                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1805                                            control_channels, master_channels, nphysin, nphysout, initial_length);
1806         }
1807
1808         catch (...) {
1809
1810                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1811                 return -1;
1812         }
1813
1814         connect_to_session (new_session);
1815
1816         //if (engine->running()) {
1817         //mixer->show_window();
1818         //}
1819         session_loaded = true;
1820         return 0;
1821 }
1822
1823 void
1824 ARDOUR_UI::show ()
1825 {
1826         if (editor) {
1827                 editor->show_window ();
1828                 shown_flag = true;
1829         }
1830
1831         if (session && mixer) {
1832                 // mixer->show_window ();
1833         }
1834         
1835         if (about) {
1836                 about->present ();
1837         }
1838 }
1839
1840 void
1841 ARDOUR_UI::show_splash ()
1842 {
1843         if (about == 0) {
1844                 about = new About();
1845         }
1846         about->present();
1847 }
1848
1849 void
1850 ARDOUR_UI::hide_splash ()
1851 {
1852         if (about) {
1853                 // about->hide();
1854         }
1855 }
1856
1857 void
1858 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1859 {
1860         size_t removed;
1861
1862         removed = rep.paths.size();
1863
1864         if (removed == 0) {
1865                 MessageDialog msgd (*editor,
1866                                     _("No audio files were ready for cleanup"), 
1867                                     true,
1868                                     Gtk::MESSAGE_INFO,
1869                                     (Gtk::ButtonsType)(Gtk::BUTTONS_CLOSE)  );
1870                 msgd.set_secondary_text (_("If this seems suprising, \n\
1871 check for any existing snapshots.\n\
1872 These may still include regions that\n\
1873 require some unused files to continue to exist."));
1874         
1875                 msgd.run ();
1876                 return;
1877         } 
1878
1879         ArdourDialog results (_("ardour: cleanup"), true, false);
1880         
1881         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1882             CleanupResultsModelColumns() { 
1883                     add (visible_name);
1884                     add (fullpath);
1885             }
1886             Gtk::TreeModelColumn<Glib::ustring> visible_name;
1887             Gtk::TreeModelColumn<Glib::ustring> fullpath;
1888         };
1889
1890         
1891         CleanupResultsModelColumns results_columns;
1892         Glib::RefPtr<Gtk::ListStore> results_model;
1893         Gtk::TreeView results_display;
1894         
1895         results_model = ListStore::create (results_columns);
1896         results_display.set_model (results_model);
1897         results_display.append_column (list_title, results_columns.visible_name);
1898
1899         results_display.set_name ("CleanupResultsList");
1900         results_display.set_headers_visible (true);
1901         results_display.set_headers_clickable (false);
1902         results_display.set_reorderable (false);
1903
1904         Gtk::ScrolledWindow list_scroller;
1905         Gtk::Label txt;
1906         Gtk::VBox dvbox;
1907         Gtk::HBox dhbox;  // the hbox for the image and text
1908         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
1909         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
1910
1911         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
1912
1913         if (rep.space < 1048576.0f) {
1914                 if (removed > 1) {
1915                   txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
1916                 } else {
1917                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
1918                 }
1919         } else {
1920                 if (removed > 1) {
1921                         txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
1922                 } else {
1923                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
1924                 }
1925         }
1926
1927         dhbox.pack_start (*dimage, true, false, 5);
1928         dhbox.pack_start (txt, true, false, 5);
1929
1930         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1931                 TreeModel::Row row = *(results_model->append());
1932                 row[results_columns.visible_name] = *i;
1933                 row[results_columns.fullpath] = *i;
1934         }
1935         
1936         list_scroller.add (results_display);
1937         list_scroller.set_size_request (-1, 150);
1938         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1939
1940         dvbox.pack_start (dhbox, true, false, 5);
1941         dvbox.pack_start (list_scroller, true, false, 5);
1942         ddhbox.pack_start (dvbox, true, false, 5);
1943
1944         results.get_vbox()->pack_start (ddhbox, true, false, 5);
1945         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
1946         results.set_default_response (RESPONSE_CLOSE);
1947         results.set_position (Gtk::WIN_POS_MOUSE);
1948         results.show_all_children ();
1949         results.set_resizable (false);
1950
1951         results.run ();
1952
1953 }
1954
1955 void
1956 ARDOUR_UI::cleanup ()
1957 {
1958         if (session == 0) {
1959                 /* shouldn't happen: menu item is insensitive */
1960                 return;
1961         }
1962
1963
1964         MessageDialog  checker (_("Are you sure you want to cleanup?"),
1965                                 true,
1966                                 Gtk::MESSAGE_QUESTION,
1967                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
1968
1969         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
1970 ALL undo/redo information will be lost if you cleanup.\n\
1971 After cleanup, unused audio files will be moved to a \
1972 \"dead sounds\" location."));
1973         
1974         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1975         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
1976         checker.set_default_response (RESPONSE_CANCEL);
1977
1978         checker.set_name (_("CleanupDialog"));
1979         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
1980         checker.set_position (Gtk::WIN_POS_MOUSE);
1981
1982         switch (checker.run()) {
1983         case RESPONSE_ACCEPT:
1984                 break;
1985         default:
1986                 return;
1987         }
1988
1989         Session::cleanup_report rep;
1990
1991         editor->prepare_for_cleanup ();
1992
1993         if (session->cleanup_sources (rep)) {
1994                 return;
1995         }
1996         checker.hide();
1997         display_cleanup_results (rep, 
1998                                  _("cleaned files"),
1999                                  _("\
2000 The following %1 %2 not in use and \n\
2001 have been moved to:\n\
2002 %3. \n\n\
2003 Flushing the wastebasket will \n\
2004 release an additional\n\
2005 %4 %5bytes of disk space.\n"
2006                                          ));
2007 }
2008
2009 void
2010 ARDOUR_UI::flush_trash ()
2011 {
2012         if (session == 0) {
2013                 /* shouldn't happen: menu item is insensitive */
2014                 return;
2015         }
2016
2017         Session::cleanup_report rep;
2018
2019         if (session->cleanup_trash_sources (rep)) {
2020                 return;
2021         }
2022
2023         display_cleanup_results (rep, 
2024                                  _("deleted file"),
2025                                  _("The following %1 %2 deleted from\n\
2026 %3,\n\
2027 releasing %4 %5bytes of disk space"));
2028 }
2029
2030 void
2031 ARDOUR_UI::add_route ()
2032 {
2033         int count;
2034
2035         if (!session) {
2036                 return;
2037         }
2038
2039         if (add_route_dialog == 0) {
2040                 add_route_dialog = new AddRouteDialog;
2041                 editor->ensure_float (*add_route_dialog);
2042         }
2043
2044         if (add_route_dialog->is_visible()) {
2045                 /* we're already doing this */
2046                 return;
2047         }
2048
2049         ResponseType r = (ResponseType) add_route_dialog->run ();
2050         
2051         add_route_dialog->hide();
2052
2053         switch (r) {
2054         case RESPONSE_ACCEPT:
2055                 break;
2056         default:
2057                 return;
2058                 break;
2059         }
2060
2061         if ((count = add_route_dialog->count()) <= 0) {
2062                 return;
2063         }
2064
2065         uint32_t input_chan = add_route_dialog->channels ();
2066         uint32_t output_chan;
2067         string name_template = add_route_dialog->name_template ();
2068         bool track = add_route_dialog->track ();
2069
2070         Session::AutoConnectOption oac = session->get_output_auto_connect();
2071
2072         if (oac & Session::AutoConnectMaster) {
2073                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2074         } else {
2075                 output_chan = input_chan;
2076         }
2077
2078         /* XXX do something with name template */
2079
2080         while (count) {
2081                 if (track) {
2082                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode());
2083                 } else {
2084                         session_add_audio_bus (input_chan, output_chan);
2085                 }
2086                 --count;
2087                 
2088                 while (Main::events_pending()) {
2089                         Main::iteration ();
2090                 }
2091         }
2092 }
2093
2094 XMLNode*
2095 ARDOUR_UI::mixer_settings () const
2096 {
2097         XMLNode* node = 0;
2098
2099         if (session) {
2100                 node = session->instant_xml(X_("Mixer"), session->path());
2101         } else {
2102                 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2103         }
2104
2105         if (!node) {
2106                 node = new XMLNode (X_("Mixer"));
2107         }
2108
2109         return node;
2110 }
2111
2112 XMLNode*
2113 ARDOUR_UI::editor_settings () const
2114 {
2115         XMLNode* node = 0;
2116
2117         if (session) {
2118                 node = session->instant_xml(X_("Editor"), session->path());
2119         } else {
2120                 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2121         }
2122
2123         if (!node) {
2124                 node = new XMLNode (X_("Editor"));
2125         }
2126         return node;
2127 }
2128
2129 XMLNode*
2130 ARDOUR_UI::keyboard_settings () const
2131 {
2132         XMLNode* node = 0;
2133
2134         node = Config->extra_xml(X_("Keyboard"));
2135         
2136         if (!node) {
2137                 node = new XMLNode (X_("Keyboard"));
2138         }
2139         return node;
2140 }
2141
2142 void
2143 ARDOUR_UI::halt_on_xrun_message ()
2144 {
2145         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2146
2147         MessageDialog msg (*editor,
2148                            _("Recording was stopped because your system could not keep up."));
2149         msg.run ();
2150 }
2151
2152 void 
2153 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::AudioFileSource*>* deletion_list)
2154 {
2155         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2156
2157         for (list<AudioFileSource*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2158                 delete *i;
2159         }
2160
2161         delete deletion_list;
2162 }
2163
2164 void
2165 ARDOUR_UI::disk_overrun_handler ()
2166 {
2167         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2168
2169         if (!have_disk_overrun_displayed) {
2170                 have_disk_overrun_displayed = true;
2171                 MessageDialog msg (*editor, X_("diskrate dialog"), _("\
2172 The disk system on your computer\n\
2173 was not able to keep up with Ardour.\n\
2174 \n\
2175 Specifically, it failed to write data to disk\n\
2176 quickly enough to keep up with recording.\n"));
2177                 msg.run ();
2178                 have_disk_overrun_displayed = false;
2179         }
2180 }
2181
2182 void
2183 ARDOUR_UI::disk_underrun_handler ()
2184 {
2185         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2186
2187         if (!have_disk_underrun_displayed) {
2188                 have_disk_underrun_displayed = true;
2189                 MessageDialog msg (*editor,
2190                         (_("The disk system on your computer\n\
2191 was not able to keep up with Ardour.\n\
2192 \n\
2193 Specifically, it failed to read data from disk\n\
2194 quickly enough to keep up with playback.\n")));
2195                 msg.run ();
2196                 have_disk_underrun_displayed = false;
2197         } 
2198 }
2199
2200 void
2201 ARDOUR_UI::disk_underrun_message_gone ()
2202 {
2203         have_disk_underrun_displayed = false;
2204 }
2205
2206 void
2207 ARDOUR_UI::disk_overrun_message_gone ()
2208 {
2209         have_disk_underrun_displayed = false;
2210 }
2211
2212 int
2213 ARDOUR_UI::pending_state_dialog ()
2214 {
2215         ArdourDialog dialog ("pending state dialog");
2216         Label  message (_("\
2217 This session appears to have been in\n\
2218 middle of recording when ardour or\n\
2219 the computer was shutdown.\n\
2220 \n\
2221 Ardour can recover any captured audio for\n\
2222 you, or it can ignore it. Please decide\n\
2223 what you would like to do.\n"));
2224
2225         dialog.get_vbox()->pack_start (message);
2226         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2227         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2228
2229         dialog.set_position (WIN_POS_CENTER);
2230         dialog.show_all ();
2231         
2232         switch (dialog.run ()) {
2233         case RESPONSE_ACCEPT:
2234                 return 1;
2235         default:
2236                 return 0;
2237         }
2238 }
2239         
2240 void
2241 ARDOUR_UI::disconnect_from_jack ()
2242 {
2243         if (engine) {
2244                 if( engine->disconnect_from_jack ()) {
2245                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2246                         msg.run ();
2247                 }
2248
2249                 update_sample_rate (0);
2250         }
2251 }
2252
2253 void
2254 ARDOUR_UI::reconnect_to_jack ()
2255 {
2256         if (engine) {
2257                 if (engine->reconnect_to_jack ()) {
2258                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
2259                         msg.run ();
2260                 }
2261
2262                 update_sample_rate (0);
2263         }
2264 }
2265
2266 void
2267 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2268 {
2269         engine->request_buffer_size (nframes);
2270         update_sample_rate (0);
2271 }
2272
2273 int
2274 ARDOUR_UI::cmdline_new_session (string path)
2275 {
2276         if (path[0] != '/') {
2277                 char buf[PATH_MAX+1];
2278                 string str;
2279
2280                 getcwd (buf, sizeof (buf));
2281                 str = buf;
2282                 str += '/';
2283                 str += path;
2284                 path = str;
2285         }
2286
2287         new_session (false, path);
2288
2289         _will_create_new_session_automatically = false; /* done it */
2290         return FALSE; /* don't call it again */
2291 }
2292
2293 void
2294 ARDOUR_UI::set_native_file_header_format (HeaderFormat hf)
2295 {
2296         Glib::RefPtr<Action> act;
2297         
2298         switch (hf) {
2299         case BWF:
2300                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2301                 break;
2302         case WAVE:
2303                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2304                 break;
2305         case WAVE64:
2306                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2307                 break;
2308         case iXML:
2309                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2310                 break;
2311         case RF64:
2312                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2313                 break;
2314         case CAF:
2315                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2316                 break;
2317         case AIFF:
2318                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2319                 break;
2320         }
2321
2322         if (act) {
2323                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2324                 if (ract && ract->get_active() && Config->get_native_file_header_format() != hf) {
2325                         Config->set_native_file_header_format (hf);
2326                         if (session) {
2327                                 session->reset_native_file_format ();
2328                         }
2329                 }
2330         }
2331 }
2332
2333 void
2334 ARDOUR_UI::set_native_file_data_format (SampleFormat sf)
2335 {
2336         Glib::RefPtr<Action> act;
2337         
2338         switch (sf) {
2339         case FormatFloat:
2340                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2341                 break;
2342         case FormatInt24:
2343                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2344                 break;
2345         }
2346
2347         if (act) {
2348                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2349
2350                 if (ract && ract->get_active() && Config->get_native_file_data_format() != sf) {
2351                         Config->set_native_file_data_format (sf);
2352                         if (session) {
2353                                 session->reset_native_file_format ();
2354                         }
2355                 }
2356         }
2357 }
2358
2359 void
2360 ARDOUR_UI::use_config ()
2361 {
2362         Glib::RefPtr<Action> act;
2363
2364         switch (Config->get_native_file_data_format ()) {
2365         case FormatFloat:
2366                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2367                 break;
2368         case FormatInt24:
2369                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2370                 break;
2371         }
2372
2373         if (act) {
2374                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2375                 ract->set_active ();
2376         }       
2377
2378         switch (Config->get_native_file_header_format ()) {
2379         case BWF:
2380                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2381                 break;
2382         case WAVE:
2383                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2384                 break;
2385         case WAVE64:
2386                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2387                 break;
2388         case iXML:
2389                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2390                 break;
2391         case RF64:
2392                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2393                 break;
2394         case CAF:
2395                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2396                 break;
2397         case AIFF:
2398                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2399                 break;
2400         }
2401
2402         if (act) {
2403                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2404                 ract->set_active ();
2405         }       
2406 }