some deep tweaking to get MIDI channel control into nearly done shape for 3.1

This commit is contained in:
Paul Davis 2013-03-28 17:10:57 -04:00
parent 613678233a
commit f1ce235b6b
4 changed files with 475 additions and 184 deletions

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2008 Paul Davis
Author: Hans Baier
Copyright (C) 2008-2013 Paul Davis
Original Author: Hans Baier
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -30,6 +30,7 @@
#include "gtkmm2ext/gtk_ui.h"
#include "gtkmm2ext/gui_thread.h"
#include "gtkmm2ext/utils.h"
#include "ardour/midi_track.h"
@ -326,16 +327,25 @@ MidiMultipleChannelSelector::invert_selection(void)
/*-----------------------------------------*/
MidiChannelSelectorWindow::MidiChannelSelectorWindow (boost::shared_ptr<MidiTrack> mt)
: ArdourWindow (string_compose (_("MIDI Channel Control for %1"), mt->name()))
: ArdourWindow (_("MIDI Channel Control"))
, track (mt)
, playback_all_button (playback_button_group, _("Playback all channels"))
, playback_filter_button (playback_button_group, _("Play only selected channels"))
, playback_force_button (playback_button_group, _("Use a single fixed channel for all playback"))
, capture_all_button (capture_button_group, _("Record all channels"))
, capture_filter_button (capture_button_group, _("Record only selected channels"))
, capture_force_button (capture_button_group, _("Force all channels to 1 channel"))
, last_drawn_capture_mode (AllChannels)
, last_drawn_playback_mode (AllChannels)
{
build ();
playback_mask_changed ();
playback_mode_changed ();
capture_mask_changed ();
capture_mode_changed ();
playback_mask_changed ();
capture_mask_changed ();
track->PlaybackChannelMaskChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::playback_mask_changed, this), gui_context());
track->PlaybackChannelModeChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::playback_mode_changed, this), gui_context());
track->CaptureChannelMaskChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::capture_mask_changed, this), gui_context());
@ -350,122 +360,93 @@ void
MidiChannelSelectorWindow::build ()
{
VBox* vpacker;
HBox* capture_mask;
HBox* capture_mask_controls;
HBox* playback_mask;
HBox* playback_mask_controls;
HBox* capture_controls;
HBox* playback_controls;
Button* b;
ToggleButton* tb;
Label* l;
vpacker = manage (new VBox);
vpacker->set_spacing (6);
vpacker->set_border_width (12);
l = manage (new Label (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Capture"))));
l = manage (new Label (string_compose (("<span size=\"larger\" weight=\"bold\">%1: %2</span>"), _("MIDI Channel Control"), track->name())));
l->set_use_markup (true);
l->set_alignment (0.5, 0.0);
vpacker->pack_start (*l, true, true);
l = manage (new Label (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Inbound"))));
l->set_use_markup (true);
vpacker->pack_start (*l);
{
RadioButtonGroup group;
capture_all_button = manage (new RadioButton (group, "Record all channels"));
vpacker->pack_start (*capture_all_button);
capture_all_button->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), AllChannels));
vpacker->pack_start (capture_all_button);
capture_all_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), AllChannels));
vpacker->pack_start (capture_filter_button);
capture_filter_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), FilterChannels));
vpacker->pack_start (capture_force_button);
capture_force_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), ForceChannel));
capture_filter_button = manage (new RadioButton (group, "Record only selected channels"));
vpacker->pack_start (*capture_filter_button);
capture_filter_button->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), FilterChannels));
capture_force_button = manage (new RadioButton (group, "Force all channels to a single fixed channel"));
vpacker->pack_start (*capture_force_button);
capture_force_button->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), ForceChannel));
}
capture_mask = manage (new HBox);
for (uint32_t n = 0; n < 16; ++n) {
char buf[3];
snprintf (buf, sizeof (buf), "%d", n+1);
tb = manage (new ToggleButton (buf));
Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to toggle recording of channel %1"), n+1));
capture_buttons.push_back (tb);
tb->set_name (X_("MidiChannelSelectorButton"));
capture_mask->pack_start (*tb);
tb->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_channel_clicked), n));
}
vpacker->pack_start (*capture_mask);
capture_mask_controls = manage (new HBox);
capture_mask_controls->set_spacing (6);
vpacker->pack_start (capture_mask_box);
capture_controls = manage (new HBox);
capture_controls->set_spacing (6);
b = manage (new Button (_("All")));
Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to enable recording all channels"));
capture_mask_controls->pack_start (*b);
capture_controls->pack_start (*b);
capture_mask_controls.push_back (b);
b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::fill_capture_mask));
b = manage (new Button (_("None")));
Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to disable recording all channels"));
capture_mask_controls->pack_start (*b);
capture_controls->pack_start (*b);
capture_mask_controls.push_back (b);
b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::zero_capture_mask));
b = manage (new Button (_("Invert")));
Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to invert currently selected recording channels"));
capture_mask_controls->pack_start (*b);
capture_controls->pack_start (*b);
capture_mask_controls.push_back (b);
b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::invert_capture_mask));
vpacker->pack_start (*capture_mask_controls);
playback_mask = manage (new HBox);
vpacker->pack_start (*capture_controls);
l = manage (new Label (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Playback"))));
l->set_use_markup (true);
vpacker->pack_start (*l);
{
RadioButtonGroup group;
vpacker->pack_start (playback_all_button);
playback_all_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), AllChannels));
vpacker->pack_start (playback_filter_button);
playback_filter_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), FilterChannels));
vpacker->pack_start (playback_force_button);
playback_force_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), ForceChannel));
playback_all_button = manage (new RadioButton (group, "Playback all channels"));
vpacker->pack_start (*playback_all_button);
playback_all_button->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), AllChannels));
vpacker->pack_start (playback_mask_box);
playback_filter_button = manage (new RadioButton (group, "Play only selected channels"));
vpacker->pack_start (*playback_filter_button);
playback_filter_button->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), FilterChannels));
playback_force_button = manage (new RadioButton (group, "Use a single fixed channel for all playback"));
vpacker->pack_start (*playback_force_button);
playback_force_button->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), ForceChannel));
}
for (uint32_t n = 0; n < 16; ++n) {
char buf[3];
snprintf (buf, sizeof (buf), "%d", n+1);
tb = manage (new ToggleButton (buf));
tb->set_name (X_("MidiChannelSelectorButton"));
playback_buttons.push_back (tb);
playback_mask->pack_start (*tb);
tb->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_channel_clicked), n));
}
vpacker->pack_start (*playback_mask);
playback_mask_controls = manage (new HBox);
playback_mask_controls->set_spacing (6);
playback_controls = manage (new HBox);
playback_controls->set_spacing (6);
b = manage (new Button (_("All")));
Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to enable playback of all channels"));
playback_mask_controls->pack_start (*b);
playback_controls->pack_start (*b);
playback_mask_controls.push_back (b);
b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::fill_playback_mask));
b = manage (new Button (_("None")));
Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to disable playback of all channels"));
playback_mask_controls->pack_start (*b);
playback_controls->pack_start (*b);
playback_mask_controls.push_back (b);
b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::zero_playback_mask));
b = manage (new Button (_("Invert")));
Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to invert current selected playback channels"));
playback_mask_controls->pack_start (*b);
playback_controls->pack_start (*b);
playback_mask_controls.push_back (b);
b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::invert_playback_mask));
vpacker->pack_start (*playback_mask_controls);
vpacker->pack_start (*playback_controls);
add (*vpacker);
}
@ -473,52 +454,94 @@ MidiChannelSelectorWindow::build ()
void
MidiChannelSelectorWindow::fill_playback_mask ()
{
track->set_playback_channel_mask (0xffff);
if (track->get_playback_channel_mode() == FilterChannels) {
track->set_playback_channel_mask (0xffff);
}
}
void
MidiChannelSelectorWindow::zero_playback_mask ()
{
track->set_playback_channel_mask (0);
if (track->get_playback_channel_mode() == FilterChannels) {
track->set_playback_channel_mask (0);
}
}
void
MidiChannelSelectorWindow::invert_playback_mask ()
{
track->set_playback_channel_mask (~track->get_playback_channel_mask());
if (track->get_playback_channel_mode() == FilterChannels) {
track->set_playback_channel_mask (~track->get_playback_channel_mask());
}
}
void
MidiChannelSelectorWindow::fill_capture_mask ()
{
track->set_capture_channel_mask (0xffff);
if (track->get_capture_channel_mode() == FilterChannels) {
track->set_capture_channel_mask (0xffff);
}
}
void
MidiChannelSelectorWindow::zero_capture_mask ()
{
track->set_capture_channel_mask (0);
if (track->get_capture_channel_mode() == FilterChannels) {
track->set_capture_channel_mask (0);
}
}
void
MidiChannelSelectorWindow::invert_capture_mask ()
{
track->set_capture_channel_mask (~track->get_capture_channel_mask());
if (track->get_capture_channel_mode() == FilterChannels) {
track->set_capture_channel_mask (~track->get_capture_channel_mask());
}
}
void
MidiChannelSelectorWindow::set_playback_selected_channels (uint16_t mask)
{
for (uint16_t i = 0; i < 16; i++) {
playback_buttons[i]->set_active ((1<<i) & mask);
switch (track->get_playback_channel_mode()) {
case AllChannels:
/* they are insensitive, so we don't care */
break;
case FilterChannels:
for (uint16_t i = 0; i < 16; i++) {
playback_buttons[i]->set_active ((1<<i) & mask);
}
break;
case ForceChannel:
/* only set the lowest set channel in the mask as active */
for (uint16_t i = 0; i < 16; i++) {
playback_buttons[i]->set_active (i == (ffs (mask) - 1));
}
break;
}
}
void
MidiChannelSelectorWindow::set_capture_selected_channels (uint16_t mask)
{
for (uint16_t i = 0; i < 16; i++) {
capture_buttons[i]->set_active ((1<<i) & mask);
switch (track->get_capture_channel_mode()) {
case AllChannels:
/* they are insensitive, so we don't care */
break;
case FilterChannels:
for (uint16_t i = 0; i < 16; i++) {
capture_buttons[i]->set_active ((1<<i) & mask);
}
break;
case ForceChannel:
/* only set the lowest set channel in the mask as active */
for (uint16_t i = 0; i < 16; i++) {
capture_buttons[i]->set_active (i == (ffs (mask) - 1));
}
break;
}
}
@ -537,42 +560,217 @@ MidiChannelSelectorWindow::capture_mask_changed ()
void
MidiChannelSelectorWindow::playback_mode_changed ()
{
switch (track->get_playback_channel_mode()) {
uint32_t first_channel = 0;
ChannelMode mode = track->get_playback_channel_mode();
switch (mode) {
case AllChannels:
playback_all_button->set_active ();
if (last_drawn_playback_mode == ForceChannel) {
/* force mode used radio buttons. not what we want,
* though one could argue that we want no buttons
* at since they are insensitive
*/
playback_buttons.clear ();
}
for (vector<Widget*>::iterator i = playback_mask_controls.begin(); i != playback_mask_controls.end(); ++i) {
(*i)->set_sensitive (false);
}
playback_all_button.set_active ();
break;
case FilterChannels:
playback_filter_button->set_active ();
if (last_drawn_playback_mode == ForceChannel) {
playback_buttons.clear ();
} else if (last_drawn_playback_mode == AllChannels) {
for (vector<ToggleButton*>::iterator i = playback_buttons.begin(); i != playback_buttons.end(); ++i) {
(*i)->set_sensitive (true);
}
}
for (vector<Widget*>::iterator i = playback_mask_controls.begin(); i != playback_mask_controls.end(); ++i) {
(*i)->set_sensitive (true);
}
playback_filter_button.set_active ();
break;
case ForceChannel:
playback_force_button->set_active ();
if (last_drawn_playback_mode == AllChannels || last_drawn_playback_mode == FilterChannels) {
playback_buttons.clear ();
first_channel = ffs (track->get_playback_channel_mask()) - 1;
}
for (vector<Widget*>::iterator i = playback_mask_controls.begin(); i != playback_mask_controls.end(); ++i) {
(*i)->set_sensitive (false);
}
playback_force_button.set_active ();
break;
}
if (playback_buttons.empty()) {
Gtkmm2ext::container_clear (playback_mask_box);
ToggleButton* tb;
RadioButtonGroup group;
for (uint32_t n = 0; n < 16; ++n) {
char buf[3];
snprintf (buf, sizeof (buf), "%d", n+1);
switch (mode) {
case AllChannels:
case FilterChannels:
tb = manage (new ToggleButton (buf));
Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to toggle playback of channel %1"), n+1));
break;
case ForceChannel:
tb = manage (new RadioButton (group, buf));
tb->property_draw_indicator() = false;
if (n == first_channel) {
tb->set_active (true);
}
Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to force all MIDI channel messages to channel %1"), n+1));
break;
}
playback_buttons.push_back (tb);
tb->set_name (X_("MidiChannelSelectorButton"));
playback_mask_box.pack_start (*tb);
tb->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_channel_clicked), n));
tb->show ();
if (mode == AllChannels) {
tb->set_sensitive (false);
}
}
if (mode != ForceChannel) {
set_playback_selected_channels (track->get_playback_channel_mask());
}
}
if (mode == AllChannels) {
for (vector<ToggleButton*>::iterator i = playback_buttons.begin(); i != playback_buttons.end(); ++i) {
(*i)->set_sensitive (false);
}
}
last_drawn_playback_mode = mode;
}
void
MidiChannelSelectorWindow::capture_mode_changed ()
{
switch (track->get_capture_channel_mode()) {
uint32_t first_channel = 0;
ChannelMode mode = track->get_capture_channel_mode();
switch (mode) {
case AllChannels:
capture_all_button->set_active ();
if (last_drawn_capture_mode == ForceChannel) {
/* force mode used radio buttons. not what we want,
* though one could argue that we want no buttons
* at since they are insensitive
*/
capture_buttons.clear ();
}
for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
(*i)->set_sensitive (false);
}
capture_all_button.set_active ();
break;
case FilterChannels:
capture_filter_button->set_active ();
if (last_drawn_capture_mode == ForceChannel) {
capture_buttons.clear ();
} else if (last_drawn_capture_mode == AllChannels) {
for (vector<ToggleButton*>::iterator i = capture_buttons.begin(); i != capture_buttons.end(); ++i) {
(*i)->set_sensitive (true);
}
}
for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
(*i)->set_sensitive (true);
}
capture_filter_button.set_active ();
break;
case ForceChannel:
capture_force_button->set_active ();
if (last_drawn_capture_mode == AllChannels || last_drawn_capture_mode == FilterChannels) {
capture_buttons.clear ();
first_channel = ffs (track->get_capture_channel_mask()) - 1;
}
for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
(*i)->set_sensitive (false);
}
capture_force_button.set_active ();
break;
}
if (capture_buttons.empty()) {
Gtkmm2ext::container_clear (capture_mask_box);
ToggleButton* tb;
RadioButtonGroup group;
for (uint32_t n = 0; n < 16; ++n) {
char buf[3];
snprintf (buf, sizeof (buf), "%d", n+1);
switch (mode) {
case AllChannels:
case FilterChannels:
tb = manage (new ToggleButton (buf));
Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to toggle recording of channel %1"), n+1));
break;
case ForceChannel:
tb = manage (new RadioButton (group, buf));
tb->property_draw_indicator() = false;
if (n == first_channel) {
tb->set_active (true);
}
Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to force all recorded channels to %1"), n+1));
break;
}
capture_buttons.push_back (tb);
tb->set_name (X_("MidiChannelSelectorButton"));
capture_mask_box.pack_start (*tb);
tb->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_channel_clicked), n));
tb->show ();
if (mode == AllChannels) {
tb->set_sensitive (false);
}
}
if (mode != ForceChannel) {
set_capture_selected_channels (track->get_capture_channel_mask());
}
}
if (mode == AllChannels) {
for (vector<ToggleButton*>::iterator i = capture_buttons.begin(); i != capture_buttons.end(); ++i) {
(*i)->set_sensitive (false);
}
}
last_drawn_capture_mode = mode;
}
void
MidiChannelSelectorWindow::playback_channel_clicked (uint16_t n)
{
if (playback_buttons[n]->get_active()) {
track->set_playback_channel_mask (track->get_playback_channel_mask() | (1<<n));
switch (track->get_playback_channel_mode()) {
case AllChannels:
break;
case FilterChannels:
track->set_playback_channel_mask (track->get_playback_channel_mask() | (1<<n));
break;
case ForceChannel:
track->set_playback_channel_mask (1<<n);
break;
}
} else {
track->set_playback_channel_mask (track->get_playback_channel_mask() & ~(1<<n));
if (track->get_playback_channel_mode() == FilterChannels) {
track->set_playback_channel_mask (track->get_playback_channel_mask() & ~(1<<n));
}
}
}
@ -580,9 +778,20 @@ void
MidiChannelSelectorWindow::capture_channel_clicked (uint16_t n)
{
if (capture_buttons[n]->get_active()) {
track->set_capture_channel_mask (track->get_capture_channel_mask() | (1<<n));
switch (track->get_capture_channel_mode()) {
case AllChannels:
break;
case FilterChannels:
track->set_capture_channel_mask (track->get_capture_channel_mask() | (1<<n));
break;
case ForceChannel:
track->set_capture_channel_mask (1<<n);
break;
}
} else {
track->set_capture_channel_mask (track->get_capture_channel_mask() & ~(1<<n));
if (track->get_capture_channel_mode() == FilterChannels) {
track->set_capture_channel_mask (track->get_capture_channel_mask() & ~(1<<n));
}
}
}
@ -593,27 +802,25 @@ MidiChannelSelectorWindow::capture_mode_toggled (ChannelMode mode)
is for the button/mode that has been turned off, and the second is for the
button/mode that has been turned on.
so we have to check the button state to know what to do.
so we take action only if the button is active (i.e it is the one
just clicked on)
*/
switch (mode) {
case AllChannels:
if (!capture_all_button->get_active()) {
return;
if (capture_all_button.get_active()) {
track->set_capture_channel_mode (AllChannels, track->get_capture_channel_mask());
}
track->set_capture_channel_mode (AllChannels, track->get_capture_channel_mask());
break;
case FilterChannels:
if (!capture_filter_button->get_active()) {
return;
if (capture_filter_button.get_active()) {
track->set_capture_channel_mode (FilterChannels, track->get_capture_channel_mask());
}
track->set_capture_channel_mode (FilterChannels, track->get_capture_channel_mask());
break;
case ForceChannel:
if (!capture_force_button->get_active()) {
return;
if (capture_force_button.get_active()) {
track->set_capture_channel_mode (ForceChannel, track->get_capture_channel_mask());
}
track->set_capture_channel_mode (ForceChannel, track->get_capture_channel_mask());
break;
}
}
@ -625,27 +832,25 @@ MidiChannelSelectorWindow::playback_mode_toggled (ChannelMode mode)
is for the button/mode that has been turned off, and the second is for the
button/mode that has been turned on.
so we have to check the button state to know what to do.
so we take action only if the button is active (i.e it is the one
just clicked on)
*/
switch (mode) {
case AllChannels:
if (!playback_all_button->get_active()) {
return;
if (playback_all_button.get_active()) {
track->set_playback_channel_mode (AllChannels, track->get_playback_channel_mask());
}
track->set_playback_channel_mode (AllChannels, track->get_playback_channel_mask());
break;
case FilterChannels:
if (!playback_filter_button->get_active()) {
return;
if (playback_filter_button.get_active()) {
track->set_playback_channel_mode (FilterChannels, track->get_playback_channel_mask());
}
track->set_playback_channel_mode (FilterChannels, track->get_playback_channel_mask());
break;
case ForceChannel:
if (!playback_force_button->get_active()) {
return;
if (playback_force_button.get_active()) {
track->set_playback_channel_mode (ForceChannel, track->get_playback_channel_mask());
}
track->set_playback_channel_mode (ForceChannel, track->get_playback_channel_mask());
break;
}
}

View File

@ -40,79 +40,79 @@ namespace ARDOUR {
class MidiChannelSelector : public Gtk::Table
{
public:
MidiChannelSelector(int n_rows = 4, int n_columns = 4, int start_row = 0, int start_column = 0);
virtual ~MidiChannelSelector() = 0;
public:
MidiChannelSelector(int n_rows = 4, int n_columns = 4, int start_row = 0, int start_column = 0);
virtual ~MidiChannelSelector() = 0;
sigc::signal<void> clicked;
sigc::signal<void> clicked;
void set_channel_colors(const uint32_t new_channel_colors[16]);
void set_default_channel_color();
void set_channel_colors(const uint32_t new_channel_colors[16]);
void set_default_channel_color();
protected:
virtual void button_toggled(Gtk::ToggleButton* button, uint8_t button_nr) = 0;
Gtk::Label _button_labels[4][4];
Gtkmm2ext::StatefulToggleButton _buttons[4][4];
int _recursion_counter;
protected:
virtual void button_toggled(Gtk::ToggleButton* button, uint8_t button_nr) = 0;
Gtk::Label _button_labels[4][4];
Gtkmm2ext::StatefulToggleButton _buttons[4][4];
int _recursion_counter;
bool was_clicked (GdkEventButton*);
bool was_clicked (GdkEventButton*);
};
class SingleMidiChannelSelector : public MidiChannelSelector
{
public:
SingleMidiChannelSelector(uint8_t active_channel = 0);
public:
SingleMidiChannelSelector(uint8_t active_channel = 0);
uint8_t get_active_channel() const { return _active_channel; }
uint8_t get_active_channel() const { return _active_channel; }
sigc::signal<void, uint8_t> channel_selected;
sigc::signal<void, uint8_t> channel_selected;
protected:
virtual void button_toggled(Gtk::ToggleButton* button, uint8_t button_nr);
protected:
virtual void button_toggled(Gtk::ToggleButton* button, uint8_t button_nr);
Gtk::ToggleButton* _last_active_button;
uint8_t _active_channel;
Gtk::ToggleButton* _last_active_button;
uint8_t _active_channel;
};
class MidiMultipleChannelSelector : public MidiChannelSelector
{
public:
MidiMultipleChannelSelector(ARDOUR::ChannelMode mode = ARDOUR::FilterChannels,
uint16_t initial_selection = 0xFFFF);
public:
MidiMultipleChannelSelector(ARDOUR::ChannelMode mode = ARDOUR::FilterChannels,
uint16_t initial_selection = 0xFFFF);
virtual ~MidiMultipleChannelSelector();
virtual ~MidiMultipleChannelSelector();
/** The channel mode or selected channel(s) has changed.
* First parameter is the new channel mode, second parameter is a bitmask
* of the currently selected channels.
*/
sigc::signal<void, ARDOUR::ChannelMode, uint16_t> mode_changed;
/** The channel mode or selected channel(s) has changed.
* First parameter is the new channel mode, second parameter is a bitmask
* of the currently selected channels.
*/
sigc::signal<void, ARDOUR::ChannelMode, uint16_t> mode_changed;
void set_channel_mode(ARDOUR::ChannelMode mode, uint16_t mask);
ARDOUR::ChannelMode get_channel_mode () const { return _channel_mode; }
void set_channel_mode(ARDOUR::ChannelMode mode, uint16_t mask);
ARDOUR::ChannelMode get_channel_mode () const { return _channel_mode; }
/**
* @return each bit in the returned word represents a midi channel, eg.
* bit 0 represents channel 0 and bit 15 represents channel 15
*
*/
uint16_t get_selected_channels() const;
void set_selected_channels(uint16_t selected_channels);
/**
* @return each bit in the returned word represents a midi channel, eg.
* bit 0 represents channel 0 and bit 15 represents channel 15
*
*/
uint16_t get_selected_channels() const;
void set_selected_channels(uint16_t selected_channels);
protected:
ARDOUR::ChannelMode _channel_mode;
ARDOUR::NoteMode _note_mode;
protected:
ARDOUR::ChannelMode _channel_mode;
ARDOUR::NoteMode _note_mode;
virtual void button_toggled(Gtk::ToggleButton* button, uint8_t button_nr);
void force_channels_button_toggled();
virtual void button_toggled(Gtk::ToggleButton* button, uint8_t button_nr);
void force_channels_button_toggled();
void select_all(bool on);
void invert_selection(void);
void select_all(bool on);
void invert_selection(void);
Gtk::Button _select_all;
Gtk::Button _select_none;
Gtk::Button _invert_selection;
Gtk::ToggleButton _force_channel;
Gtk::Button _select_all;
Gtk::Button _select_none;
Gtk::Button _invert_selection;
Gtk::ToggleButton _force_channel;
};
class MidiChannelSelectorWindow : public ArdourWindow, public PBD::ScopedConnectionList
@ -129,12 +129,22 @@ class MidiChannelSelectorWindow : public ArdourWindow, public PBD::ScopedConnect
std::vector<Gtk::ToggleButton*> playback_buttons;
std::vector<Gtk::ToggleButton*> capture_buttons;
Gtk::ToggleButton* playback_all_button;
Gtk::ToggleButton* playback_filter_button;
Gtk::ToggleButton* playback_force_button;
Gtk::ToggleButton* capture_all_button;
Gtk::ToggleButton* capture_filter_button;
Gtk::ToggleButton* capture_force_button;
std::vector<Gtk::Widget*> playback_mask_controls;
std::vector<Gtk::Widget*> capture_mask_controls;
Gtk::HBox capture_mask_box;
Gtk::HBox playback_mask_box;
Gtk::RadioButtonGroup playback_button_group;
Gtk::RadioButton playback_all_button;
Gtk::RadioButton playback_filter_button;
Gtk::RadioButton playback_force_button;
Gtk::RadioButtonGroup capture_button_group;
Gtk::RadioButton capture_all_button;
Gtk::RadioButton capture_filter_button;
Gtk::RadioButton capture_force_button;
ARDOUR::ChannelMode last_drawn_capture_mode;
ARDOUR::ChannelMode last_drawn_playback_mode;
void build();
void set_capture_selected_channels (uint16_t);

View File

@ -19,6 +19,8 @@
#include <cstdlib>
#include <cmath>
#include <strings.h> // for ffs(3)
#include <algorithm>
#include <string>
#include <vector>
@ -95,7 +97,7 @@ using namespace Gtkmm2ext;
using namespace Editing;
// Minimum height at which a control is displayed
static const uint32_t MIDI_CONTROLS_BOX_MIN_HEIGHT = 130;
static const uint32_t MIDI_CONTROLS_BOX_MIN_HEIGHT = 140;
static const uint32_t KEYBOARD_MIN_HEIGHT = 130;
MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session* sess, Canvas& canvas)
@ -212,6 +214,22 @@ MidiTimeAxisView::set_route (boost::shared_ptr<Route> rt)
_view->RegionViewAdded.connect (
sigc::mem_fun(*this, &MidiTimeAxisView::region_view_added));
midi_track()->PlaybackChannelModeChanged.connect (*this, invalidator (*this),
boost::bind (&MidiTimeAxisView::playback_channel_mode_changed, this),
gui_context());
midi_track()->PlaybackChannelMaskChanged.connect (*this, invalidator (*this),
boost::bind (&MidiTimeAxisView::playback_channel_mode_changed, this),
gui_context());
midi_track()->CaptureChannelModeChanged.connect (*this, invalidator (*this),
boost::bind (&MidiTimeAxisView::capture_channel_mode_changed, this),
gui_context());
midi_track()->CaptureChannelMaskChanged.connect (*this, invalidator (*this),
boost::bind (&MidiTimeAxisView::capture_channel_mode_changed, this),
gui_context());
playback_channel_mode_changed ();
capture_channel_mode_changed ();
if (!_editor.have_idled()) {
/* first idle will do what we need */
} else {
@ -247,19 +265,37 @@ MidiTimeAxisView::set_route (boost::shared_ptr<Route> rt)
_midi_controls_box.set_homogeneous(false);
_midi_controls_box.set_border_width (10);
_channel_status_box.set_homogeneous (false);
_channel_status_box.set_spacing (6);
_channel_selector_button.set_label (_("Chns"));
/* fixed sized labels to prevent silly nonsense */
_playback_channel_status.set_size_request (65, -1);
_capture_channel_status.set_size_request (60, -1);
_channel_status_box.pack_start (_playback_channel_status, false, false);
_channel_status_box.pack_start (_capture_channel_status, false, false);
_channel_status_box.pack_start (_channel_selector_button, false, false);
_channel_status_box.show_all ();
_channel_selector_button.signal_clicked().connect (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_channel_selector));
_midi_controls_box.pack_start (_channel_status_box, false, false, 10);
if (!patch_manager.all_models().empty()) {
_midi_controls_box.resize(2, 2);
_midnam_model_selector.set_size_request(22, 30);
_midnam_model_selector.set_border_width(2);
_midnam_model_selector.show ();
_midi_controls_box.attach(_midnam_model_selector, 0, 1, 0, 1);
_midi_controls_box.pack_start (_midnam_model_selector);
_midnam_custom_device_mode_selector.set_size_request(10, 30);
_midnam_custom_device_mode_selector.set_border_width(2);
_midnam_custom_device_mode_selector.show ();
_midi_controls_box.attach(_midnam_custom_device_mode_selector, 0, 1, 1, 2);
_midi_controls_box.pack_start (_midnam_custom_device_mode_selector);
}
model_changed();
@ -478,6 +514,7 @@ MidiTimeAxisView::toggle_channel_selector ()
_channel_selector->set_default_channel_color ();
}
_channel_selector->set_position (WIN_POS_MOUSE);
_channel_selector->show_all ();
} else {
_channel_selector->cycle_visibility ();
@ -1440,3 +1477,35 @@ MidiTimeAxisView::contents_height_changed ()
{
_range_scroomer->set_size_request (-1, _view->child_height ());
}
void
MidiTimeAxisView::playback_channel_mode_changed ()
{
switch (midi_track()->get_playback_channel_mode()) {
case AllChannels:
_playback_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2</i>", _("Play"), ("all")));
break;
case FilterChannels:
_playback_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2</i>", _("Play"), ("some")));
break;
case ForceChannel:
_playback_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2>%3</i>", _("Play"), ("all"), ffs (midi_track()->get_playback_channel_mask())));
break;
}
}
void
MidiTimeAxisView::capture_channel_mode_changed ()
{
switch (midi_track()->get_capture_channel_mode()) {
case AllChannels:
_capture_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2</i>", _("Rec"), ("all")));
break;
case FilterChannels:
_capture_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2</i>", _("Rec"), ("some")));
break;
case ForceChannel:
_capture_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2>%3</i>", _("Rec"), ("all"), ffs (midi_track()->get_capture_channel_mask())));
break;
}
}

View File

@ -134,7 +134,11 @@ class MidiTimeAxisView : public RouteTimeAxisView
Gtk::RadioMenuItem* _meter_color_mode_item;
Gtk::RadioMenuItem* _channel_color_mode_item;
Gtk::RadioMenuItem* _track_color_mode_item;
Gtk::Table _midi_controls_box;
Gtk::Label _playback_channel_status;
Gtk::Label _capture_channel_status;
Gtk::HBox _channel_status_box;
Gtk::Button _channel_selector_button;
Gtk::VBox _midi_controls_box;
MidiChannelSelectorWindow* _channel_selector;
Gtk::ComboBoxText _midnam_model_selector;
Gtk::ComboBoxText _midnam_custom_device_mode_selector;
@ -172,6 +176,9 @@ class MidiTimeAxisView : public RouteTimeAxisView
ParameterMenuMap _controller_menu_map;
StepEditor* _step_editor;
void capture_channel_mode_changed();
void playback_channel_mode_changed();
};
#endif /* __ardour_midi_time_axis_h__ */