along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <map>
#include <vector>
+#include <sigc++/bind.h>
+
#include <gtkmm/messagedialog.h>
#include <glibmm/thread.h>
#include <ardour/port.h>
#include <ardour/insert.h>
#include <ardour/session.h>
-#include <ardour/diskstream.h>
+#include <ardour/audio_diskstream.h>
#include <gtkmm2ext/doi.h>
#include <gtkmm2ext/gtk_ui.h>
using namespace Glib;
using namespace sigc;
using namespace ARDOUR;
+using namespace PBD;
using namespace Gtkmm2ext;
-IOSelectorWindow::IOSelectorWindow (Session& sess, IO& ior, bool input, bool can_cancel)
+IOSelectorWindow::IOSelectorWindow (Session& sess, boost::shared_ptr<IO> ior, bool input, bool can_cancel)
: ArdourDialog ("i/o selector"),
_selector (sess, ior, input),
ok_button (can_cancel ? _("OK"): _("Close")),
string title;
if (input) {
- title = string_compose(_("%1 input"), ior.name());
+ title = string_compose(_("%1 input"), ior->name());
} else {
- title = string_compose(_("%1 output"), ior.name());
+ title = string_compose(_("%1 output"), ior->name());
}
ok_button.set_name ("IOSelectorButton");
The IO Selector "widget"
*************************/
-IOSelector::IOSelector (Session& sess, IO& ior, bool input)
+IOSelector::IOSelector (Session& sess, boost::shared_ptr<IO> ior, bool input)
: session (sess),
io (ior),
for_input (input),
port_button_box.pack_start (add_port_button, false, false);
+ // The IO selector only works for single typed IOs
+ const ARDOUR::DataType t = io->default_type();
+
if (for_input) {
- if (io.input_maximum() < 0 || io.input_maximum() > (int) io.n_inputs()) {
+ if (io->input_maximum().get(t) < 0 || io->input_maximum().get(t) > (size_t) io->n_inputs().get(t)) {
add_port_button.set_sensitive (true);
} else {
add_port_button.set_sensitive (false);
}
} else {
- if (io.output_maximum() < 0 || io.output_maximum() > (int) io.n_outputs()) {
+ if (io->output_maximum().get(t) < 0 || io->output_maximum().get(t) > (size_t) io->n_outputs().get(t)) {
add_port_button.set_sensitive (true);
} else {
add_port_button.set_sensitive (false);
port_button_box.pack_start (remove_port_button, false, false);
if (for_input) {
- if (io.input_minimum() < 0 || io.input_minimum() < (int) io.n_inputs()) {
+ if (io->input_minimum().get(t) < 0 || io->input_minimum().get(t) < (size_t) io->n_inputs().get(t)) {
remove_port_button.set_sensitive (true);
} else {
remove_port_button.set_sensitive (false);
}
} else {
- if (io.output_minimum() < 0 || io.output_minimum() < (int) io.n_outputs()) {
+ if (io->output_minimum().get(t) < 0 || io->output_minimum().get(t) < (size_t) io->n_outputs().get(t)) {
remove_port_button.set_sensitive (true);
} else {
remove_port_button.set_sensitive (false);
remove_port_button.signal_clicked().connect (mem_fun(*this, &IOSelector::remove_port));
if (for_input) {
- io.input_changed.connect (mem_fun(*this, &IOSelector::ports_changed));
+ io->input_changed.connect (mem_fun(*this, &IOSelector::ports_changed));
} else {
- io.output_changed.connect (mem_fun(*this, &IOSelector::ports_changed));
+ io->output_changed.connect (mem_fun(*this, &IOSelector::ports_changed));
}
- io.name_changed.connect (mem_fun(*this, &IOSelector::name_changed));
+ io->name_changed.connect (mem_fun(*this, &IOSelector::name_changed));
}
IOSelector::~IOSelector ()
{
}
+void
+IOSelector::set_button_sensitivity ()
+{
+ DataType t = io->default_type();
+
+ if (for_input) {
+
+ if (io->input_maximum().get(t) < 0 || io->input_maximum().get(t) > io->n_inputs().get(t)) {
+ add_port_button.set_sensitive (true);
+ } else {
+ add_port_button.set_sensitive (false);
+ }
+
+ } else {
+
+ if (io->output_maximum().get(t) < 0 || io->output_maximum().get(t) > io->n_outputs().get(t)) {
+ add_port_button.set_sensitive (true);
+ } else {
+ add_port_button.set_sensitive (false);
+ }
+
+ }
+
+ if (for_input) {
+ if (io->n_inputs().get(t) && (io->input_minimum().get(t) < 0 || io->input_minimum().get(t) < io->n_inputs().get(t))) {
+ remove_port_button.set_sensitive (true);
+ } else {
+ remove_port_button.set_sensitive (false);
+ }
+
+ } else {
+ if (io->n_outputs().get(t) && (io->output_minimum().get(t) < 0 || io->output_minimum().get(t) < io->n_outputs().get(t))) {
+ remove_port_button.set_sensitive (true);
+ } else {
+ remove_port_button.set_sensitive (false);
+ }
+ }
+}
+
+
void
IOSelector::name_changed (void* src)
{
IOSelector::clear_connections ()
{
if (for_input) {
- io.disconnect_inputs (this);
+ io->disconnect_inputs (this);
} else {
- io.disconnect_outputs (this);
+ io->disconnect_outputs (this);
}
}
gint current_page;
vector<string> rowdata;
+ page_selection_connection.disconnect ();
+
current_page = notebook.get_current_page ();
+
pages.clear ();
/* get relevant current JACK ports */
- ports = session.engine().get_ports ("", JACK_DEFAULT_AUDIO_TYPE, for_input ? JackPortIsOutput : JackPortIsInput);
+ ports = session.engine().get_ports ("", io->default_type().to_jack_type(), for_input ? JackPortIsOutput : JackPortIsInput);
if (ports == 0) {
return;
row[port_display_columns.full_name] = s->second;
}
- //display->get_selection()->signal_changed().connect (bind (mem_fun(*this, &IOSelector::port_selection_changed), display));
display->signal_button_release_event().connect (bind (mem_fun(*this, &IOSelector::port_selection_changed), display));
Label *tab_label = manage (new Label);
}
notebook.set_current_page (current_page);
- //notebook.signal_show().connect (bind (mem_fun (notebook, &Notebook::set_current_page), current_page));
+ page_selection_connection = notebook.signal_show().connect (bind (mem_fun (notebook, &Notebook::set_current_page), current_page));
selector_box.show_all ();
}
{
TreeView *firsttview = 0;
TreeView *selected_port_tview = 0;
-
{
Glib::Mutex::Lock lm (port_display_lock);
Port *port;
uint32_t limit;
+
+ // The IO selector only works for single typed IOs
+ const ARDOUR::DataType t = io->default_type();
if (for_input) {
- limit = io.n_inputs();
+ limit = io->n_inputs().get(t);
} else {
- limit = io.n_outputs();
+ limit = io->n_outputs().get(t);
}
-
- for (slist<TreeView *>::iterator i = port_displays.begin(); i != port_displays.end(); ) {
+ for (slist<TreeView *>::iterator i = port_displays.begin(); i != port_displays.end(); ) {
+
slist<TreeView *>::iterator tmp;
-
+
tmp = i;
++tmp;
-
+
port_box.remove (**i);
delete *i;
port_displays.erase (i);
-
+
i = tmp;
}
-
-
+
for (uint32_t n = 0; n < limit; ++n) {
TreeView* tview;
string really_short_name;
if (for_input) {
- port = io.input (n);
+ port = io->input (n);
} else {
- port = io.output (n);
+ port = io->output (n);
}
/* we know there is '/' because we put it there */
-
+
really_short_name = port->short_name();
really_short_name = really_short_name.substr (really_short_name.find ('/') + 1);
tview = manage (new TreeView());
RefPtr<ListStore> port_model = ListStore::create (port_display_columns);
-
+
if (!firsttview) {
firsttview = tview;
}
tview->set_model (port_model);
tview->append_column (really_short_name, port_display_columns.displayed_name);
tview->get_selection()->set_mode (SELECTION_SINGLE);
- tview->set_data ("port", port);
+ tview->set_data (X_("port"), port);
tview->set_headers_visible (true);
- tview->set_name ("IOSelectorPortList");
+ tview->set_name (X_("IOSelectorPortList"));
port_box.pack_start (*tview);
port_displays.insert (port_displays.end(), tview);
/* now fill the clist with the current connections */
-
const char **connections = port->get_connections ();
-
+
if (connections) {
for (uint32_t c = 0; connections[c]; ++c) {
TreeModel::Row row = *(port_model->append());
row[port_display_columns.displayed_name] = connections[c];
row[port_display_columns.full_name] = connections[c];
}
- }
+ }
if (for_input) {
- if (io.input_maximum() == 1) {
+ if (io->input_maximum().get(io->default_type()) == 1) {
selected_port = port;
selected_port_tview = tview;
} else {
selected_port_tview = tview;
}
}
-
+
} else {
-
- if (io.output_maximum() == 1) {
+
+ if (io->output_maximum().get(t) == 1) {
selected_port = port;
selected_port_tview = tview;
} else {
}
}
}
-
+
TreeViewColumn* col = tview->get_column (0);
col->set_clickable (true);
-
- /* handle button events on the column header and within the treeview itself */
+
+ /* handle button events on the column header ... */
col->signal_clicked().connect (bind (mem_fun(*this, &IOSelector::select_treeview), tview));
+
+ /* ... and within the treeview itself */
tview->signal_button_release_event().connect (bind (mem_fun(*this, &IOSelector::connection_button_release), tview));
}
-
+
port_box.show_all ();
-
- if (selected_port_tview) {
- // GTK2FIX
- // selected_port_tview->click_column(0);
- selected_port_tview->set_name ("IOSelectorPortListSelected");
- for (slist<TreeView *>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) {
- if (*i != selected_port_tview) {
- (*i)->set_name ("IOSelectorPortList");
- (*i)->queue_draw ();
- }
- }
- } else {
- selected_port = 0;
- selector_box.hide_all ();
- }
}
+ if (!selected_port_tview) {
+ selected_port_tview = firsttview;
+ }
+
if (selected_port_tview) {
select_treeview (selected_port_tview);
- } else if (firsttview) {
- // select first
- select_treeview (firsttview);
}
}
ustring other_port_name = (*i)[port_display_columns.full_name];
if (for_input) {
- if ((status = io.connect_input (selected_port, other_port_name, this)) == 0) {
+ if ((status = io->connect_input (selected_port, other_port_name, this)) == 0) {
Port *p = session.engine().get_port_by_name (other_port_name);
- p->enable_metering();
+ if (p) {
+ p->enable_metering();
+ }
}
} else {
- status = io.connect_output (selected_port, other_port_name, this);
+ status = io->connect_output (selected_port, other_port_name, this);
}
if (status == 0) {
{
/* add a new port, then hide the button if we're up to the maximum allowed */
+ // The IO selector only works for single typed IOs
+ const ARDOUR::DataType t = io->default_type();
+
if (for_input) {
try {
- io.add_input_port ("", this);
+ io->add_input_port ("", this);
}
catch (AudioEngine::PortRegistrationFailure& err) {
msg.run ();
}
- if (io.input_maximum() >= 0 && io.input_maximum() <= (int) io.n_inputs()) {
- add_port_button.set_sensitive (false);
- }
-
- if (io.input_minimum() < (int) io.n_inputs()) {
- remove_port_button.set_sensitive (true);
- }
-
} else {
try {
- io.add_output_port ("", this);
+ io->add_output_port ("", this);
}
catch (AudioEngine::PortRegistrationFailure& err) {
MessageDialog msg (0, _("There are no more JACK ports available."));
msg.run ();
}
-
- if (io.output_maximum() >= 0 && io.output_maximum() <= (int) io.n_outputs()) {
- add_port_button.set_sensitive (false);
- }
}
+
+ set_button_sensitivity ();
}
void
{
uint32_t nports;
+ // The IO selector only works for single typed IOs
+ const ARDOUR::DataType t = io->default_type();
+
// always remove last port
if (for_input) {
- if ((nports = io.n_inputs()) > 0) {
- io.remove_input_port (io.input(nports-1), this);
- }
- if (io.input_minimum() == (int) io.n_inputs()) {
- remove_port_button.set_sensitive (false);
+ if ((nports = io->n_inputs().get(t)) > 0) {
+ io->remove_input_port (io->input(nports-1), this);
}
} else {
- if ((nports = io.n_outputs()) > 0) {
- io.remove_output_port (io.output(nports-1), this);
+ if ((nports = io->n_outputs().get(t)) > 0) {
+ io->remove_output_port (io->output(nports-1), this);
}
}
-}
-
-gint
-IOSelector::remove_port_when_idle (Port *port)
-{
- if (for_input) {
- io.remove_input_port (port, this);
- } else {
- io.remove_output_port (port, this);
- }
-
- return FALSE;
+
+ set_button_sensitivity ();
}
gint
return false;
}
- if (!(Keyboard::is_delete_event (ev))) {
- //return false;
- }
-
if (!treeview->get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) {
return false;
}
- cerr << "path = " << path.to_string() << endl;
-
+
if ((iter = treeview->get_model()->get_iter (path.to_string()))) {
/* path is valid */
ustring connected_port_name = (*iter)[port_display_columns.full_name];
- Port *port = reinterpret_cast<Port *> (treeview->get_data (_("port")));
+ Port *port = reinterpret_cast<Port *> (treeview->get_data (X_("port")));
if (for_input) {
Port *p = session.engine().get_port_by_name (connected_port_name);
- p->disable_metering();
- io.disconnect_input (port, connected_port_name, this);
+ if (p) {
+ p->disable_metering();
+ }
+ io->disconnect_input (port, connected_port_name, this);
} else {
- io.disconnect_output (port, connected_port_name, this);
+ io->disconnect_output (port, connected_port_name, this);
}
}
return true;
}
-gint
-IOSelector::port_column_button_release (GdkEventButton* event, TreeView* treeview)
-{
- /* this handles button release on the button at the top of a single-column
- treeview (representing a port)
- */
- cerr << "IOSelector::port_column_button_release() called" << endl;
-
- if (Keyboard::is_delete_event (event)) {
- Port* port;
- {
- Glib::Mutex::Lock lm (port_display_lock);
-
- port = static_cast<Port *> (treeview->get_data (_("port")));
-
- if (port == selected_port) {
- selected_port = 0;
- treeview->set_name ("IOSelectorPortList");
- treeview->queue_draw();
- }
- }
-
- /* remove the port when idle - if we do it here, we will destroy the widget
- for whom we are handling an event. not good.
- */
-
- signal_idle().connect (bind (mem_fun(*this, &IOSelector::remove_port_when_idle), port));
-
- } else {
- select_treeview (treeview);
- }
-
- return TRUE;
-}
-
void
IOSelector::select_next_treeview ()
{
slist<TreeView*>::iterator next;
+ if (port_displays.empty() || port_displays.size() == 1) {
+ return;
+ }
+
for (slist<TreeView *>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) {
if ((*i)->get_name() == "IOSelectorPortListSelected") {
*/
Glib::Mutex::Lock lm (port_display_lock);
- Port* port = reinterpret_cast<Port *> (tview->get_data (_("port")));
+ Port* port = reinterpret_cast<Port *> (tview->get_data (X_("port")));
+
+ selected_port = port;
+
+ tview->set_name ("IOSelectorPortListSelected");
+ tview->queue_draw ();
+
+ /* ugly hack to force the column header button to change as well */
+
+ TreeViewColumn* col = tview->get_column (0);
+ GtkTreeViewColumn* ccol = col->gobj();
- if (port != selected_port) {
- selected_port = port;
+ if (ccol->button) {
+ gtk_widget_set_name (ccol->button, "IOSelectorPortListSelected");
+ gtk_widget_queue_draw (ccol->button);
+ }
+
+ for (slist<TreeView*>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) {
+ if (*i == tview) {
+ continue;
+ }
- tview->set_name ("IOSelectorPortListSelected");
+ col = (*i)->get_column (0);
+ ccol = col->gobj();
- for (slist<TreeView*>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) {
- if (*i != tview) {
- (*i)->set_name ("IOSelectorPortList");
- (*i)->queue_draw ();
- }
+ if (ccol->button) {
+ gtk_widget_set_name (ccol->button, "IOSelectorPortList");
+ gtk_widget_queue_draw (ccol->button);
}
- selector_box.show_all ();
+
+ (*i)->set_name ("IOSelectorPortList");
+ (*i)->queue_draw ();
}
+
+ selector_box.show_all ();
}
void
display_ports ();
if (for_input) {
- if (io.input_maximum() != 0) {
+ if (io->input_maximum().get(io->default_type()) != 0) {
rescan ();
}
} else {
- if (io.output_maximum() != 0) {
+ if (io->output_maximum().get(io->default_type()) != 0) {
rescan();
}
}
}
-PortInsertUI::PortInsertUI (Session& sess, PortInsert& pi)
+PortInsertUI::PortInsertUI (Session& sess, boost::shared_ptr<PortInsert> pi)
: input_selector (sess, pi, true),
output_selector (sess, pi, false)
{
}
-PortInsertWindow::PortInsertWindow (Session& sess, PortInsert& pi, bool can_cancel)
+PortInsertWindow::PortInsertWindow (Session& sess, boost::shared_ptr<PortInsert> pi, bool can_cancel)
: ArdourDialog ("port insert dialog"),
- _portinsertui(sess, pi),
+ _portinsertui (sess, pi),
ok_button (can_cancel ? _("OK"): _("Close")),
cancel_button (_("Cancel")),
rescan_button (_("Rescan"))
set_name ("IOSelectorWindow");
string title = _("ardour: ");
- title += pi.name();
+ title += pi->name();
set_title (title);
ok_button.set_name ("IOSelectorButton");
rescan_button.signal_clicked().connect (mem_fun(*this, &PortInsertWindow::rescan));
signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), reinterpret_cast<Window *> (this)));
- pi.GoingAway.connect (mem_fun(*this, &PortInsertWindow::plugin_going_away));
+
+ going_away_connection = pi->GoingAway.connect (mem_fun(*this, &PortInsertWindow::plugin_going_away));
}
void
-PortInsertWindow::plugin_going_away (ARDOUR::Redirect* ignored)
+PortInsertWindow::plugin_going_away ()
{
- ENSURE_GUI_THREAD(bind (mem_fun(*this, &PortInsertWindow::plugin_going_away), ignored));
-
+ ENSURE_GUI_THREAD(mem_fun(*this, &PortInsertWindow::plugin_going_away));
+ going_away_connection.disconnect ();
delete_when_idle (this);
}