New session dialog now opens as well as makes new sessions. Avoid seeing an ugly...
[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     $Id$
19 */
20
21 #include "i18n.h"
22 #include "new_session_dialog.h"
23 #include "glade_path.h"
24
25 #include <ardour/recent_sessions.h>
26 #include <ardour/session.h>
27
28 #include <pbd/basename.h>
29
30 #include <gtkmm/entry.h>
31 #include <gtkmm/filechooserbutton.h>
32 #include <gtkmm/spinbutton.h>
33 #include <gtkmm/checkbutton.h>
34 #include <gtkmm/radiobutton.h>
35 #include <gtkmm/filefilter.h>
36 #include <gtkmm/stock.h>
37
38
39 const char* NewSessionDialogFactory::s_m_top_level_widget_name = X_("NewSessionDialog");
40 const char* NewSessionDialogFactory::top_level_widget_name() { return s_m_top_level_widget_name; }
41
42 Glib::RefPtr<Gnome::Glade::Xml>
43 NewSessionDialogFactory::create()
44 {
45         return GladeFactory::create(GladePath::path(X_("new_session_dialog.glade")));
46 }
47
48
49 NewSessionDialog::NewSessionDialog(BaseObjectType* cobject,
50                                    const Glib::RefPtr<Gnome::Glade::Xml>& xml)
51         : Gtk::Dialog(cobject)    
52 {
53         // look up the widgets we care about.
54         xml->get_widget(X_("NewSessionDialog"), m_new_session_dialog);
55         xml->get_widget(X_("SessionNameEntry"), m_name);
56         xml->get_widget(X_("SessionFolderChooser"), m_folder);
57         xml->get_widget(X_("SessionTemplateChooser"), m_template);
58         
59         xml->get_widget(X_("CreateMasterBus"), m_create_master_bus);
60         xml->get_widget(X_("MasterChannelCount"), m_master_bus_channel_count);
61         
62         xml->get_widget(X_("CreateControlBus"), m_create_control_bus);
63         xml->get_widget(X_("ControlChannelCount"), m_control_bus_channel_count);
64
65         xml->get_widget(X_("ConnectInputs"), m_connect_inputs);
66         xml->get_widget(X_("LimitInputPorts"), m_limit_input_ports);
67         xml->get_widget(X_("InputLimitCount"), m_input_limit_count);
68
69         xml->get_widget(X_("ConnectOutputs"), m_connect_outputs);
70         xml->get_widget(X_("LimitOutputPorts"), m_limit_output_ports);
71         xml->get_widget(X_("OutputLimitCount"), m_output_limit_count);  
72         xml->get_widget(X_("ConnectOutsToMaster"), m_connect_outputs_to_master);
73         xml->get_widget(X_("ConnectOutsToPhysical"), m_connect_outputs_to_physical);
74
75         xml->get_widget(X_("OpenFilechooserButton"), m_open_filechooser);
76         xml->get_widget(X_("TheNotebook"), m_notebook);
77         xml->get_widget(X_("TheTreeview"), m_treeview);
78         xml->get_widget(X_("OkButton"), m_okbutton);
79
80
81         if (m_treeview) {
82                 /* Shamelessly ripped from ardour_ui.cc */
83                 std::vector<string *> *sessions;
84                 std::vector<string *>::iterator i;
85                 RecentSessionsSorter cmp;
86                 
87                 recent_model = Gtk::TreeStore::create (recent_columns);
88                 m_treeview->set_model (recent_model);
89                 m_treeview->append_column (_("Recent Sessions"), recent_columns.visible_name);
90                 m_treeview->set_headers_visible (false);
91                 m_treeview->get_selection()->set_mode (Gtk::SELECTION_SINGLE);
92                 
93                 recent_model->clear ();
94                 
95                 ARDOUR::RecentSessions rs;
96                 ARDOUR::read_recent_sessions (rs);
97                 
98                 /* sort them alphabetically */
99                 sort (rs.begin(), rs.end(), cmp);
100                 sessions = new std::vector<std::string*>;
101                 
102                 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
103                         sessions->push_back (new string ((*i).second));
104                 }
105           
106                 for (i = sessions->begin(); i != sessions->end(); ++i) {
107                   
108                   std::vector<std::string*>* states;
109                   std::vector<const gchar*> item;
110                   std::string fullpath = *(*i);
111                   
112                   /* remove any trailing / */
113                   
114                   if (fullpath[fullpath.length()-1] == '/') {
115                           fullpath = fullpath.substr (0, fullpath.length()-1);
116                   }
117             
118                   /* now get available states for this session */
119                   
120                   if ((states = ARDOUR::Session::possible_states (fullpath)) == 0) {
121                           /* no state file? */
122                           continue;
123                   }
124             
125                   Gtk::TreeModel::Row row = *(recent_model->append());
126                   
127                   row[recent_columns.visible_name] = PBD::basename (fullpath);
128                   row[recent_columns.fullpath] = fullpath;
129                   
130                   if (states->size() > 1) {
131                     
132                           /* add the children */
133                     
134                           for (std::vector<std::string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
135                             
136                                   Gtk::TreeModel::Row child_row = *(recent_model->append (row.children()));
137                                   
138                                   child_row[recent_columns.visible_name] = **i2;
139                                   child_row[recent_columns.fullpath] = fullpath;
140                                   
141                                   delete *i2;
142                           }
143                   }
144                   
145                   delete states;
146                 }
147                 delete sessions;
148         }
149         
150         m_new_session_dialog->set_response_sensitive (Gtk::RESPONSE_OK, false);
151         m_new_session_dialog->set_default_response (Gtk::RESPONSE_OK);
152         m_notebook->show_all_children();
153         m_notebook->set_current_page(0);
154
155         Gtk::FileFilter* filter = manage (new (Gtk::FileFilter));
156
157         filter->add_pattern(X_("*.ardour"));
158         filter->add_pattern(X_("*.ardour.bak"));
159         m_open_filechooser->set_filter (*filter);
160
161         ///@ todo connect some signals
162
163         m_name->signal_key_release_event().connect(mem_fun (*this, &NewSessionDialog::entry_key_release));
164         m_notebook->signal_switch_page().connect (mem_fun (*this, &NewSessionDialog::notebook_page_changed));
165         m_treeview->get_selection()->signal_changed().connect (mem_fun (*this, &NewSessionDialog::treeview_selection_changed));
166         m_treeview->signal_row_activated().connect (mem_fun (*this, &NewSessionDialog::recent_row_activated));
167         m_open_filechooser->signal_selection_changed ().connect (mem_fun (*this, &NewSessionDialog::file_chosen));
168 }
169
170 void
171 NewSessionDialog::set_session_name(const Glib::ustring& name)
172 {
173         m_name->set_text(name);
174 }
175
176 std::string
177 NewSessionDialog::session_name() const
178 {
179         std::string str = Glib::filename_from_utf8(m_open_filechooser->get_filename());
180         std::string::size_type position = str.find_last_of ('/');
181         str = str.substr (position+1);
182         position = str.find_last_of ('.');
183         str = str.substr (0, position);
184
185         /*
186           XXX what to do if it's a .bak file?
187           load_session doesn't allow it!
188
189         if ((position = str.rfind(".bak")) != string::npos) {
190                 str = str.substr (0, position);
191         }         
192         */
193
194         if (m_notebook->get_current_page() == 0) {
195                 return Glib::filename_from_utf8(m_name->get_text());
196         } else {
197                 if (m_treeview->get_selection()->count_selected_rows() == 0) {
198                         return Glib::filename_from_utf8(str);
199                 }
200                 Gtk::TreeModel::iterator i = m_treeview->get_selection()->get_selected();
201                 return (*i)[recent_columns.visible_name];
202         }
203 }
204
205 std::string
206 NewSessionDialog::session_folder() const
207 {
208         if (m_notebook->get_current_page() == 0) {
209                 return Glib::filename_from_utf8(m_folder->get_current_folder());
210         } else {
211                
212                 if (m_treeview->get_selection()->count_selected_rows() == 0) {
213                         return Glib::filename_from_utf8(m_open_filechooser->get_current_folder());
214                 }
215                 Gtk::TreeModel::iterator i = m_treeview->get_selection()->get_selected();
216                 return (*i)[recent_columns.fullpath];
217         }
218 }
219
220 bool
221 NewSessionDialog::use_session_template() const
222 {
223         if(m_template->get_filename().empty() && (m_notebook->get_current_page() == 0)) return false;
224         return true;
225 }
226
227 std::string
228 NewSessionDialog::session_template_name() const
229 {
230         return Glib::filename_from_utf8(m_template->get_filename());
231 }
232
233 bool
234 NewSessionDialog::create_master_bus() const
235 {
236         return m_create_master_bus->get_active();
237 }
238
239 int
240 NewSessionDialog::master_channel_count() const
241 {
242         return m_master_bus_channel_count->get_value_as_int();
243 }
244
245 bool
246 NewSessionDialog::create_control_bus() const
247 {
248         return m_create_control_bus->get_active();
249 }
250
251 int
252 NewSessionDialog::control_channel_count() const
253 {
254         return m_control_bus_channel_count->get_value_as_int();
255 }
256
257 bool
258 NewSessionDialog::connect_inputs() const
259 {
260         return m_connect_inputs->get_active();
261 }
262
263 bool
264 NewSessionDialog::limit_inputs_used_for_connection() const
265 {
266         return m_limit_input_ports->get_active();
267 }
268
269 int
270 NewSessionDialog::input_limit_count() const
271 {
272         return m_input_limit_count->get_value_as_int();
273 }
274
275 bool
276 NewSessionDialog::connect_outputs() const
277 {
278         return m_connect_outputs->get_active();
279 }
280
281 bool
282 NewSessionDialog::limit_outputs_used_for_connection() const
283 {
284         return m_limit_output_ports->get_active();
285 }
286
287 int
288 NewSessionDialog::output_limit_count() const
289 {
290         return m_output_limit_count->get_value_as_int();
291 }
292
293 bool
294 NewSessionDialog::connect_outs_to_master() const
295 {
296         return m_connect_outputs_to_master->get_active();
297 }
298
299 bool
300 NewSessionDialog::connect_outs_to_physical() const
301 {
302         return m_connect_outputs_to_physical->get_active();
303 }
304
305 int
306 NewSessionDialog::get_current_page()
307 {
308         return m_notebook->get_current_page();
309         
310 }
311
312 void
313 NewSessionDialog::reset_name()
314 {
315         m_name->set_text(Glib::ustring());
316         
317 }
318
319 bool
320 NewSessionDialog::entry_key_release (GdkEventKey* ev)
321 {
322         if (m_name->get_text() != "") {
323                 m_new_session_dialog->set_response_sensitive (Gtk::RESPONSE_OK, true);
324         } else {
325                 m_new_session_dialog->set_response_sensitive (Gtk::RESPONSE_OK, false);
326         }
327         return true;
328 }
329
330 void
331 NewSessionDialog::notebook_page_changed (GtkNotebookPage* np, uint pagenum)
332 {
333         if (pagenum == 1) {
334                 m_okbutton->set_label(_("Open"));
335                 m_okbutton->set_image (*(new Gtk::Image (Gtk::Stock::OPEN, Gtk::ICON_SIZE_BUTTON)));
336                 if (m_treeview->get_selection()->count_selected_rows() == 0) {
337                         m_new_session_dialog->set_response_sensitive (Gtk::RESPONSE_OK, false);
338                 } else {
339                         m_new_session_dialog->set_response_sensitive (Gtk::RESPONSE_OK, true);
340                 }
341         } else {
342                 m_okbutton->set_label(_("New"));
343                 m_okbutton->set_image (*(new Gtk::Image (Gtk::Stock::NEW, Gtk::ICON_SIZE_BUTTON)));
344                 if (m_name->get_text() == "") {
345                         m_new_session_dialog->set_response_sensitive (Gtk::RESPONSE_OK, false);
346                 } else {
347                         m_new_session_dialog->set_response_sensitive (Gtk::RESPONSE_OK, true);
348                 }
349         }
350 }
351
352 void
353 NewSessionDialog::treeview_selection_changed ()
354 {
355   if (m_treeview->get_selection()->count_selected_rows() == 0) {
356           if (!m_open_filechooser->get_filename().empty()) {
357                   m_new_session_dialog->set_response_sensitive (Gtk::RESPONSE_OK, true);
358           } else {
359                   m_new_session_dialog->set_response_sensitive (Gtk::RESPONSE_OK, false);
360           }
361   } else {
362           m_new_session_dialog->set_response_sensitive (Gtk::RESPONSE_OK, true);
363   }
364 }
365
366 void
367 NewSessionDialog::file_chosen ()
368 {
369         m_treeview->get_selection()->unselect_all();
370   
371         if (m_treeview->get_selection()->count_selected_rows() == 0) {
372                 m_new_session_dialog->set_response_sensitive (Gtk::RESPONSE_OK, true);
373         }
374 }
375
376 void
377 NewSessionDialog::recent_row_activated (const Gtk::TreePath& path, Gtk::TreeViewColumn* col)
378 {
379         m_new_session_dialog->response (Gtk::RESPONSE_YES);
380 }
381
382 /// @todo
383 void
384 NewSessionDialog::reset_template()
385 {
386
387 }
388
389 void
390 NewSessionDialog::reset()
391 {
392         reset_name();
393         reset_template();
394 }