X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fmidi_channel_selector.cc;h=c889602b8c849fb9e2d858f0bdbdece59c1c89f8;hb=fcbb78b010a53686d1c350864d731a73bd204956;hp=0018c169ab62ebd30a3802a58a33a0272432aca4;hpb=8d44391f4ba571c4dbcec0a87033c83414f515e8;p=ardour.git diff --git a/gtk2_ardour/midi_channel_selector.cc b/gtk2_ardour/midi_channel_selector.cc index 0018c169ab..c889602b8c 100644 --- a/gtk2_ardour/midi_channel_selector.cc +++ b/gtk2_ardour/midi_channel_selector.cc @@ -1,34 +1,55 @@ +/* + Copyright (C) 2008 Paul Davis + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include #include "midi_channel_selector.h" #include "gtkmm/separator.h" #include "i18n.h" -#include +#include "rgb_macros.h" using namespace std; using namespace Gtk; -using namespace sigc; - -MidiChannelSelector::MidiChannelSelector(int no_rows, int no_columns, int start_row, int start_column) : - Table(no_rows, no_columns, true), _recursion_counter(0) -{ - assert(no_rows >= 4); - assert(no_rows >= start_row + 4); - assert(no_columns >=4); - assert(no_columns >= start_column + 4); - +using namespace ARDOUR; + +MidiChannelSelector::MidiChannelSelector(int n_rows, int n_columns, int start_row, int start_column) + : Table(n_rows, n_columns, true) + , _recursion_counter(0) +{ + assert(n_rows >= 4); + assert(n_rows >= start_row + 4); + assert(n_columns >=4); + assert(n_columns >= start_column + 4); + property_column_spacing() = 0; property_row_spacing() = 0; - + uint8_t channel_nr = 0; - for(int row = 0; row < 4; ++row) { - for(int column = 0; column < 4; ++column) { + for (int row = 0; row < 4; ++row) { + for (int column = 0; column < 4; ++column) { ostringstream channel; channel << int(++channel_nr); _button_labels[row][column].set_text(channel.str()); _button_labels[row][column].set_justify(JUSTIFY_RIGHT); _buttons[row][column].add(_button_labels[row][column]); _buttons[row][column].signal_toggled().connect( - bind( - mem_fun(this, &MidiChannelSelector::button_toggled), + sigc::bind( + sigc::mem_fun(this, &MidiChannelSelector::button_toggled), &_buttons[row][column], channel_nr - 1)); @@ -43,25 +64,51 @@ MidiChannelSelector::~MidiChannelSelector() { } +void +MidiChannelSelector::set_channel_colors(const uint32_t new_channel_colors[16]) +{ + for (int row = 0; row < 4; ++row) { + for (int column = 0; column < 4; ++column) { + char color_normal[8]; + char color_active[8]; + snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[row * 4 + column], 0x000000ff, 0.6)); + snprintf(color_active, 8, "#%x", new_channel_colors[row * 4 + column]); + _buttons[row][column].modify_bg(STATE_NORMAL, Gdk::Color(color_normal)); + _buttons[row][column].modify_bg(STATE_ACTIVE, Gdk::Color(color_active)); + } + } +} + +void +MidiChannelSelector::set_default_channel_color() +{ + for (int row = 0; row < 4; ++row) { + for (int column = 0; column < 4; ++column) { + _buttons[row][column].unset_bg(STATE_NORMAL); + _buttons[row][column].unset_bg(STATE_ACTIVE); + } + } +} + SingleMidiChannelSelector::SingleMidiChannelSelector(uint8_t active_channel) : MidiChannelSelector() { _last_active_button = 0; - ToggleButton *button = &_buttons[active_channel / 4][active_channel % 4]; + ToggleButton* button = &_buttons[active_channel / 4][active_channel % 4]; _active_channel = active_channel; button->set_active(true); _last_active_button = button; } void -SingleMidiChannelSelector::button_toggled(ToggleButton *button, uint8_t channel) -{ +SingleMidiChannelSelector::button_toggled(ToggleButton* button, uint8_t channel) +{ ++_recursion_counter; - if(_recursion_counter == 1) { - // if the current button is active it must + if (_recursion_counter == 1) { + // if the current button is active it must // be different from the first one - if(button->get_active()) { - if(_last_active_button) { + if (button->get_active()) { + if (_last_active_button) { _last_active_button->set_active(false); _active_channel = channel; _last_active_button = button; @@ -76,24 +123,25 @@ SingleMidiChannelSelector::button_toggled(ToggleButton *button, uint8_t channel) --_recursion_counter; } -MidiMultipleChannelSelector::MidiMultipleChannelSelector(uint16_t initial_selection, int8_t force_channel) - : MidiChannelSelector(4, 6, 0, 0), _mode(FILTERING_MULTIPLE_CHANNELS) +MidiMultipleChannelSelector::MidiMultipleChannelSelector(ChannelMode mode, uint16_t mask) + : MidiChannelSelector(4, 6, 0, 0) + , _channel_mode(mode) { _select_all.add(*manage(new Label(_("All")))); _select_all.signal_clicked().connect( - bind(mem_fun(this, &MidiMultipleChannelSelector::select_all), true)); - + sigc::bind(sigc::mem_fun(this, &MidiMultipleChannelSelector::select_all), true)); + _select_none.add(*manage(new Label(_("None")))); _select_none.signal_clicked().connect( - bind(mem_fun(this, &MidiMultipleChannelSelector::select_all), false)); - + sigc::bind(sigc::mem_fun(this, &MidiMultipleChannelSelector::select_all), false)); + _invert_selection.add(*manage(new Label(_("Invert")))); _invert_selection.signal_clicked().connect( - mem_fun(this, &MidiMultipleChannelSelector::invert_selection)); - + sigc::mem_fun(this, &MidiMultipleChannelSelector::invert_selection)); + _force_channel.add(*manage(new Label(_("Force")))); _force_channel.signal_toggled().connect( - mem_fun(this, &MidiMultipleChannelSelector::force_channels_button_toggled)); + sigc::mem_fun(this, &MidiMultipleChannelSelector::force_channels_button_toggled)); set_homogeneous(false); attach(*manage(new VSeparator()), 4, 5, 0, 4, SHRINK, FILL, 0, 0); @@ -102,72 +150,56 @@ MidiMultipleChannelSelector::MidiMultipleChannelSelector(uint16_t initial_select attach(_select_none, 5, 6, 1, 2); attach(_invert_selection, 5, 6, 2, 3); attach(_force_channel, 5, 6, 3, 4); - - set_selected_channels(initial_selection); + + set_selected_channels(mask); } MidiMultipleChannelSelector::~MidiMultipleChannelSelector() { - selection_changed.clear(); - force_channel_changed.clear(); + mode_changed.clear(); } -const int8_t -MidiMultipleChannelSelector::get_force_channel() const +void +MidiMultipleChannelSelector::set_channel_mode(ChannelMode mode, uint16_t mask) { - if(_mode == FORCING_SINGLE_CHANNEL) { - for(int8_t i = 0; i < 16; i++) { - const ToggleButton *button = &_buttons[i / 4][i % 4]; - if(button->get_active()) { - return i; - } + switch (mode) { + case AllChannels: + _force_channel.set_active(false); + set_selected_channels(0xFFFF); + break; + case FilterChannels: + _force_channel.set_active(false); + set_selected_channels(mask); + break; + case ForceChannel: + _force_channel.set_active(true); + for (uint16_t i = 0; i < 16; i++) { + ToggleButton* button = &_buttons[i / 4][i % 4]; + button->set_active(i == mask); } - - // this point should not be reached. - assert(false); - } - - return -1; -} - -void -MidiMultipleChannelSelector::set_force_channel(int8_t channel) -{ - if(channel < 0) { - // if forcing is already activated, deactivate - if(_mode == FORCING_SINGLE_CHANNEL) { - _force_channel.toggled(); - } - // if not, nothing to do - } else { - // otherwise simulate activating force channels by pressing the - // two buttons the user would press - _force_channel.toggled(); - _buttons[channel / 4][channel % 4].toggled(); } } - -const uint16_t -MidiMultipleChannelSelector::get_selected_channels() const -{ +uint16_t +MidiMultipleChannelSelector::get_selected_channels() const +{ uint16_t selected_channels = 0; - for(uint16_t i = 0; i < 16; i++) { - const ToggleButton *button = &_buttons[i / 4][i % 4]; - if(button->get_active()) { + for (uint16_t i = 0; i < 16; i++) { + const ToggleButton* button = &_buttons[i / 4][i % 4]; + if (button->get_active()) { selected_channels |= (1L << i); - } + } } - - return selected_channels; + + return selected_channels; } -void +void MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels) { - for(uint16_t i = 0; i < 16; i++) { - ToggleButton *button = &_buttons[i / 4][i % 4]; - if(selected_channels & (1L << i)) { + for (uint16_t i = 0; i < 16; i++) { + ToggleButton* button = &_buttons[i / 4][i % 4]; + if (selected_channels & (1L << i)) { button->set_active(true); } else { button->set_active(false); @@ -176,84 +208,90 @@ MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels) } void -MidiMultipleChannelSelector::button_toggled(ToggleButton *button, uint8_t channel) +MidiMultipleChannelSelector::button_toggled(ToggleButton */*button*/, uint8_t channel) { ++_recursion_counter; - if(_recursion_counter == 1) { - if(_mode == FORCING_SINGLE_CHANNEL) { + if (_recursion_counter == 1) { + if (_channel_mode == ForceChannel) { + mode_changed.emit(_channel_mode, channel); set_selected_channels(1 << channel); + } else { + mode_changed.emit(_channel_mode, get_selected_channels()); } - - force_channel_changed.emit(get_force_channel()); - selection_changed.emit(get_selected_channels()); } --_recursion_counter; } -void +void MidiMultipleChannelSelector::force_channels_button_toggled() { - if(_force_channel.get_active()) { - _mode = FORCING_SINGLE_CHANNEL; + if (_force_channel.get_active()) { + _channel_mode = ForceChannel; bool found_first_active = false; // leave only the first button enabled - for(int i = 0; i <= 15; i++) { - ToggleButton *button = &_buttons[i / 4][i % 4]; - if(button->get_active()) { - if(found_first_active) { + uint16_t active_channel = 0; + for (int i = 0; i <= 15; i++) { + ToggleButton* button = &_buttons[i / 4][i % 4]; + if (button->get_active()) { + if (found_first_active) { ++_recursion_counter; button->set_active(false); --_recursion_counter; } else { found_first_active = true; + active_channel = i; } - } + } } - - if(!found_first_active) { + + if (!found_first_active) { _buttons[0][0].set_active(true); } - + _select_all.set_sensitive(false); _select_none.set_sensitive(false); _invert_selection.set_sensitive(false); - force_channel_changed.emit(get_force_channel()); - selection_changed.emit(get_selected_channels()); + mode_changed.emit(_channel_mode, active_channel); } else { - _mode = FILTERING_MULTIPLE_CHANNELS; + _channel_mode = FilterChannels; _select_all.set_sensitive(true); _select_none.set_sensitive(true); _invert_selection.set_sensitive(true); - force_channel_changed.emit(get_force_channel()); - selection_changed.emit(get_selected_channels()); + mode_changed.emit(FilterChannels, get_selected_channels()); } } -void +void MidiMultipleChannelSelector::select_all(bool on) { + if (_channel_mode == ForceChannel) + return; + ++_recursion_counter; - for(uint16_t i = 0; i < 16; i++) { - ToggleButton *button = &_buttons[i / 4][i % 4]; + for (uint16_t i = 0; i < 16; i++) { + ToggleButton* button = &_buttons[i / 4][i % 4]; button->set_active(on); } --_recursion_counter; - selection_changed.emit(get_selected_channels()); + mode_changed.emit(_channel_mode, get_selected_channels()); } -void +void MidiMultipleChannelSelector::invert_selection(void) { + if (_channel_mode == ForceChannel) + return; + ++_recursion_counter; - for(uint16_t i = 0; i < 16; i++) { - ToggleButton *button = &_buttons[i / 4][i % 4]; - if(button->get_active()) { + for (uint16_t i = 0; i < 16; i++) { + ToggleButton* button = &_buttons[i / 4][i % 4]; + if (button->get_active()) { button->set_active(false); } else { button->set_active(true); } } --_recursion_counter; - selection_changed.emit(get_selected_channels()); + mode_changed.emit(_channel_mode, get_selected_channels()); }