# Master speed lock is mapped to lock.
toggle_lock: { note_number: 25 }
locked: { note_number: 25 }
+locked_blinking: { note_number: 25 velocity: 2 }
optional MIDIButtonProto toggle_lock = 36;
optional int32 toggle_lock_bank = 37;
optional MIDILightProto locked = 38;
+ optional MIDILightProto locked_blinking = 39;
optional MIDIButtonProto cue_in = 27;
optional int32 cue_in_bank = 28;
connect(defer_timeout, &QTimer::timeout, this, &MainWindow::defer_timer_expired);
ui->undo_action->setEnabled(true);
+ lock_blink_timeout = new QTimer(this);
+ lock_blink_timeout->setSingleShot(true);
+ connect(lock_blink_timeout, &QTimer::timeout, this, &MainWindow::lock_blink_timer_expired);
+
connect(ui->clip_list->selectionModel(), &QItemSelectionModel::currentChanged,
this, &MainWindow::clip_list_selection_changed);
enable_or_disable_queue_button();
db.store_settings(settings);
}
+void MainWindow::lock_blink_timer_expired()
+{
+ midi_mapper.set_locked(MIDIMapper::LightState(ui->speed_lock_btn->isChecked())); // Presumably On, or the timer should have been canceled.
+}
+
void MainWindow::play_clicked()
{
if (playlist_clips->empty())
// TODO: Make for a less abrupt transition if we're not already at 100%.
ui->speed_slider->setValue(100); // Also actually sets the master speed and updates the label.
ui->speed_slider->setEnabled(!ui->speed_lock_btn->isChecked());
- midi_mapper.set_locked(ui->speed_lock_btn->isChecked());
+ midi_mapper.set_locked(MIDIMapper::LightState(ui->speed_lock_btn->isChecked()));
+ lock_blink_timeout->stop();
}
void MainWindow::live_player_done()
post_to_main_thread([this, speed] {
if (ui->speed_lock_btn->isChecked()) {
+ midi_mapper.set_locked(MIDIMapper::Blinking);
+ lock_blink_timeout->start(1000);
return;
}
// NOTE: The undo stack always has the current state on top.
std::deque<StateProto> undo_stack, redo_stack;
+ // If we need to blink the lock light, we do so for only a second.
+ // This timer signals that we should end it.
+ QTimer *lock_blink_timeout;
+
// Before a change that should be deferred (see above), currently_deferring_model_changes
// must be set to true, and current_change_id must be given contents describing what's
// changed to avoid accidental grouping.
void state_changed(const StateProto &state); // Called post-filtering.
void save_settings();
+ void lock_blink_timer_expired();
+
enum Rounding { FIRST_AT_OR_AFTER,
LAST_BEFORE };
void preview_single_frame(int64_t pts, unsigned stream_idx, Rounding rounding);
if (play_enabled_light) {
activate_mapped_light(*mapping_proto, MIDIMappingProto::kPlayEnabledFieldNumber, &active_lights);
}
- if (locked_light) {
+ if (locked_light == On) {
activate_mapped_light(*mapping_proto, MIDIMappingProto::kLockedFieldNumber, &active_lights);
+ } else if (locked_light == Blinking) {
+ activate_mapped_light(*mapping_proto, MIDIMappingProto::kLockedBlinkingFieldNumber, &active_lights);
}
if (current_highlighted_camera >= 0 && current_highlighted_camera < mapping_proto->camera_size()) {
const CameraMIDIMappingProto &camera = mapping_proto->camera(current_highlighted_camera);
class MIDIMapper : public MIDIReceiver {
public:
+ // Converts conveniently from a bool.
+ enum LightState {
+ Off = 0,
+ On = 1,
+ Blinking = 2
+ };
+
MIDIMapper(ControllerReceiver *receiver);
virtual ~MIDIMapper();
void set_midi_mapping(const MIDIMappingProto &new_mapping);
play_enabled_light = enabled;
refresh_lights();
}
- void set_locked(bool locked) {
+ void set_locked(LightState locked) {
locked_light = locked;
refresh_lights();
}
std::atomic<bool> preview_enabled_light{false};
std::atomic<bool> queue_enabled_light{false};
std::atomic<bool> play_enabled_light{false};
- std::atomic<bool> locked_light{true};
+ std::atomic<LightState> locked_light{On};
std::atomic<int> current_highlighted_camera{-1};
MIDIDevice midi_device;