2 Copyright (C) 2007 Paul Davis
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.
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.
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.
20 #include <gtkmm/stock.h>
21 #include <gtkmm/button.h>
22 #include <gtkmm/label.h>
23 #include <gtkmm/entry.h>
24 #include <gtkmm/table.h>
25 #include <gtkmm/comboboxtext.h>
26 #include <gtkmm/alignment.h>
28 #include "ardour/session.h"
29 #include "ardour/user_bundle.h"
30 #include "ardour/audioengine.h"
31 #include "bundle_manager.h"
32 #include "gui_thread.h"
37 using namespace ARDOUR
;
39 BundleEditorMatrix::BundleEditorMatrix (Gtk::Window
* parent
, Session
* session
, boost::shared_ptr
<Bundle
> bundle
)
40 : PortMatrix (parent
, session
, DataType::NIL
)
43 _port_group
= boost::shared_ptr
<PortGroup
> (new PortGroup (""));
44 _port_group
->add_bundle (_bundle
);
51 BundleEditorMatrix::setup_ports (int dim
)
54 _ports
[OURS
].clear ();
55 _ports
[OURS
].add_group (_port_group
);
57 _ports
[OTHER
].suspend_signals ();
59 /* when we gather, allow the matrix to contain bundles with duplicate port sets,
60 otherwise in some cases the basic system IO ports may be hidden, making
61 the bundle editor useless */
63 _ports
[OTHER
].gather (_session
, DataType::NIL
, _bundle
->ports_are_inputs(), true);
64 _ports
[OTHER
].remove_bundle (_bundle
);
65 _ports
[OTHER
].resume_signals ();
70 BundleEditorMatrix::set_state (BundleChannel c
[2], bool s
)
72 Bundle::PortList
const& pl
= c
[OTHER
].bundle
->channel_ports (c
[OTHER
].channel
);
73 for (Bundle::PortList::const_iterator i
= pl
.begin(); i
!= pl
.end(); ++i
) {
75 c
[OURS
].bundle
->add_port_to_channel (c
[OURS
].channel
, *i
);
77 c
[OURS
].bundle
->remove_port_from_channel (c
[OURS
].channel
, *i
);
83 BundleEditorMatrix::get_state (BundleChannel c
[2]) const
85 Bundle::PortList
const& pl
= c
[OTHER
].bundle
->channel_ports (c
[OTHER
].channel
);
87 return PortMatrixNode::NOT_ASSOCIATED
;
90 for (Bundle::PortList::const_iterator i
= pl
.begin(); i
!= pl
.end(); ++i
) {
91 if (!c
[OURS
].bundle
->port_attached_to_channel (c
[OURS
].channel
, *i
)) {
92 return PortMatrixNode::NOT_ASSOCIATED
;
96 return PortMatrixNode::ASSOCIATED
;
100 BundleEditorMatrix::can_add_channel (boost::shared_ptr
<Bundle
> b
) const
106 return PortMatrix::can_add_channel (b
);
110 BundleEditorMatrix::add_channel (boost::shared_ptr
<Bundle
> b
, DataType t
)
115 d
.set_position (Gtk::WIN_POS_MOUSE
);
117 if (d
.run () != Gtk::RESPONSE_ACCEPT
) {
121 _bundle
->add_channel (d
.get_name(), t
);
126 PortMatrix::add_channel (b
, t
);
132 BundleEditorMatrix::can_remove_channels (boost::shared_ptr
<Bundle
> b
) const
138 return PortMatrix::can_remove_channels (b
);
142 BundleEditorMatrix::remove_channel (BundleChannel bc
)
144 bc
.bundle
->remove_channel (bc
.channel
);
149 BundleEditorMatrix::can_rename_channels (boost::shared_ptr
<Bundle
> b
) const
155 return PortMatrix::can_rename_channels (b
);
159 BundleEditorMatrix::rename_channel (BundleChannel bc
)
161 NameChannelDialog
d (bc
.bundle
, bc
.channel
);
162 d
.set_position (Gtk::WIN_POS_MOUSE
);
164 if (d
.run () != Gtk::RESPONSE_ACCEPT
) {
168 bc
.bundle
->set_channel_name (bc
.channel
, d
.get_name ());
172 BundleEditorMatrix::list_is_global (int dim
) const
174 return (dim
== OTHER
);
178 BundleEditorMatrix::disassociation_verb () const
180 return _("Disassociate");
183 BundleEditor::BundleEditor (Session
* session
, boost::shared_ptr
<UserBundle
> bundle
)
184 : ArdourDialog (_("Edit Bundle")), _matrix (this, session
, bundle
), _bundle (bundle
)
186 Gtk::Table
* t
= new Gtk::Table (3, 2);
190 Gtk::Alignment
* a
= new Gtk::Alignment (1, 0.5, 0, 1);
191 a
->add (*Gtk::manage (new Gtk::Label (_("Name:"))));
192 t
->attach (*Gtk::manage (a
), 0, 1, 0, 1, Gtk::FILL
, Gtk::FILL
);
193 t
->attach (_name
, 1, 2, 0, 1);
194 _name
.set_text (_bundle
->name ());
195 _name
.signal_changed().connect (sigc::mem_fun (*this, &BundleEditor::name_changed
));
197 /* Direction (input or output) */
198 a
= new Gtk::Alignment (1, 0.5, 0, 1);
199 a
->add (*Gtk::manage (new Gtk::Label (_("Direction:"))));
200 t
->attach (*Gtk::manage (a
), 0, 1, 1, 2, Gtk::FILL
, Gtk::FILL
);
201 a
= new Gtk::Alignment (0, 0.5, 0, 1);
202 a
->add (_input_or_output
);
203 t
->attach (*Gtk::manage (a
), 1, 2, 1, 2);
204 _input_or_output
.append_text (_("Input"));
205 _input_or_output
.append_text (_("Output"));
207 if (bundle
->ports_are_inputs()) {
208 _input_or_output
.set_active_text (_("Input"));
210 _input_or_output
.set_active_text (_("Output"));
213 _input_or_output
.signal_changed().connect (sigc::mem_fun (*this, &BundleEditor::input_or_output_changed
));
215 get_vbox()->pack_start (*Gtk::manage (t
), false, false);
216 get_vbox()->pack_start (_matrix
);
217 get_vbox()->set_spacing (4);
219 add_button (Gtk::Stock::CLOSE
, Gtk::RESPONSE_ACCEPT
);
224 BundleEditor::on_show ()
226 Gtk::Window::on_show ();
227 pair
<uint32_t, uint32_t> const pm_max
= _matrix
.max_size ();
228 resize_window_to_proportion_of_monitor (this, pm_max
.first
, pm_max
.second
);
232 BundleEditor::name_changed ()
234 _bundle
->set_name (_name
.get_text ());
238 BundleEditor::input_or_output_changed ()
240 _bundle
->remove_ports_from_channels ();
242 if (_input_or_output
.get_active_text() == _("Output")) {
243 _bundle
->set_ports_are_outputs ();
245 _bundle
->set_ports_are_inputs ();
248 _matrix
.setup_all_ports ();
252 BundleEditor::on_map ()
254 _matrix
.setup_all_ports ();
259 BundleManager::BundleManager (Session
* session
)
260 : ArdourDialog (_("Bundle Manager"))
261 , edit_button (_("Edit"))
262 , delete_button (_("Delete"))
264 set_session (session
);
266 _list_model
= Gtk::ListStore::create (_list_model_columns
);
267 _tree_view
.set_model (_list_model
);
268 _tree_view
.append_column (_("Name"), _list_model_columns
.name
);
269 _tree_view
.set_headers_visible (false);
271 boost::shared_ptr
<BundleList
> bundles
= _session
->bundles ();
272 for (BundleList::iterator i
= bundles
->begin(); i
!= bundles
->end(); ++i
) {
276 /* New / Edit / Delete buttons */
277 Gtk::VBox
* buttons
= new Gtk::VBox
;
278 buttons
->set_spacing (8);
279 Gtk::Button
* b
= new Gtk::Button (_("New"));
280 b
->set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::NEW
, Gtk::ICON_SIZE_BUTTON
)));
281 b
->signal_clicked().connect (sigc::mem_fun (*this, &BundleManager::new_clicked
));
282 buttons
->pack_start (*Gtk::manage (b
), false, false);
283 edit_button
.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::EDIT
, Gtk::ICON_SIZE_BUTTON
)));
284 edit_button
.signal_clicked().connect (sigc::mem_fun (*this, &BundleManager::edit_clicked
));
285 buttons
->pack_start (edit_button
, false, false);
286 delete_button
.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::DELETE
, Gtk::ICON_SIZE_BUTTON
)));
287 delete_button
.signal_clicked().connect (sigc::mem_fun (*this, &BundleManager::delete_clicked
));
288 buttons
->pack_start (delete_button
, false, false);
290 Gtk::HBox
* h
= new Gtk::HBox
;
292 h
->set_border_width (8);
293 h
->pack_start (_tree_view
);
294 h
->pack_start (*Gtk::manage (buttons
), false, false);
296 get_vbox()->set_spacing (8);
297 get_vbox()->pack_start (*Gtk::manage (h
));
299 set_default_size (480, 240);
301 _tree_view
.get_selection()->signal_changed().connect (
302 sigc::mem_fun (*this, &BundleManager::set_button_sensitivity
)
305 _tree_view
.signal_row_activated().connect (
306 sigc::mem_fun (*this, &BundleManager::row_activated
)
309 set_button_sensitivity ();
315 BundleManager::set_button_sensitivity ()
317 bool const sel
= (_tree_view
.get_selection()->get_selected() != 0);
318 edit_button
.set_sensitive (sel
);
319 delete_button
.set_sensitive (sel
);
324 BundleManager::new_clicked ()
326 boost::shared_ptr
<UserBundle
> b (new UserBundle (_("Bundle")));
328 /* Start off with a single channel */
329 /* XXX: allow user to specify type */
330 b
->add_channel ("1", DataType::AUDIO
);
332 _session
->add_bundle (b
);
335 BundleEditor
e (_session
, b
);
340 BundleManager::edit_clicked ()
342 Gtk::TreeModel::iterator i
= _tree_view
.get_selection()->get_selected();
344 boost::shared_ptr
<UserBundle
> b
= (*i
)[_list_model_columns
.bundle
];
345 BundleEditor
e (_session
, b
);
351 BundleManager::delete_clicked ()
353 Gtk::TreeModel::iterator i
= _tree_view
.get_selection()->get_selected();
355 boost::shared_ptr
<UserBundle
> b
= (*i
)[_list_model_columns
.bundle
];
356 _session
->remove_bundle (b
);
357 _list_model
->erase (i
);
362 BundleManager::add_bundle (boost::shared_ptr
<Bundle
> b
)
364 boost::shared_ptr
<UserBundle
> u
= boost::dynamic_pointer_cast
<UserBundle
> (b
);
369 Gtk::TreeModel::iterator i
= _list_model
->append ();
370 (*i
)[_list_model_columns
.name
] = u
->name ();
371 (*i
)[_list_model_columns
.bundle
] = u
;
373 u
->Changed
.connect (bundle_connections
, invalidator (*this), ui_bind (&BundleManager::bundle_changed
, this, _1
, u
), gui_context());
377 BundleManager::bundle_changed (Bundle::Change c
, boost::shared_ptr
<UserBundle
> b
)
379 if ((c
& Bundle::NameChanged
) == 0) {
383 Gtk::TreeModel::iterator i
= _list_model
->children().begin ();
384 while (i
!= _list_model
->children().end()) {
385 boost::shared_ptr
<UserBundle
> t
= (*i
)[_list_model_columns
.bundle
];
392 if (i
!= _list_model
->children().end()) {
393 (*i
)[_list_model_columns
.name
] = b
->name ();
398 BundleManager::row_activated (Gtk::TreeModel::Path
const & p
, Gtk::TreeViewColumn
*)
400 Gtk::TreeModel::iterator i
= _list_model
->get_iter (p
);
405 boost::shared_ptr
<UserBundle
> b
= (*i
)[_list_model_columns
.bundle
];
406 BundleEditor
e (_session
, b
);
410 NameChannelDialog::NameChannelDialog ()
411 : ArdourDialog (_("Add Channel")),
417 NameChannelDialog::NameChannelDialog (boost::shared_ptr
<Bundle
> b
, uint32_t c
)
418 : ArdourDialog (_("Rename Channel")),
423 _name
.set_text (b
->channel_name (c
));
429 NameChannelDialog::setup ()
431 Gtk::HBox
* box
= Gtk::manage (new Gtk::HBox ());
433 box
->pack_start (*Gtk::manage (new Gtk::Label (_("Name"))));
434 box
->pack_start (_name
);
435 _name
.set_activates_default (true);
437 get_vbox ()->pack_end (*box
);
440 add_button (Gtk::Stock::CANCEL
, Gtk::RESPONSE_CANCEL
);
442 add_button (Gtk::Stock::ADD
, Gtk::RESPONSE_ACCEPT
);
444 add_button (Gtk::Stock::APPLY
, Gtk::RESPONSE_ACCEPT
);
446 set_default_response (Gtk::RESPONSE_ACCEPT
);
450 NameChannelDialog::get_name () const
452 return _name
.get_text ();