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