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