fixes for plugin selector and open session
[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 <pbd/error.h>
32 #include <pbd/compose.h>
33 #include <pbd/basename.h>
34 #include <pbd/pathscanner.h>
35 #include <pbd/failed_constructor.h>
36 #include <gtkmm2ext/gtk_ui.h>
37 #include <gtkmm2ext/pix.h>
38 #include <gtkmm2ext/utils.h>
39 #include <gtkmm2ext/click_box.h>
40 #include <gtkmm2ext/fastmeter.h>
41 #include <gtkmm2ext/stop_signal.h>
42 #include <gtkmm2ext/popup.h>
43
44 #include <midi++/port.h>
45 #include <midi++/mmc.h>
46
47 #include <ardour/ardour.h>
48 #include <ardour/port.h>
49 #include <ardour/audioengine.h>
50 #include <ardour/playlist.h>
51 #include <ardour/utils.h>
52 #include <ardour/diskstream.h>
53 #include <ardour/filesource.h>
54 #include <ardour/recent_sessions.h>
55 #include <ardour/session_diskstream.h>
56 #include <ardour/port.h>
57 #include <ardour/audio_track.h>
58
59 #include "actions.h"
60 #include "ardour_ui.h"
61 #include "ardour_message.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
75 #include "i18n.h"
76
77 using namespace ARDOUR;
78 using namespace Gtkmm2ext;
79 using namespace Gtk;
80 using namespace sigc;
81
82 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
83
84 sigc::signal<void,bool> ARDOUR_UI::Blink;
85 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
86 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
87 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
88
89 /* XPM */
90 static const gchar *h_meter_strip_xpm[] = {
91 "186 5 187 2",
92 "       c None",
93 ".      c #2BFE00",
94 "+      c #2DFE00",
95 "@      c #2FFE01",
96 "#      c #32FE01",
97 "$      c #34FE02",
98 "%      c #36FE02",
99 "&      c #38FE03",
100 "*      c #3BFE03",
101 "=      c #3DFD04",
102 "-      c #3FFD04",
103 ";      c #41FD05",
104 ">      c #44FD05",
105 ",      c #46FD06",
106 "'      c #48FD06",
107 ")      c #4AFD07",
108 "!      c #4DFD07",
109 "~      c #4FFD08",
110 "{      c #51FC08",
111 "]      c #53FC09",
112 "^      c #56FC09",
113 "/      c #58FC09",
114 "(      c #5AFC0A",
115 "_      c #5CFC0A",
116 ":      c #5FFC0B",
117 "<      c #61FC0B",
118 "[      c #63FB0C",
119 "}      c #65FB0C",
120 "|      c #68FB0D",
121 "1      c #6AFB0D",
122 "2      c #6CFB0E",
123 "3      c #6EFB0E",
124 "4      c #71FB0F",
125 "5      c #73FB0F",
126 "6      c #75FB10",
127 "7      c #77FA10",
128 "8      c #7AFA11",
129 "9      c #7CFA11",
130 "0      c #7EFA12",
131 "a      c #80FA12",
132 "b      c #83FA12",
133 "c      c #85FA13",
134 "d      c #87FA13",
135 "e      c #89FA14",
136 "f      c #8CF914",
137 "g      c #8EF915",
138 "h      c #90F915",
139 "i      c #92F916",
140 "j      c #95F916",
141 "k      c #97F917",
142 "l      c #99F917",
143 "m      c #9BF918",
144 "n      c #9EF818",
145 "o      c #A0F819",
146 "p      c #A2F819",
147 "q      c #A4F81A",
148 "r      c #A7F81A",
149 "s      c #A9F81A",
150 "t      c #ABF81B",
151 "u      c #ADF81B",
152 "v      c #B0F81C",
153 "w      c #B2F71C",
154 "x      c #B4F71D",
155 "y      c #B6F71D",
156 "z      c #B9F71E",
157 "A      c #BBF71E",
158 "B      c #BDF71F",
159 "C      c #BFF71F",
160 "D      c #C2F720",
161 "E      c #C4F720",
162 "F      c #C6F621",
163 "G      c #C8F621",
164 "H      c #CBF622",
165 "I      c #CDF622",
166 "J      c #CFF623",
167 "K      c #D1F623",
168 "L      c #D4F624",
169 "M      c #D6F624",
170 "N      c #D8F524",
171 "O      c #DAF525",
172 "P      c #DDF525",
173 "Q      c #DFF526",
174 "R      c #E1F526",
175 "S      c #E3F527",
176 "T      c #E6F527",
177 "U      c #E8F528",
178 "V      c #EAF528",
179 "W      c #ECF429",
180 "X      c #EFF429",
181 "Y      c #F1F42A",
182 "Z      c #F3F42A",
183 "`      c #F5F42B",
184 " .     c #F8F42B",
185 "..     c #FAF42C",
186 "+.     c #FCF42C",
187 "@.     c #FFF42D",
188 "#.     c #FFF22C",
189 "$.     c #FFF12B",
190 "%.     c #FFF02A",
191 "&.     c #FFEF2A",
192 "*.     c #FFEE29",
193 "=.     c #FFED28",
194 "-.     c #FFEC28",
195 ";.     c #FFEB27",
196 ">.     c #FFE926",
197 ",.     c #FFE826",
198 "'.     c #FFE725",
199 ").     c #FFE624",
200 "!.     c #FFE524",
201 "~.     c #FFE423",
202 "{.     c #FFE322",
203 "].     c #FFE222",
204 "^.     c #FFE021",
205 "/.     c #FFDF20",
206 "(.     c #FFDE20",
207 "_.     c #FFDD1F",
208 ":.     c #FFDC1E",
209 "<.     c #FFDB1E",
210 "[.     c #FFDA1D",
211 "}.     c #FFD91C",
212 "|.     c #FFD71B",
213 "1.     c #FFD61B",
214 "2.     c #FFD51A",
215 "3.     c #FFD419",
216 "4.     c #FFD319",
217 "5.     c #FFD218",
218 "6.     c #FFD117",
219 "7.     c #FFD017",
220 "8.     c #FFCF16",
221 "9.     c #FFCD15",
222 "0.     c #FFCC15",
223 "a.     c #FFCB14",
224 "b.     c #FFCA13",
225 "c.     c #FFC913",
226 "d.     c #FFC812",
227 "e.     c #FFC711",
228 "f.     c #FFC611",
229 "g.     c #FFC410",
230 "h.     c #FFC30F",
231 "i.     c #FFC20F",
232 "j.     c #FFC10E",
233 "k.     c #FFC00D",
234 "l.     c #FFBF0C",
235 "m.     c #FFBE0C",
236 "n.     c #FFBD0B",
237 "o.     c #FFBB0A",
238 "p.     c #FFBA0A",
239 "q.     c #FFB909",
240 "r.     c #FFB808",
241 "s.     c #FFB708",
242 "t.     c #FFB607",
243 "u.     c #FFB506",
244 "v.     c #FFB406",
245 "w.     c #FFB205",
246 "x.     c #FFB104",
247 "y.     c #FFB004",
248 "z.     c #FFAF03",
249 "A.     c #FFAE02",
250 "B.     c #FFAD02",
251 "C.     c #FFAC01",
252 "D.     c #FFAB00",
253 "E.     c #FFA900",
254 "F.     c #F11F00",
255 "G.     c #F21E00",
256 "H.     c #F21C00",
257 "I.     c #F31B00",
258 "J.     c #F31A00",
259 "K.     c #F41800",
260 "L.     c #F41700",
261 "M.     c #F51600",
262 "N.     c #F61400",
263 "O.     c #F61300",
264 "P.     c #F71100",
265 "Q.     c #F71000",
266 "R.     c #F80F00",
267 "S.     c #F90D00",
268 "T.     c #F90C00",
269 "U.     c #FA0B00",
270 "V.     c #FA0900",
271 "W.     c #FB0800",
272 "X.     c #FC0600",
273 "Y.     c #FC0500",
274 "Z.     c #FD0400",
275 "`.     c #FD0200",
276 " +     c #FE0100",
277 ".+     c #FE0000",
278 "++     c #FF0000",
279 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
280 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
281 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
282 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
283 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++"};
284
285 /* XPM */
286 static const gchar * v_meter_strip_xpm[] = {
287 "5 250 230 2",
288 "       c None",
289 ".      c #FE0000",
290 "+      c #FF0000",
291 "@      c #FE0100",
292 "#      c #FD0200",
293 "$      c #FD0300",
294 "%      c #FD0400",
295 "&      c #FC0500",
296 "*      c #FC0600",
297 "=      c #FC0700",
298 "-      c #FB0800",
299 ";      c #FA0900",
300 ">      c #FA0A00",
301 ",      c #FA0B00",
302 "'      c #F90C00",
303 ")      c #F90D00",
304 "!      c #F80E00",
305 "~      c #F80F00",
306 "{      c #F71000",
307 "]      c #F71100",
308 "^      c #F61200",
309 "/      c #F61300",
310 "(      c #F61400",
311 "_      c #F51600",
312 ":      c #F41700",
313 "<      c #F41800",
314 "[      c #F31A00",
315 "}      c #F31B00",
316 "|      c #F21C00",
317 "1      c #F21E00",
318 "2      c #F11F00",
319 "3      c #F54A00",
320 "4      c #FFA900",
321 "5      c #FFAB00",
322 "6      c #FFAC01",
323 "7      c #FFAD02",
324 "8      c #FFAE02",
325 "9      c #FFAF03",
326 "0      c #FFB004",
327 "a      c #FFB104",
328 "b      c #FFB205",
329 "c      c #FFB406",
330 "d      c #FFB506",
331 "e      c #FFB607",
332 "f      c #FFB708",
333 "g      c #FFB808",
334 "h      c #FFB909",
335 "i      c #FFBA0A",
336 "j      c #FFBB0A",
337 "k      c #FFBC0A",
338 "l      c #FFBD0B",
339 "m      c #FFBE0C",
340 "n      c #FFBF0C",
341 "o      c #FFC00D",
342 "p      c #FFC10E",
343 "q      c #FFC20F",
344 "r      c #FFC30F",
345 "s      c #FFC410",
346 "t      c #FFC511",
347 "u      c #FFC611",
348 "v      c #FFC711",
349 "w      c #FFC812",
350 "x      c #FFC913",
351 "y      c #FFCA13",
352 "z      c #FFCB14",
353 "A      c #FFCC15",
354 "B      c #FFCD15",
355 "C      c #FFCF16",
356 "D      c #FFD017",
357 "E      c #FFD117",
358 "F      c #FFD218",
359 "G      c #FFD319",
360 "H      c #FFD419",
361 "I      c #FFD51A",
362 "J      c #FFD61B",
363 "K      c #FFD71B",
364 "L      c #FFD81C",
365 "M      c #FFD91C",
366 "N      c #FFDA1D",
367 "O      c #FFDB1E",
368 "P      c #FFDC1E",
369 "Q      c #FFDD1F",
370 "R      c #FFDE20",
371 "S      c #FFDF20",
372 "T      c #FFE021",
373 "U      c #FFE222",
374 "V      c #FFE322",
375 "W      c #FFE423",
376 "X      c #FFE524",
377 "Y      c #FFE624",
378 "Z      c #FFE725",
379 "`      c #FFE826",
380 " .     c #FFE926",
381 "..     c #FFEA26",
382 "+.     c #FFEB27",
383 "@.     c #FFEC28",
384 "#.     c #FFED28",
385 "$.     c #FFEE29",
386 "%.     c #FFEF2A",
387 "&.     c #FFF02A",
388 "*.     c #FFF12B",
389 "=.     c #FFF22C",
390 "-.     c #FFF32D",
391 ";.     c #FFF42D",
392 ">.     c #FDF42C",
393 ",.     c #FBF42C",
394 "'.     c #FAF42C",
395 ").     c #F8F42B",
396 "!.     c #F6F42B",
397 "~.     c #F4F42B",
398 "{.     c #F3F42A",
399 "].     c #F1F42A",
400 "^.     c #F0F429",
401 "/.     c #EEF429",
402 "(.     c #ECF429",
403 "_.     c #EAF528",
404 ":.     c #E9F528",
405 "<.     c #E7F528",
406 "[.     c #E5F527",
407 "}.     c #E3F527",
408 "|.     c #E2F526",
409 "1.     c #E0F526",
410 "2.     c #DFF526",
411 "3.     c #DDF525",
412 "4.     c #DBF525",
413 "5.     c #D9F525",
414 "6.     c #D8F524",
415 "7.     c #D6F624",
416 "8.     c #D5F624",
417 "9.     c #D3F624",
418 "0.     c #D1F623",
419 "a.     c #CFF623",
420 "b.     c #CEF622",
421 "c.     c #CCF622",
422 "d.     c #CBF622",
423 "e.     c #C9F621",
424 "f.     c #C7F621",
425 "g.     c #C5F621",
426 "h.     c #C4F720",
427 "i.     c #C2F720",
428 "j.     c #C0F71F",
429 "k.     c #BEF71F",
430 "l.     c #BDF71F",
431 "m.     c #BBF71E",
432 "n.     c #BAF71E",
433 "o.     c #B8F71E",
434 "p.     c #B6F71D",
435 "q.     c #B5F71D",
436 "r.     c #B3F71D",
437 "s.     c #B2F71C",
438 "t.     c #B0F81C",
439 "u.     c #AEF81B",
440 "v.     c #ACF81B",
441 "w.     c #ABF81B",
442 "x.     c #A9F81A",
443 "y.     c #A8F81A",
444 "z.     c #A6F81A",
445 "A.     c #A4F81A",
446 "B.     c #A2F819",
447 "C.     c #A1F819",
448 "D.     c #9FF819",
449 "E.     c #9EF818",
450 "F.     c #9BF918",
451 "G.     c #9AF917",
452 "H.     c #98F917",
453 "I.     c #97F917",
454 "J.     c #95F916",
455 "K.     c #93F916",
456 "L.     c #91F916",
457 "M.     c #90F915",
458 "N.     c #8EF915",
459 "O.     c #8DF914",
460 "P.     c #8BF914",
461 "Q.     c #89FA14",
462 "R.     c #87FA13",
463 "S.     c #86FA13",
464 "T.     c #84FA13",
465 "U.     c #83FA12",
466 "V.     c #81FA12",
467 "W.     c #7FFA12",
468 "X.     c #7DFA12",
469 "Y.     c #7CFA11",
470 "Z.     c #7AFA11",
471 "`.     c #78FA10",
472 " +     c #76FA10",
473 ".+     c #75FB10",
474 "++     c #73FB0F",
475 "@+     c #72FB0F",
476 "#+     c #70FB0F",
477 "$+     c #6EFB0E",
478 "%+     c #6DFB0E",
479 "&+     c #6BFB0E",
480 "*+     c #6AFB0D",
481 "=+     c #68FB0D",
482 "-+     c #66FB0C",
483 ";+     c #64FB0C",
484 ">+     c #63FB0C",
485 ",+     c #61FC0B",
486 "'+     c #60FC0B",
487 ")+     c #5EFC0B",
488 "!+     c #5CFC0A",
489 "~+     c #5AFC0A",
490 "{+     c #59FC09",
491 "]+     c #57FC09",
492 "^+     c #56FC09",
493 "/+     c #53FC09",
494 "(+     c #52FC08",
495 "_+     c #50FC08",
496 ":+     c #4FFD08",
497 "<+     c #4DFD07",
498 "[+     c #4BFD07",
499 "}+     c #49FD07",
500 "|+     c #48FD06",
501 "1+     c #46FD06",
502 "2+     c #45FD05",
503 "3+     c #43FD05",
504 "4+     c #41FD05",
505 "5+     c #3FFD04",
506 "6+     c #3EFD04",
507 "7+     c #3CFD04",
508 "8+     c #3BFE03",
509 "9+     c #39FE03",
510 "0+     c #37FE02",
511 "a+     c #35FE02",
512 "b+     c #34FE02",
513 "c+     c #32FE01",
514 "d+     c #30FE01",
515 "e+     c #2EFE01",
516 "f+     c #2DFE00",
517 "g+     c #2BFE00",
518 ". . + + + ",
519 ". . + + + ",
520 "@ @ @ @ @ ",
521 "# # # # # ",
522 "$ $ $ $ $ ",
523 "% % % % % ",
524 "& & & & & ",
525 "* * * * * ",
526 "= = = = = ",
527 "- - - - - ",
528 "; ; ; ; ; ",
529 "> > > > > ",
530 ", , , , , ",
531 "' ' ' ' ' ",
532 ") ) ) ) ) ",
533 "! ! ! ! ! ",
534 "~ ~ ~ ~ ~ ",
535 "{ { { { { ",
536 "] ] ] ] ] ",
537 "^ ^ ^ ^ ^ ",
538 "/ / / / / ",
539 "( ( ( ( ( ",
540 "_ _ _ _ _ ",
541 ": : : : : ",
542 ": : : : : ",
543 "< < < < < ",
544 "[ [ [ [ [ ",
545 "} } } } } ",
546 "} } } } } ",
547 "| | | | | ",
548 "1 1 1 1 1 ",
549 "2 2 2 2 2 ",
550 "3 3 3 3 3 ",
551 "4 4 4 4 4 ",
552 "5 5 5 5 5 ",
553 "6 6 6 6 6 ",
554 "6 6 6 6 6 ",
555 "7 7 7 7 7 ",
556 "8 8 8 8 8 ",
557 "9 9 9 9 9 ",
558 "9 9 9 9 9 ",
559 "0 0 0 0 0 ",
560 "a a a a a ",
561 "a a a a a ",
562 "b b b b b ",
563 "c c c c c ",
564 "d d d d d ",
565 "d d d d d ",
566 "e e e e e ",
567 "f f f f f ",
568 "g g g g g ",
569 "g g g g g ",
570 "h h h h h ",
571 "i i i i i ",
572 "j j j j j ",
573 "k k k k k ",
574 "l l l l l ",
575 "m m m m m ",
576 "n n n n n ",
577 "n n n n n ",
578 "o o o o o ",
579 "p p p p p ",
580 "q q q q q ",
581 "q q q q q ",
582 "r r r r r ",
583 "s s s s s ",
584 "t t t t t ",
585 "u u u u u ",
586 "v v v v v ",
587 "w w w w w ",
588 "x x x x x ",
589 "x x x x x ",
590 "y y y y y ",
591 "z z z z z ",
592 "A A A A A ",
593 "A A A A A ",
594 "B B B B B ",
595 "C C C C C ",
596 "D D D D D ",
597 "D D D D D ",
598 "E E E E E ",
599 "F F F F F ",
600 "G G G G G ",
601 "G G G G G ",
602 "H H H H H ",
603 "I I I I I ",
604 "I I I I I ",
605 "J J J J J ",
606 "K K K K K ",
607 "L L L L L ",
608 "M M M M M ",
609 "N N N N N ",
610 "O O O O O ",
611 "P P P P P ",
612 "P P P P P ",
613 "Q Q Q Q Q ",
614 "R R R R R ",
615 "S S S S S ",
616 "S S S S S ",
617 "T T T T T ",
618 "U U U U U ",
619 "V V V V V ",
620 "V V V V V ",
621 "W W W W W ",
622 "X X X X X ",
623 "Y Y Y Y Y ",
624 "Y Y Y Y Y ",
625 "Z Z Z Z Z ",
626 "` ` ` ` ` ",
627 " . . . . .",
628 "..........",
629 "+.+.+.+.+.",
630 "@.@.@.@.@.",
631 "#.#.#.#.#.",
632 "#.#.#.#.#.",
633 "$.$.$.$.$.",
634 "%.%.%.%.%.",
635 "&.&.&.&.&.",
636 "&.&.&.&.&.",
637 "*.*.*.*.*.",
638 "=.=.=.=.=.",
639 "-.-.-.-.-.",
640 ";.;.;.;.;.",
641 ";.;.;.;.;.",
642 ">.>.>.>.>.",
643 ",.,.,.,.,.",
644 "'.'.'.'.'.",
645 ").).).).).",
646 "!.!.!.!.!.",
647 "~.~.~.~.~.",
648 "{.{.{.{.{.",
649 "].].].].].",
650 "^.^.^.^.^.",
651 "/././././.",
652 "(.(.(.(.(.",
653 "_._._._._.",
654 ":.:.:.:.:.",
655 "<.<.<.<.<.",
656 "[.[.[.[.[.",
657 "}.}.}.}.}.",
658 "|.|.|.|.|.",
659 "1.1.1.1.1.",
660 "2.2.2.2.2.",
661 "3.3.3.3.3.",
662 "4.4.4.4.4.",
663 "5.5.5.5.5.",
664 "6.6.6.6.6.",
665 "7.7.7.7.7.",
666 "8.8.8.8.8.",
667 "9.9.9.9.9.",
668 "0.0.0.0.0.",
669 "a.a.a.a.a.",
670 "b.b.b.b.b.",
671 "c.c.c.c.c.",
672 "d.d.d.d.d.",
673 "e.e.e.e.e.",
674 "f.f.f.f.f.",
675 "g.g.g.g.g.",
676 "h.h.h.h.h.",
677 "i.i.i.i.i.",
678 "j.j.j.j.j.",
679 "k.k.k.k.k.",
680 "l.l.l.l.l.",
681 "m.m.m.m.m.",
682 "n.n.n.n.n.",
683 "o.o.o.o.o.",
684 "p.p.p.p.p.",
685 "q.q.q.q.q.",
686 "r.r.r.r.r.",
687 "s.s.s.s.s.",
688 "t.t.t.t.t.",
689 "u.u.u.u.u.",
690 "v.v.v.v.v.",
691 "w.w.w.w.w.",
692 "x.x.x.x.x.",
693 "y.y.y.y.y.",
694 "z.z.z.z.z.",
695 "A.A.A.A.A.",
696 "B.B.B.B.B.",
697 "C.C.C.C.C.",
698 "D.D.D.D.D.",
699 "E.E.E.E.E.",
700 "F.F.F.F.F.",
701 "G.G.G.G.G.",
702 "H.H.H.H.H.",
703 "I.I.I.I.I.",
704 "J.J.J.J.J.",
705 "K.K.K.K.K.",
706 "L.L.L.L.L.",
707 "M.M.M.M.M.",
708 "N.N.N.N.N.",
709 "O.O.O.O.O.",
710 "P.P.P.P.P.",
711 "Q.Q.Q.Q.Q.",
712 "R.R.R.R.R.",
713 "S.S.S.S.S.",
714 "T.T.T.T.T.",
715 "U.U.U.U.U.",
716 "V.V.V.V.V.",
717 "W.W.W.W.W.",
718 "X.X.X.X.X.",
719 "Y.Y.Y.Y.Y.",
720 "Z.Z.Z.Z.Z.",
721 "`.`.`.`.`.",
722 " + + + + +",
723 ".+.+.+.+.+",
724 "++++++++++",
725 "@+@+@+@+@+",
726 "#+#+#+#+#+",
727 "$+$+$+$+$+",
728 "%+%+%+%+%+",
729 "&+&+&+&+&+",
730 "*+*+*+*+*+",
731 "=+=+=+=+=+",
732 "-+-+-+-+-+",
733 ";+;+;+;+;+",
734 ">+>+>+>+>+",
735 ",+,+,+,+,+",
736 "'+'+'+'+'+",
737 ")+)+)+)+)+",
738 "!+!+!+!+!+",
739 "~+~+~+~+~+",
740 "{+{+{+{+{+",
741 "]+]+]+]+]+",
742 "^+^+^+^+^+",
743 "/+/+/+/+/+",
744 "(+(+(+(+(+",
745 "_+_+_+_+_+",
746 ":+:+:+:+:+",
747 "<+<+<+<+<+",
748 "[+[+[+[+[+",
749 "}+}+}+}+}+",
750 "|+|+|+|+|+",
751 "1+1+1+1+1+",
752 "2+2+2+2+2+",
753 "3+3+3+3+3+",
754 "4+4+4+4+4+",
755 "5+5+5+5+5+",
756 "6+6+6+6+6+",
757 "7+7+7+7+7+",
758 "8+8+8+8+8+",
759 "9+9+9+9+9+",
760 "0+0+0+0+0+",
761 "a+a+a+a+a+",
762 "b+b+b+b+b+",
763 "c+c+c+c+c+",
764 "d+d+d+d+d+",
765 "e+e+e+e+e+",
766 "f+f+f+f+f+",
767 "g+g+g+g+g+"};
768
769 static const char* channel_setup_names[] = {
770         "mono",
771         "stereo",
772         "3 channels",
773         "4 channels",
774         "5 channels",
775         "8 channels",
776         "manual setup",
777         0
778 };
779
780 vector<string> channel_combo_strings;
781
782 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
783
784         : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
785           
786           primary_clock (X_("TransportClockDisplay"), true, false, true),
787           secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
788           preroll_clock (X_("PreRollClock"), true, true),
789           postroll_clock (X_("PostRollClock"), true, true),
790
791           /* adjuster table */
792
793           adjuster_table (3, 3),
794
795           /* preroll stuff */
796
797           preroll_button (_("pre\nroll")),
798           postroll_button (_("post\nroll")),
799
800           /* big clock */
801
802           big_clock ("BigClockDisplay", true),
803
804           /* transport */
805
806           shuttle_units_button (_("% ")),
807           shuttle_style_button (_("spring")),
808
809           punch_in_button (_("punch\nin")),
810           punch_out_button (_("punch\nout")),
811           auto_return_button (_("auto\nreturn")),
812           auto_play_button (_("auto\nplay")),
813           auto_input_button (_("auto\ninput")),
814           click_button (_("click")),
815           follow_button (_("follow\nPH")),
816           auditioning_alert_button (_("AUDITIONING")),
817           solo_alert_button (_("SOLO")),
818           shown_flag (false)
819
820 {
821         using namespace Gtk::Menu_Helpers;
822
823         Gtkmm2ext::init();
824
825         /* actually, its already loaded, but ... */
826
827         cerr << "Loading UI configuration file " << rcfile << endl;
828
829         about = 0;
830
831         if (theArdourUI == 0) {
832                 theArdourUI = this;
833         }
834
835         // allow run-time rebinding of accels
836
837         Settings::get_default()->property_gtk_can_change_accels() = true;
838
839         ActionManager::init ();
840         
841         m_new_session_dialog = 0;
842         m_new_session_dialog_ref = NewSessionDialogFactory::create();
843         m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
844         editor = 0;
845         mixer = 0;
846         session = 0;
847         _session_is_new = false;
848         big_clock_window = 0;
849         session_selector_window = 0;
850         last_key_press_time = 0;
851         connection_editor = 0;
852         add_route_dialog = 0;
853         route_params = 0;
854         option_editor = 0;
855         location_ui = 0;
856         open_session_selector = 0;
857         have_configure_timeout = false;
858         have_disk_overrun_displayed = false;
859         have_disk_underrun_displayed = false;
860         _will_create_new_session_automatically = false;
861         session_loaded = false;
862
863
864         last_configure_time.tv_sec = 0;
865         last_configure_time.tv_usec = 0;
866
867         shuttle_grabbed = false;
868         shuttle_fract = 0.0;
869
870         set_shuttle_units (Percentage);
871         set_shuttle_behaviour (Sprung);
872
873         shuttle_style_menu = 0;
874         shuttle_unit_menu = 0;
875
876         gettimeofday (&last_peak_grab, 0);
877         gettimeofday (&last_shuttle_request, 0);
878
879         ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
880         ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
881         ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
882         ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
883
884         /* handle pending state with a dialog */
885
886         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
887
888         channel_combo_strings = internationalize (channel_setup_names);
889         
890         /* have to wait for AudioEngine and Configuration before proceeding */
891 }
892
893 void
894 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
895 {
896         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
897         
898         string msg = string_compose (_("\
899 You cannot record-enable\n\
900 track %1\n\
901 because it has no input connections.\n\
902 You would be wasting space recording silence."),
903                               ds->name());
904
905         ArdourMessage message (editor, X_("cannotrecord"), msg);
906 }
907
908 void
909 ARDOUR_UI::set_engine (AudioEngine& e)
910 {
911         engine = &e;
912
913         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
914         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
915         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
916         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
917
918         _tooltips.enable();
919
920         keyboard = new Keyboard;
921         install_keybindings ();
922
923         FastMeter::set_vertical_xpm (v_meter_strip_xpm);
924         FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
925
926         if (setup_windows ()) {
927                 throw failed_constructor ();
928         }
929
930         if (GTK_ARDOUR::show_key_actions) {
931                 // GTK2FIX
932                 // show_all_actions ();
933                 exit (0);
934         }
935
936         /* start with timecode, metering enabled
937         */
938         
939         blink_timeout_tag = -1;
940
941         /* this being a GUI and all, we want peakfiles */
942
943         FileSource::set_build_peakfiles (true);
944         FileSource::set_build_missing_peakfiles (true);
945
946         if (Source::start_peak_thread ()) {
947                 throw failed_constructor();
948         }
949
950         /* start the time-of-day-clock */
951         
952         update_wall_clock ();
953         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
954
955         update_disk_space ();
956         update_cpu_load ();
957         update_sample_rate (engine->frame_rate());
958
959         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
960         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
961 }
962
963 ARDOUR_UI::~ARDOUR_UI ()
964 {
965         save_ardour_state ();
966
967         if (keyboard) {
968                 delete keyboard;
969         }
970
971         if (editor) {
972                 delete editor;
973         }
974
975         if (mixer) {
976                 delete mixer;
977         }
978
979         if (add_route_dialog) {
980                 delete add_route_dialog;
981         }
982
983         Source::stop_peak_thread ();
984 }
985
986 gint
987 ARDOUR_UI::configure_timeout ()
988 {
989         struct timeval now;
990         struct timeval diff;
991
992         if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
993                 /* no configure events yet */
994                 return TRUE;
995         }
996
997         gettimeofday (&now, 0);
998         timersub (&now, &last_configure_time, &diff);
999
1000         /* force a gap of 0.5 seconds since the last configure event
1001          */
1002
1003         if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1004                 return TRUE;
1005         } else {
1006                 have_configure_timeout = false;
1007                 save_ardour_state ();
1008                 return FALSE;
1009         }
1010 }
1011
1012 gboolean
1013 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1014 {
1015         if (have_configure_timeout) {
1016                 gettimeofday (&last_configure_time, 0);
1017         } else {
1018                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1019                 have_configure_timeout = true;
1020         }
1021                 
1022         return FALSE;
1023 }
1024
1025 void
1026 ARDOUR_UI::save_ardour_state ()
1027 {
1028         if (!keyboard || !mixer || !editor) {
1029                 return;
1030         }
1031         
1032         /* XXX this is all a bit dubious. add_extra_xml() uses
1033            a different lifetime model from add_instant_xml().
1034         */
1035
1036         XMLNode* node = new XMLNode (keyboard->get_state());
1037         Config->add_extra_xml (*node);
1038         Config->save_state();
1039
1040         XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1041         XMLNode& mnode (mixer->get_state());
1042
1043         if (session) {
1044                 session->add_instant_xml(enode, session->path());
1045                 session->add_instant_xml(mnode, session->path());
1046         } else {
1047                 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1048                 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1049         }
1050 }
1051
1052 void
1053 ARDOUR_UI::startup ()
1054 {
1055         /* Once the UI is up and running, start the audio engine. Doing
1056            this before the UI is up and running can cause problems
1057            when not running with SCHED_FIFO, because the amount of
1058            CPU and disk work needed to get the UI started can interfere
1059            with the scheduling of the audio thread.
1060         */
1061
1062         Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1063 }
1064
1065 void
1066 ARDOUR_UI::finish()
1067 {
1068         if (session && session->dirty()) {
1069                 switch (ask_about_saving_session(_("quit"))) {
1070                 case -1:
1071                         return;
1072                         break;
1073                 case 1:
1074                         /* use the default name */
1075                         if (save_state_canfail ("")) {
1076                                 /* failed - don't quit */
1077                                 ArdourMessage (editor, X_("badsave dialog"),
1078                                                _("\
1079 Ardour was unable to save your session.\n\n\
1080 If you still wish to quit, please use the\n\n\
1081 \"Just quit\" option."));
1082                                 return;
1083                         }
1084                         break;
1085                 case 0:
1086                         break;
1087                 }
1088         }
1089
1090         quit ();
1091 }
1092
1093 int
1094 ARDOUR_UI::ask_about_saving_session (string what)
1095 {
1096         ArdourDialog window (_("ardour: save session?"));
1097         Gtk::Label  prompt_label;
1098         string msg;
1099
1100         msg = string_compose(_("Save and %1"), what);
1101         window.add_button (msg, RESPONSE_ACCEPT);
1102         msg = string_compose(_("Just %1"), what);
1103         window.add_button (msg, RESPONSE_APPLY);
1104         msg = string_compose(_("Don't %1"), what);
1105         window.add_button (msg, RESPONSE_REJECT);
1106
1107         Gtk::Button noquit_button (msg);
1108         noquit_button.set_name ("EditorGTKButton");
1109
1110         string prompt;
1111         string type;
1112
1113         if (session->snap_name() == session->name()) {
1114                 type = _("session");
1115         } else {
1116                 type = _("snapshot");
1117         }
1118         prompt = string_compose(_("The %1\n\"%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?"), 
1119                          type, session->snap_name());
1120         
1121         prompt_label.set_text (prompt);
1122         prompt_label.set_alignment (0.5, 0.5);
1123         prompt_label.set_name (X_("PrompterLabel"));
1124         
1125         window.get_vbox()->pack_start (prompt_label);
1126
1127         window.set_name (_("Prompter"));
1128         window.set_position (Gtk::WIN_POS_MOUSE);
1129         window.set_modal (true);
1130         window.show_all ();
1131
1132         save_the_session = 0;
1133
1134         editor->ensure_float (window);
1135
1136         ResponseType r = (ResponseType) window.run();
1137
1138         window.hide ();
1139
1140         switch (r) {
1141         case RESPONSE_ACCEPT: // save and get out of here
1142                 return 1;
1143         case RESPONSE_APPLY:  // get out of here
1144                 return 0;
1145         default:
1146                 break;
1147         }
1148
1149         return -1;
1150 }
1151         
1152 gint
1153 ARDOUR_UI::every_second ()
1154 {
1155         update_cpu_load ();
1156         update_buffer_load ();
1157         update_disk_space ();
1158         // update_disk_rate ();
1159         return TRUE;
1160 }
1161
1162 gint
1163 ARDOUR_UI::every_point_one_seconds ()
1164 {
1165         struct timeval now;
1166         struct timeval diff;
1167         
1168         /* do not attempt to grab peak power more than once per cycle.
1169          */
1170
1171         gettimeofday (&now, 0);
1172         timersub (&now, &last_peak_grab, &diff);
1173
1174         if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1175                 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1176                 last_peak_grab = now;
1177         } 
1178
1179         update_speed_display ();
1180         RapidScreenUpdate(); /* EMIT_SIGNAL */
1181         return TRUE;
1182 }
1183
1184 gint
1185 ARDOUR_UI::every_point_zero_one_seconds ()
1186 {
1187         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1188         return TRUE;
1189 }
1190
1191 void
1192 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1193 {
1194         char buf[32];
1195
1196         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1197
1198         if (!engine->connected()) {
1199
1200                 snprintf (buf, sizeof (buf), _("disconnected"));
1201
1202         } else {
1203
1204                 jack_nframes_t rate = engine->frame_rate();
1205                 
1206                 if (fmod (rate, 1000.0) != 0.0) {
1207                         snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), 
1208                                   (float) rate/1000.0f,
1209                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1210                 } else {
1211                         snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), 
1212                                   rate/1000,
1213                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1214                 }
1215         }
1216
1217         sample_rate_label.set_text (buf);
1218 }
1219
1220 void
1221 ARDOUR_UI::update_cpu_load ()
1222 {
1223         char buf[32];
1224         snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1225         cpu_load_label.set_text (buf);
1226 }
1227
1228 void
1229 ARDOUR_UI::update_disk_rate ()
1230 {
1231         char buf[64];
1232
1233         if (session) {
1234                 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"), 
1235                           session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1236                 disk_rate_label.set_text (buf);
1237         } else {
1238                 disk_rate_label.set_text ("");
1239         }
1240 }
1241
1242 void
1243 ARDOUR_UI::update_buffer_load ()
1244 {
1245         char buf[64];
1246
1247         if (session) {
1248                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
1249                           session->playback_load(), session->capture_load());
1250                 buffer_load_label.set_text (buf);
1251         } else {
1252                 buffer_load_label.set_text ("");
1253         }
1254 }
1255
1256 void
1257 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1258 {
1259         if (ds.record_enabled()) {
1260                 rec_enabled_diskstreams++;
1261         }
1262 }
1263
1264 void
1265 ARDOUR_UI::update_disk_space()
1266 {
1267         if (session == 0) {
1268                 return;
1269         }
1270
1271         jack_nframes_t frames = session->available_capture_duration();
1272         char buf[64];
1273
1274         if (frames == max_frames) {
1275                 strcpy (buf, _("space: 24hrs+"));
1276         } else {
1277                 int hrs;
1278                 int mins;
1279                 int secs;
1280                 jack_nframes_t fr = session->frame_rate();
1281                 
1282                 if (session->actively_recording()){
1283                         
1284                         rec_enabled_diskstreams = 0;
1285                         session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1286                         
1287                         if (rec_enabled_diskstreams) {
1288                                 frames /= rec_enabled_diskstreams;
1289                         }
1290                         
1291                 } else {
1292                         
1293                         /* hmmm. shall we divide by the route count? or the diskstream count?
1294                            or what? for now, do nothing ...
1295                         */
1296                         
1297                 }
1298                 
1299                 hrs  = frames / (fr * 3600);
1300                 frames -= hrs * fr * 3600;
1301                 mins = frames / (fr * 60);
1302                 frames -= mins * fr * 60;
1303                 secs = frames / fr;
1304                 
1305                 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1306         }
1307
1308         disk_space_label.set_text (buf);
1309 }                 
1310
1311 gint
1312 ARDOUR_UI::update_wall_clock ()
1313 {
1314         time_t now;
1315         struct tm *tm_now;
1316         char buf[16];
1317
1318         time (&now);
1319         tm_now = localtime (&now);
1320
1321         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1322         wall_clock_label.set_text (buf);
1323
1324         return TRUE;
1325 }
1326
1327 void
1328 ARDOUR_UI::toggle_recording_plugins ()
1329 {
1330         /* XXX use toggle_some_session_state */
1331
1332         if (session == 0) {
1333                 return;
1334         }
1335
1336         session->set_recording_plugins (!session->get_recording_plugins());
1337 }
1338         
1339 void
1340 ARDOUR_UI::toggle_auto_play ()
1341
1342 {
1343         toggle_some_session_state (auto_play_button,
1344                                    &Session::get_auto_play,
1345                                    &Session::set_auto_play);
1346 }
1347
1348 void
1349 ARDOUR_UI::toggle_auto_return ()
1350
1351 {
1352         toggle_some_session_state (auto_return_button,
1353                                    &Session::get_auto_return,
1354                                    &Session::set_auto_return);
1355 }
1356
1357 void
1358 ARDOUR_UI::toggle_click ()
1359 {
1360         toggle_some_session_state (click_button,
1361                                    &Session::get_clicking,
1362                                    &Session::set_clicking);
1363 }
1364
1365 void
1366 ARDOUR_UI::follow_changed ()
1367 {
1368         bool x;
1369
1370         if (!editor) {
1371                 return;
1372         }
1373
1374         if (follow_button.get_active() != (x = editor->follow_playhead())) {
1375                 follow_button.set_active (x);
1376         }
1377 }
1378
1379 void
1380 ARDOUR_UI::toggle_follow ()
1381 {
1382         bool x;
1383
1384         if (!editor) {
1385                 return;
1386         }
1387
1388         if (editor->follow_playhead() != (x = follow_button.get_active())) {
1389                 editor->set_follow_playhead (x);
1390         }
1391 }
1392
1393 void
1394 ARDOUR_UI::toggle_session_auto_loop ()
1395 {
1396         if (session) {
1397                 if (session->get_auto_loop()) {
1398                         if (session->transport_rolling()) {
1399                                 transport_roll();
1400                         }
1401                         else {
1402                                 session->request_auto_loop (false);
1403                         }
1404                 }
1405                 else {
1406                         session->request_auto_loop (true);
1407                 }
1408         }
1409 }
1410
1411 void
1412 ARDOUR_UI::toggle_session_punch_in ()
1413 {
1414         if (session) {
1415                 session->set_punch_in (!session->get_punch_in());
1416         }
1417 }
1418
1419 void
1420 ARDOUR_UI::toggle_punch_out ()
1421 {
1422         toggle_some_session_state (punch_out_button,
1423                                    &Session::get_punch_out,
1424                                    &Session::set_punch_out);
1425 }
1426
1427 void
1428 ARDOUR_UI::toggle_punch_in ()
1429 {
1430         toggle_some_session_state (punch_in_button,
1431                                    &Session::get_punch_in,
1432                                    &Session::set_punch_in);
1433 }
1434
1435 void
1436 ARDOUR_UI::map_button_state ()
1437
1438 {
1439         map_some_session_state (auto_return_button,
1440                                 &Session::get_auto_return);
1441         map_some_session_state (auto_play_button,
1442                                 &Session::get_auto_play);
1443         map_some_session_state (auto_input_button,
1444                                 &Session::get_auto_input);
1445         map_some_session_state (punch_in_button,
1446                                 &Session::get_punch_in);
1447         map_some_session_state (punch_out_button,
1448                                 &Session::get_punch_out);
1449         map_some_session_state (click_button,
1450                                 &Session::get_clicking);
1451 }
1452
1453 void
1454 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1455 {
1456         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1457 }
1458
1459 void
1460 ARDOUR_UI::map_control_change (Session::ControlType t)
1461 {
1462         switch (t) {
1463         case Session::AutoPlay:
1464                 map_some_session_state (auto_play_button, &Session::get_auto_play);
1465                 break;
1466
1467         case Session::AutoLoop:
1468                 break;
1469
1470         case Session::AutoReturn:
1471                 map_some_session_state (auto_return_button, &Session::get_auto_return);
1472                 break;
1473
1474         case Session::AutoInput:
1475                 map_some_session_state (auto_input_button, &Session::get_auto_input);
1476                 break;
1477
1478         case Session::PunchOut:
1479                 map_some_session_state (punch_in_button, &Session::get_punch_out);
1480                 break;
1481
1482         case Session::PunchIn:
1483                 map_some_session_state (punch_in_button, &Session::get_punch_in);
1484                 break;
1485
1486         case Session::Clicking:
1487                 map_some_session_state (click_button, &Session::get_clicking);
1488                 break;
1489
1490         case Session::SlaveType:
1491 //              map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1492                 break;
1493
1494         case Session::SendMTC:
1495 //              map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1496                 break;
1497
1498         case Session::SendMMC:
1499 //              map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1500                 break;
1501
1502         case Session::MMCControl:       
1503 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1504                 break;
1505
1506         case Session::MidiFeedback:       
1507 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1508                 break;
1509         case Session::MidiControl:       
1510 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1511                 break;
1512                 
1513         case Session::Live:
1514                 break;
1515
1516         case Session::RecordingPlugins:
1517                 break;
1518
1519         case Session::CrossFadesActive:
1520                 break;
1521                 
1522         case Session::EditingMode:
1523                 break;
1524
1525         case Session::PlayRange:
1526                 break;
1527
1528         case Session::AlignChoice:
1529                 /* don't care, this is handled by the options editor */
1530                 break;
1531         case Session::SeamlessLoop:
1532                 /* don't care, this is handled by the options editor */
1533                 break;
1534                
1535         }
1536 }
1537
1538 void
1539 ARDOUR_UI::control_methods_adjusted ()
1540
1541 {
1542         int which_method;
1543
1544         which_method = (int) online_control_button->adjustment.get_value();
1545         switch (which_method) {
1546         case 0:
1547                 allow_mmc_and_local ();
1548                 break;
1549         case 1:
1550                 allow_mmc_only ();
1551                 break;
1552         case 2:
1553                 allow_local_only ();
1554                 break;
1555         default:
1556                 fatal << _("programming error: impossible control method") << endmsg;
1557         }
1558 }
1559         
1560
1561 void
1562 ARDOUR_UI::mmc_device_id_adjusted ()
1563
1564 {
1565 #if 0
1566         if (mmc) {
1567                 int dev_id = (int) mmc_id_button->adjustment.get_value();
1568                 mmc->set_device_id (dev_id);
1569         }
1570 #endif
1571 }
1572
1573 void
1574 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1575                                    bool (Session::*get)() const)
1576         
1577 {
1578         bool x;
1579
1580         if (session == 0) {
1581                 return;
1582         }
1583         
1584         if (button.get_active() != (x = (session->*get)())) {
1585                 button.set_active (x);
1586         }
1587 }
1588
1589 void
1590 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1591                                       bool (Session::*get)() const,
1592                                       void (Session::*set)(bool))
1593
1594 {
1595         bool button_state;
1596         bool session_state;
1597
1598         if (session == 0) {
1599                 return;
1600         }
1601
1602         button_state = button.get_active ();
1603         session_state = (session->*get)();
1604
1605         if (button_state != session_state) {
1606                 (session->*set) (button_state);
1607 #if 0
1608         
1609                 /* check that it worked, and reverse
1610                    the button state if it didn't
1611                 */
1612
1613                 if ((session->*get)() != button_state) {
1614                         button->set_active (!button_state);
1615                 }
1616 #endif
1617
1618         }
1619 }       
1620
1621 gint
1622 ARDOUR_UI::session_menu (GdkEventButton *ev)
1623 {
1624         session_popup_menu->popup (0, 0);
1625         return TRUE;
1626 }
1627
1628 void
1629 ARDOUR_UI::redisplay_recent_sessions ()
1630 {
1631         vector<string *> *sessions;
1632         vector<string *>::iterator i;
1633         RecentSessionsSorter cmp;
1634         
1635         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1636         recent_session_model->clear ();
1637
1638         RecentSessions rs;
1639         ARDOUR::read_recent_sessions (rs);
1640
1641         if (rs.empty()) {
1642                 recent_session_display.set_model (recent_session_model);
1643                 return;
1644         }
1645
1646         /* sort them alphabetically */
1647         sort (rs.begin(), rs.end(), cmp);
1648         sessions = new vector<string*>;
1649
1650         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1651                 sessions->push_back (new string ((*i).second));
1652         }
1653
1654         for (i = sessions->begin(); i != sessions->end(); ++i) {
1655
1656                 vector<string*>* states;
1657                 vector<const gchar*> item;
1658                 string fullpath = *(*i);
1659                 
1660                 /* remove any trailing / */
1661
1662                 if (fullpath[fullpath.length()-1] == '/') {
1663                         fullpath = fullpath.substr (0, fullpath.length()-1);
1664                 }
1665
1666                 /* now get available states for this session */
1667
1668                 if ((states = Session::possible_states (fullpath)) == 0) {
1669                         /* no state file? */
1670                         continue;
1671                 }
1672
1673                 TreeModel::Row row = *(recent_session_model->append());
1674
1675                 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1676                 row[recent_session_columns.fullpath] = fullpath;
1677
1678                 if (states->size() > 1) {
1679
1680                         /* add the children */
1681                         
1682                         for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1683                                 
1684                                 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1685
1686                                 child_row[recent_session_columns.visible_name] = **i2;
1687                                 child_row[recent_session_columns.fullpath] = fullpath;
1688
1689                                 delete *i2;
1690                         }
1691                 }
1692
1693                 delete states;
1694         }
1695
1696         recent_session_display.set_model (recent_session_model);
1697         delete sessions;
1698 }
1699
1700 void
1701 ARDOUR_UI::build_session_selector ()
1702 {
1703         session_selector_window = new ArdourDialog ("session selector");
1704         
1705         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1706
1707         session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1708         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1709
1710         recent_session_model = TreeStore::create (recent_session_columns);
1711         recent_session_display.set_model (recent_session_model);
1712         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1713         recent_session_display.set_headers_visible (false);
1714
1715         scroller->add (recent_session_display);
1716         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1717
1718         session_selector_window->set_name ("SessionSelectorWindow");
1719         session_selector_window->set_size_request (200, 400);
1720         session_selector_window->get_vbox()->pack_start (*scroller);
1721 }
1722
1723 void
1724 ARDOUR_UI::open_recent_session ()
1725 {
1726         /* popup selector window */
1727
1728         if (session_selector_window == 0) {
1729                 build_session_selector ();
1730         }
1731
1732         redisplay_recent_sessions ();
1733
1734         ResponseType r = (ResponseType) session_selector_window->run ();
1735
1736         session_selector_window->hide();
1737
1738         switch (r) {
1739         case RESPONSE_ACCEPT:
1740                 break;
1741         default:
1742                 return;
1743         }
1744
1745         Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1746
1747         if (i == recent_session_model->children().end()) {
1748                 return;
1749         }
1750         
1751         Glib::ustring path = (*i)[recent_session_columns.fullpath];
1752         Glib::ustring state = (*i)[recent_session_columns.visible_name];
1753
1754         _session_is_new = false;
1755
1756         load_session (path, state);
1757 }
1758
1759 bool
1760 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) 
1761 {
1762         struct stat statbuf;
1763         
1764         if (stat (info.filename.c_str(), &statbuf) != 0) {
1765                 return false;
1766         }
1767
1768         if (!S_ISDIR(statbuf.st_mode)) {
1769                 return false;
1770         }
1771
1772         string session_file = info.filename;
1773         session_file += '/';
1774         session_file += PBD::basename (info.filename);
1775         session_file += ".ardour";
1776         
1777         if (stat (session_file.c_str(), &statbuf) != 0) {
1778                 return false;
1779         }
1780
1781         return S_ISREG (statbuf.st_mode);
1782 }
1783
1784 void
1785 ARDOUR_UI::open_session ()
1786 {
1787         /* popup selector window */
1788
1789         if (open_session_selector == 0) {
1790                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1791                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1792                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1793                 
1794                 FileFilter filter_ardour;
1795                 filter_ardour.set_name (_("Ardour sessions"));
1796                 filter_ardour.add_pattern("*.ardour");
1797                 open_session_selector->add_filter (filter_ardour);
1798         }
1799
1800         switch (open_session_selector->run ()) {
1801         case RESPONSE_OK:
1802                 break;
1803         default:
1804                 open_session_selector->hide();
1805                 return;
1806         }
1807
1808         open_session_selector->hide();
1809         string session_path = open_session_selector->get_filename();
1810         string path, name;
1811         bool isnew;
1812
1813         if (session_path.length() > 0) {
1814                 if (Session::find_session (session_path, path, name, isnew) == 0) {
1815                         _session_is_new = isnew;
1816                         load_session (path, name);
1817                 }
1818         }
1819 }
1820
1821
1822 void
1823 ARDOUR_UI::session_add_midi_track ()
1824 {
1825         cerr << _("Patience is a virtue.\n");
1826 }
1827
1828 void
1829 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1830 {
1831         Route* route;
1832
1833         if (session == 0) {
1834                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1835                 return;
1836         }
1837
1838         try { 
1839                 if (disk) {
1840                         if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1841                                 error << _("could not create new audio track") << endmsg;
1842                         }
1843                 } else {
1844                         if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1845                                 error << _("could not create new audio bus") << endmsg;
1846                         }
1847                 }
1848                 
1849 #if CONTROLOUTS
1850                 if (need_control_room_outs) {
1851                         pan_t pans[2];
1852                         
1853                         pans[0] = 0.5;
1854                         pans[1] = 0.5;
1855                         
1856                         route->set_stereo_control_outs (control_lr_channels);
1857                         route->control_outs()->set_stereo_pan (pans, this);
1858                 }
1859 #endif /* CONTROLOUTS */
1860         }
1861
1862         catch (...) {
1863                 ArdourMessage msg (editor, X_("noport dialog"),
1864                                    _("There are insufficient JACK ports available\n\
1865 to create a new track or bus.\n\
1866 You should save Ardour, exit and\n\
1867 restart JACK with more ports."));
1868         }
1869 }
1870
1871 void
1872 ARDOUR_UI::diskstream_added (DiskStream* ds)
1873 {
1874 }
1875
1876 void
1877 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1878 {
1879         jack_nframes_t _preroll;
1880
1881         if (session) {
1882                 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1883
1884                 if (new_position > _preroll) {
1885                         new_position -= _preroll;
1886                 } else {
1887                         new_position = 0;
1888                 }
1889
1890                 session->request_locate (new_position);
1891         }
1892 }
1893
1894 void
1895 ARDOUR_UI::transport_goto_start ()
1896 {
1897         if (session) {
1898                 session->request_locate (0);
1899
1900                 
1901                 /* force displayed area in editor to start no matter
1902                    what "follow playhead" setting is.
1903                 */
1904                 
1905                 if (editor) {
1906                         editor->reposition_x_origin (0);
1907                 }
1908         }
1909 }
1910
1911 void
1912 ARDOUR_UI::transport_goto_end ()
1913 {
1914         if (session) {
1915                 jack_nframes_t frame = session->current_end_frame();
1916                 session->request_locate (frame);
1917
1918                 /* force displayed area in editor to start no matter
1919                    what "follow playhead" setting is.
1920                 */
1921                 
1922                 if (editor) {
1923                         editor->reposition_x_origin (frame);
1924                 }
1925         }
1926 }
1927
1928 gint 
1929 ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
1930 {
1931
1932
1933         if (session) {
1934                         if (session->transport_stopped()) {
1935                         session->request_locate (session->last_transport_start());
1936                 } else {
1937                         if (session->get_auto_loop()) {
1938                                 session->request_auto_loop (false);
1939                         }
1940
1941                         Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
1942                         session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
1943                         }
1944         }
1945
1946         return TRUE;
1947 }
1948
1949 gint
1950 ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
1951 {
1952         transport_roll ();
1953         return TRUE;
1954 }
1955
1956 void
1957 ARDOUR_UI::transport_stop ()
1958 {
1959         if (!session) {
1960                 return;
1961         }
1962
1963         if (session->is_auditioning()) {
1964                 session->cancel_audition ();
1965                 return;
1966         }
1967         
1968         if (session->get_auto_loop()) {
1969                 session->request_auto_loop (false);
1970         }
1971         
1972         session->request_stop ();
1973 }
1974
1975 void
1976 ARDOUR_UI::transport_stop_and_forget_capture ()
1977 {
1978         if (session) {
1979                 session->request_stop (true);
1980         }
1981 }
1982
1983 void
1984 ARDOUR_UI::remove_last_capture()
1985 {
1986         if (editor) {
1987                 editor->remove_last_capture();
1988         }
1989 }
1990
1991 void
1992 ARDOUR_UI::transport_record ()
1993 {
1994         if (session) {
1995                 switch (session->record_status()) {
1996                 case Session::Disabled:
1997                         if (session->ntracks() == 0) {
1998                                 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1999                                 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
2000                                 return;
2001                         }
2002                         session->maybe_enable_record ();
2003                         break;
2004                 case Session::Recording:
2005                 case Session::Enabled:
2006                         session->disable_record ();
2007                 }
2008         }
2009 }
2010
2011 void
2012 ARDOUR_UI::transport_roll ()
2013 {
2014         bool rolling;
2015
2016         if (!session) {
2017                 return;
2018         }
2019
2020         rolling = session->transport_rolling ();
2021
2022         if (session->get_auto_loop()) {
2023                 session->request_auto_loop (false);
2024                 auto_loop_button.set_active (false);
2025                 roll_button.set_active (true);
2026         } else if (session->get_play_range ()) {
2027                 session->request_play_range (false);
2028                 play_selection_button.set_active (false);
2029         } else if (rolling) {
2030                 session->request_locate (session->last_transport_start(), true);
2031         }
2032
2033         session->request_transport_speed (1.0f);
2034 }
2035
2036 void
2037 ARDOUR_UI::transport_loop()
2038 {
2039         if (session) {
2040                 if (session->get_auto_loop()) {
2041                         if (session->transport_rolling()) {
2042                                 Location * looploc = session->locations()->auto_loop_location();
2043                                 if (looploc) {
2044                                         session->request_locate (looploc->start(), true);
2045                                 }
2046                         }
2047                 }
2048                 else {
2049                         session->request_auto_loop (true);
2050                 }
2051         }
2052 }
2053
2054 void
2055 ARDOUR_UI::transport_play_selection ()
2056 {
2057         if (!session) {
2058                 return;
2059         }
2060
2061         if (!session->get_play_range()) {
2062                 session->request_stop ();
2063         }
2064
2065         editor->play_selection ();
2066 }
2067
2068 void
2069 ARDOUR_UI::transport_rewind (int option)
2070 {
2071         float current_transport_speed;
2072  
2073         if (session) {
2074                 current_transport_speed = session->transport_speed();
2075                 
2076                 if (current_transport_speed >= 0.0f) {
2077                         switch (option) {
2078                         case 0:
2079                                 session->request_transport_speed (-1.0f);
2080                                 break;
2081                         case 1:
2082                                 session->request_transport_speed (-4.0f);
2083                                 break;
2084                         case -1:
2085                                 session->request_transport_speed (-0.5f);
2086                                 break;
2087                         }
2088                 } else {
2089                         /* speed up */
2090                         session->request_transport_speed (current_transport_speed * 1.5f);
2091                 }
2092         }
2093 }
2094
2095 void
2096 ARDOUR_UI::transport_forward (int option)
2097 {
2098         float current_transport_speed;
2099         
2100         if (session) {
2101                 current_transport_speed = session->transport_speed();
2102                 
2103                 if (current_transport_speed <= 0.0f) {
2104                         switch (option) {
2105                         case 0:
2106                                 session->request_transport_speed (1.0f);
2107                                 break;
2108                         case 1:
2109                                 session->request_transport_speed (4.0f);
2110                                 break;
2111                         case -1:
2112                                 session->request_transport_speed (0.5f);
2113                                 break;
2114                         }
2115                 } else {
2116                         /* speed up */
2117                         session->request_transport_speed (current_transport_speed * 1.5f);
2118                 }
2119         }
2120 }
2121
2122 void
2123 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2124 {
2125         if (session == 0) {
2126                 return;
2127         }
2128
2129         DiskStream *ds;
2130
2131         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2132                 Port *port = ds->io()->input (0);
2133                 port->request_monitor_input (!port->monitoring_input());
2134         }
2135 }
2136
2137 void
2138 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2139 {
2140         if (session == 0) {
2141                 return;
2142         }
2143
2144         DiskStream *ds;
2145
2146         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2147                 ds->set_record_enabled (!ds->record_enabled(), this);
2148         }
2149 }
2150
2151 void
2152 ARDOUR_UI::queue_transport_change ()
2153 {
2154         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2155 }
2156
2157 void
2158 ARDOUR_UI::map_transport_state ()
2159 {
2160         float sp = session->transport_speed();
2161
2162         if (sp == 1.0f) {
2163                 transport_rolling ();
2164         } else if (sp < 0.0f) {
2165                 transport_rewinding ();
2166         } else if (sp > 0.0f) {
2167                 transport_forwarding ();
2168         } else {
2169                 transport_stopped ();
2170         }
2171 }
2172
2173 void
2174 ARDOUR_UI::send_all_midi_feedback ()
2175 {
2176         if (session) {
2177                 session->send_all_midi_feedback();
2178         }
2179 }
2180
2181 void
2182 ARDOUR_UI::allow_local_only ()
2183 {
2184
2185 }
2186
2187 void
2188 ARDOUR_UI::allow_mmc_only ()
2189 {
2190
2191 }
2192
2193 void
2194 ARDOUR_UI::allow_mmc_and_local ()
2195 {
2196
2197 }
2198
2199 void
2200 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2201 {
2202         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2203                 (int) adj.get_value()].c_str());
2204 }
2205
2206 void
2207 ARDOUR_UI::engine_stopped ()
2208 {
2209         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2210         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2211         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2212 }
2213
2214
2215 void
2216 ARDOUR_UI::engine_running ()
2217 {
2218         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2219         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2220         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2221 }
2222
2223 void
2224 ARDOUR_UI::engine_halted ()
2225 {
2226         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2227
2228         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2229         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2230
2231         update_sample_rate (0);
2232
2233         ArdourMessage msg (editor, X_("halted"),
2234                            _("\
2235 JACK has either been shutdown or it\n\
2236 disconnected Ardour because Ardour\n\
2237 was not fast enough. You can save the\n\
2238 session and/or try to reconnect to JACK ."));
2239 }
2240
2241 int32_t
2242 ARDOUR_UI::do_engine_start ()
2243 {
2244         try { 
2245                 engine->start();
2246         }
2247
2248         catch (AudioEngine::PortRegistrationFailure& err) {
2249                 engine->stop ();
2250                 error << _("Unable to create all required ports")
2251                       << endmsg;
2252                 unload_session ();
2253                 return -1;
2254         }
2255
2256         catch (...) {
2257                 engine->stop ();
2258                 error << _("Unable to start the session running")
2259                       << endmsg;
2260                 unload_session ();
2261                 return -2;
2262         }
2263         
2264         return 0;
2265 }
2266
2267 gint
2268 ARDOUR_UI::start_engine ()
2269 {
2270         if (do_engine_start () == 0) {
2271                 if (session && _session_is_new) {
2272                         /* we need to retain initial visual 
2273                            settings for a new session 
2274                         */
2275                         session->save_state ("");
2276                 }
2277
2278                 /* there is too much going on, in too many threads, for us to 
2279                    end up with a clean session. So wait 1 second after loading,
2280                    and fix it up. its ugly, but until i come across a better
2281                    solution, its what we have.
2282                 */
2283
2284                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2285         }
2286
2287         return FALSE;
2288 }
2289
2290 void
2291 ARDOUR_UI::update_clocks ()
2292 {
2293          Clock (session->audible_frame()); /* EMIT_SIGNAL */
2294 }
2295
2296 void
2297 ARDOUR_UI::start_clocking ()
2298 {
2299         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2300 }
2301
2302 void
2303 ARDOUR_UI::stop_clocking ()
2304 {
2305         clock_signal_connection.disconnect ();
2306 }
2307         
2308 void
2309 ARDOUR_UI::toggle_clocking ()
2310 {
2311 #if 0
2312         if (clock_button.get_active()) {
2313                 start_clocking ();
2314         } else {
2315                 stop_clocking ();
2316         }
2317 #endif
2318 }
2319
2320 gint
2321 ARDOUR_UI::_blink (void *arg)
2322
2323 {
2324         ((ARDOUR_UI *) arg)->blink ();
2325         return TRUE;
2326 }
2327
2328 void
2329 ARDOUR_UI::blink ()
2330 {
2331          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2332 }
2333
2334 void
2335 ARDOUR_UI::start_blinking ()
2336 {
2337         /* Start the blink signal. Everybody with a blinking widget
2338            uses Blink to drive the widget's state.
2339         */
2340
2341         if (blink_timeout_tag < 0) {
2342                 blink_on = false;       
2343                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2344         }
2345 }
2346
2347 void
2348 ARDOUR_UI::stop_blinking ()
2349 {
2350         if (blink_timeout_tag >= 0) {
2351                 gtk_timeout_remove (blink_timeout_tag);
2352                 blink_timeout_tag = -1;
2353         }
2354 }
2355
2356
2357 void
2358 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2359 {
2360         using namespace Gtk;
2361         using namespace Menu_Helpers;
2362
2363         if (dstream.hidden()) {
2364                 return;
2365         }
2366
2367         MenuList& items = diskstream_menu->items();
2368         items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2369 }
2370         
2371 void
2372 ARDOUR_UI::diskstream_selected (gint32 id)
2373 {
2374         selected_dstream = id;
2375         Main::quit ();
2376 }
2377
2378 gint32
2379 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2380 {
2381         using namespace Gtk;
2382         using namespace Menu_Helpers;
2383
2384         if (session == 0) {
2385                 return -1;
2386         }
2387
2388         diskstream_menu = new Menu();
2389         diskstream_menu->set_name ("ArdourContextMenu");
2390         using namespace Gtk;
2391         using namespace Menu_Helpers;
2392
2393         MenuList& items = diskstream_menu->items();
2394         items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2395
2396         session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2397
2398         if (ev) {
2399                 diskstream_menu->popup (ev->button, ev->time);
2400         } else {
2401                 diskstream_menu->popup (0, 0);
2402         }
2403
2404         selected_dstream = -1;
2405
2406         Main::run ();
2407
2408         delete diskstream_menu;
2409
2410         return selected_dstream;
2411 }
2412
2413 void
2414 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
2415                           string& buf,
2416                           IO& io,
2417                           bool in)
2418 {
2419         if (in) {
2420                 if (io.n_inputs() == 0) {
2421                         buf = _("none");
2422                         return;
2423                 }
2424                 
2425                 /* XXX we're not handling multiple ports yet. */
2426
2427                 const char **connections = io.input(0)->get_connections();
2428                 
2429                 if (connections == 0 || connections[0] == '\0') {
2430                         buf = _("off");
2431                 } else {
2432                         buf = connections[0];
2433                 }
2434
2435                 free (connections);
2436
2437         } else {
2438
2439                 if (io.n_outputs() == 0) {
2440                         buf = _("none");
2441                         return;
2442                 }
2443                 
2444                 /* XXX we're not handling multiple ports yet. */
2445
2446                 const char **connections = io.output(0)->get_connections();
2447                 
2448                 if (connections == 0 || connections[0] == '\0') {
2449                         buf = _("off");
2450                 } else {
2451                         buf = connections[0];
2452                 }
2453
2454                 free (connections);
2455         }
2456 }
2457
2458 void
2459 ARDOUR_UI::snapshot_session ()
2460 {
2461         ArdourPrompter prompter (true);
2462         string snapname;
2463         string now;
2464         time_t n;
2465
2466         time (&n);
2467         now = ctime (&n);
2468         now = now.substr (0, now.length() - 1);
2469
2470         prompter.set_name ("Prompter");
2471         prompter.set_prompt (_("Name for snapshot"));
2472         prompter.set_initial_text (now);
2473         
2474         switch (prompter.run()) {
2475         case RESPONSE_ACCEPT:
2476                 prompter.get_result (snapname);
2477                 if (snapname.length()){
2478                         save_state (snapname);
2479                 }
2480                 break;
2481
2482         default:
2483                 break;
2484         }
2485 }
2486
2487 void
2488 ARDOUR_UI::save_state (string name)
2489 {
2490         (void) save_state_canfail (name);
2491 }
2492                 
2493 int
2494 ARDOUR_UI::save_state_canfail (string name)
2495 {
2496         if (session) {
2497                 int ret;
2498
2499                 if (name.length() == 0) {
2500                         name = session->snap_name();
2501                 }
2502
2503                 if ((ret = session->save_state (name)) != 0) {
2504                         return ret;
2505                 }
2506         }
2507         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2508         return 0;
2509 }
2510
2511 void
2512 ARDOUR_UI::restore_state (string name)
2513 {
2514         if (session) {
2515                 if (name.length() == 0) {
2516                         name = session->name();
2517                 }
2518                 session->restore_state (name);
2519         }
2520 }
2521
2522 void
2523 ARDOUR_UI::primary_clock_value_changed ()
2524 {
2525         if (session) {
2526                 session->request_locate (primary_clock.current_time ());
2527         }
2528 }
2529
2530 void
2531 ARDOUR_UI::secondary_clock_value_changed ()
2532 {
2533         if (session) {
2534                 session->request_locate (secondary_clock.current_time ());
2535         }
2536 }
2537
2538 void
2539 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2540 {
2541         if (session && dstream && dstream->record_enabled()) {
2542
2543                 Session::RecordState rs;
2544                 
2545                 rs = session->record_status ();
2546
2547                 switch (rs) {
2548                 case Session::Disabled:
2549                 case Session::Enabled:
2550                         if (w->get_state() != STATE_SELECTED) {
2551                                 w->set_state (STATE_SELECTED);
2552                         }
2553                         break;
2554
2555                 case Session::Recording:
2556                         if (w->get_state() != STATE_ACTIVE) {
2557                                 w->set_state (STATE_ACTIVE);
2558                         }
2559                         break;
2560                 }
2561
2562         } else {
2563                 if (w->get_state() != STATE_NORMAL) {
2564                         w->set_state (STATE_NORMAL);
2565                 }
2566         }
2567 }
2568
2569 void
2570 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
2571 {
2572         if (session == 0) {
2573                 return;
2574         }
2575         
2576         switch (session->record_status()) {
2577         case Session::Enabled:
2578                 if (onoff) {
2579                         rec_button.set_state (STATE_ACTIVE);
2580                 } else {
2581                         rec_button.set_state (STATE_NORMAL);
2582                 }
2583                 break;
2584
2585         case Session::Recording:
2586                 rec_button.set_state (STATE_ACTIVE);
2587                 break;
2588
2589         default:
2590                 rec_button.set_active (false);
2591                 rec_button.set_state (STATE_NORMAL);
2592                 break;
2593         }
2594 }
2595
2596 gint
2597 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2598 {
2599         window->hide();
2600         Gtk::Main::quit ();
2601         return TRUE;
2602 }
2603
2604 void
2605 ARDOUR_UI::start_keyboard_prefix ()
2606 {
2607         keyboard->start_prefix();
2608 }
2609
2610 void
2611 ARDOUR_UI::save_template ()
2612
2613 {
2614         ArdourPrompter prompter (true);
2615         string name;
2616
2617         prompter.set_name (X_("Prompter"));
2618         prompter.set_prompt (_("Name for mix template:"));
2619         prompter.set_initial_text(session->name() + _("-template"));
2620         
2621         switch (prompter.run()) {
2622         case RESPONSE_ACCEPT:
2623                 prompter.get_result (name);
2624                 
2625                 if (name.length()) {
2626                         session->save_template (name);
2627                 }
2628                 break;
2629
2630         default:
2631                 break;
2632         }
2633 }
2634
2635 void
2636 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2637 {
2638         m_new_session_dialog->show_all();
2639         m_new_session_dialog->set_transient_for(*editor);
2640         m_new_session_dialog->set_name(predetermined_path);
2641
2642         int response = Gtk::RESPONSE_CANCEL;
2643
2644         do {
2645                 response = m_new_session_dialog->run ();
2646         
2647                 if(response == Gtk::RESPONSE_OK) {
2648
2649                         _session_is_new = true;
2650                         
2651                         std::string session_name = m_new_session_dialog->session_name();
2652                         std::string session_path = m_new_session_dialog->session_folder();
2653                         
2654                         /*
2655                           XXX This is needed because session constructor wants a 
2656                           non-existant path. hopefully this will be fixed at some point.
2657                         */
2658                         session_path = Glib::build_filename(session_path, session_name);
2659                         
2660                         std::string template_name = m_new_session_dialog->session_template_name();
2661                         
2662                         if (m_new_session_dialog->use_session_template()) {
2663                                 
2664                                 load_session (session_path, session_name, &template_name);
2665                                 
2666                         } else {
2667                                 
2668                                 uint32_t cchns;
2669                                 uint32_t mchns;
2670                                 Session::AutoConnectOption iconnect;
2671                                 Session::AutoConnectOption oconnect;
2672                                 
2673                                 if (m_new_session_dialog->create_control_bus()) {
2674                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2675                                 } else {
2676                                         cchns = 0;
2677                                 }
2678                                 
2679                                 if (m_new_session_dialog->create_master_bus()) {
2680                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2681                                 } else {
2682                                         mchns = 0;
2683                                 }
2684                                 
2685                                 if (m_new_session_dialog->connect_inputs()) {
2686                                         iconnect = Session::AutoConnectPhysical;
2687                                 } else {
2688                                         iconnect = Session::AutoConnectOption (0);
2689                                 }
2690                                 
2691                                 /// @todo some minor tweaks.
2692
2693                                 if (m_new_session_dialog->connect_outs_to_master()) {
2694                                         oconnect = Session::AutoConnectMaster;
2695                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2696                                         oconnect = Session::AutoConnectPhysical;
2697                                 } else {
2698                                         oconnect = Session::AutoConnectOption (0);
2699                                 } 
2700                                 
2701                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2702                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2703                                 
2704                                 build_session (session_path,
2705                                                session_name,
2706                                                cchns,
2707                                                mchns,
2708                                                iconnect,
2709                                                oconnect,
2710                                                nphysin,
2711                                                nphysout, 
2712                                                engine->frame_rate() * 60 * 5);
2713                         }               
2714                 }
2715
2716         } while(response == Gtk::RESPONSE_HELP);
2717         m_new_session_dialog->hide_all();
2718 }
2719
2720 int
2721 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2722 {
2723         Session *new_session;
2724         int x;
2725         session_loaded = false;
2726         x = unload_session ();
2727
2728         if (x < 0) {
2729                 return -1;
2730         } else if (x > 0) {
2731                 return 0;
2732         }
2733
2734         /* if it already exists, we must have write access */
2735
2736         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2737                 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2738 You do not have write access to this session.\n\
2739 This prevents the session from being loaded."));
2740                 return -1;
2741         }
2742
2743         try {
2744                 new_session = new Session (*engine, path, snap_name, mix_template);
2745         }
2746
2747         catch (...) {
2748
2749                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2750                 return -1;
2751         }
2752
2753         connect_to_session (new_session);
2754
2755         //if (engine->running()) {
2756         //mixer->show_window();
2757         //}
2758         session_loaded = true;
2759         return 0;
2760 }
2761
2762 int
2763 ARDOUR_UI::make_session_clean ()
2764 {
2765         if (session) {
2766                 session->set_clean ();
2767         }
2768
2769         return FALSE;
2770 }
2771
2772 int
2773 ARDOUR_UI::build_session (string path, string snap_name, 
2774                           uint32_t control_channels,
2775                           uint32_t master_channels, 
2776                           Session::AutoConnectOption input_connect,
2777                           Session::AutoConnectOption output_connect,
2778                           uint32_t nphysin,
2779                           uint32_t nphysout,
2780                           jack_nframes_t initial_length)
2781 {
2782         Session *new_session;
2783         int x;
2784
2785         session_loaded = false;
2786         x = unload_session ();
2787         if (x < 0) {
2788                 return -1;
2789         } else if (x > 0) {
2790                 return 0;
2791         }
2792         
2793         _session_is_new = true;
2794
2795         try {
2796                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2797                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2798         }
2799
2800         catch (...) {
2801
2802                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2803                 return -1;
2804         }
2805
2806         connect_to_session (new_session);
2807
2808         //if (engine->running()) {
2809         //mixer->show_window();
2810         //}
2811         session_loaded = true;
2812         return 0;
2813 }
2814
2815 void
2816 ARDOUR_UI::show ()
2817 {
2818         if (editor) {
2819                 editor->show_window ();
2820                 shown_flag = true;
2821         }
2822
2823         if (session && mixer) {
2824                 // mixer->show_window ();
2825         }
2826         
2827         if (about) {
2828                 about->present ();
2829         }
2830 }
2831
2832 void
2833 ARDOUR_UI::show_splash ()
2834 {
2835         if (about == 0) {
2836                 about = new About();
2837         }
2838         about->present();
2839 }
2840
2841 void
2842 ARDOUR_UI::hide_splash ()
2843 {
2844         if (about) {
2845                 // about->hide();
2846         }
2847 }
2848
2849 void
2850 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2851 {
2852         size_t removed;
2853
2854         removed = rep.paths.size();
2855
2856         if (removed == 0) {
2857                 ArdourMessage msg (editor, X_("cleanupresults"),
2858                                    _("\
2859 No audio files were ready for cleanup\n\n\
2860 If this seems suprising, check for any existing\n\
2861 snapshots. These may still include regions that\n\
2862 require some unused files to continue to exist."));
2863                 return;
2864         } 
2865
2866         ArdourDialog results (_("ardour: cleanup"), true);
2867         
2868         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2869             CleanupResultsModelColumns() { 
2870                     add (visible_name);
2871                     add (fullpath);
2872             }
2873             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2874             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2875         };
2876
2877         
2878         Glib::RefPtr<Gtk::ListStore> results_model;
2879         CleanupResultsModelColumns results_columns;
2880         Gtk::TreeView results_display;
2881         
2882         results_model = ListStore::create (results_columns);
2883         results_display.set_model (results_model);
2884         results_display.append_column (list_title, results_columns.visible_name);
2885         results_display.set_headers_visible (true);
2886
2887         Gtk::ScrolledWindow list_scroller;
2888         Gtk::Label txt;
2889
2890         if (rep.space < 1048576.0f) {
2891                 if (removed > 1) {
2892                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2893                 } else {
2894                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2895                 }
2896         } else {
2897                 if (removed > 1) {
2898                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2899                 } else {
2900                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2901                 }
2902         }
2903
2904         results.get_vbox()->pack_start (txt, false, false);
2905         
2906         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2907                 TreeModel::Row row = *(results_model->append());
2908                 row[results_columns.visible_name] = *i;
2909                 row[results_columns.fullpath] = *i;
2910         }
2911         
2912         list_scroller.add (results_display);
2913         list_scroller.set_size_request (-1, 250);
2914         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2915         
2916         results.get_vbox()->pack_start (list_scroller, true, true);
2917         results.add_button (Stock::OK, RESPONSE_ACCEPT);
2918         results.set_position (Gtk::WIN_POS_MOUSE);
2919
2920         results.run ();
2921 }
2922
2923 void
2924 ARDOUR_UI::cleanup ()
2925 {
2926         if (session == 0) {
2927                 /* shouldn't happen: menu item is insensitive */
2928                 return;
2929         }
2930
2931         ArdourDialog checker (_("ardour cleanup"));
2932         Gtk::Label label (_("\
2933 Cleanup is a destructive operation.\n\
2934 ALL undo/redo information will be lost if you cleanup.\n\
2935 Unused audio files will be moved to a \"dead sounds\" location."));
2936         
2937         checker.get_vbox()->pack_start (label, false, false);
2938         checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2939         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2940
2941         checker.set_name (_("CleanupDialog"));
2942         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2943         checker.set_position (Gtk::WIN_POS_MOUSE);
2944
2945         switch (checker.run()) {
2946         case RESPONSE_ACCEPT:
2947                 break;
2948         default:
2949                 return;
2950         }
2951
2952         Session::cleanup_report rep;
2953
2954         editor->prepare_for_cleanup ();
2955
2956         if (session->cleanup_sources (rep)) {
2957                 return;
2958         }
2959
2960         display_cleanup_results (rep, 
2961                                  _("cleaned files"),
2962                                  _("\
2963 The following %1 %2 were not in use.\n\
2964 The next time you flush the wastebasket\n\
2965 it will release an additional %3 %4bytes\n\
2966 of disk space"
2967                                          ));
2968 }
2969
2970 void
2971 ARDOUR_UI::flush_trash ()
2972 {
2973         if (session == 0) {
2974                 /* shouldn't happen: menu item is insensitive */
2975                 return;
2976         }
2977
2978         Session::cleanup_report rep;
2979
2980         if (session->cleanup_trash_sources (rep)) {
2981                 return;
2982         }
2983
2984         display_cleanup_results (rep, 
2985                                  _("deleted file"),
2986                                  _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2987 }
2988
2989 void
2990 ARDOUR_UI::add_route ()
2991 {
2992         int count;
2993
2994         if (!session) {
2995                 return;
2996         }
2997
2998         if (add_route_dialog == 0) {
2999                 add_route_dialog = new AddRouteDialog;
3000                 editor->ensure_float (*add_route_dialog);
3001         }
3002
3003         if (add_route_dialog->is_visible()) {
3004                 /* we're already doing this */
3005                 return;
3006         }
3007
3008         ResponseType r = (ResponseType) add_route_dialog->run ();
3009         
3010         add_route_dialog->hide();
3011
3012         switch (r) {
3013         case RESPONSE_ACCEPT:
3014                 break;
3015         default:
3016                 return;
3017                 break;
3018         }
3019
3020         if ((count = add_route_dialog->count()) <= 0) {
3021                 return;
3022         }
3023
3024         uint32_t input_chan = add_route_dialog->channels ();
3025         uint32_t output_chan;
3026         string name_template = add_route_dialog->name_template ();
3027         bool track = add_route_dialog->track ();
3028
3029         Session::AutoConnectOption oac = session->get_output_auto_connect();
3030
3031         if (oac & Session::AutoConnectMaster) {
3032                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3033         } else {
3034                 output_chan = input_chan;
3035         }
3036
3037         /* XXX do something with name template */
3038
3039         while (count) {
3040                 if (track) {
3041                         session_add_audio_track (input_chan, output_chan);
3042                 } else {
3043                         session_add_audio_bus (input_chan, output_chan);
3044                 }
3045                 --count;
3046                 
3047                 while (Main::events_pending()) {
3048                         Main::iteration ();
3049                 }
3050         }
3051 }
3052
3053 XMLNode*
3054 ARDOUR_UI::mixer_settings () const
3055 {
3056         XMLNode* node = 0;
3057
3058         if (session) {
3059                 node = session->instant_xml(X_("Mixer"), session->path());
3060         } else {
3061                 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3062         }
3063
3064         if (!node) {
3065                 node = new XMLNode (X_("Mixer"));
3066         }
3067
3068         return node;
3069 }
3070
3071 XMLNode*
3072 ARDOUR_UI::editor_settings () const
3073 {
3074         XMLNode* node = 0;
3075
3076         if (session) {
3077                 node = session->instant_xml(X_("Editor"), session->path());
3078         } else {
3079                 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3080         }
3081
3082         if (!node) {
3083                 node = new XMLNode (X_("Editor"));
3084         }
3085         return node;
3086 }
3087
3088 XMLNode*
3089 ARDOUR_UI::keyboard_settings () const
3090 {
3091         XMLNode* node = 0;
3092
3093         node = Config->extra_xml(X_("Keyboard"));
3094         
3095         if (!node) {
3096                 node = new XMLNode (X_("Keyboard"));
3097         }
3098         return node;
3099 }
3100
3101 void
3102 ARDOUR_UI::halt_on_xrun_message ()
3103 {
3104         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3105
3106         ArdourMessage msg (editor, X_("haltonxrun"),
3107                            _("Recording was stopped because your system could not keep up."));
3108 }
3109
3110 void 
3111 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3112 {
3113         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3114
3115         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3116                 delete *i;
3117         }
3118
3119         delete deletion_list;
3120 }
3121
3122 void
3123 ARDOUR_UI::disk_overrun_handler ()
3124 {
3125         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3126
3127         if (!have_disk_overrun_displayed) {
3128                 have_disk_overrun_displayed = true;
3129                 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3130 The disk system on your computer\n\
3131 was not able to keep up with Ardour.\n\
3132 \n\
3133 Specifically, it failed to write data to disk\n\
3134 quickly enough to keep up with recording.\n"));
3135                 have_disk_overrun_displayed = false;
3136         }
3137 }
3138
3139 void
3140 ARDOUR_UI::disk_underrun_handler ()
3141 {
3142         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3143
3144         if (!have_disk_underrun_displayed) {
3145                 have_disk_underrun_displayed = true;
3146                 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3147                         (_("The disk system on your computer\n\
3148 was not able to keep up with Ardour.\n\
3149 \n\
3150 Specifically, it failed to read data from disk\n\
3151 quickly enough to keep up with playback.\n")));
3152                 have_disk_underrun_displayed = false;
3153         } 
3154 }
3155
3156 void
3157 ARDOUR_UI::disk_underrun_message_gone ()
3158 {
3159         have_disk_underrun_displayed = false;
3160 }
3161
3162 void
3163 ARDOUR_UI::disk_overrun_message_gone ()
3164 {
3165         have_disk_underrun_displayed = false;
3166 }
3167
3168 int
3169 ARDOUR_UI::pending_state_dialog ()
3170 {
3171         ArdourDialog dialog ("pending state dialog");
3172         Label  message (_("\
3173 This session appears to have been in\n\
3174 middle of recording when ardour or\n\
3175 the computer was shutdown.\n\
3176 \n\
3177 Ardour can recover any captured audio for\n\
3178 you, or it can ignore it. Please decide\n\
3179 what you would like to do.\n"));
3180
3181         dialog.get_vbox()->pack_start (message);
3182         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3183         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3184
3185         dialog.set_position (WIN_POS_CENTER);
3186         dialog.show_all ();
3187         
3188         switch (dialog.run ()) {
3189         case RESPONSE_ACCEPT:
3190                 break;
3191         default:
3192                 return 1;
3193         }
3194
3195         return 0;
3196 }
3197         
3198         
3199 void
3200 ARDOUR_UI::disconnect_from_jack ()
3201 {
3202         if (engine) {
3203                 if( engine->disconnect_from_jack ()) {
3204                         ArdourMessage msg (editor, X_("nojack dialog"),
3205                                            _("Could not disconnect from JACK"));
3206                 }
3207
3208                 update_sample_rate (0);
3209         }
3210 }
3211
3212 void
3213 ARDOUR_UI::reconnect_to_jack ()
3214 {
3215         if (engine) {
3216                 if (engine->reconnect_to_jack ()) {
3217                         ArdourMessage msg (editor, X_("nojack dialog"),
3218                                            _("Could not reconnect to JACK"));
3219                 }
3220
3221                 update_sample_rate (0);
3222         }
3223 }
3224
3225 void
3226 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3227 {
3228         engine->request_buffer_size (nframes);
3229         update_sample_rate (0);
3230 }
3231
3232 int
3233 ARDOUR_UI::cmdline_new_session (string path)
3234 {
3235         if (path[0] != '/') {
3236                 char buf[PATH_MAX+1];
3237                 string str;
3238
3239                 getcwd (buf, sizeof (buf));
3240                 str = buf;
3241                 str += '/';
3242                 str += path;
3243                 path = str;
3244         }
3245
3246         new_session (false, path);
3247
3248         _will_create_new_session_automatically = false; /* done it */
3249         return FALSE; /* don't call it again */
3250 }