button hacks and more
[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
808           punch_in_button (_("punch\nin")),
809           punch_out_button (_("punch\nout")),
810           auto_return_button (_("auto\nreturn")),
811           auto_play_button (_("auto\nplay")),
812           auto_input_button (_("auto\ninput")),
813           click_button (_("click")),
814           follow_button (_("follow\nPH")),
815           auditioning_alert_button (_("AUDITIONING")),
816           solo_alert_button (_("SOLO")),
817           shown_flag (false)
818
819 {
820         using namespace Gtk::Menu_Helpers;
821
822         Gtkmm2ext::init();
823
824         /* actually, its already loaded, but ... */
825
826         cerr << "Loading UI configuration file " << rcfile << endl;
827
828         about = 0;
829
830         if (theArdourUI == 0) {
831                 theArdourUI = this;
832         }
833
834         // allow run-time rebinding of accels
835
836         Settings::get_default()->property_gtk_can_change_accels() = true;
837
838         ActionManager::init ();
839         
840         m_new_session_dialog = 0;
841         m_new_session_dialog_ref = NewSessionDialogFactory::create();
842         m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
843         editor = 0;
844         mixer = 0;
845         session = 0;
846         _session_is_new = false;
847         big_clock_window = 0;
848         session_selector_window = 0;
849         last_key_press_time = 0;
850         connection_editor = 0;
851         add_route_dialog = 0;
852         route_params = 0;
853         option_editor = 0;
854         location_ui = 0;
855         sfdb = 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                 vector<string> names;
932                 vector<string> paths;
933                 vector<string> keys;
934                 vector<AccelKey> bindings;
935
936                 ActionManager::get_all_actions (names, paths, keys, bindings);
937
938                 vector<string>::iterator n;
939                 vector<string>::iterator k;
940                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
941                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
942                 }
943
944                 exit (0);
945         }
946
947         /* start with timecode, metering enabled
948         */
949         
950         blink_timeout_tag = -1;
951
952         /* this being a GUI and all, we want peakfiles */
953
954         FileSource::set_build_peakfiles (true);
955         FileSource::set_build_missing_peakfiles (true);
956
957         if (Source::start_peak_thread ()) {
958                 throw failed_constructor();
959         }
960
961         /* start the time-of-day-clock */
962         
963         update_wall_clock ();
964         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
965
966         update_disk_space ();
967         update_cpu_load ();
968         update_sample_rate (engine->frame_rate());
969
970         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
971         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
972 }
973
974 ARDOUR_UI::~ARDOUR_UI ()
975 {
976         save_ardour_state ();
977
978         if (keyboard) {
979                 delete keyboard;
980         }
981
982         if (editor) {
983                 delete editor;
984         }
985
986         if (mixer) {
987                 delete mixer;
988         }
989
990         if (add_route_dialog) {
991                 delete add_route_dialog;
992         }
993
994         Source::stop_peak_thread ();
995 }
996
997 gint
998 ARDOUR_UI::configure_timeout ()
999 {
1000         struct timeval now;
1001         struct timeval diff;
1002
1003         if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
1004                 /* no configure events yet */
1005                 return TRUE;
1006         }
1007
1008         gettimeofday (&now, 0);
1009         timersub (&now, &last_configure_time, &diff);
1010
1011         /* force a gap of 0.5 seconds since the last configure event
1012          */
1013
1014         if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1015                 return TRUE;
1016         } else {
1017                 have_configure_timeout = false;
1018                 save_ardour_state ();
1019                 return FALSE;
1020         }
1021 }
1022
1023 gboolean
1024 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1025 {
1026         if (have_configure_timeout) {
1027                 gettimeofday (&last_configure_time, 0);
1028         } else {
1029                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1030                 have_configure_timeout = true;
1031         }
1032                 
1033         return FALSE;
1034 }
1035
1036 void
1037 ARDOUR_UI::save_ardour_state ()
1038 {
1039         if (!keyboard || !mixer || !editor) {
1040                 return;
1041         }
1042         
1043         /* XXX this is all a bit dubious. add_extra_xml() uses
1044            a different lifetime model from add_instant_xml().
1045         */
1046
1047         XMLNode* node = new XMLNode (keyboard->get_state());
1048         Config->add_extra_xml (*node);
1049         Config->save_state();
1050
1051         XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1052         XMLNode& mnode (mixer->get_state());
1053
1054         if (session) {
1055                 session->add_instant_xml(enode, session->path());
1056                 session->add_instant_xml(mnode, session->path());
1057         } else {
1058                 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1059                 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1060         }
1061 }
1062
1063 void
1064 ARDOUR_UI::startup ()
1065 {
1066         /* Once the UI is up and running, start the audio engine. Doing
1067            this before the UI is up and running can cause problems
1068            when not running with SCHED_FIFO, because the amount of
1069            CPU and disk work needed to get the UI started can interfere
1070            with the scheduling of the audio thread.
1071         */
1072
1073         Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1074 }
1075
1076 void
1077 ARDOUR_UI::finish()
1078 {
1079         if (session && session->dirty()) {
1080                 switch (ask_about_saving_session(_("quit"))) {
1081                 case -1:
1082                         return;
1083                         break;
1084                 case 1:
1085                         /* use the default name */
1086                         if (save_state_canfail ("")) {
1087                                 /* failed - don't quit */
1088                                 ArdourMessage (editor, X_("badsave dialog"),
1089                                                _("\
1090 Ardour was unable to save your session.\n\n\
1091 If you still wish to quit, please use the\n\n\
1092 \"Just quit\" option."));
1093                                 return;
1094                         }
1095                         break;
1096                 case 0:
1097                         break;
1098                 }
1099         }
1100
1101         quit ();
1102 }
1103
1104 int
1105 ARDOUR_UI::ask_about_saving_session (stringcr_t what)
1106 {
1107         ArdourDialog window (_("ardour: save session?"));
1108         Gtk::Label  prompt_label;
1109         string msg;
1110
1111         msg = string_compose(_("Save and %1"), what);
1112         window.add_button (msg, RESPONSE_ACCEPT);
1113         msg = string_compose(_("Just %1"), what);
1114         window.add_button (msg, RESPONSE_APPLY);
1115         msg = string_compose(_("Don't %1"), what);
1116         window.add_button (msg, RESPONSE_REJECT);
1117
1118         Gtk::Button noquit_button (msg);
1119         noquit_button.set_name ("EditorGTKButton");
1120
1121         string prompt;
1122         string type;
1123
1124         if (session->snap_name() == session->name()) {
1125                 type = _("session");
1126         } else {
1127                 type = _("snapshot");
1128         }
1129         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?"), 
1130                          type, session->snap_name());
1131         
1132         prompt_label.set_text (prompt);
1133         prompt_label.set_alignment (0.5, 0.5);
1134         prompt_label.set_name (X_("PrompterLabel"));
1135         
1136         window.get_vbox()->pack_start (prompt_label);
1137
1138         window.set_name (_("Prompter"));
1139         window.set_position (Gtk::WIN_POS_MOUSE);
1140         window.set_modal (true);
1141         window.show_all ();
1142
1143         save_the_session = 0;
1144
1145         editor->ensure_float (window);
1146
1147         ResponseType r = (ResponseType) window.run();
1148
1149         window.hide ();
1150
1151         switch (r) {
1152         case RESPONSE_ACCEPT: // save and get out of here
1153                 return 1;
1154         case RESPONSE_APPLY:  // get out of here
1155                 return 0;
1156         default:
1157                 break;
1158         }
1159
1160         return -1;
1161 }
1162         
1163 gint
1164 ARDOUR_UI::every_second ()
1165 {
1166         update_cpu_load ();
1167         update_buffer_load ();
1168         update_disk_space ();
1169         // update_disk_rate ();
1170         return TRUE;
1171 }
1172
1173 gint
1174 ARDOUR_UI::every_point_one_seconds ()
1175 {
1176         struct timeval now;
1177         struct timeval diff;
1178         
1179         /* do not attempt to grab peak power more than once per cycle.
1180          */
1181
1182         gettimeofday (&now, 0);
1183         timersub (&now, &last_peak_grab, &diff);
1184
1185         if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1186                 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1187                 last_peak_grab = now;
1188         } 
1189
1190         update_speed_display ();
1191         RapidScreenUpdate(); /* EMIT_SIGNAL */
1192         return TRUE;
1193 }
1194
1195 gint
1196 ARDOUR_UI::every_point_zero_one_seconds ()
1197 {
1198         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1199         return TRUE;
1200 }
1201
1202 void
1203 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1204 {
1205         char buf[32];
1206
1207         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1208
1209         if (!engine->connected()) {
1210
1211                 snprintf (buf, sizeof (buf), _("disconnected"));
1212
1213         } else {
1214
1215                 jack_nframes_t rate = engine->frame_rate();
1216                 
1217                 if (fmod (rate, 1000.0) != 0.0) {
1218                         snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), 
1219                                   (float) rate/1000.0f,
1220                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1221                 } else {
1222                         snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), 
1223                                   rate/1000,
1224                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1225                 }
1226         }
1227
1228         sample_rate_label.set_text (buf);
1229 }
1230
1231 void
1232 ARDOUR_UI::update_cpu_load ()
1233 {
1234         char buf[32];
1235         snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1236         cpu_load_label.set_text (buf);
1237 }
1238
1239 void
1240 ARDOUR_UI::update_disk_rate ()
1241 {
1242         char buf[64];
1243
1244         if (session) {
1245                 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"), 
1246                           session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1247                 disk_rate_label.set_text (buf);
1248         } else {
1249                 disk_rate_label.set_text ("");
1250         }
1251 }
1252
1253 void
1254 ARDOUR_UI::update_buffer_load ()
1255 {
1256         char buf[64];
1257
1258         if (session) {
1259                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
1260                           session->playback_load(), session->capture_load());
1261                 buffer_load_label.set_text (buf);
1262         } else {
1263                 buffer_load_label.set_text ("");
1264         }
1265 }
1266
1267 void
1268 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1269 {
1270         if (ds.record_enabled()) {
1271                 rec_enabled_diskstreams++;
1272         }
1273 }
1274
1275 void
1276 ARDOUR_UI::update_disk_space()
1277 {
1278         if (session == 0) {
1279                 return;
1280         }
1281
1282         jack_nframes_t frames = session->available_capture_duration();
1283         char buf[64];
1284
1285         if (frames == max_frames) {
1286                 strcpy (buf, _("space: 24hrs+"));
1287         } else {
1288                 int hrs;
1289                 int mins;
1290                 int secs;
1291                 jack_nframes_t fr = session->frame_rate();
1292                 
1293                 if (session->actively_recording()){
1294                         
1295                         rec_enabled_diskstreams = 0;
1296                         session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1297                         
1298                         if (rec_enabled_diskstreams) {
1299                                 frames /= rec_enabled_diskstreams;
1300                         }
1301                         
1302                 } else {
1303                         
1304                         /* hmmm. shall we divide by the route count? or the diskstream count?
1305                            or what? for now, do nothing ...
1306                         */
1307                         
1308                 }
1309                 
1310                 hrs  = frames / (fr * 3600);
1311                 frames -= hrs * fr * 3600;
1312                 mins = frames / (fr * 60);
1313                 frames -= mins * fr * 60;
1314                 secs = frames / fr;
1315                 
1316                 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1317         }
1318
1319         disk_space_label.set_text (buf);
1320 }                 
1321
1322 gint
1323 ARDOUR_UI::update_wall_clock ()
1324 {
1325         time_t now;
1326         struct tm *tm_now;
1327         char buf[16];
1328
1329         time (&now);
1330         tm_now = localtime (&now);
1331
1332         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1333         wall_clock_label.set_text (buf);
1334
1335         return TRUE;
1336 }
1337
1338 void
1339 ARDOUR_UI::toggle_recording_plugins ()
1340 {
1341         /* XXX use toggle_some_session_state */
1342
1343         if (session == 0) {
1344                 return;
1345         }
1346
1347         session->set_recording_plugins (!session->get_recording_plugins());
1348 }
1349         
1350 void
1351 ARDOUR_UI::toggle_auto_play ()
1352
1353 {
1354         toggle_some_session_state (auto_play_button,
1355                                    &Session::get_auto_play,
1356                                    &Session::set_auto_play);
1357 }
1358
1359 void
1360 ARDOUR_UI::toggle_auto_return ()
1361
1362 {
1363         toggle_some_session_state (auto_return_button,
1364                                    &Session::get_auto_return,
1365                                    &Session::set_auto_return);
1366 }
1367
1368 void
1369 ARDOUR_UI::toggle_click ()
1370 {
1371         toggle_some_session_state (click_button,
1372                                    &Session::get_clicking,
1373                                    &Session::set_clicking);
1374 }
1375
1376 void
1377 ARDOUR_UI::follow_changed ()
1378 {
1379         bool x;
1380
1381         if (!editor) {
1382                 return;
1383         }
1384
1385         if (follow_button.get_active() != (x = editor->follow_playhead())) {
1386                 follow_button.set_active (x);
1387         }
1388 }
1389
1390 void
1391 ARDOUR_UI::toggle_follow ()
1392 {
1393         bool x;
1394
1395         if (!editor) {
1396                 return;
1397         }
1398
1399         if (editor->follow_playhead() != (x = follow_button.get_active())) {
1400                 editor->set_follow_playhead (x);
1401         }
1402 }
1403
1404 void
1405 ARDOUR_UI::toggle_session_auto_loop ()
1406 {
1407         if (session) {
1408                 if (session->get_auto_loop()) {
1409                         if (session->transport_rolling()) {
1410                                 transport_roll();
1411                         }
1412                         else {
1413                                 session->request_auto_loop (false);
1414                         }
1415                 }
1416                 else {
1417                         session->request_auto_loop (true);
1418                 }
1419         }
1420 }
1421
1422 void
1423 ARDOUR_UI::toggle_session_punch_in ()
1424 {
1425         if (session) {
1426                 session->set_punch_in (!session->get_punch_in());
1427         }
1428 }
1429
1430 void
1431 ARDOUR_UI::toggle_punch_out ()
1432 {
1433         toggle_some_session_state (punch_out_button,
1434                                    &Session::get_punch_out,
1435                                    &Session::set_punch_out);
1436 }
1437
1438 void
1439 ARDOUR_UI::toggle_punch_in ()
1440 {
1441         toggle_some_session_state (punch_in_button,
1442                                    &Session::get_punch_in,
1443                                    &Session::set_punch_in);
1444 }
1445
1446 void
1447 ARDOUR_UI::map_button_state ()
1448
1449 {
1450         map_some_session_state (auto_return_button,
1451                                 &Session::get_auto_return);
1452         map_some_session_state (auto_play_button,
1453                                 &Session::get_auto_play);
1454         map_some_session_state (auto_input_button,
1455                                 &Session::get_auto_input);
1456         map_some_session_state (punch_in_button,
1457                                 &Session::get_punch_in);
1458         map_some_session_state (punch_out_button,
1459                                 &Session::get_punch_out);
1460         map_some_session_state (click_button,
1461                                 &Session::get_clicking);
1462 }
1463
1464 void
1465 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1466 {
1467         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1468 }
1469
1470 void
1471 ARDOUR_UI::map_control_change (Session::ControlType t)
1472 {
1473         switch (t) {
1474         case Session::AutoPlay:
1475                 map_some_session_state (auto_play_button, &Session::get_auto_play);
1476                 break;
1477
1478         case Session::AutoLoop:
1479                 break;
1480
1481         case Session::AutoReturn:
1482                 map_some_session_state (auto_return_button, &Session::get_auto_return);
1483                 break;
1484
1485         case Session::AutoInput:
1486                 map_some_session_state (auto_input_button, &Session::get_auto_input);
1487                 break;
1488
1489         case Session::PunchOut:
1490                 map_some_session_state (punch_in_button, &Session::get_punch_out);
1491                 break;
1492
1493         case Session::PunchIn:
1494                 map_some_session_state (punch_in_button, &Session::get_punch_in);
1495                 break;
1496
1497         case Session::Clicking:
1498                 map_some_session_state (click_button, &Session::get_clicking);
1499                 break;
1500
1501         case Session::SlaveType:
1502 //              map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1503                 break;
1504
1505         case Session::SendMTC:
1506 //              map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1507                 break;
1508
1509         case Session::SendMMC:
1510 //              map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1511                 break;
1512
1513         case Session::MMCControl:       
1514 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1515                 break;
1516
1517         case Session::MidiFeedback:       
1518 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1519                 break;
1520         case Session::MidiControl:       
1521 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1522                 break;
1523                 
1524         case Session::Live:
1525                 break;
1526
1527         case Session::RecordingPlugins:
1528                 break;
1529
1530         case Session::CrossFadesActive:
1531                 break;
1532                 
1533         case Session::EditingMode:
1534                 break;
1535
1536         case Session::PlayRange:
1537                 break;
1538
1539         case Session::AlignChoice:
1540                 /* don't care, this is handled by the options editor */
1541                 break;
1542         case Session::SeamlessLoop:
1543                 /* don't care, this is handled by the options editor */
1544                 break;
1545                
1546         }
1547 }
1548
1549 void
1550 ARDOUR_UI::control_methods_adjusted ()
1551
1552 {
1553         int which_method;
1554
1555         which_method = (int) online_control_button->adjustment.get_value();
1556         switch (which_method) {
1557         case 0:
1558                 allow_mmc_and_local ();
1559                 break;
1560         case 1:
1561                 allow_mmc_only ();
1562                 break;
1563         case 2:
1564                 allow_local_only ();
1565                 break;
1566         default:
1567                 fatal << _("programming error: impossible control method") << endmsg;
1568         }
1569 }
1570         
1571
1572 void
1573 ARDOUR_UI::mmc_device_id_adjusted ()
1574
1575 {
1576 #if 0
1577         if (mmc) {
1578                 int dev_id = (int) mmc_id_button->adjustment.get_value();
1579                 mmc->set_device_id (dev_id);
1580         }
1581 #endif
1582 }
1583
1584 void
1585 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1586                                    bool (Session::*get)() const)
1587         
1588 {
1589         bool x;
1590
1591         if (session == 0) {
1592                 return;
1593         }
1594         
1595         if (button.get_active() != (x = (session->*get)())) {
1596                 button.set_active (x);
1597         }
1598 }
1599
1600 void
1601 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1602                                       bool (Session::*get)() const,
1603                                       void (Session::*set)(bool))
1604
1605 {
1606         bool button_state;
1607         bool session_state;
1608
1609         if (session == 0) {
1610                 return;
1611         }
1612
1613         button_state = button.get_active ();
1614         session_state = (session->*get)();
1615
1616         if (button_state != session_state) {
1617                 (session->*set) (button_state);
1618 #if 0
1619         
1620                 /* check that it worked, and reverse
1621                    the button state if it didn't
1622                 */
1623
1624                 if ((session->*get)() != button_state) {
1625                         button->set_active (!button_state);
1626                 }
1627 #endif
1628
1629         }
1630 }       
1631
1632 gint
1633 ARDOUR_UI::session_menu (GdkEventButton *ev)
1634 {
1635         session_popup_menu->popup (0, 0);
1636         return TRUE;
1637 }
1638
1639 void
1640 ARDOUR_UI::redisplay_recent_sessions ()
1641 {
1642         vector<string *> *sessions;
1643         vector<string *>::iterator i;
1644         RecentSessionsSorter cmp;
1645         
1646         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1647         recent_session_model->clear ();
1648
1649         RecentSessions rs;
1650         ARDOUR::read_recent_sessions (rs);
1651
1652         if (rs.empty()) {
1653                 recent_session_display.set_model (recent_session_model);
1654                 return;
1655         }
1656
1657         /* sort them alphabetically */
1658         sort (rs.begin(), rs.end(), cmp);
1659         sessions = new vector<string*>;
1660
1661         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1662                 sessions->push_back (new string ((*i).second));
1663         }
1664
1665         for (i = sessions->begin(); i != sessions->end(); ++i) {
1666
1667                 vector<string*>* states;
1668                 vector<const gchar*> item;
1669                 string fullpath = *(*i);
1670                 
1671                 /* remove any trailing / */
1672
1673                 if (fullpath[fullpath.length()-1] == '/') {
1674                         fullpath = fullpath.substr (0, fullpath.length()-1);
1675                 }
1676
1677                 /* now get available states for this session */
1678
1679                 if ((states = Session::possible_states (fullpath)) == 0) {
1680                         /* no state file? */
1681                         continue;
1682                 }
1683
1684                 TreeModel::Row row = *(recent_session_model->append());
1685
1686                 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1687                 row[recent_session_columns.fullpath] = fullpath;
1688
1689                 if (states->size() > 1) {
1690
1691                         /* add the children */
1692                         
1693                         for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1694                                 
1695                                 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1696
1697                                 child_row[recent_session_columns.visible_name] = **i2;
1698                                 child_row[recent_session_columns.fullpath] = fullpath;
1699
1700                                 delete *i2;
1701                         }
1702                 }
1703
1704                 delete states;
1705         }
1706
1707         recent_session_display.set_model (recent_session_model);
1708         delete sessions;
1709 }
1710
1711 void
1712 ARDOUR_UI::build_session_selector ()
1713 {
1714         session_selector_window = new ArdourDialog ("session selector");
1715         
1716         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1717         
1718         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1719         session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1720
1721         recent_session_model = TreeStore::create (recent_session_columns);
1722         recent_session_display.set_model (recent_session_model);
1723         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1724         recent_session_display.set_headers_visible (false);
1725
1726         scroller->add (recent_session_display);
1727         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1728
1729         session_selector_window->set_name ("SessionSelectorWindow");
1730         session_selector_window->set_size_request (200, 400);
1731         session_selector_window->get_vbox()->pack_start (*scroller);
1732         session_selector_window->show_all_children();
1733 }
1734
1735 void
1736 ARDOUR_UI::open_recent_session ()
1737 {
1738         /* popup selector window */
1739
1740         if (session_selector_window == 0) {
1741                 build_session_selector ();
1742         }
1743
1744         redisplay_recent_sessions ();
1745
1746         ResponseType r = (ResponseType) session_selector_window->run ();
1747
1748         session_selector_window->hide();
1749
1750         switch (r) {
1751         case RESPONSE_ACCEPT:
1752                 break;
1753         default:
1754                 return;
1755         }
1756
1757         Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1758
1759         if (i == recent_session_model->children().end()) {
1760                 return;
1761         }
1762         
1763         Glib::ustring path = (*i)[recent_session_columns.fullpath];
1764         Glib::ustring state = (*i)[recent_session_columns.visible_name];
1765
1766         _session_is_new = false;
1767
1768         load_session (path, state);
1769 }
1770
1771 bool
1772 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) 
1773 {
1774         struct stat statbuf;
1775
1776         if (stat (info.filename.c_str(), &statbuf) != 0) {
1777                 return false;
1778         }
1779
1780         if (!S_ISDIR(statbuf.st_mode)) {
1781                 return false;
1782         }
1783
1784         string session_file = info.filename;
1785         session_file += '/';
1786         session_file += PBD::basename (info.filename);
1787         session_file += ".ardour";
1788         
1789         if (stat (session_file.c_str(), &statbuf) != 0) {
1790                 return false;
1791         }
1792
1793         return S_ISREG (statbuf.st_mode);
1794 }
1795
1796 void
1797 ARDOUR_UI::open_session ()
1798 {
1799         /* popup selector window */
1800
1801         if (open_session_selector == 0) {
1802
1803                 /* ardour sessions are folders */
1804
1805                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1806                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1807                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1808
1809                 FileFilter session_filter;
1810                 session_filter.add_pattern ("*.ardour");
1811                 session_filter.set_name (_("Ardour sessions"));
1812                 open_session_selector->add_filter (session_filter);
1813                 open_session_selector->set_filter (session_filter);
1814         }
1815
1816         int response = open_session_selector->run();
1817         open_session_selector->hide ();
1818
1819         switch (response) {
1820         case RESPONSE_ACCEPT:
1821                 break;
1822         default:
1823                 open_session_selector->hide();
1824                 return;
1825         }
1826
1827         open_session_selector->hide();
1828         string session_path = open_session_selector->get_filename();
1829         string path, name;
1830         bool isnew;
1831
1832         if (session_path.length() > 0) {
1833                 if (Session::find_session (session_path, path, name, isnew) == 0) {
1834                         _session_is_new = isnew;
1835                         load_session (path, name);
1836                 }
1837         }
1838 }
1839
1840
1841 void
1842 ARDOUR_UI::session_add_midi_track ()
1843 {
1844         cerr << _("Patience is a virtue.\n");
1845 }
1846
1847 void
1848 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1849 {
1850         Route* route;
1851
1852         if (session == 0) {
1853                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1854                 return;
1855         }
1856
1857         try { 
1858                 if (disk) {
1859                         if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1860                                 error << _("could not create new audio track") << endmsg;
1861                         }
1862                 } else {
1863                         if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1864                                 error << _("could not create new audio bus") << endmsg;
1865                         }
1866                 }
1867                 
1868 #if CONTROLOUTS
1869                 if (need_control_room_outs) {
1870                         pan_t pans[2];
1871                         
1872                         pans[0] = 0.5;
1873                         pans[1] = 0.5;
1874                         
1875                         route->set_stereo_control_outs (control_lr_channels);
1876                         route->control_outs()->set_stereo_pan (pans, this);
1877                 }
1878 #endif /* CONTROLOUTS */
1879         }
1880
1881         catch (...) {
1882                 ArdourMessage msg (editor, X_("noport dialog"),
1883                                    _("There are insufficient JACK ports available\n\
1884 to create a new track or bus.\n\
1885 You should save Ardour, exit and\n\
1886 restart JACK with more ports."));
1887         }
1888 }
1889
1890 void
1891 ARDOUR_UI::diskstream_added (DiskStream* ds)
1892 {
1893 }
1894
1895 void
1896 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1897 {
1898         jack_nframes_t _preroll;
1899
1900         if (session) {
1901                 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1902
1903                 if (new_position > _preroll) {
1904                         new_position -= _preroll;
1905                 } else {
1906                         new_position = 0;
1907                 }
1908
1909                 session->request_locate (new_position);
1910         }
1911 }
1912
1913 void
1914 ARDOUR_UI::transport_goto_start ()
1915 {
1916         if (session) {
1917                 session->request_locate (0);
1918
1919                 
1920                 /* force displayed area in editor to start no matter
1921                    what "follow playhead" setting is.
1922                 */
1923                 
1924                 if (editor) {
1925                         editor->reposition_x_origin (0);
1926                 }
1927         }
1928 }
1929
1930 void
1931 ARDOUR_UI::transport_goto_end ()
1932 {
1933         if (session) {
1934                 jack_nframes_t frame = session->current_end_frame();
1935                 session->request_locate (frame);
1936
1937                 /* force displayed area in editor to start no matter
1938                    what "follow playhead" setting is.
1939                 */
1940                 
1941                 if (editor) {
1942                         editor->reposition_x_origin (frame);
1943                 }
1944         }
1945 }
1946
1947 void
1948 ARDOUR_UI::transport_stop ()
1949 {
1950         if (!session) {
1951                 return;
1952         }
1953
1954         if (session->is_auditioning()) {
1955                 session->cancel_audition ();
1956                 return;
1957         }
1958         
1959         if (session->get_auto_loop()) {
1960                 session->request_auto_loop (false);
1961         }
1962         
1963         session->request_stop ();
1964 }
1965
1966 void
1967 ARDOUR_UI::transport_stop_and_forget_capture ()
1968 {
1969         if (session) {
1970                 session->request_stop (true);
1971         }
1972 }
1973
1974 void
1975 ARDOUR_UI::remove_last_capture()
1976 {
1977         if (editor) {
1978                 editor->remove_last_capture();
1979         }
1980 }
1981
1982 void
1983 ARDOUR_UI::transport_record ()
1984 {
1985         if (session) {
1986                 switch (session->record_status()) {
1987                 case Session::Disabled:
1988                         if (session->ntracks() == 0) {
1989                                 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1990                                 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1991                                 return;
1992                         }
1993                         session->maybe_enable_record ();
1994                         break;
1995                 case Session::Recording:
1996                 case Session::Enabled:
1997                         session->disable_record ();
1998                 }
1999         }
2000 }
2001
2002 void
2003 ARDOUR_UI::transport_roll ()
2004 {
2005         bool rolling;
2006
2007         if (!session) {
2008                 return;
2009         }
2010
2011         rolling = session->transport_rolling ();
2012
2013         if (session->get_auto_loop()) {
2014                 session->request_auto_loop (false);
2015                 auto_loop_button.set_active (false);
2016                 roll_button.set_active (true);
2017         } else if (session->get_play_range ()) {
2018                 session->request_play_range (false);
2019                 play_selection_button.set_active (false);
2020         } else if (rolling) {
2021                 session->request_locate (session->last_transport_start(), true);
2022         }
2023
2024         session->request_transport_speed (1.0f);
2025 }
2026
2027 void
2028 ARDOUR_UI::transport_loop()
2029 {
2030         if (session) {
2031                 if (session->get_auto_loop()) {
2032                         if (session->transport_rolling()) {
2033                                 Location * looploc = session->locations()->auto_loop_location();
2034                                 if (looploc) {
2035                                         session->request_locate (looploc->start(), true);
2036                                 }
2037                         }
2038                 }
2039                 else {
2040                         session->request_auto_loop (true);
2041                 }
2042         }
2043 }
2044
2045 void
2046 ARDOUR_UI::transport_play_selection ()
2047 {
2048         if (!session) {
2049                 return;
2050         }
2051
2052         if (!session->get_play_range()) {
2053                 session->request_stop ();
2054         }
2055
2056         editor->play_selection ();
2057 }
2058
2059 void
2060 ARDOUR_UI::transport_rewind (int option)
2061 {
2062         float current_transport_speed;
2063  
2064         if (session) {
2065                 current_transport_speed = session->transport_speed();
2066                 
2067                 if (current_transport_speed >= 0.0f) {
2068                         switch (option) {
2069                         case 0:
2070                                 session->request_transport_speed (-1.0f);
2071                                 break;
2072                         case 1:
2073                                 session->request_transport_speed (-4.0f);
2074                                 break;
2075                         case -1:
2076                                 session->request_transport_speed (-0.5f);
2077                                 break;
2078                         }
2079                 } else {
2080                         /* speed up */
2081                         session->request_transport_speed (current_transport_speed * 1.5f);
2082                 }
2083         }
2084 }
2085
2086 void
2087 ARDOUR_UI::transport_forward (int option)
2088 {
2089         float current_transport_speed;
2090         
2091         if (session) {
2092                 current_transport_speed = session->transport_speed();
2093                 
2094                 if (current_transport_speed <= 0.0f) {
2095                         switch (option) {
2096                         case 0:
2097                                 session->request_transport_speed (1.0f);
2098                                 break;
2099                         case 1:
2100                                 session->request_transport_speed (4.0f);
2101                                 break;
2102                         case -1:
2103                                 session->request_transport_speed (0.5f);
2104                                 break;
2105                         }
2106                 } else {
2107                         /* speed up */
2108                         session->request_transport_speed (current_transport_speed * 1.5f);
2109                 }
2110         }
2111 }
2112
2113 void
2114 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2115 {
2116         if (session == 0) {
2117                 return;
2118         }
2119
2120         DiskStream *ds;
2121
2122         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2123                 Port *port = ds->io()->input (0);
2124                 port->request_monitor_input (!port->monitoring_input());
2125         }
2126 }
2127
2128 void
2129 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2130 {
2131         if (session == 0) {
2132                 return;
2133         }
2134
2135         DiskStream *ds;
2136
2137         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2138                 ds->set_record_enabled (!ds->record_enabled(), this);
2139         }
2140 }
2141
2142 void
2143 ARDOUR_UI::queue_transport_change ()
2144 {
2145         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2146 }
2147
2148 void
2149 ARDOUR_UI::map_transport_state ()
2150 {
2151         float sp = session->transport_speed();
2152
2153         if (sp == 1.0f) {
2154                 transport_rolling ();
2155         } else if (sp < 0.0f) {
2156                 transport_rewinding ();
2157         } else if (sp > 0.0f) {
2158                 transport_forwarding ();
2159         } else {
2160                 transport_stopped ();
2161         }
2162 }
2163
2164 void
2165 ARDOUR_UI::send_all_midi_feedback ()
2166 {
2167         if (session) {
2168                 session->send_all_midi_feedback();
2169         }
2170 }
2171
2172 void
2173 ARDOUR_UI::allow_local_only ()
2174 {
2175
2176 }
2177
2178 void
2179 ARDOUR_UI::allow_mmc_only ()
2180 {
2181
2182 }
2183
2184 void
2185 ARDOUR_UI::allow_mmc_and_local ()
2186 {
2187
2188 }
2189
2190 void
2191 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2192 {
2193         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2194                 (int) adj.get_value()].c_str());
2195 }
2196
2197 void
2198 ARDOUR_UI::engine_stopped ()
2199 {
2200         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2201         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2202         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2203 }
2204
2205
2206 void
2207 ARDOUR_UI::engine_running ()
2208 {
2209         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2210         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2211         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2212 }
2213
2214 void
2215 ARDOUR_UI::engine_halted ()
2216 {
2217         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2218
2219         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2220         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2221
2222         update_sample_rate (0);
2223
2224         ArdourMessage msg (editor, X_("halted"),
2225                            _("\
2226 JACK has either been shutdown or it\n\
2227 disconnected Ardour because Ardour\n\
2228 was not fast enough. You can save the\n\
2229 session and/or try to reconnect to JACK ."));
2230 }
2231
2232 int32_t
2233 ARDOUR_UI::do_engine_start ()
2234 {
2235         try { 
2236                 engine->start();
2237         }
2238
2239         catch (AudioEngine::PortRegistrationFailure& err) {
2240                 engine->stop ();
2241                 error << _("Unable to create all required ports")
2242                       << endmsg;
2243                 unload_session ();
2244                 return -1;
2245         }
2246
2247         catch (...) {
2248                 engine->stop ();
2249                 error << _("Unable to start the session running")
2250                       << endmsg;
2251                 unload_session ();
2252                 return -2;
2253         }
2254         
2255         return 0;
2256 }
2257
2258 gint
2259 ARDOUR_UI::start_engine ()
2260 {
2261         if (do_engine_start () == 0) {
2262                 if (session && _session_is_new) {
2263                         /* we need to retain initial visual 
2264                            settings for a new session 
2265                         */
2266                         session->save_state ("");
2267                 }
2268
2269                 /* there is too much going on, in too many threads, for us to 
2270                    end up with a clean session. So wait 1 second after loading,
2271                    and fix it up. its ugly, but until i come across a better
2272                    solution, its what we have.
2273                 */
2274
2275                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2276         }
2277
2278         return FALSE;
2279 }
2280
2281 void
2282 ARDOUR_UI::update_clocks ()
2283 {
2284          Clock (session->audible_frame()); /* EMIT_SIGNAL */
2285 }
2286
2287 void
2288 ARDOUR_UI::start_clocking ()
2289 {
2290         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2291 }
2292
2293 void
2294 ARDOUR_UI::stop_clocking ()
2295 {
2296         clock_signal_connection.disconnect ();
2297 }
2298         
2299 void
2300 ARDOUR_UI::toggle_clocking ()
2301 {
2302 #if 0
2303         if (clock_button.get_active()) {
2304                 start_clocking ();
2305         } else {
2306                 stop_clocking ();
2307         }
2308 #endif
2309 }
2310
2311 gint
2312 ARDOUR_UI::_blink (void *arg)
2313
2314 {
2315         ((ARDOUR_UI *) arg)->blink ();
2316         return TRUE;
2317 }
2318
2319 void
2320 ARDOUR_UI::blink ()
2321 {
2322          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2323 }
2324
2325 void
2326 ARDOUR_UI::start_blinking ()
2327 {
2328         /* Start the blink signal. Everybody with a blinking widget
2329            uses Blink to drive the widget's state.
2330         */
2331
2332         if (blink_timeout_tag < 0) {
2333                 blink_on = false;       
2334                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2335         }
2336 }
2337
2338 void
2339 ARDOUR_UI::stop_blinking ()
2340 {
2341         if (blink_timeout_tag >= 0) {
2342                 gtk_timeout_remove (blink_timeout_tag);
2343                 blink_timeout_tag = -1;
2344         }
2345 }
2346
2347
2348 void
2349 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2350 {
2351         using namespace Gtk;
2352         using namespace Menu_Helpers;
2353
2354         if (dstream.hidden()) {
2355                 return;
2356         }
2357
2358         MenuList& items = diskstream_menu->items();
2359         items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2360 }
2361         
2362 void
2363 ARDOUR_UI::diskstream_selected (gint32 id)
2364 {
2365         selected_dstream = id;
2366         Main::quit ();
2367 }
2368
2369 gint32
2370 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2371 {
2372         using namespace Gtk;
2373         using namespace Menu_Helpers;
2374
2375         if (session == 0) {
2376                 return -1;
2377         }
2378
2379         diskstream_menu = new Menu();
2380         diskstream_menu->set_name ("ArdourContextMenu");
2381         using namespace Gtk;
2382         using namespace Menu_Helpers;
2383
2384         MenuList& items = diskstream_menu->items();
2385         items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2386
2387         session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2388
2389         if (ev) {
2390                 diskstream_menu->popup (ev->button, ev->time);
2391         } else {
2392                 diskstream_menu->popup (0, 0);
2393         }
2394
2395         selected_dstream = -1;
2396
2397         Main::run ();
2398
2399         delete diskstream_menu;
2400
2401         return selected_dstream;
2402 }
2403
2404 void
2405 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
2406                           string& buf,
2407                           IO& io,
2408                           bool in)
2409 {
2410         if (in) {
2411                 if (io.n_inputs() == 0) {
2412                         buf = _("none");
2413                         return;
2414                 }
2415                 
2416                 /* XXX we're not handling multiple ports yet. */
2417
2418                 const char **connections = io.input(0)->get_connections();
2419                 
2420                 if (connections == 0 || connections[0] == '\0') {
2421                         buf = _("off");
2422                 } else {
2423                         buf = connections[0];
2424                 }
2425
2426                 free (connections);
2427
2428         } else {
2429
2430                 if (io.n_outputs() == 0) {
2431                         buf = _("none");
2432                         return;
2433                 }
2434                 
2435                 /* XXX we're not handling multiple ports yet. */
2436
2437                 const char **connections = io.output(0)->get_connections();
2438                 
2439                 if (connections == 0 || connections[0] == '\0') {
2440                         buf = _("off");
2441                 } else {
2442                         buf = connections[0];
2443                 }
2444
2445                 free (connections);
2446         }
2447 }
2448
2449 void
2450 ARDOUR_UI::snapshot_session ()
2451 {
2452         ArdourPrompter prompter (true);
2453         string snapname;
2454         string now;
2455         time_t n;
2456
2457         time (&n);
2458         now = ctime (&n);
2459         now = now.substr (0, now.length() - 1);
2460
2461         prompter.set_name ("Prompter");
2462         prompter.set_prompt (_("Name for snapshot"));
2463         prompter.set_initial_text (now);
2464         
2465         switch (prompter.run()) {
2466         case RESPONSE_ACCEPT:
2467                 prompter.get_result (snapname);
2468                 if (snapname.length()){
2469                         save_state (snapname);
2470                 }
2471                 break;
2472
2473         default:
2474                 break;
2475         }
2476 }
2477
2478 void
2479 ARDOUR_UI::save_state (stringcr_t name)
2480 {
2481         (void) save_state_canfail (name);
2482 }
2483                 
2484 int
2485 ARDOUR_UI::save_state_canfail (string name)
2486 {
2487         if (session) {
2488                 int ret;
2489
2490                 if (name.length() == 0) {
2491                         name = session->snap_name();
2492                 }
2493
2494                 if ((ret = session->save_state (name)) != 0) {
2495                         return ret;
2496                 }
2497         }
2498         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2499         return 0;
2500 }
2501
2502 void
2503 ARDOUR_UI::restore_state (string name)
2504 {
2505         if (session) {
2506                 if (name.length() == 0) {
2507                         name = session->name();
2508                 }
2509                 session->restore_state (name);
2510         }
2511 }
2512
2513 void
2514 ARDOUR_UI::primary_clock_value_changed ()
2515 {
2516         if (session) {
2517                 session->request_locate (primary_clock.current_time ());
2518         }
2519 }
2520
2521 void
2522 ARDOUR_UI::secondary_clock_value_changed ()
2523 {
2524         if (session) {
2525                 session->request_locate (secondary_clock.current_time ());
2526         }
2527 }
2528
2529 void
2530 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2531 {
2532         if (session && dstream && dstream->record_enabled()) {
2533
2534                 Session::RecordState rs;
2535                 
2536                 rs = session->record_status ();
2537
2538                 switch (rs) {
2539                 case Session::Disabled:
2540                 case Session::Enabled:
2541                         if (w->get_state() != STATE_SELECTED) {
2542                                 w->set_state (STATE_SELECTED);
2543                         }
2544                         break;
2545
2546                 case Session::Recording:
2547                         if (w->get_state() != STATE_ACTIVE) {
2548                                 w->set_state (STATE_ACTIVE);
2549                         }
2550                         break;
2551                 }
2552
2553         } else {
2554                 if (w->get_state() != STATE_NORMAL) {
2555                         w->set_state (STATE_NORMAL);
2556                 }
2557         }
2558 }
2559
2560 void
2561 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
2562 {
2563         if (session == 0) {
2564                 return;
2565         }
2566         
2567         switch (session->record_status()) {
2568         case Session::Enabled:
2569                 if (onoff) {
2570                         rec_button.set_state (1);
2571                 } else {
2572                         rec_button.set_state (0);
2573                 }
2574                 break;
2575
2576         case Session::Recording:
2577                 rec_button.set_state (2);
2578                 break;
2579
2580         default:
2581                 rec_button.set_state (0);
2582                 break;
2583         }
2584 }
2585
2586 gint
2587 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2588 {
2589         window->hide();
2590         Gtk::Main::quit ();
2591         return TRUE;
2592 }
2593
2594 void
2595 ARDOUR_UI::start_keyboard_prefix ()
2596 {
2597         keyboard->start_prefix();
2598 }
2599
2600 void
2601 ARDOUR_UI::save_template ()
2602
2603 {
2604         ArdourPrompter prompter (true);
2605         string name;
2606
2607         prompter.set_name (X_("Prompter"));
2608         prompter.set_prompt (_("Name for mix template:"));
2609         prompter.set_initial_text(session->name() + _("-template"));
2610         
2611         switch (prompter.run()) {
2612         case RESPONSE_ACCEPT:
2613                 prompter.get_result (name);
2614                 
2615                 if (name.length()) {
2616                         session->save_template (name);
2617                 }
2618                 break;
2619
2620         default:
2621                 break;
2622         }
2623 }
2624
2625 void
2626 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2627 {
2628         m_new_session_dialog->show_all();
2629         m_new_session_dialog->set_transient_for(*editor);
2630         m_new_session_dialog->set_name(predetermined_path);
2631
2632         int response = Gtk::RESPONSE_CANCEL;
2633
2634         do {
2635                 response = m_new_session_dialog->run ();
2636         
2637                 if(response == Gtk::RESPONSE_OK) {
2638
2639                         _session_is_new = true;
2640                         
2641                         std::string session_name = m_new_session_dialog->session_name();
2642                         std::string session_path = m_new_session_dialog->session_folder();
2643                         
2644                         /*
2645                           XXX This is needed because session constructor wants a 
2646                           non-existant path. hopefully this will be fixed at some point.
2647                         */
2648                         session_path = Glib::build_filename(session_path, session_name);
2649                         
2650                         std::string template_name = m_new_session_dialog->session_template_name();
2651                         
2652                         if (m_new_session_dialog->use_session_template()) {
2653                                 
2654                                 load_session (session_path, session_name, &template_name);
2655                                 
2656                         } else {
2657                                 
2658                                 uint32_t cchns;
2659                                 uint32_t mchns;
2660                                 Session::AutoConnectOption iconnect;
2661                                 Session::AutoConnectOption oconnect;
2662                                 
2663                                 if (m_new_session_dialog->create_control_bus()) {
2664                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2665                                 } else {
2666                                         cchns = 0;
2667                                 }
2668                                 
2669                                 if (m_new_session_dialog->create_master_bus()) {
2670                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2671                                 } else {
2672                                         mchns = 0;
2673                                 }
2674                                 
2675                                 if (m_new_session_dialog->connect_inputs()) {
2676                                         iconnect = Session::AutoConnectPhysical;
2677                                 } else {
2678                                         iconnect = Session::AutoConnectOption (0);
2679                                 }
2680                                 
2681                                 /// @todo some minor tweaks.
2682
2683                                 if (m_new_session_dialog->connect_outs_to_master()) {
2684                                         oconnect = Session::AutoConnectMaster;
2685                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2686                                         oconnect = Session::AutoConnectPhysical;
2687                                 } else {
2688                                         oconnect = Session::AutoConnectOption (0);
2689                                 } 
2690                                 
2691                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2692                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2693                                 
2694                                 build_session (session_path,
2695                                                session_name,
2696                                                cchns,
2697                                                mchns,
2698                                                iconnect,
2699                                                oconnect,
2700                                                nphysin,
2701                                                nphysout, 
2702                                                engine->frame_rate() * 60 * 5);
2703                         }               
2704                 }
2705
2706         } while(response == Gtk::RESPONSE_HELP);
2707         m_new_session_dialog->hide_all();
2708 }
2709
2710 int
2711 ARDOUR_UI::load_session (stringcr_t path, stringcr_t snap_name, string* mix_template)
2712 {
2713         Session *new_session;
2714         int x;
2715         session_loaded = false;
2716         x = unload_session ();
2717
2718         if (x < 0) {
2719                 return -1;
2720         } else if (x > 0) {
2721                 return 0;
2722         }
2723
2724         /* if it already exists, we must have write access */
2725
2726         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2727                 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2728 You do not have write access to this session.\n\
2729 This prevents the session from being loaded."));
2730                 return -1;
2731         }
2732
2733         try {
2734                 new_session = new Session (*engine, path, snap_name, mix_template);
2735         }
2736
2737         catch (...) {
2738
2739                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2740                 return -1;
2741         }
2742
2743         connect_to_session (new_session);
2744
2745         //if (engine->running()) {
2746         //mixer->show_window();
2747         //}
2748         session_loaded = true;
2749         return 0;
2750 }
2751
2752 int
2753 ARDOUR_UI::make_session_clean ()
2754 {
2755         if (session) {
2756                 session->set_clean ();
2757         }
2758
2759         return FALSE;
2760 }
2761
2762 int
2763 ARDOUR_UI::build_session (stringcr_t path, stringcr_t snap_name, 
2764                           uint32_t control_channels,
2765                           uint32_t master_channels, 
2766                           Session::AutoConnectOption input_connect,
2767                           Session::AutoConnectOption output_connect,
2768                           uint32_t nphysin,
2769                           uint32_t nphysout,
2770                           jack_nframes_t initial_length)
2771 {
2772         Session *new_session;
2773         int x;
2774
2775         session_loaded = false;
2776         x = unload_session ();
2777         if (x < 0) {
2778                 return -1;
2779         } else if (x > 0) {
2780                 return 0;
2781         }
2782         
2783         _session_is_new = true;
2784
2785         try {
2786                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2787                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2788         }
2789
2790         catch (...) {
2791
2792                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2793                 return -1;
2794         }
2795
2796         connect_to_session (new_session);
2797
2798         //if (engine->running()) {
2799         //mixer->show_window();
2800         //}
2801         session_loaded = true;
2802         return 0;
2803 }
2804
2805 void
2806 ARDOUR_UI::show ()
2807 {
2808         if (editor) {
2809                 editor->show_window ();
2810                 shown_flag = true;
2811         }
2812
2813         if (session && mixer) {
2814                 // mixer->show_window ();
2815         }
2816         
2817         if (about) {
2818                 about->present ();
2819         }
2820 }
2821
2822 void
2823 ARDOUR_UI::show_splash ()
2824 {
2825         if (about == 0) {
2826                 about = new About();
2827         }
2828         about->present();
2829 }
2830
2831 void
2832 ARDOUR_UI::hide_splash ()
2833 {
2834         if (about) {
2835                 // about->hide();
2836         }
2837 }
2838
2839 void
2840 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, stringcr_t msg)
2841 {
2842         size_t removed;
2843
2844         removed = rep.paths.size();
2845
2846         if (removed == 0) {
2847                 ArdourMessage msg (editor, X_("cleanupresults"),
2848                                    _("\
2849 No audio files were ready for cleanup\n\n\
2850 If this seems suprising, check for any existing\n\
2851 snapshots. These may still include regions that\n\
2852 require some unused files to continue to exist."));
2853                 return;
2854         } 
2855
2856         ArdourDialog results (_("ardour: cleanup"), true);
2857         
2858         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2859             CleanupResultsModelColumns() { 
2860                     add (visible_name);
2861                     add (fullpath);
2862             }
2863             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2864             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2865         };
2866
2867         
2868         Glib::RefPtr<Gtk::ListStore> results_model;
2869         CleanupResultsModelColumns results_columns;
2870         Gtk::TreeView results_display;
2871         
2872         results_model = ListStore::create (results_columns);
2873         results_display.set_model (results_model);
2874         results_display.append_column (list_title, results_columns.visible_name);
2875         results_display.set_headers_visible (true);
2876
2877         Gtk::ScrolledWindow list_scroller;
2878         Gtk::Label txt;
2879
2880         if (rep.space < 1048576.0f) {
2881                 if (removed > 1) {
2882                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2883                 } else {
2884                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2885                 }
2886         } else {
2887                 if (removed > 1) {
2888                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2889                 } else {
2890                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2891                 }
2892         }
2893
2894         results.get_vbox()->pack_start (txt, false, false);
2895         
2896         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2897                 TreeModel::Row row = *(results_model->append());
2898                 row[results_columns.visible_name] = *i;
2899                 row[results_columns.fullpath] = *i;
2900         }
2901         
2902         list_scroller.add (results_display);
2903         list_scroller.set_size_request (-1, 250);
2904         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2905         
2906         results.get_vbox()->pack_start (list_scroller, true, true);
2907         results.add_button (Stock::OK, RESPONSE_ACCEPT);
2908         results.set_position (Gtk::WIN_POS_MOUSE);
2909
2910         results.run ();
2911 }
2912
2913 void
2914 ARDOUR_UI::cleanup ()
2915 {
2916         if (session == 0) {
2917                 /* shouldn't happen: menu item is insensitive */
2918                 return;
2919         }
2920
2921         ArdourDialog checker (_("ardour cleanup"));
2922         Gtk::Label label (_("\
2923 Cleanup is a destructive operation.\n\
2924 ALL undo/redo information will be lost if you cleanup.\n\
2925 Unused audio files will be moved to a \"dead sounds\" location."));
2926         
2927         checker.get_vbox()->pack_start (label, false, false);
2928         checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2929         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2930
2931         checker.set_name (_("CleanupDialog"));
2932         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2933         checker.set_position (Gtk::WIN_POS_MOUSE);
2934
2935         switch (checker.run()) {
2936         case RESPONSE_ACCEPT:
2937                 break;
2938         default:
2939                 return;
2940         }
2941
2942         Session::cleanup_report rep;
2943
2944         editor->prepare_for_cleanup ();
2945
2946         if (session->cleanup_sources (rep)) {
2947                 return;
2948         }
2949
2950         display_cleanup_results (rep, 
2951                                  _("cleaned files"),
2952                                  _("\
2953 The following %1 %2 were not in use.\n\
2954 The next time you flush the wastebasket\n\
2955 it will release an additional %3 %4bytes\n\
2956 of disk space"
2957                                          ));
2958 }
2959
2960 void
2961 ARDOUR_UI::flush_trash ()
2962 {
2963         if (session == 0) {
2964                 /* shouldn't happen: menu item is insensitive */
2965                 return;
2966         }
2967
2968         Session::cleanup_report rep;
2969
2970         if (session->cleanup_trash_sources (rep)) {
2971                 return;
2972         }
2973
2974         display_cleanup_results (rep, 
2975                                  _("deleted file"),
2976                                  _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2977 }
2978
2979 void
2980 ARDOUR_UI::add_route ()
2981 {
2982         int count;
2983
2984         if (!session) {
2985                 return;
2986         }
2987
2988         if (add_route_dialog == 0) {
2989                 add_route_dialog = new AddRouteDialog;
2990                 editor->ensure_float (*add_route_dialog);
2991         }
2992
2993         if (add_route_dialog->is_visible()) {
2994                 /* we're already doing this */
2995                 return;
2996         }
2997
2998         ResponseType r = (ResponseType) add_route_dialog->run ();
2999         
3000         add_route_dialog->hide();
3001
3002         switch (r) {
3003         case RESPONSE_ACCEPT:
3004                 break;
3005         default:
3006                 return;
3007                 break;
3008         }
3009
3010         if ((count = add_route_dialog->count()) <= 0) {
3011                 return;
3012         }
3013
3014         uint32_t input_chan = add_route_dialog->channels ();
3015         uint32_t output_chan;
3016         string name_template = add_route_dialog->name_template ();
3017         bool track = add_route_dialog->track ();
3018
3019         Session::AutoConnectOption oac = session->get_output_auto_connect();
3020
3021         if (oac & Session::AutoConnectMaster) {
3022                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3023         } else {
3024                 output_chan = input_chan;
3025         }
3026
3027         /* XXX do something with name template */
3028
3029         while (count) {
3030                 if (track) {
3031                         session_add_audio_track (input_chan, output_chan);
3032                 } else {
3033                         session_add_audio_bus (input_chan, output_chan);
3034                 }
3035                 --count;
3036                 
3037                 while (Main::events_pending()) {
3038                         Main::iteration ();
3039                 }
3040         }
3041 }
3042
3043 XMLNode*
3044 ARDOUR_UI::mixer_settings () const
3045 {
3046         XMLNode* node = 0;
3047
3048         if (session) {
3049                 node = session->instant_xml(X_("Mixer"), session->path());
3050         } else {
3051                 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3052         }
3053
3054         if (!node) {
3055                 node = new XMLNode (X_("Mixer"));
3056         }
3057
3058         return node;
3059 }
3060
3061 XMLNode*
3062 ARDOUR_UI::editor_settings () const
3063 {
3064         XMLNode* node = 0;
3065
3066         if (session) {
3067                 node = session->instant_xml(X_("Editor"), session->path());
3068         } else {
3069                 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3070         }
3071
3072         if (!node) {
3073                 node = new XMLNode (X_("Editor"));
3074         }
3075         return node;
3076 }
3077
3078 XMLNode*
3079 ARDOUR_UI::keyboard_settings () const
3080 {
3081         XMLNode* node = 0;
3082
3083         node = Config->extra_xml(X_("Keyboard"));
3084         
3085         if (!node) {
3086                 node = new XMLNode (X_("Keyboard"));
3087         }
3088         return node;
3089 }
3090
3091 void
3092 ARDOUR_UI::halt_on_xrun_message ()
3093 {
3094         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3095
3096         ArdourMessage msg (editor, X_("haltonxrun"),
3097                            _("Recording was stopped because your system could not keep up."));
3098 }
3099
3100 void 
3101 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3102 {
3103         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3104
3105         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3106                 delete *i;
3107         }
3108
3109         delete deletion_list;
3110 }
3111
3112 void
3113 ARDOUR_UI::disk_overrun_handler ()
3114 {
3115         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3116
3117         if (!have_disk_overrun_displayed) {
3118                 have_disk_overrun_displayed = true;
3119                 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3120 The disk system on your computer\n\
3121 was not able to keep up with Ardour.\n\
3122 \n\
3123 Specifically, it failed to write data to disk\n\
3124 quickly enough to keep up with recording.\n"));
3125                 have_disk_overrun_displayed = false;
3126         }
3127 }
3128
3129 void
3130 ARDOUR_UI::disk_underrun_handler ()
3131 {
3132         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3133
3134         if (!have_disk_underrun_displayed) {
3135                 have_disk_underrun_displayed = true;
3136                 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3137                         (_("The disk system on your computer\n\
3138 was not able to keep up with Ardour.\n\
3139 \n\
3140 Specifically, it failed to read data from disk\n\
3141 quickly enough to keep up with playback.\n")));
3142                 have_disk_underrun_displayed = false;
3143         } 
3144 }
3145
3146 void
3147 ARDOUR_UI::disk_underrun_message_gone ()
3148 {
3149         have_disk_underrun_displayed = false;
3150 }
3151
3152 void
3153 ARDOUR_UI::disk_overrun_message_gone ()
3154 {
3155         have_disk_underrun_displayed = false;
3156 }
3157
3158 int
3159 ARDOUR_UI::pending_state_dialog ()
3160 {
3161         ArdourDialog dialog ("pending state dialog");
3162         Label  message (_("\
3163 This session appears to have been in\n\
3164 middle of recording when ardour or\n\
3165 the computer was shutdown.\n\
3166 \n\
3167 Ardour can recover any captured audio for\n\
3168 you, or it can ignore it. Please decide\n\
3169 what you would like to do.\n"));
3170
3171         dialog.get_vbox()->pack_start (message);
3172         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3173         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3174
3175         dialog.set_position (WIN_POS_CENTER);
3176         dialog.show_all ();
3177         
3178         switch (dialog.run ()) {
3179         case RESPONSE_ACCEPT:
3180                 break;
3181         default:
3182                 return 1;
3183         }
3184
3185         return 0;
3186 }
3187         
3188         
3189 void
3190 ARDOUR_UI::disconnect_from_jack ()
3191 {
3192         if (engine) {
3193                 if( engine->disconnect_from_jack ()) {
3194                         ArdourMessage msg (editor, X_("nojack dialog"),
3195                                            _("Could not disconnect from JACK"));
3196                 }
3197
3198                 update_sample_rate (0);
3199         }
3200 }
3201
3202 void
3203 ARDOUR_UI::reconnect_to_jack ()
3204 {
3205         if (engine) {
3206                 if (engine->reconnect_to_jack ()) {
3207                         ArdourMessage msg (editor, X_("nojack dialog"),
3208                                            _("Could not reconnect to JACK"));
3209                 }
3210
3211                 update_sample_rate (0);
3212         }
3213 }
3214
3215 void
3216 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3217 {
3218         engine->request_buffer_size (nframes);
3219         update_sample_rate (0);
3220 }
3221
3222 int
3223 ARDOUR_UI::cmdline_new_session (string path)
3224 {
3225         if (path[0] != '/') {
3226                 char buf[PATH_MAX+1];
3227                 string str;
3228
3229                 getcwd (buf, sizeof (buf));
3230                 str = buf;
3231                 str += '/';
3232                 str += path;
3233                 path = str;
3234         }
3235
3236         new_session (false, path);
3237
3238         _will_create_new_session_automatically = false; /* done it */
3239         return FALSE; /* don't call it again */
3240 }