ardour
bundle_manager.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2007 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 <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>
27 
28 #include "ardour/session.h"
29 #include "ardour/user_bundle.h"
30 #include "bundle_manager.h"
31 #include "gui_thread.h"
32 #include "i18n.h"
33 #include "utils.h"
34 
35 using namespace std;
36 using namespace ARDOUR;
37 using namespace ARDOUR_UI_UTILS;
38 
40  : PortMatrix (parent, session, DataType::NIL)
41  , _bundle (bundle)
42 {
45 
46  setup_all_ports ();
47  init ();
48 }
49 
50 void
52 {
53  if (dim == OURS) {
54  _ports[OURS].clear ();
56  } else {
58 
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 */
62 
63  _ports[OTHER].gather (_session, DataType::NIL, _bundle->ports_are_inputs(), true, show_only_bundles ());
66  }
67 }
68 
69 void
71 {
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) {
74  if (s) {
75  c[OURS].bundle->add_port_to_channel (c[OURS].channel, *i);
76  } else {
77  c[OURS].bundle->remove_port_from_channel (c[OURS].channel, *i);
78  }
79  }
80 }
81 
84 {
85  if (c[0].bundle->nchannels() == ChanCount::ZERO || c[1].bundle->nchannels() == ChanCount::ZERO) {
87  }
88 
89  Bundle::PortList const& pl = c[OTHER].bundle->channel_ports (c[OTHER].channel);
90  if (pl.empty ()) {
92  }
93 
94  for (Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
95  if (!c[OURS].bundle->port_attached_to_channel (c[OURS].channel, *i)) {
97  }
98  }
99 
101 }
102 
103 bool
105 {
106  if (b == _bundle) {
107  return true;
108  }
109 
110  return PortMatrix::can_add_channels (b);
111 }
112 
113 void
115 {
116  if (b == _bundle) {
117 
119 
120  if (d.run () != Gtk::RESPONSE_ACCEPT) {
121  return;
122  }
123 
124  _bundle->add_channel (d.get_name(), t);
125  setup_ports (OURS);
126 
127  } else {
128 
130 
131  }
132 }
133 
134 bool
136 {
137  if (b == _bundle) {
138  return true;
139  }
140 
142 }
143 
144 void
146 {
147  bc.bundle->remove_channel (bc.channel);
148  setup_ports (OURS);
149 }
150 
151 bool
153 {
154  if (b == _bundle) {
155  return true;
156  }
157 
159 }
160 
161 void
163 {
164  NameChannelDialog d (bc.bundle, bc.channel);
165 
166  if (d.run () != Gtk::RESPONSE_ACCEPT) {
167  return;
168  }
169 
170  bc.bundle->set_channel_name (bc.channel, d.get_name ());
171 }
172 
173 bool
175 {
176  return (dim == OTHER);
177 }
178 
179 string
181 {
182  return _("Disassociate");
183 }
184 
186  : ArdourDialog (_("Edit Bundle")), _matrix (this, session, bundle), _bundle (bundle)
187 {
188  Gtk::Table* t = new Gtk::Table (3, 2);
189  t->set_spacings (4);
190 
191  /* Bundle name */
192  Gtk::Alignment* a = new Gtk::Alignment (1, 0.5, 0, 1);
193  a->add (*Gtk::manage (new Gtk::Label (_("Name:"))));
194  t->attach (*Gtk::manage (a), 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
195  t->attach (_name, 1, 2, 0, 1);
196  _name.set_text (_bundle->name ());
197  _name.signal_changed().connect (sigc::mem_fun (*this, &BundleEditor::name_changed));
198 
199  /* Direction (input or output) */
200  a = new Gtk::Alignment (1, 0.5, 0, 1);
201  a->add (*Gtk::manage (new Gtk::Label (_("Direction:"))));
202  t->attach (*Gtk::manage (a), 0, 1, 1, 2, Gtk::FILL, Gtk::FILL);
203  a = new Gtk::Alignment (0, 0.5, 0, 1);
204  a->add (_input_or_output);
205  t->attach (*Gtk::manage (a), 1, 2, 1, 2);
206  _input_or_output.append_text (_("Input"));
207  _input_or_output.append_text (_("Output"));
208 
209  if (bundle->ports_are_inputs()) {
210  _input_or_output.set_active_text (_("Input"));
211  } else {
212  _input_or_output.set_active_text (_("Output"));
213  }
214 
215  _input_or_output.signal_changed().connect (sigc::mem_fun (*this, &BundleEditor::input_or_output_changed));
216 
217  get_vbox()->pack_start (*Gtk::manage (t), false, false);
218  get_vbox()->pack_start (_matrix);
219  get_vbox()->set_spacing (4);
220 
221  add_button (Gtk::Stock::CLOSE, Gtk::RESPONSE_ACCEPT);
222  show_all ();
223 
224  signal_key_press_event().connect (sigc::mem_fun (_matrix, &BundleEditorMatrix::key_press));
225 }
226 
227 void
229 {
230  Gtk::Window::on_show ();
231  pair<uint32_t, uint32_t> const pm_max = _matrix.max_size ();
232  resize_window_to_proportion_of_monitor (this, pm_max.first, pm_max.second);
233 }
234 
235 void
237 {
238  _bundle->set_name (_name.get_text ());
239 }
240 
241 void
243 {
245 
246  if (_input_or_output.get_active_text() == _("Output")) {
248  } else {
250  }
251 
253 }
254 
255 void
257 {
259  Window::on_map ();
260 }
261 
262 
264  : ArdourDialog (_("Bundle Manager"))
265  , edit_button (_("Edit"))
266  , delete_button (_("Delete"))
267 {
268  set_session (session);
269 
270  _list_model = Gtk::ListStore::create (_list_model_columns);
271  _tree_view.set_model (_list_model);
272  _tree_view.append_column (_("Name"), _list_model_columns.name);
273  _tree_view.set_headers_visible (false);
274 
276  for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
277  add_bundle (*i);
278  }
279 
280  /* New / Edit / Delete buttons */
281  Gtk::VBox* buttons = new Gtk::VBox;
282  buttons->set_spacing (8);
283  Gtk::Button* b = new Gtk::Button (_("New"));
284  b->set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::NEW, Gtk::ICON_SIZE_BUTTON)));
285  b->signal_clicked().connect (sigc::mem_fun (*this, &BundleManager::new_clicked));
286  buttons->pack_start (*Gtk::manage (b), false, false);
287  edit_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::EDIT, Gtk::ICON_SIZE_BUTTON)));
288  edit_button.signal_clicked().connect (sigc::mem_fun (*this, &BundleManager::edit_clicked));
289  buttons->pack_start (edit_button, false, false);
290  delete_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID(GTK_STOCK_DELETE), Gtk::ICON_SIZE_BUTTON)));
291  delete_button.signal_clicked().connect (sigc::mem_fun (*this, &BundleManager::delete_clicked));
292  buttons->pack_start (delete_button, false, false);
293 
294  Gtk::HBox* h = new Gtk::HBox;
295  h->set_spacing (8);
296  h->set_border_width (8);
297  h->pack_start (_tree_view);
298  h->pack_start (*Gtk::manage (buttons), false, false);
299 
300  get_vbox()->set_spacing (8);
301  get_vbox()->pack_start (*Gtk::manage (h));
302 
303  set_default_size (480, 240);
304 
305  _tree_view.get_selection()->signal_changed().connect (
306  sigc::mem_fun (*this, &BundleManager::set_button_sensitivity)
307  );
308 
309  _tree_view.signal_row_activated().connect (
310  sigc::mem_fun (*this, &BundleManager::row_activated)
311  );
312 
313  Gtk::Button* close_but = add_button (Gtk::Stock::CLOSE, Gtk::RESPONSE_ACCEPT);
314  close_but->signal_clicked ().connect (sigc::mem_fun (*this, &Gtk::Window::hide));
315 
317 
318  show_all ();
319 }
320 
321 void
323 {
324  bool const sel = (_tree_view.get_selection()->get_selected() != 0);
325  edit_button.set_sensitive (sel);
326  delete_button.set_sensitive (sel);
327 }
328 
329 
330 void
332 {
333  boost::shared_ptr<UserBundle> b (new UserBundle (_("Bundle")));
334 
335  /* Start off with a single channel */
336  /* XXX: allow user to specify type */
337  b->add_channel ("1", DataType::AUDIO);
338 
339  _session->add_bundle (b);
340  add_bundle (b);
341 
342  BundleEditor e (_session, b);
343  e.run ();
344 }
345 
346 void
348 {
349  Gtk::TreeModel::iterator i = _tree_view.get_selection()->get_selected();
350  if (i) {
352  BundleEditor e (_session, b);
353  e.run ();
354  }
355 }
356 
357 void
359 {
360  Gtk::TreeModel::iterator i = _tree_view.get_selection()->get_selected();
361  if (i) {
363  _session->remove_bundle (b);
364  _list_model->erase (i);
365  }
366 }
367 
368 void
370 {
372  if (u == 0) {
373  return;
374  }
375 
376  Gtk::TreeModel::iterator i = _list_model->append ();
377  (*i)[_list_model_columns.name] = u->name ();
378  (*i)[_list_model_columns.bundle] = u;
379 
380  u->Changed.connect (bundle_connections, invalidator (*this), boost::bind (&BundleManager::bundle_changed, this, _1, u), gui_context());
381 }
382 
383 void
385 {
386  if ((c & Bundle::NameChanged) == 0) {
387  return;
388  }
389 
390  Gtk::TreeModel::iterator i = _list_model->children().begin ();
391  while (i != _list_model->children().end()) {
393  if (t == b) {
394  break;
395  }
396  ++i;
397  }
398 
399  if (i != _list_model->children().end()) {
400  (*i)[_list_model_columns.name] = b->name ();
401  }
402 }
403 
404 void
405 BundleManager::row_activated (Gtk::TreeModel::Path const & p, Gtk::TreeViewColumn*)
406 {
407  Gtk::TreeModel::iterator i = _list_model->get_iter (p);
408  if (!i) {
409  return;
410  }
411 
413  BundleEditor e (_session, b);
414  e.run ();
415 }
416 
418  : ArdourDialog (_("Add Channel")),
419  _adding (true)
420 {
421  setup ();
422 }
423 
425  : ArdourDialog (_("Rename Channel")),
426  _bundle (b),
427  _adding (false)
428 {
429  _name.set_text (b->channel_name (c));
430 
431  setup ();
432 }
433 
434 void
436 {
437  Gtk::HBox* box = Gtk::manage (new Gtk::HBox ());
438 
439  box->pack_start (*Gtk::manage (new Gtk::Label (_("Name"))));
440  box->pack_start (_name);
441  _name.set_activates_default (true);
442 
443  get_vbox ()->pack_end (*box);
444  box->show_all ();
445 
446  add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
447  if (_adding) {
448  add_button (Gtk::Stock::ADD, Gtk::RESPONSE_ACCEPT);
449  } else {
450  add_button (Gtk::Stock::APPLY, Gtk::RESPONSE_ACCEPT);
451  }
452  set_default_response (Gtk::RESPONSE_ACCEPT);
453 }
454 
455 string
457 {
458  return _name.get_text ();
459 }
460 
void rename_channel(ARDOUR::BundleChannel)
void input_or_output_changed()
void add_channel(boost::shared_ptr< ARDOUR::Bundle >, ARDOUR::DataType)
void resize_window_to_proportion_of_monitor(Gtk::Window *, int, int)
Definition: utils.cc:831
void setup_all_ports()
Definition: port_matrix.cc:642
void bundle_changed(ARDOUR::Bundle::Change, boost::shared_ptr< ARDOUR::UserBundle >)
void suspend_signals()
Definition: port_group.cc:758
boost::shared_ptr< ARDOUR::UserBundle > _bundle
bool can_add_channels(boost::shared_ptr< ARDOUR::Bundle >) const
std::string get_name() const
std::string channel_name(uint32_t) const
Definition: bundle.cc:266
void resume_signals()
Definition: port_group.cc:764
the ports are not associated
virtual bool can_add_channels(boost::shared_ptr< ARDOUR::Bundle >) const
Definition: port_matrix.cc:718
void gather(ARDOUR::Session *, ARDOUR::DataType, bool, bool, bool)
Definition: port_group.cc:329
ModelColumns _list_model_columns
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
std::vector< std::string > PortList
Definition: bundle.h:50
void set_ports_are_inputs()
Definition: bundle.cc:474
PortMatrixNode::State get_state(ARDOUR::BundleChannel c[2]) const
virtual bool can_rename_channels(boost::shared_ptr< ARDOUR::Bundle >) const
Definition: port_matrix.h:152
Gtk::TreeModelColumn< std::string > name
Definition: Beats.hpp:239
void add_bundle(boost::shared_ptr< Bundle >, bool emit_signal=true)
Definition: session.cc:4271
Gtk::Button delete_button
void add_group(boost::shared_ptr< PortGroup >)
Definition: port_group.cc:718
PBD::ScopedConnectionList bundle_connections
#define invalidator(x)
Definition: gui_thread.h:40
Glib::RefPtr< Gtk::ListStore > _list_model
the ports are associated
#define _(Text)
Definition: i18n.h:11
void remove_channel(ARDOUR::BundleChannel)
void set_state(ARDOUR::BundleChannel c[2], bool s)
void add_bundle(boost::shared_ptr< ARDOUR::Bundle >, bool allow_dups=false)
Definition: port_group.cc:73
virtual bool can_remove_channels(boost::shared_ptr< ARDOUR::Bundle >) const
Definition: port_matrix.cc:741
bool list_is_global(int) const
void row_activated(Gtk::TreeModel::Path const &p, Gtk::TreeViewColumn *c)
BundleEditorMatrix _matrix
Definition: amp.h:29
bool ports_are_inputs() const
Definition: bundle.h:114
std::string disassociation_verb() const
boost::shared_ptr< BundleList > bundles()
Definition: session.h:241
#define gui_context()
Definition: gui_thread.h:36
void remove_ports_from_channels()
Definition: bundle.cc:357
void add_channel(std::string const &, DataType)
Definition: bundle.cc:155
BundleManager(ARDOUR::Session *)
std::string name() const
Definition: bundle.h:110
Gtk::TreeModelColumn< boost::shared_ptr< ARDOUR::UserBundle > > bundle
bool show_only_bundles() const
Definition: port_matrix.h:94
void set_ports_are_outputs()
Definition: bundle.cc:481
BundleEditor(ARDOUR::Session *, boost::shared_ptr< ARDOUR::UserBundle >)
PBD::Signal1< void, Change > Changed
Definition: bundle.h:131
std::pair< uint32_t, uint32_t > max_size() const
Definition: port_matrix.cc:672
Gtk::ComboBoxText _input_or_output
bool can_rename_channels(boost::shared_ptr< ARDOUR::Bundle >) const
virtual void add_channel(boost::shared_ptr< ARDOUR::Bundle >, ARDOUR::DataType)
Definition: port_matrix.cc:724
Gtk::Entry _name
boost::shared_ptr< Bundle > bundle
Definition: bundle.h:168
Gtk::TreeView _tree_view
bool key_press(GdkEventKey *)
void add_bundle(boost::shared_ptr< ARDOUR::Bundle >)
int channel
channel index, or -1 for "all"
Definition: bundle.h:169
void remove_bundle(boost::shared_ptr< Bundle >)
Definition: session.cc:4287
virtual void set_session(ARDOUR::Session *)
Gtk::Button edit_button
boost::shared_ptr< ARDOUR::Bundle > _bundle
void set_button_sensitivity()
void set_name(std::string const &)
Definition: bundle.cc:491
BundleEditorMatrix(Gtk::Window *, ARDOUR::Session *, boost::shared_ptr< ARDOUR::Bundle >)
boost::shared_ptr< PortGroup > _port_group
bool can_remove_channels(boost::shared_ptr< ARDOUR::Bundle >) const
ARDOUR::Session * _session
void init()
Definition: port_matrix.cc:122
PortGroupList _ports[2]
Definition: port_matrix.h:176
void remove_bundle(boost::shared_ptr< ARDOUR::Bundle >)
Definition: port_group.cc:729