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