#include <ardour/sndfilesource.h>
#include <ardour/crossfade.h>
#include <midi++/manager.h>
+#include <midi++/factory.h>
+#include <midi++/port_request.h>
#include <gtkmm2ext/stop_signal.h>
#include <gtkmm2ext/utils.h>
#include <gtkmm2ext/window_title.h>
#include "utils.h"
#include "editing.h"
#include "option_editor.h"
+#include "midi_port_dialog.h"
#include "i18n.h"
/* MIDI */
- mmc_device_id_adjustment (0.0, 0.0, (double) 0x7f, 1.0, 16.0),
- mmc_device_id_spinner (mmc_device_id_adjustment),
+ mmc_receive_device_id_adjustment (0.0, 0.0, (double) 0x7f, 1.0, 16.0),
+ mmc_receive_device_id_spinner (mmc_receive_device_id_adjustment),
+ mmc_send_device_id_adjustment (0.0, 0.0, (double) 0x7f, 1.0, 16.0),
+ mmc_send_device_id_spinner (mmc_send_device_id_adjustment),
/* Click */
}
}
-
void
OptionEditor::setup_midi_options ()
{
HBox* hbox;
+ Label* label;
+
+ midi_port_table.set_row_spacings (6);
+ midi_port_table.set_col_spacings (10);
+
+ redisplay_midi_ports ();
+
+ mmc_receive_device_id_adjustment.signal_value_changed().connect (mem_fun (*this, &OptionEditor::mmc_receive_device_id_adjusted));
+ mmc_send_device_id_adjustment.signal_value_changed().connect (mem_fun (*this, &OptionEditor::mmc_send_device_id_adjusted));
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (6);
+ hbox->pack_start (midi_port_table, true, false);
+
+ midi_packer.pack_start (*hbox, false, false);
+ midi_packer.pack_start (add_midi_port_button, false, false);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (6);
+ hbox->set_spacing (6);
+ label = (manage (new Label (_("Inbound MMC Device ID"))));
+ hbox->pack_start (mmc_receive_device_id_spinner, false, false);
+ hbox->pack_start (*label, false, false);
+ midi_packer.pack_start (*hbox, false, false);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (6);
+ hbox->set_spacing (6);
+ label = (manage (new Label (_("Outbound MMC Device ID"))));
+ hbox->pack_start (mmc_send_device_id_spinner, false, false);
+ hbox->pack_start (*label, false, false);
+ midi_packer.pack_start (*hbox, false, false);
+
+ add_midi_port_button.signal_clicked().connect (mem_fun (*this, &OptionEditor::add_midi_port));
+}
+
+void
+OptionEditor::redisplay_midi_ports ()
+{
MIDI::Manager::PortMap::const_iterator i;
const MIDI::Manager::PortMap& ports = MIDI::Manager::instance()->get_midi_ports();
int n;
- ToggleButton* tb;
- RadioButton* rb;
- Gtk::Table* table = manage (new Table (ports.size() + 4, 10));
+ /* remove all existing widgets */
- table->set_row_spacings (6);
- table->set_col_spacings (10);
+ // XXX broken in gtkmm 2.10
+ // midi_port_table.clear ();
- table->attach (*(manage (new Label (_("Port")))), 0, 1, 0, 1);
- table->attach (*(manage (new Label (_("Offline")))), 1, 2, 0, 1);
- table->attach (*(manage (new Label (_("Trace\nInput")))), 2, 3, 0, 1);
- table->attach (*(manage (new Label (_("Trace\nOutput")))), 3, 4, 0, 1);
- table->attach (*(manage (new Label (_("MTC")))), 4, 5, 0, 1);
- table->attach (*(manage (new Label (_("MMC")))), 6, 7, 0, 1);
- table->attach (*(manage (new Label (_("MIDI Parameter\nControl")))), 8, 9, 0, 1);
+ for (vector<Widget*>::iterator w = midi_port_table_widgets.begin(); w != midi_port_table_widgets.end(); ++w) {
+ midi_port_table.remove (**w);
+ }
- table->attach (*(manage (new HSeparator())), 0, 9, 1, 2);
- table->attach (*(manage (new VSeparator())), 5, 6, 0, 8);
- table->attach (*(manage (new VSeparator())), 7, 8, 0, 8);
-
- table->attach (*(manage (new Label (_("MMC Device ID")))), 9, 10, 0, 1);
- table->attach (mmc_device_id_spinner, 9, 10, 1, 2);
-
- mmc_device_id_adjustment.signal_value_changed().connect (mem_fun (*this, &OptionEditor::mmc_device_id_adjusted));
+ midi_port_table_widgets.clear ();
- for (n = 0, i = ports.begin(); i != ports.end(); ++n, ++i) {
+ midi_port_table.resize (ports.size() + 4, 11);
+
+ Gtk::Label* label;
- pair<MIDI::Port*,vector<RadioButton*> > newpair;
+ label = (manage (new Label (_("Port"))));
+ label->show ();
+ midi_port_table_widgets.push_back (label);
+ midi_port_table.attach (*label, 0, 1, 0, 1);
+ label = (manage (new Label (_("Offline"))));
+ label->show ();
+ midi_port_table_widgets.push_back (label);
+ midi_port_table.attach (*label, 1, 2, 0, 1);
+ label = (manage (new Label (_("Trace\nInput"))));
+ label->show ();
+ midi_port_table_widgets.push_back (label);
+ midi_port_table.attach (*label, 2, 3, 0, 1);
+ label = (manage (new Label (_("Trace\nOutput"))));
+ label->show ();
+ midi_port_table_widgets.push_back (label);
+ midi_port_table.attach (*label, 3, 4, 0, 1);
+ label = (manage (new Label (_("MTC"))));
+ label->show ();
+ midi_port_table_widgets.push_back (label);
+ midi_port_table.attach (*label, 4, 5, 0, 1);
+ label = (manage (new Label (_("MMC"))));
+ label->show ();
+ midi_port_table_widgets.push_back (label);
+ midi_port_table.attach (*label, 6, 7, 0, 1);
+ label = (manage (new Label (_("MIDI Parameter\nControl"))));
+ label->show ();
+ midi_port_table_widgets.push_back (label);
+ midi_port_table.attach (*label, 8, 9, 0, 1);
+
+ Gtk::HSeparator* hsep = (manage (new HSeparator()));
+ hsep->show ();
+ midi_port_table_widgets.push_back (hsep);
+ midi_port_table.attach (*hsep, 0, 9, 1, 2);
+ Gtk::VSeparator* vsep = (manage (new VSeparator()));
+ vsep->show ();
+ midi_port_table_widgets.push_back (vsep);
+ midi_port_table.attach (*vsep, 5, 6, 0, 8);
+ vsep = (manage (new VSeparator()));
+ vsep->show ();
+ midi_port_table_widgets.push_back (vsep);
+ midi_port_table.attach (*vsep, 7, 8, 0, 8);
+
+ for (n = 0, i = ports.begin(); i != ports.end(); ++n, ++i) {
- newpair.first = i->second;
+ ToggleButton* tb;
+ RadioButton* rb;
+ Button* bb;
- table->attach (*(manage (new Label (i->first))), 0, 1, n+2, n+3,FILL|EXPAND, FILL );
+ /* the remove button. create early so we can pass it to various callbacks */
+
+ bb = manage (new Button (Stock::REMOVE));
+ bb->set_name ("OptionEditorToggleButton");
+ bb->show ();
+ midi_port_table_widgets.push_back (bb);
+ midi_port_table.attach (*bb, 9, 10, n+2, n+3, FILL|EXPAND, FILL);
+ bb->signal_clicked().connect (bind (mem_fun(*this, &OptionEditor::remove_midi_port), i->second));
+ bb->set_sensitive (port_removable (i->second));
+
+ label = (manage (new Label (i->first)));
+ label->show ();
+ midi_port_table_widgets.push_back (label);
+ midi_port_table.attach (*label, 0, 1, n+2, n+3,FILL|EXPAND, FILL );
+
tb = manage (new ToggleButton (_("online")));
tb->set_name ("OptionEditorToggleButton");
set_size_request_to_display_given_text (*tb, _("online"), 15, 12);
}
- tb->set_active (!(*i).second->input()->offline());
- tb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::port_online_toggled), (*i).second, tb));
- (*i).second->input()->OfflineStatusChanged.connect (bind (mem_fun(*this, &OptionEditor::map_port_online), (*i).second, tb));
- table->attach (*tb, 1, 2, n+2, n+3, FILL|EXPAND, FILL);
+ if (i->second->input()) {
+ tb->set_active (!i->second->input()->offline());
+ tb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::port_online_toggled), i->second, tb));
+ i->second->input()->OfflineStatusChanged.connect (bind (mem_fun(*this, &OptionEditor::map_port_online), (*i).second, tb));
+ }
+ tb->show ();
+ midi_port_table_widgets.push_back (tb);
+ midi_port_table.attach (*tb, 1, 2, n+2, n+3, FILL|EXPAND, FILL);
tb = manage (new ToggleButton ());
tb->set_name ("OptionEditorToggleButton");
tb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::port_trace_in_toggled), (*i).second, tb));
tb->set_size_request (10, 10);
- table->attach (*tb, 2, 3, n+2, n+3, FILL|EXPAND, FILL);
+ tb->show ();
+ midi_port_table_widgets.push_back (tb);
+ midi_port_table.attach (*tb, 2, 3, n+2, n+3, FILL|EXPAND, FILL);
tb = manage (new ToggleButton ());
tb->set_name ("OptionEditorToggleButton");
tb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::port_trace_out_toggled), (*i).second, tb));
tb->set_size_request (10, 10);
- table->attach (*tb, 3, 4, n+2, n+3, FILL|EXPAND, FILL);
+ tb->show ();
+ midi_port_table_widgets.push_back (tb);
+ midi_port_table.attach (*tb, 3, 4, n+2, n+3, FILL|EXPAND, FILL);
rb = manage (new RadioButton ());
- newpair.second.push_back (rb);
rb->set_name ("OptionEditorToggleButton");
if (n == 0) {
mtc_button_group = rb->get_group();
rb->set_group (mtc_button_group);
}
- table->attach (*rb, 4, 5, n+2, n+3, FILL|EXPAND, FILL);
- rb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::mtc_port_chosen), (*i).second, rb));
+ rb->show ();
+ midi_port_table_widgets.push_back (rb);
+ midi_port_table.attach (*rb, 4, 5, n+2, n+3, FILL|EXPAND, FILL);
+ rb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::mtc_port_chosen), (*i).second, rb, bb));
- if (Config->get_mtc_port_name() == i->first) {
+ if (session && i->second == session->mtc_port()) {
rb->set_active (true);
}
rb = manage (new RadioButton ());
- newpair.second.push_back (rb);
rb->set_name ("OptionEditorToggleButton");
if (n == 0) {
mmc_button_group = rb->get_group();
} else {
rb->set_group (mmc_button_group);
}
- table->attach (*rb, 6, 7, n+2, n+3, FILL|EXPAND, FILL);
- rb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::mmc_port_chosen), (*i).second, rb));
+ rb->show ();
+ midi_port_table_widgets.push_back (rb);
+ midi_port_table.attach (*rb, 6, 7, n+2, n+3, FILL|EXPAND, FILL);
+ rb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::mmc_port_chosen), (*i).second, rb, bb));
- if (Config->get_mmc_port_name() == i->first) {
+ if (session && i->second == session->mmc_port()) {
rb->set_active (true);
}
rb = manage (new RadioButton ());
- newpair.second.push_back (rb);
rb->set_name ("OptionEditorToggleButton");
if (n == 0) {
midi_button_group = rb->get_group();
} else {
rb->set_group (midi_button_group);
}
- table->attach (*rb, 8, 9, n+2, n+3, FILL|EXPAND, FILL);
- rb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::midi_port_chosen), (*i).second, rb));
+ rb->show ();
+ midi_port_table_widgets.push_back (rb);
+ midi_port_table.attach (*rb, 8, 9, n+2, n+3, FILL|EXPAND, FILL);
+ rb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::midi_port_chosen), (*i).second, rb, bb));
- if (Config->get_midi_port_name() == i->first) {
+ if (session && i->second == session->midi_port()) {
rb->set_active (true);
}
-
- port_toggle_buttons.insert (newpair);
+
}
- table->show_all ();
+ midi_port_table.show();
+}
- hbox = manage (new HBox);
- hbox->set_border_width (6);
- hbox->pack_start (*table, true, false);
- midi_packer.pack_start (*hbox, false, false);
+void
+OptionEditor::remove_midi_port (MIDI::Port* port)
+{
+ MIDI::Manager::instance()->remove_port (port);
+ redisplay_midi_ports ();
+}
+
+void
+OptionEditor::add_midi_port ()
+{
+ MidiPortDialog dialog;
+
+ dialog.set_position (WIN_POS_MOUSE);
+ dialog.set_transient_for (*this);
+
+ dialog.show ();
+
+ int ret = dialog.run ();
+
+ switch (ret) {
+ case RESPONSE_ACCEPT:
+ break;
+ default:
+ return;
+ break;
+ }
+
+ Glib::ustring mode = dialog.port_mode_combo.get_active_text();
+ std::string smod;
+
+ if (mode == _("input")) {
+ smod = X_("input");
+ } else if (mode == (_("output"))) {
+ smod = X_("output");
+ } else {
+ smod = "duplex";
+ }
+
+ MIDI::PortRequest req (X_("ardour"),
+ dialog.port_name.get_text(),
+ smod,
+ MIDI::PortFactory::default_port_type());
+
+ if (MIDI::Manager::instance()->add_port (req) != 0) {
+ redisplay_midi_ports ();
+ }
+}
+
+bool
+OptionEditor::port_removable (MIDI::Port *port)
+{
+ if (!session) {
+ return true;
+ }
+
+ if (port == session->mtc_port() ||
+ port == session->mmc_port() ||
+ port == session->midi_port()) {
+ return false;
+ }
+ return true;
}
void
-OptionEditor::mtc_port_chosen (MIDI::Port *port, Gtk::RadioButton* rb)
+OptionEditor::mtc_port_chosen (MIDI::Port *port, Gtk::RadioButton* rb, Gtk::Button* bb)
{
if (session) {
if (rb->get_active()) {
- if (port) {
- session->set_mtc_port (port->name());
- Config->set_mtc_port_name (port->name());
- } else {
- session->set_mtc_port ("");
- }
- rb->set_active (true);
+ session->set_mtc_port (port->name());
+ Config->set_mtc_port_name (port->name());
+ } else {
+ session->set_mtc_port ("");
}
+ bb->set_sensitive (port_removable (port));
}
}
void
-OptionEditor::mmc_port_chosen (MIDI::Port* port, Gtk::RadioButton* rb)
+OptionEditor::mmc_port_chosen (MIDI::Port* port, Gtk::RadioButton* rb, Gtk::Button* bb)
{
if (session) {
if (rb->get_active()) {
- if (port) {
- session->set_mmc_port (port->name());
- Config->set_mtc_port_name (port->name());
- } else {
- session->set_mmc_port ("");
- }
- rb->set_active (true);
+ session->set_mmc_port (port->name());
+ Config->set_mtc_port_name (port->name());
+ } else {
+ session->set_mmc_port ("");
}
+ bb->set_sensitive (port_removable (port));
}
}
void
-OptionEditor::midi_port_chosen (MIDI::Port* port, Gtk::RadioButton* rb)
+OptionEditor::midi_port_chosen (MIDI::Port* port, Gtk::RadioButton* rb, Gtk::Button* bb)
{
if (session) {
if (rb->get_active()) {
- if (port) {
- session->set_midi_port (port->name());
- Config->set_midi_port_name (port->name());
- } else {
- session->set_midi_port ("");
- }
- rb->set_active (true);
+ session->set_midi_port (port->name());
+ Config->set_midi_port_name (port->name());
+ } else {
+ session->set_midi_port ("");
}
+ bb->set_sensitive (port_removable (port));
}
}
}
void
-OptionEditor::mmc_device_id_adjusted ()
+OptionEditor::mmc_receive_device_id_adjusted ()
+{
+ uint8_t id = (uint8_t) mmc_receive_device_id_spinner.get_value();
+
+ if (id != Config->get_mmc_receive_device_id()) {
+ Config->set_mmc_receive_device_id (id);
+ }
+}
+
+void
+OptionEditor::mmc_send_device_id_adjusted ()
{
- uint8_t id = (uint8_t) mmc_device_id_spinner.get_value();
+ uint8_t id = (uint8_t) mmc_send_device_id_spinner.get_value();
- if (id != Config->get_mmc_device_id()) {
- Config->set_mmc_device_id (id);
+ if (id != Config->get_mmc_send_device_id()) {
+ Config->set_mmc_send_device_id (id);
}
}
int
Session::set_mtc_port (string port_tag)
{
-#if 0
- MIDI::byte old_device_id = 0;
- bool reset_id = false;
+ MTC_Slave *ms;
if (port_tag.length() == 0) {
- if (_mmc_port == 0) {
+
+ if (_slave && ((ms = dynamic_cast<MTC_Slave*> (_slave)) != 0)) {
+ error << _("Ardour is slaved to MTC - port cannot be reset") << endmsg;
+ return -1;
+ }
+
+ if (_mtc_port == 0) {
return 0;
}
- _mmc_port = 0;
+
+ _mtc_port = 0;
goto out;
}
MIDI::Port* port;
if ((port = MIDI::Manager::instance()->port (port_tag)) == 0) {
+ error << string_compose (_("unknown port %1 requested for MTC"), port_tag) << endl;
return -1;
}
- _mmc_port = port;
+ _mtc_port = port;
- if (mmc) {
- old_device_id = mmc->device_id();
- reset_id = true;
- delete mmc;
+ if (_slave && ((ms = dynamic_cast<MTC_Slave*> (_slave)) != 0)) {
+ ms->rebind (*port);
}
- mmc = new MIDI::MachineControl (*_mmc_port, 1.0,
- MMC_CommandSignature,
- MMC_ResponseSignature);
-
- if (reset_id) {
- mmc->set_device_id (old_device_id);
- }
-
- mmc->Play.connect
- (mem_fun (*this, &Session::mmc_deferred_play));
- mmc->DeferredPlay.connect
- (mem_fun (*this, &Session::mmc_deferred_play));
- mmc->Stop.connect
- (mem_fun (*this, &Session::mmc_stop));
- mmc->FastForward.connect
- (mem_fun (*this, &Session::mmc_fast_forward));
- mmc->Rewind.connect
- (mem_fun (*this, &Session::mmc_rewind));
- mmc->Pause.connect
- (mem_fun (*this, &Session::mmc_pause));
- mmc->RecordPause.connect
- (mem_fun (*this, &Session::mmc_record_pause));
- mmc->RecordStrobe.connect
- (mem_fun (*this, &Session::mmc_record_strobe));
- mmc->RecordExit.connect
- (mem_fun (*this, &Session::mmc_record_exit));
- mmc->Locate.connect
- (mem_fun (*this, &Session::mmc_locate));
- mmc->Step.connect
- (mem_fun (*this, &Session::mmc_step));
- mmc->Shuttle.connect
- (mem_fun (*this, &Session::mmc_shuttle));
- mmc->TrackRecordStatusChange.connect
- (mem_fun (*this, &Session::mmc_record_enable));
-
-
- /* also handle MIDI SPP because its so common */
-
- _mmc_port->input()->start.connect (mem_fun (*this, &Session::spp_start));
- _mmc_port->input()->contineu.connect (mem_fun (*this, &Session::spp_continue));
- _mmc_port->input()->stop.connect (mem_fun (*this, &Session::spp_stop));
-
- Config->set_mmc_port_name (port_tag);
+ Config->set_mtc_port_name (port_tag);
out:
- MMC_PortChanged(); /* EMIT SIGNAL */
+ MTC_PortChanged(); /* EMIT SIGNAL */
change_midi_ports ();
set_dirty();
-#endif
return 0;
}
void
-Session::set_mmc_device_id (uint32_t device_id)
+Session::set_mmc_receive_device_id (uint32_t device_id)
{
if (mmc) {
- mmc->set_device_id (device_id);
+ mmc->set_receive_device_id (device_id);
+ }
+}
+
+void
+Session::set_mmc_send_device_id (uint32_t device_id)
+{
+ if (mmc) {
+ mmc->set_send_device_id (device_id);
}
}
int
Session::set_mmc_port (string port_tag)
{
-#if 0
- MIDI::byte old_device_id = 0;
+ MIDI::byte old_recv_device_id = 0;
+ MIDI::byte old_send_device_id = 0;
bool reset_id = false;
if (port_tag.length() == 0) {
_mmc_port = port;
if (mmc) {
- old_device_id = mmc->device_id();
+ old_recv_device_id = mmc->receive_device_id();
+ old_recv_device_id = mmc->send_device_id();
reset_id = true;
delete mmc;
}
MMC_ResponseSignature);
if (reset_id) {
- mmc->set_device_id (old_device_id);
+ mmc->set_receive_device_id (old_recv_device_id);
+ mmc->set_send_device_id (old_send_device_id);
}
mmc->Play.connect
Config->set_mmc_port_name (port_tag);
out:
-#endif
MMC_PortChanged(); /* EMIT SIGNAL */
change_midi_ports ();
set_dirty();
mmc_buffer[0] = 0xf0; // SysEx
mmc_buffer[1] = 0x7f; // Real Time SysEx ID for MMC
- mmc_buffer[2] = 0x7f; // "broadcast" device ID
+ mmc_buffer[2] = mmc->send_device_id();
mmc_buffer[3] = 0x6; // MCC
/* Set up the qtr frame message */