if user asks for session templates, make sure user template dir exists, and switch...
[ardour.git] / gtk2_ardour / new_session_dialog.cc
1 /*
2     Copyright (C) 2005 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 */
19
20 #include <pbd/error.h>
21
22 #include <ardour/recent_sessions.h>
23 #include <ardour/session.h>
24 #include <ardour/profile.h>
25
26 #include <gtkmm/entry.h>
27 #include <gtkmm/filechooserbutton.h>
28 #include <gtkmm/spinbutton.h>
29 #include <gtkmm/checkbutton.h>
30 #include <gtkmm/radiobutton.h>
31 #include <gtkmm/filefilter.h>
32 #include <gtkmm/stock.h>
33 #include <gdkmm/cursor.h>
34
35 #include <gtkmm2ext/window_title.h>
36
37 using namespace Gtk;
38 using namespace Gtkmm2ext;
39 using namespace PBD;
40
41 #include "opts.h"
42 #include "utils.h"
43 #include "i18n.h"
44 #include "new_session_dialog.h"
45
46 NewSessionDialog::NewSessionDialog()
47         : ArdourDialog ("session control")
48 {
49         in_destructor = false;
50         session_name_label = new Gtk::Label(_("Name :"));
51         last_name_page = NewPage;
52         m_name = new Gtk::Entry();
53         m_name->set_text(ARDOUR_COMMAND_LINE::session_name);
54
55         chan_count_label_1 = new Gtk::Label(_("channels"));
56         chan_count_label_2 = new Gtk::Label(_("channels"));
57         chan_count_label_3 = new Gtk::Label(_("channels"));
58         chan_count_label_4 = new Gtk::Label(_("channels"));
59
60         chan_count_label_1->set_alignment(0,0.5);
61         chan_count_label_1->set_padding(0,0);
62         chan_count_label_1->set_line_wrap(false);
63
64         chan_count_label_2->set_alignment(0,0.5);
65         chan_count_label_2->set_padding(0,0);
66         chan_count_label_2->set_line_wrap(false);
67
68         chan_count_label_3->set_alignment(0,0.5);
69         chan_count_label_3->set_padding(0,0);
70         chan_count_label_3->set_line_wrap(false);
71
72         chan_count_label_4->set_alignment(0,0.5);
73         chan_count_label_4->set_padding(0,0);
74         chan_count_label_4->set_line_wrap(false);
75
76         bus_label = new Gtk::Label(_("<b>Busses</b>"));
77         input_label = new Gtk::Label(_("<b>Inputs</b>"));
78         output_label = new Gtk::Label(_("<b>Outputs</b>"));
79
80         session_location_label = new Gtk::Label(_("Create Folder In :"));
81         m_folder = new Gtk::FileChooserButton(Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
82         session_template_label = new Gtk::Label(_("Template :"));
83         m_template = new Gtk::FileChooserButton();
84         m_create_control_bus = new Gtk::CheckButton(_("Create Monitor Bus"));
85         
86         Gtk::Adjustment *m_control_bus_channel_count_adj = Gtk::manage(new Gtk::Adjustment(2, 0, 100, 1, 10));
87         m_control_bus_channel_count = new Gtk::SpinButton(*m_control_bus_channel_count_adj, 1, 0);
88         
89         Gtk::Adjustment *m_master_bus_channel_count_adj = Gtk::manage(new Gtk::Adjustment(2, 0, 100, 1, 10));
90         m_master_bus_channel_count = new Gtk::SpinButton(*m_master_bus_channel_count_adj, 1, 0);
91         m_create_master_bus = new Gtk::CheckButton(_("Create Master Bus"));
92         advanced_table = new Gtk::Table(2, 2, true);
93         m_connect_inputs = new Gtk::CheckButton(_("Automatically Connect to Physical Inputs"));
94         m_limit_input_ports = new Gtk::CheckButton(_("Use only"));
95         
96         Gtk::Adjustment *m_input_limit_count_adj = Gtk::manage(new Gtk::Adjustment(1, 0, 100, 1, 10));
97         m_input_limit_count = new Gtk::SpinButton(*m_input_limit_count_adj, 1, 0);
98         input_port_limit_hbox = new Gtk::HBox(false, 0);
99         input_port_vbox = new Gtk::VBox(false, 0);
100         input_table = new Gtk::Table(2, 2, false);
101
102         bus_frame = new Gtk::Frame();
103         bus_table = new Gtk::Table (2, 3, false);
104         
105         input_frame = new Gtk::Frame();
106         m_connect_outputs = new Gtk::CheckButton(_("Automatically Connect Outputs"));
107         m_limit_output_ports = new Gtk::CheckButton(_("Use only"));
108         
109         Gtk::Adjustment *m_output_limit_count_adj = Gtk::manage(new Gtk::Adjustment(1, 0, 100, 1, 10));
110         m_output_limit_count = new Gtk::SpinButton(*m_output_limit_count_adj, 1, 0);
111         output_port_limit_hbox = new Gtk::HBox(false, 0);
112         output_port_vbox = new Gtk::VBox(false, 0);
113         
114         Gtk::RadioButton::Group _RadioBGroup_m_connect_outputs_to_master;
115         m_connect_outputs_to_master = new Gtk::RadioButton(_RadioBGroup_m_connect_outputs_to_master, _("... to Master Bus"));
116         m_connect_outputs_to_physical = new Gtk::RadioButton(_RadioBGroup_m_connect_outputs_to_master, _("... to Physical Outputs"));
117         output_conn_vbox = new Gtk::VBox(false, 0);
118         output_vbox = new Gtk::VBox(false, 0);
119
120         output_frame = new Gtk::Frame();
121         advanced_vbox = new Gtk::VBox(false, 0);
122         advanced_label = new Gtk::Label(_("Advanced Options"));
123         advanced_expander = new Gtk::Expander();
124         new_session_table = new Gtk::Table(2, 2, false);
125         m_open_filechooser = new Gtk::FileChooserButton();
126         open_session_hbox = new Gtk::HBox(false, 0);
127         m_treeview = new Gtk::TreeView();
128         recent_scrolledwindow = new Gtk::ScrolledWindow();
129
130         recent_sesion_label = new Gtk::Label(_("Recent:"));
131         recent_frame = new Gtk::Frame();
132         open_session_vbox = new Gtk::VBox(false, 0);
133         m_notebook = new Gtk::Notebook();
134         session_name_label->set_alignment(0, 0.5);
135         session_name_label->set_padding(6,0);
136         session_name_label->set_line_wrap(false);
137         session_name_label->set_selectable(false);
138         m_name->set_editable(true);
139         m_name->set_max_length(0);
140         m_name->set_has_frame(true);
141         m_name->set_activates_default(true);
142         m_name->set_width_chars (40);
143         session_location_label->set_alignment(0,0.5);
144         session_location_label->set_padding(6,0);
145         session_location_label->set_line_wrap(false);
146         session_location_label->set_selectable(false);
147         session_template_label->set_alignment(0,0.5);
148         session_template_label->set_padding(6,0);
149         session_template_label->set_line_wrap(false);
150         session_template_label->set_selectable(false);
151         m_create_control_bus->set_flags(Gtk::CAN_FOCUS);
152         m_create_control_bus->set_relief(Gtk::RELIEF_NORMAL);
153         m_create_control_bus->set_mode(true);
154         m_create_control_bus->set_active(false);
155         m_create_control_bus->set_border_width(0);
156         m_control_bus_channel_count->set_flags(Gtk::CAN_FOCUS);
157         m_control_bus_channel_count->set_update_policy(Gtk::UPDATE_ALWAYS);
158         m_control_bus_channel_count->set_numeric(true);
159         m_control_bus_channel_count->set_digits(0);
160         m_control_bus_channel_count->set_wrap(false);
161         m_control_bus_channel_count->set_sensitive(false);
162         m_master_bus_channel_count->set_flags(Gtk::CAN_FOCUS);
163         m_master_bus_channel_count->set_update_policy(Gtk::UPDATE_ALWAYS);
164         m_master_bus_channel_count->set_numeric(true);
165         m_master_bus_channel_count->set_digits(0);
166         m_master_bus_channel_count->set_wrap(false);
167         open_session_file_label = new Gtk::Label(_("Browse:"));
168         open_session_file_label->set_alignment(0, 0.5);
169         m_create_master_bus->set_flags(Gtk::CAN_FOCUS);
170         m_create_master_bus->set_relief(Gtk::RELIEF_NORMAL);
171         m_create_master_bus->set_mode(true);
172         m_create_master_bus->set_active(true);
173         m_create_master_bus->set_border_width(0);
174         advanced_table->set_row_spacings(0);
175         advanced_table->set_col_spacings(0);
176         
177         m_connect_inputs->set_flags(Gtk::CAN_FOCUS);
178         m_connect_inputs->set_relief(Gtk::RELIEF_NORMAL);
179         m_connect_inputs->set_mode(true);
180         m_connect_inputs->set_active(true);
181         m_connect_inputs->set_border_width(0);
182
183         m_limit_input_ports->set_flags(Gtk::CAN_FOCUS);
184         m_limit_input_ports->set_relief(Gtk::RELIEF_NORMAL);
185         m_limit_input_ports->set_mode(true);
186         m_limit_input_ports->set_sensitive(true);
187         m_limit_input_ports->set_border_width(0);
188         m_input_limit_count->set_flags(Gtk::CAN_FOCUS);
189         m_input_limit_count->set_update_policy(Gtk::UPDATE_ALWAYS);
190         m_input_limit_count->set_numeric(true);
191         m_input_limit_count->set_digits(0);
192         m_input_limit_count->set_wrap(false);
193         m_input_limit_count->set_sensitive(false);
194
195         bus_hbox = new Gtk::HBox (false, 0);
196         bus_hbox->pack_start (*bus_table, Gtk::PACK_SHRINK, 18);
197
198         bus_label->set_alignment(0, 0.5);
199         bus_label->set_padding(0,0);
200         bus_label->set_line_wrap(false);
201         bus_label->set_selectable(false);
202         bus_label->set_use_markup(true);
203         bus_frame->set_shadow_type(Gtk::SHADOW_NONE);
204         bus_frame->set_label_align(0,0.5);
205         bus_frame->add(*bus_hbox);
206         bus_frame->set_label_widget(*bus_label);
207         
208         bus_table->set_row_spacings (0);
209         bus_table->set_col_spacings (0);
210         bus_table->attach (*m_create_master_bus, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
211         bus_table->attach (*m_master_bus_channel_count, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
212         bus_table->attach (*chan_count_label_1, 2, 3, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
213         bus_table->attach (*m_create_control_bus, 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
214         bus_table->attach (*m_control_bus_channel_count, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
215         bus_table->attach (*chan_count_label_2, 2, 3, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
216
217         input_port_limit_hbox->pack_start(*m_limit_input_ports, Gtk::PACK_SHRINK, 6);
218         input_port_limit_hbox->pack_start(*m_input_limit_count, Gtk::PACK_SHRINK, 0);
219         input_port_limit_hbox->pack_start(*chan_count_label_3, Gtk::PACK_SHRINK, 6);
220         input_port_vbox->pack_start(*m_connect_inputs, Gtk::PACK_SHRINK, 0);
221         input_port_vbox->pack_start(*input_port_limit_hbox, Gtk::PACK_EXPAND_PADDING, 0);
222         input_table->set_row_spacings(0);
223         input_table->set_col_spacings(0);
224         input_table->attach(*input_port_vbox, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 6);
225
226         input_hbox = new Gtk::HBox (false, 0);
227         input_hbox->pack_start (*input_table, Gtk::PACK_SHRINK, 18);
228
229         input_label->set_alignment(0, 0.5);
230         input_label->set_padding(0,0);
231         input_label->set_line_wrap(false);
232         input_label->set_selectable(false);
233         input_label->set_use_markup(true);
234         input_frame->set_shadow_type(Gtk::SHADOW_NONE);
235         input_frame->set_label_align(0,0.5);
236         input_frame->add(*input_hbox);
237         input_frame->set_label_widget(*input_label);
238
239         m_connect_outputs->set_flags(Gtk::CAN_FOCUS);
240         m_connect_outputs->set_relief(Gtk::RELIEF_NORMAL);
241         m_connect_outputs->set_mode(true);
242         m_connect_outputs->set_active(true);
243         m_connect_outputs->set_border_width(0);
244         m_limit_output_ports->set_flags(Gtk::CAN_FOCUS);
245         m_limit_output_ports->set_relief(Gtk::RELIEF_NORMAL);
246         m_limit_output_ports->set_mode(true);
247         m_limit_output_ports->set_sensitive(true);
248         m_limit_output_ports->set_border_width(0);
249         m_output_limit_count->set_flags(Gtk::CAN_FOCUS);
250         m_output_limit_count->set_update_policy(Gtk::UPDATE_ALWAYS);
251         m_output_limit_count->set_numeric(false);
252         m_output_limit_count->set_digits(0);
253         m_output_limit_count->set_wrap(false);
254         m_output_limit_count->set_sensitive(false);
255         output_port_limit_hbox->pack_start(*m_limit_output_ports, Gtk::PACK_SHRINK, 6);
256         output_port_limit_hbox->pack_start(*m_output_limit_count, Gtk::PACK_SHRINK, 0);
257         output_port_limit_hbox->pack_start(*chan_count_label_4, Gtk::PACK_SHRINK, 6);
258         m_connect_outputs_to_master->set_flags(Gtk::CAN_FOCUS);
259         m_connect_outputs_to_master->set_relief(Gtk::RELIEF_NORMAL);
260         m_connect_outputs_to_master->set_mode(true);
261         m_connect_outputs_to_master->set_active(false);
262         m_connect_outputs_to_master->set_border_width(0);
263         m_connect_outputs_to_physical->set_flags(Gtk::CAN_FOCUS);
264         m_connect_outputs_to_physical->set_relief(Gtk::RELIEF_NORMAL);
265         m_connect_outputs_to_physical->set_mode(true);
266         m_connect_outputs_to_physical->set_active(false);
267         m_connect_outputs_to_physical->set_border_width(0);
268         output_conn_vbox->pack_start(*m_connect_outputs, Gtk::PACK_SHRINK, 0);
269         output_conn_vbox->pack_start(*m_connect_outputs_to_master, Gtk::PACK_SHRINK, 0);
270         output_conn_vbox->pack_start(*m_connect_outputs_to_physical, Gtk::PACK_SHRINK, 0);
271         output_vbox->set_border_width(6);
272
273         output_port_vbox->pack_start(*output_port_limit_hbox, Gtk::PACK_SHRINK, 0);
274
275         output_vbox->pack_start(*output_conn_vbox);
276         output_vbox->pack_start(*output_port_vbox);
277
278         output_label->set_alignment(0, 0.5);
279         output_label->set_padding(0,0);
280         output_label->set_line_wrap(false);
281         output_label->set_selectable(false);
282         output_label->set_use_markup(true);
283         output_frame->set_shadow_type(Gtk::SHADOW_NONE);
284         output_frame->set_label_align(0,0.5);
285
286         output_hbox = new Gtk::HBox (false, 0);
287         output_hbox->pack_start (*output_vbox, Gtk::PACK_SHRINK, 18);
288
289         output_frame->add(*output_hbox);
290         output_frame->set_label_widget(*output_label);
291
292         advanced_vbox->pack_start(*advanced_table, Gtk::PACK_SHRINK, 0);
293         advanced_vbox->pack_start(*bus_frame, Gtk::PACK_SHRINK, 6);
294         advanced_vbox->pack_start(*input_frame, Gtk::PACK_SHRINK, 6);
295         advanced_vbox->pack_start(*output_frame, Gtk::PACK_SHRINK, 0);
296         advanced_label->set_padding(0,0);
297         advanced_label->set_line_wrap(false);
298         advanced_label->set_selectable(false);
299         advanced_label->set_alignment(0, 0.5);
300         advanced_expander->set_flags(Gtk::CAN_FOCUS);
301         advanced_expander->set_border_width(0);
302         advanced_expander->set_expanded(false);
303         advanced_expander->set_spacing(0);
304         advanced_expander->add(*advanced_vbox);
305         advanced_expander->set_label_widget(*advanced_label);
306         new_session_table->set_border_width(12);
307         new_session_table->set_row_spacings(6);
308         new_session_table->set_col_spacings(0);
309         new_session_table->attach(*session_name_label, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL, 0, 0);
310         new_session_table->attach(*m_name, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0);
311         new_session_table->attach(*session_location_label, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL, 0, 0);
312         new_session_table->attach(*m_folder, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0);
313         new_session_table->attach(*session_template_label, 0, 1, 2, 3, Gtk::FILL, Gtk::FILL, 0, 0);
314         new_session_table->attach(*m_template, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0);
315
316         if (!ARDOUR::Profile->get_sae()) {
317                 new_session_table->attach(*advanced_expander, 0, 2, 3, 4, Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 6);
318         }
319
320         open_session_hbox->pack_start(*open_session_file_label, false, false, 12);
321         open_session_hbox->pack_start(*m_open_filechooser, true, true, 12);
322         m_treeview->set_flags(Gtk::CAN_FOCUS);
323         m_treeview->set_headers_visible(true);
324         m_treeview->set_rules_hint(false);
325         m_treeview->set_reorderable(false);
326         m_treeview->set_enable_search(true);
327         m_treeview->set_fixed_height_mode(false);
328         m_treeview->set_hover_selection(false);
329         m_treeview->set_size_request(-1, 150);
330         recent_scrolledwindow->set_flags(Gtk::CAN_FOCUS);
331         recent_scrolledwindow->set_border_width(6);
332         recent_scrolledwindow->set_shadow_type(Gtk::SHADOW_IN);
333         recent_scrolledwindow->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
334         recent_scrolledwindow->property_window_placement().set_value(Gtk::CORNER_TOP_LEFT);
335         recent_scrolledwindow->add(*m_treeview);
336
337         recent_sesion_label->set_padding(0,0);
338         recent_sesion_label->set_line_wrap(false);
339         recent_sesion_label->set_selectable(false);
340         recent_frame->set_border_width(12);
341         recent_frame->set_shadow_type(Gtk::SHADOW_NONE);
342         recent_frame->add(*recent_scrolledwindow);
343         recent_frame->set_label_widget(*recent_sesion_label);
344         open_session_vbox->pack_start(*recent_frame, Gtk::PACK_EXPAND_WIDGET, 0);
345         open_session_vbox->pack_start(*open_session_hbox, Gtk::PACK_SHRINK, 12);
346
347         m_notebook->set_flags(Gtk::CAN_FOCUS);
348         m_notebook->set_scrollable(true);
349         
350         get_vbox()->set_homogeneous(false);
351         get_vbox()->set_spacing(0);
352         get_vbox()->pack_start(*m_notebook, Gtk::PACK_SHRINK, 0);
353
354         /* 
355            icon setting is done again in the editor (for the whole app),
356            but its all chickens and eggs at this point.
357         */
358
359         list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
360         Glib::RefPtr<Gdk::Pixbuf> icon;
361
362         if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
363                 window_icons.push_back (icon);
364         }
365         if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
366                 window_icons.push_back (icon);
367         }
368         if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
369                 window_icons.push_back (icon);
370         }
371         if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
372                 window_icons.push_back (icon);
373         }
374         if (!window_icons.empty()) {
375                 set_icon_list (window_icons);
376         }
377
378         WindowTitle title(Glib::get_application_name());
379         title += _("Session Control");
380         set_title(title.get_string());
381
382         set_position (Gtk::WIN_POS_MOUSE);
383         set_resizable(false);
384         set_has_separator(false);
385         add_button(Gtk::Stock::QUIT, Gtk::RESPONSE_CANCEL);
386         add_button(Gtk::Stock::CLEAR, Gtk::RESPONSE_NONE);
387         m_okbutton = add_button(Gtk::Stock::NEW, Gtk::RESPONSE_OK);
388
389         recent_model = Gtk::TreeStore::create (recent_columns);
390         m_treeview->set_model (recent_model);
391         m_treeview->append_column (_("Recent Sessions"), recent_columns.visible_name);
392         m_treeview->set_headers_visible (false);
393         m_treeview->get_selection()->set_mode (Gtk::SELECTION_SINGLE);
394
395         std::string path = ARDOUR::get_user_ardour_path();
396         
397         if (path.empty()) {
398                 path = ARDOUR::get_system_data_path();
399         }
400
401         const char * const template_dir_name = X_("templates");
402
403         //if SYSTEM template folder exists, add it to the file chooser
404         const std::string sys_templates_path = ARDOUR::get_system_data_path() + template_dir_name;
405 printf("system template path = %s\n", sys_templates_path.c_str());
406         if (Glib::file_test(sys_templates_path, Glib::FILE_TEST_IS_DIR))
407         {
408                 m_template->add_shortcut_folder(sys_templates_path);
409                 m_template->set_current_folder (sys_templates_path);
410         }
411
412         //if USER template folder exists, add it to the file chooser
413         const std::string user_template_path = ARDOUR::get_user_ardour_path() + template_dir_name;
414         bool utp_exists = true;
415
416         if (!Glib::file_test(user_template_path, Glib::FILE_TEST_IS_DIR)) {
417                 if (g_mkdir_with_parents (user_template_path.c_str(), 0755)) {
418                         utp_exists = false;
419                 }
420         }
421
422         if (utp_exists) {
423                 m_template->add_shortcut_folder(user_template_path);
424                 m_template->set_current_folder (user_template_path);
425         }
426
427         m_template->set_title(_("select template"));
428         Gtk::FileFilter* session_filter = manage (new (Gtk::FileFilter));
429         session_filter->add_pattern(X_("*.ardour"));
430         session_filter->add_pattern(X_("*.ardour.bak"));
431         m_open_filechooser->set_filter (*session_filter);
432         m_open_filechooser->set_current_folder(getenv ("HOME"));
433         m_open_filechooser->set_title(_("select session file"));
434
435         Gtk::FileFilter* template_filter = manage (new (Gtk::FileFilter));
436         template_filter->add_pattern(X_("*.ardour"));
437         template_filter->add_pattern(X_("*.ardour.bak"));
438         template_filter->add_pattern(X_("*.template"));
439         m_template->set_filter (*template_filter);
440
441         m_folder->set_current_folder(getenv ("HOME"));
442         m_folder->set_title(_("select directory"));
443
444         on_new_session_page = true;
445         m_notebook->set_current_page(0);
446         m_notebook->show();
447         m_notebook->show_all_children();
448
449         engine_page_session_folder = X_("");
450         engine_page_session_name = X_("");
451
452         set_default_response (Gtk::RESPONSE_OK);
453         if (!ARDOUR_COMMAND_LINE::session_name.length()) {
454                 set_response_sensitive (Gtk::RESPONSE_OK, false);
455                 set_response_sensitive (Gtk::RESPONSE_NONE, false);
456         } else {
457                 set_response_sensitive (Gtk::RESPONSE_OK, true);
458                 set_response_sensitive (Gtk::RESPONSE_NONE, true);
459         }
460
461         ///@ connect some signals
462
463         m_connect_inputs->signal_clicked().connect (mem_fun (*this, &NewSessionDialog::connect_inputs_clicked));
464         m_connect_outputs->signal_clicked().connect (mem_fun (*this, &NewSessionDialog::connect_outputs_clicked));
465         m_limit_input_ports->signal_clicked().connect (mem_fun (*this, &NewSessionDialog::limit_inputs_clicked));
466         m_limit_output_ports->signal_clicked().connect (mem_fun (*this, &NewSessionDialog::limit_outputs_clicked));
467         m_create_master_bus->signal_clicked().connect (mem_fun (*this, &NewSessionDialog::master_bus_button_clicked));
468         m_create_control_bus->signal_clicked().connect (mem_fun (*this, &NewSessionDialog::monitor_bus_button_clicked));
469         m_name->signal_changed().connect(mem_fun (*this, &NewSessionDialog::on_new_session_name_entry_changed));
470         m_notebook->signal_switch_page().connect (mem_fun (*this, &NewSessionDialog::notebook_page_changed));
471         m_treeview->get_selection()->signal_changed().connect (mem_fun (*this, &NewSessionDialog::treeview_selection_changed));
472         m_treeview->signal_row_activated().connect (mem_fun (*this, &NewSessionDialog::recent_row_activated));
473         m_open_filechooser->signal_selection_changed ().connect (mem_fun (*this, &NewSessionDialog::file_chosen));
474         m_template->signal_selection_changed ().connect (mem_fun (*this, &NewSessionDialog::template_chosen));
475         
476         page_set = Pages (0);
477 }
478
479 NewSessionDialog::~NewSessionDialog()
480 {
481         in_destructor = true;
482 }
483
484 int
485 NewSessionDialog::run ()
486 {
487         if (!page_set) {
488                 /* nothing to display */
489                 return Gtk::RESPONSE_OK;
490         }
491         if (!(page_set & NewPage) && !(page_set & OpenPage)) {
492                 set_response_sensitive (Gtk::RESPONSE_OK, true);
493         }
494         return ArdourDialog::run ();
495 }
496
497 void
498 NewSessionDialog::set_have_engine (bool yn)
499 {
500
501         m_notebook->remove_page (engine_control);
502         page_set = Pages (page_set & ~EnginePage);
503         
504         if (!yn) {
505
506                 engine_control.discover_servers ();
507
508                 if (engine_control.interface_chosen()) {
509                         m_notebook->append_page (engine_control, _("Audio Setup"));
510                         m_notebook->show_all_children();
511                         page_set = Pages (page_set | EnginePage);
512                 } else {
513                         m_notebook->prepend_page (engine_control, _("Audio Setup"));
514                         page_set = Pages (page_set | EnginePage);
515
516                         /* no interface ever selected - make it the first and only page */
517                         if (page_set & NewPage) {
518                                 m_notebook->remove_page (*new_session_table);
519                                 page_set = Pages (page_set & ~NewPage);
520                         }
521                         if (page_set & OpenPage) {
522                                 m_notebook->remove_page (*open_session_vbox);
523                                 page_set = Pages (page_set & ~OpenPage);
524                         }
525                         m_notebook->show_all_children();
526                 }
527         }
528 }
529
530 void
531 NewSessionDialog::set_existing_session (bool yn)
532 {
533         if (yn) {
534
535                 if (page_set & NewPage) {
536                         m_notebook->remove_page (*new_session_table);
537                         page_set = Pages (page_set & ~NewPage);
538                 }
539
540                 if (page_set & OpenPage) {
541                         m_notebook->remove_page (*open_session_vbox);
542                         page_set = Pages (page_set & ~OpenPage);
543                 }
544
545         } else {
546                 if (!(page_set & NewPage)) {
547                         m_notebook->append_page(*new_session_table, _("New Session"));
548                         m_notebook->pages().back().set_tab_label_packing(false, true, Gtk::PACK_START);
549                         page_set = Pages (page_set | NewPage);
550                 }
551                 if (!(page_set & OpenPage)) {
552                         m_notebook->append_page(*open_session_vbox, _("Open Session"));
553                         m_notebook->pages().back().set_tab_label_packing(false, true, Gtk::PACK_START);
554                         page_set = Pages (page_set | OpenPage);
555                 }
556
557                 m_notebook->show_all_children();
558         }
559 }
560
561 void
562 NewSessionDialog::set_session_name (const Glib::ustring& name)
563 {
564         m_name->set_text (name);
565         engine_page_session_name = name;
566 }
567
568 void
569 NewSessionDialog::set_session_folder(const Glib::ustring& dir)
570 {
571         Glib::ustring realdir = dir;
572
573         /* this little tangled mess is a result of 4 things:
574
575             1) GtkFileChooser vomits when given a non-absolute directory
576                    argument to set_current_folder()
577             2) canonicalize_file_name() doesn't exist on OS X
578             3) linux man page for realpath() says "do not use this function"
579             4) canonicalize_file_name() & realpath() have entirely
580                    different semantics on OS X and Linux when given
581                    a non-existent path.
582                    
583            as result of all this, we take two distinct pathways through the code.
584         */
585
586
587 #ifdef __APPLE__
588
589         char buf[PATH_MAX];
590
591         if(realpath (dir.c_str(), buf) != 0) {
592                 if (!Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
593                         realdir = Glib::path_get_dirname (realdir);
594                 }
595                 m_folder->set_current_folder (realdir);
596                 engine_page_session_folder = realdir;
597         }
598
599         
600 #else 
601         char* res;
602         if (!Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
603                 realdir = Glib::path_get_dirname (realdir);
604         }
605
606         if ((res = canonicalize_file_name (realdir.c_str())) != 0) {
607                 m_folder->set_current_folder (res);
608                 engine_page_session_folder = res;
609                 free (res);
610         }
611         
612 #endif
613
614 }
615
616 std::string
617 NewSessionDialog::session_name() const
618 {
619         std::string str = Glib::filename_from_utf8(m_open_filechooser->get_filename());
620         std::string::size_type position = str.find_last_of ('/');
621         str = str.substr (position+1);
622         position = str.find_last_of ('.');
623         str = str.substr (0, position);
624
625         /*
626           XXX what to do if it's a .bak file?
627           load_session doesn't allow it!
628
629         if ((position = str.rfind(".bak")) != string::npos) {
630                 str = str.substr (0, position);
631         }         
632         */
633
634         switch (which_page()) {
635         case NewPage:
636                 return Glib::filename_from_utf8(m_name->get_text());
637
638         case EnginePage:
639                 if (!(page_set & (OpenPage|NewPage))) {
640                         return engine_page_session_name;
641                 } else if (last_name_page == NewPage) {
642                         return Glib::filename_from_utf8(m_name->get_text());
643                 } else {
644                         /* relax and use the open page stuff at the end */
645                 }
646                 break;
647
648         default:
649                 break;
650         } 
651
652         if (m_treeview->get_selection()->count_selected_rows() == 0) {
653                 return Glib::filename_from_utf8(str);
654         }
655
656         Gtk::TreeModel::iterator i = m_treeview->get_selection()->get_selected();
657         return (*i)[recent_columns.visible_name];
658 }
659
660 std::string
661 NewSessionDialog::session_folder() const
662 {
663         switch (which_page()) {
664         case NewPage:
665                 return Glib::filename_from_utf8(m_folder->get_filename());
666                 
667         case EnginePage:
668                 if (!(page_set & (OpenPage|NewPage))) {
669                         return Glib::filename_from_utf8(engine_page_session_folder);
670                 } else if (last_name_page == NewPage) {
671                         /* use m_folder since it should be set */
672                         return Glib::filename_from_utf8(m_folder->get_filename());
673                 } else {
674                         /* relax and use the open page stuff at the end */
675                 }
676                 break;
677
678         default:
679                 break;
680         }
681                
682         if (m_treeview->get_selection()->count_selected_rows() == 0) {
683                 const string filename(Glib::filename_from_utf8(m_open_filechooser->get_filename()));
684                 return Glib::path_get_dirname(filename);
685         }
686
687         Gtk::TreeModel::iterator i = m_treeview->get_selection()->get_selected();
688         return (*i)[recent_columns.fullpath];
689 }
690
691 bool
692 NewSessionDialog::use_session_template() const
693 {
694         if(m_template->get_filename().empty() && (which_page() == NewPage)) return false;
695         return true;
696 }
697
698 std::string
699 NewSessionDialog::session_template_name() const
700 {
701         return Glib::filename_from_utf8(m_template->get_filename());
702 }
703
704 bool
705 NewSessionDialog::create_master_bus() const
706 {
707         return m_create_master_bus->get_active();
708 }
709
710 int
711 NewSessionDialog::master_channel_count() const
712 {
713         return m_master_bus_channel_count->get_value_as_int();
714 }
715
716 bool
717 NewSessionDialog::create_control_bus() const
718 {
719         return m_create_control_bus->get_active();
720 }
721
722 int
723 NewSessionDialog::control_channel_count() const
724 {
725         return m_control_bus_channel_count->get_value_as_int();
726 }
727
728 bool
729 NewSessionDialog::connect_inputs() const
730 {
731         return m_connect_inputs->get_active();
732 }
733
734 bool
735 NewSessionDialog::limit_inputs_used_for_connection() const
736 {
737         return m_limit_input_ports->get_active();
738 }
739
740 int
741 NewSessionDialog::input_limit_count() const
742 {
743         return m_input_limit_count->get_value_as_int();
744 }
745
746 bool
747 NewSessionDialog::connect_outputs() const
748 {
749         return m_connect_outputs->get_active();
750 }
751
752 bool
753 NewSessionDialog::limit_outputs_used_for_connection() const
754 {
755         return m_limit_output_ports->get_active();
756 }
757
758 int
759 NewSessionDialog::output_limit_count() const
760 {
761         return m_output_limit_count->get_value_as_int();
762 }
763
764 bool
765 NewSessionDialog::connect_outs_to_master() const
766 {
767         return m_connect_outputs_to_master->get_active();
768 }
769
770 bool
771 NewSessionDialog::connect_outs_to_physical() const
772 {
773         return m_connect_outputs_to_physical->get_active();
774 }
775
776 int
777 NewSessionDialog::get_current_page()
778 {
779         return m_notebook->get_current_page();
780 }
781
782 NewSessionDialog::Pages
783 NewSessionDialog::which_page () const
784 {
785         int num = m_notebook->get_current_page();
786
787         if (page_set == NewPage) {
788                 return NewPage;
789
790         } else if (page_set == OpenPage) {
791                 return OpenPage;
792
793         } else if (page_set == EnginePage) {
794                 return EnginePage;
795
796         } else if (page_set == (NewPage|OpenPage)) {
797                 switch (num) {
798                 case 0:
799                         return NewPage;
800                 default:
801                         return OpenPage;
802                 }
803
804         } else if (page_set == (NewPage|EnginePage)) {
805                 if (engine_control.interface_chosen()) {
806                         switch (num) {
807                         case 0:
808                                 return NewPage;
809                         default:
810                                 return EnginePage;
811                         } 
812                 } else {
813                         switch (num) {
814                         case 0:
815                                 return EnginePage;
816                         default:
817                                 return NewPage;
818                         } 
819                 }
820
821         } else if (page_set == (NewPage|EnginePage|OpenPage)) {
822                 if (engine_control.interface_chosen()) {
823                         switch (num) {
824                         case 0:
825                                 return NewPage;
826                         case 1:
827                                 return OpenPage;
828                         default:
829                                 return EnginePage;
830                         }
831                 } else {
832                         switch (num) {
833                         case 0:
834                                 return EnginePage;
835                         case 1:
836                                 return NewPage;
837                         default:
838                                 return OpenPage;
839                         }
840                 }
841
842         } else if (page_set == (OpenPage|EnginePage)) {
843                 if (engine_control.interface_chosen()) {
844                         switch (num) {
845                         case 0:
846                                 return OpenPage;
847                         default:
848                                 return EnginePage;
849                         }
850                 } else {
851                         switch (num) {
852                         case 0:
853                                 return EnginePage;
854                         default:
855                                 return OpenPage;
856                         }
857                 }
858         }
859
860         return NewPage; /* shouldn't get here */
861 }
862
863 void
864 NewSessionDialog::set_current_page(int page)
865 {
866         return m_notebook->set_current_page (page);
867 }
868
869 void
870 NewSessionDialog::reset_name()
871 {
872         m_name->set_text("");
873         set_response_sensitive (Gtk::RESPONSE_OK, false);
874         
875 }
876
877 void
878 NewSessionDialog::on_new_session_name_entry_changed ()
879 {
880         if (m_name->get_text() != "") {
881                 set_response_sensitive (Gtk::RESPONSE_OK, true);
882                 set_response_sensitive (Gtk::RESPONSE_NONE, true);
883         } else {
884                 set_response_sensitive (Gtk::RESPONSE_OK, false);
885         }
886 }
887
888 void
889 NewSessionDialog::notebook_page_changed (GtkNotebookPage* np, uint pagenum)
890 {
891         if (in_destructor) {
892                 return;
893         }
894
895         switch (which_page()) {
896         case OpenPage:
897                 on_new_session_page = false;
898                 m_okbutton->set_label(_("Open"));
899                 m_okbutton->set_image (*(manage (new Gtk::Image (Gtk::Stock::OPEN, Gtk::ICON_SIZE_BUTTON))));
900                 set_response_sensitive (Gtk::RESPONSE_NONE, false);
901                 if (m_treeview->get_selection()->count_selected_rows() == 0) {
902                         set_response_sensitive (Gtk::RESPONSE_OK, false);
903                 } else {
904                         set_response_sensitive (Gtk::RESPONSE_OK, true);
905                 }
906                 last_name_page = OpenPage;
907                 break;
908
909         case EnginePage:
910                 on_new_session_page = false;
911                 if (!engine_control.interface_chosen()) {
912                         m_okbutton->set_label(_("Start Audio Engine"));
913                 } else {
914                         m_okbutton->set_label(_("Start"));
915                 }
916                 m_okbutton->set_image (*(manage (new Gtk::Image (Gtk::Stock::OPEN, Gtk::ICON_SIZE_BUTTON))));
917                 set_response_sensitive (Gtk::RESPONSE_NONE, false);
918                 set_response_sensitive (Gtk::RESPONSE_OK, true);
919                 break;
920
921         case NewPage:
922                 on_new_session_page = true;
923                 m_okbutton->set_label(_("New"));
924                 m_okbutton->set_image (*(new Gtk::Image (Gtk::Stock::NEW, Gtk::ICON_SIZE_BUTTON)));
925                 if (m_name->get_text() == "") {
926                         set_response_sensitive (Gtk::RESPONSE_OK, false);
927                         m_name->grab_focus();
928                 } else {
929                         set_response_sensitive (Gtk::RESPONSE_OK, true);
930                 }
931                 last_name_page = NewPage;
932                 break;
933         }
934 }
935
936 void
937 NewSessionDialog::treeview_selection_changed ()
938 {
939         if (m_treeview->get_selection()->count_selected_rows() == 0) {
940                 if (!m_open_filechooser->get_filename().empty()) {
941                         set_response_sensitive (Gtk::RESPONSE_OK, true);
942                 } else {
943                         set_response_sensitive (Gtk::RESPONSE_OK, false);
944                 }
945         } else {
946                 set_response_sensitive (Gtk::RESPONSE_OK, true);
947         }
948 }
949
950 void
951 NewSessionDialog::file_chosen ()
952 {
953         switch (which_page()) {
954       case OpenPage:
955          break;
956            case NewPage:
957            case EnginePage:
958                    return;
959         }
960
961         m_treeview->get_selection()->unselect_all();
962
963         Glib::RefPtr<Gdk::Window> win (get_window());
964
965         if (win) {
966                 win->set_cursor(Gdk::Cursor(Gdk::WATCH));
967         }
968
969         if (!m_open_filechooser->get_filename().empty()) {
970                 set_response_sensitive (Gtk::RESPONSE_OK, true);
971                 response (Gtk::RESPONSE_OK);
972         } else {
973                 set_response_sensitive (Gtk::RESPONSE_OK, false);
974         }
975 }
976
977 void
978 NewSessionDialog::template_chosen ()
979 {
980         if (m_template->get_filename() != "" ) {;
981                 set_response_sensitive (Gtk::RESPONSE_NONE, true);
982         } else {
983                 set_response_sensitive (Gtk::RESPONSE_NONE, false);
984         }
985 }
986
987 void
988 NewSessionDialog::recent_row_activated (const Gtk::TreePath& path, Gtk::TreeViewColumn* col)
989 {
990         response (Gtk::RESPONSE_OK);
991 }
992
993 void
994 NewSessionDialog::connect_inputs_clicked ()
995 {
996         m_limit_input_ports->set_sensitive(m_connect_inputs->get_active());
997
998                 if (m_connect_inputs->get_active() && m_limit_input_ports->get_active()) {
999                 m_input_limit_count->set_sensitive(true);
1000                 } else {
1001                 m_input_limit_count->set_sensitive(false);
1002                 }
1003 }
1004
1005 void
1006 NewSessionDialog::connect_outputs_clicked ()
1007 {
1008         m_limit_output_ports->set_sensitive(m_connect_outputs->get_active());
1009
1010                 if (m_connect_outputs->get_active() && m_limit_output_ports->get_active()) {
1011                 m_output_limit_count->set_sensitive(true);
1012                 } else {
1013                 m_output_limit_count->set_sensitive(false);
1014                 }
1015 }
1016
1017 void
1018 NewSessionDialog::limit_inputs_clicked ()
1019 {
1020         m_input_limit_count->set_sensitive(m_limit_input_ports->get_active());
1021 }
1022
1023 void
1024 NewSessionDialog::limit_outputs_clicked ()
1025 {
1026         m_output_limit_count->set_sensitive(m_limit_output_ports->get_active());
1027 }
1028
1029 void
1030 NewSessionDialog::master_bus_button_clicked ()
1031 {
1032         m_master_bus_channel_count->set_sensitive(m_create_master_bus->get_active());
1033 }
1034
1035 void
1036 NewSessionDialog::monitor_bus_button_clicked ()
1037 {
1038         m_control_bus_channel_count->set_sensitive(m_create_control_bus->get_active());
1039 }
1040
1041 void
1042 NewSessionDialog::reset_template()
1043 {
1044         m_template->unselect_all ();
1045 }
1046
1047 void
1048 NewSessionDialog::reset_recent()
1049 {
1050         /* Shamelessly ripped from ardour_ui.cc */
1051         std::vector<string *> *sessions;
1052         std::vector<string *>::iterator i;
1053         RecentSessionsSorter cmp;
1054         
1055         recent_model->clear ();
1056
1057         ARDOUR::RecentSessions rs;
1058         ARDOUR::read_recent_sessions (rs);
1059         
1060         /* sort them alphabetically */
1061         sort (rs.begin(), rs.end(), cmp);
1062         sessions = new std::vector<std::string*>;
1063         
1064         for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1065                 sessions->push_back (new string ((*i).second));
1066         }
1067         
1068         for (i = sessions->begin(); i != sessions->end(); ++i) {
1069
1070                 std::vector<std::string*>* states;
1071                 std::vector<const gchar*> item;
1072                 std::string fullpath = *(*i);
1073                 
1074                 /* remove any trailing / */
1075                 
1076                 if (fullpath[fullpath.length()-1] == '/') {
1077                         fullpath = fullpath.substr (0, fullpath.length()-1);
1078                 }
1079             
1080                 /* check whether session still exists */
1081                 if (!Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS)) {
1082                         /* session doesn't exist */
1083                         continue;
1084                 }               
1085                 
1086                 /* now get available states for this session */
1087                   
1088                 if ((states = ARDOUR::Session::possible_states (fullpath)) == 0) {
1089                         /* no state file? */
1090                         continue;
1091                 }
1092             
1093                 Gtk::TreeModel::Row row = *(recent_model->append());
1094                 
1095                 row[recent_columns.visible_name] = Glib::path_get_basename (fullpath);
1096                 row[recent_columns.fullpath] = fullpath;
1097                 
1098                 if (states->size()) {
1099                     
1100                         /* add the children */
1101                     
1102                         for (std::vector<std::string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1103
1104                                 Gtk::TreeModel::Row child_row = *(recent_model->append (row.children()));
1105                                 
1106                                 child_row[recent_columns.visible_name] = **i2;
1107                                 child_row[recent_columns.fullpath] = fullpath;
1108                                 
1109                                 delete *i2;
1110                         }
1111                 }
1112
1113                 delete states;
1114         }
1115         delete sessions;
1116 }
1117
1118 void
1119 NewSessionDialog::reset()
1120 {
1121         reset_name();
1122         reset_template();
1123         set_response_sensitive (Gtk::RESPONSE_NONE, false);
1124 }