tracks can now be muted
This commit is contained in:
parent
239e851cb7
commit
eaa740fb53
|
@ -74,6 +74,7 @@ void JSongWriter::collect(Json::Value &root, Loop &loop) {
|
|||
void JSongWriter::collect(Json::Value &root, Track &track) {
|
||||
root["midi_channel"] = track.midi_channel;
|
||||
root["midi_port"] = track.midi_port;
|
||||
root["mute"] = track.mute;
|
||||
}
|
||||
|
||||
void JSongWriter::collect(Json::Value &root, Model &model) {
|
||||
|
@ -218,6 +219,7 @@ void JSongReader::build(const Json::Value &root, Loop &loop) {
|
|||
void JSongReader::build(const Json::Value &root, Track &track) {
|
||||
extract(root["midi_channel"], track.midi_channel);
|
||||
extract(root["midi_port"], track.midi_port);
|
||||
extract(root["mute"], track.mute);
|
||||
}
|
||||
|
||||
void JSongReader::build(const Json::Value &root, Model &model) {
|
||||
|
|
13
main.cpp
13
main.cpp
|
@ -761,7 +761,18 @@ public:
|
|||
|
||||
builder->get_widget_derived("track_view", track_view);
|
||||
assert(track_view);
|
||||
track_view->set_model(model);
|
||||
track_view->set_model(model);
|
||||
track_view->signal_mute_toggled().connect(
|
||||
sigc::mem_fun(*this, &App::on_track_view_mute_toggled));
|
||||
|
||||
}
|
||||
|
||||
void on_track_view_mute_toggled(int index, bool mute) {
|
||||
if (!player)
|
||||
return;
|
||||
if (mute) {
|
||||
player->stop_events(index);
|
||||
}
|
||||
}
|
||||
|
||||
void init_timer() {
|
||||
|
|
|
@ -416,6 +416,7 @@ int Loop::get_end() const {
|
|||
Track::Track() {
|
||||
midi_port = 0;
|
||||
midi_channel = 0;
|
||||
mute = false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
|
|
@ -237,6 +237,7 @@ class Track {
|
|||
public:
|
||||
int midi_port;
|
||||
int midi_channel;
|
||||
bool mute;
|
||||
|
||||
Track();
|
||||
};
|
||||
|
|
40
player.cpp
40
player.cpp
|
@ -178,7 +178,7 @@ void Player::stop() {
|
|||
playing = false;
|
||||
seek(read_position);
|
||||
for (size_t bus = 0; bus < model->tracks.size(); ++bus) {
|
||||
rt_messages.all_notes_off(bus);
|
||||
rt_messages.all_notes_off(bus);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,6 +237,10 @@ void Player::play_event(int track, const class PatternEvent &event) {
|
|||
rt_messages.on_note(track, event.channel, note, ValueNone);
|
||||
}
|
||||
|
||||
void Player::stop_events(int track) {
|
||||
rt_messages.all_notes_off(track);
|
||||
}
|
||||
|
||||
void Player::mix_events(MessageQueue &queue, int samples) {
|
||||
assert(model);
|
||||
|
||||
|
@ -246,7 +250,7 @@ void Player::mix_events(MessageQueue &queue, int samples) {
|
|||
// send status package
|
||||
queue.status_msg();
|
||||
mix_frame(queue);
|
||||
long long framesize = get_frame_size();
|
||||
long long framesize = get_frame_size();
|
||||
queue.write_samples += framesize;
|
||||
queue.position++;
|
||||
if (model->enable_loop && (queue.position == model->loop.get_end())) {
|
||||
|
@ -273,25 +277,29 @@ void Player::mix_frame(MessageQueue &queue) {
|
|||
for (iter = events.begin(); iter != events.end(); ++iter) {
|
||||
Song::Event &event = (*iter)->second;
|
||||
Pattern &pattern = *event.pattern;
|
||||
|
||||
if (model->tracks[event.track].mute)
|
||||
continue; // ignore event
|
||||
|
||||
Pattern::iterator row_iter = pattern.begin();
|
||||
Pattern::Row row;
|
||||
pattern.collect_events(queue.position - event.frame, row_iter, row);
|
||||
|
||||
// first run: process all cc events
|
||||
for (int channel = 0; channel < pattern.get_channel_count(); ++channel) {
|
||||
int command = row.get_value(channel, ParamCommand);
|
||||
int ccindex = row.get_value(channel, ParamCCIndex);
|
||||
int ccvalue = row.get_value(channel, ParamCCValue);
|
||||
if (command != ValueNone) {
|
||||
int value = row.get_value(channel, ParamValue);
|
||||
if (command == Message::TypeCommandTempo) {
|
||||
if (value != ValueNone)
|
||||
model->beats_per_minute = std::max(1,value);
|
||||
} else {
|
||||
queue.on_command(event.track, channel, (Message::Type)command,
|
||||
value, ccindex, ccvalue);
|
||||
}
|
||||
}
|
||||
int command = row.get_value(channel, ParamCommand);
|
||||
int ccindex = row.get_value(channel, ParamCCIndex);
|
||||
int ccvalue = row.get_value(channel, ParamCCValue);
|
||||
if (command != ValueNone) {
|
||||
int value = row.get_value(channel, ParamValue);
|
||||
if (command == Message::TypeCommandTempo) {
|
||||
if (value != ValueNone)
|
||||
model->beats_per_minute = std::max(1,value);
|
||||
} else {
|
||||
queue.on_command(event.track, channel, (Message::Type)command,
|
||||
value, ccindex, ccvalue);
|
||||
}
|
||||
}
|
||||
queue.on_cc(event.track, ccindex, ccvalue);
|
||||
}
|
||||
|
||||
|
@ -299,7 +307,7 @@ void Player::mix_frame(MessageQueue &queue) {
|
|||
for (int channel = 0; channel < pattern.get_channel_count(); ++channel) {
|
||||
queue.on_note(event.track, channel,
|
||||
row.get_value(channel, ParamNote),
|
||||
row.get_value(channel, ParamVolume));
|
||||
row.get_value(channel, ParamVolume));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ public:
|
|||
bool is_playing() const;
|
||||
|
||||
void play_event(int track, const class PatternEvent &event);
|
||||
void stop_events(int track);
|
||||
|
||||
protected:
|
||||
void premix();
|
||||
|
|
|
@ -67,6 +67,12 @@ TrackBar::TrackBar(int index, TrackView &view) {
|
|||
port_eventbox.signal_button_press_event().connect(
|
||||
sigc::mem_fun(*this, &TrackBar::on_port_button_press_event));
|
||||
pack_start(port_eventbox, false, true);
|
||||
|
||||
mute.set_label("M");
|
||||
mute.signal_toggled().connect(
|
||||
sigc::mem_fun(*this, &TrackBar::on_mute_toggled));
|
||||
view.group_mutes->add_widget(mute);
|
||||
pack_start(mute, false, true);
|
||||
|
||||
update();
|
||||
|
||||
|
@ -80,6 +86,15 @@ TrackBar::~TrackBar() {
|
|||
view->remove(*this);
|
||||
}
|
||||
|
||||
void TrackBar::on_mute_toggled() {
|
||||
bool active = mute.get_active();
|
||||
if (model->tracks[index].mute == active)
|
||||
return;
|
||||
model->tracks[index].mute = active;
|
||||
update();
|
||||
view->_mute_toggled(index, active);
|
||||
}
|
||||
|
||||
void TrackBar::on_channel(int channel) {
|
||||
model->tracks[index].midi_channel = channel;
|
||||
update();
|
||||
|
@ -138,6 +153,8 @@ void TrackBar::update() {
|
|||
|
||||
sprintf(buffer, "port-%i", track.midi_port);
|
||||
port.set_text(buffer);
|
||||
|
||||
mute.set_active(track.mute);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -149,6 +166,7 @@ TrackView::TrackView(BaseObjectType* cobject,
|
|||
group_names = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_HORIZONTAL);
|
||||
group_channels = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_HORIZONTAL);
|
||||
group_ports = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_HORIZONTAL);
|
||||
group_mutes = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_HORIZONTAL);
|
||||
}
|
||||
|
||||
TrackView::~TrackView() {
|
||||
|
@ -163,6 +181,10 @@ void TrackView::destroy_bars() {
|
|||
|
||||
}
|
||||
|
||||
TrackView::type_mute_toggled TrackView::signal_mute_toggled() {
|
||||
return _mute_toggled;
|
||||
}
|
||||
|
||||
void TrackView::set_model(class Model &model) {
|
||||
this->model = &model;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ public:
|
|||
Gtk::Menu port_menu;
|
||||
Gtk::Label port;
|
||||
Gtk::RadioButtonGroup port_radio_group;
|
||||
Gtk::ToggleButton mute;
|
||||
|
||||
Model *model;
|
||||
class TrackView *view;
|
||||
|
@ -40,6 +41,7 @@ public:
|
|||
bool on_channel_button_press_event(GdkEventButton *event);
|
||||
bool on_port_button_press_event(GdkEventButton *event);
|
||||
bool on_name_button_press_event(GdkEventButton *event);
|
||||
void on_mute_toggled();
|
||||
|
||||
void on_channel(int channel);
|
||||
void on_port(int port);
|
||||
|
@ -48,8 +50,10 @@ public:
|
|||
//=============================================================================
|
||||
|
||||
class TrackView : public Gtk::VBox {
|
||||
friend class TrackBar;
|
||||
public:
|
||||
typedef std::vector<TrackBar *> TrackBarArray;
|
||||
typedef std::vector<TrackBar *> TrackBarArray;
|
||||
typedef sigc::signal<void, int, bool> type_mute_toggled;
|
||||
|
||||
TrackView(BaseObjectType* cobject,
|
||||
const Glib::RefPtr<Gtk::Builder>& builder);
|
||||
|
@ -58,6 +62,7 @@ public:
|
|||
Glib::RefPtr<Gtk::SizeGroup> group_names;
|
||||
Glib::RefPtr<Gtk::SizeGroup> group_channels;
|
||||
Glib::RefPtr<Gtk::SizeGroup> group_ports;
|
||||
Glib::RefPtr<Gtk::SizeGroup> group_mutes;
|
||||
|
||||
Model *model;
|
||||
TrackBarArray bars;
|
||||
|
@ -65,6 +70,11 @@ public:
|
|||
void destroy_bars();
|
||||
void set_model(class Model &model);
|
||||
void update_tracks();
|
||||
|
||||
type_mute_toggled signal_mute_toggled();
|
||||
|
||||
protected:
|
||||
type_mute_toggled _mute_toggled;
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
|
Loading…
Reference in New Issue