void toggle_compressor(unsigned bus_idx) override;
void clear_peak(unsigned bus_idx) override;
+ // Raw receivers are not used.
+ void controller_changed(unsigned controller) override {}
+ void note_on(unsigned note) override {}
+
private:
void reset_audio_mapping_ui();
void setup_audio_miniview();
return *mapping_proto;
}
+ControllerReceiver *MIDIMapper::set_receiver(ControllerReceiver *new_receiver)
+{
+ lock_guard<mutex> lock(mapping_mu);
+ swap(receiver, new_receiver);
+ return new_receiver; // Now old receiver.
+}
+
#define RETURN_ON_ERROR(msg, expr) do { \
int err = (expr); \
if (err < 0) { \
const int controller = event->data.control.param;
const float value = map_controller_to_float(event->data.control.value);
+ receiver->controller_changed(controller);
+
// Global controllers.
match_controller(controller, MIDIMappingBusProto::kLocutFieldNumber, MIDIMappingProto::kLocutBankFieldNumber,
value, bind(&ControllerReceiver::set_locut, receiver, _2));
case SND_SEQ_EVENT_NOTEON: {
const int note = event->data.note.note;
+ receiver->note_on(note);
+
printf("Note: %d\n", note);
// Bank change commands. TODO: Highlight the bank change in the UI.
virtual void toggle_auto_gain_staging(unsigned bus_idx) = 0;
virtual void toggle_compressor(unsigned bus_idx) = 0;
virtual void clear_peak(unsigned bus_idx) = 0;
+
+ // Raw events; used for the editor dialog only.
+ virtual void controller_changed(unsigned controller) = 0;
+ virtual void note_on(unsigned note) = 0;
};
class MIDIMapper {
void start_thread();
const MIDIMappingProto &get_current_mapping() const;
+ // Overwrites and returns the previous value.
+ ControllerReceiver *set_receiver(ControllerReceiver *new_receiver);
+
private:
void thread_func();
void handle_event(snd_seq_t *seq, snd_seq_event_t *event);
void match_button(int note, int field_number, int bank_field_number, std::function<void(unsigned)> func);
bool bank_mismatch(int bank_field_number);
- ControllerReceiver *receiver;
std::atomic<bool> should_quit{false};
int should_quit_fd;
mutable std::mutex mapping_mu;
+ ControllerReceiver *receiver; // Under <mapping_mu>.
std::unique_ptr<MIDIMappingProto> mapping_proto; // Under <mapping_mu>.
int num_controller_banks; // Under <mapping_mu>.
std::atomic<int> current_controller_bank{0};
ui->setupUi(this);
const MIDIMappingProto mapping_proto = mapper->get_current_mapping(); // Take a copy.
+ old_receiver = mapper->set_receiver(this);
QStringList labels;
labels << "";
MIDIMappingDialog::~MIDIMappingDialog()
{
+ mapper->set_receiver(old_receiver);
}
void MIDIMappingDialog::ok_clicked()
{
unique_ptr<MIDIMappingProto> new_mapping = construct_mapping_proto_from_ui();
mapper->set_midi_mapping(*new_mapping);
+ mapper->set_receiver(old_receiver);
accept();
}
void MIDIMappingDialog::cancel_clicked()
{
+ mapper->set_receiver(old_receiver);
reject();
}
ic.combo_box->setCurrentIndex(get_bank(mapping_proto, ic.field_number, -1) + 1);
}
}
+
+void MIDIMappingDialog::controller_changed(unsigned controller)
+{
+ for (const InstantiatedSpinner &is : controller_spinners) {
+ if (is.spinner->hasFocus()) {
+ is.spinner->setValue(controller);
+ is.spinner->selectAll();
+ }
+ }
+}
+
+void MIDIMappingDialog::note_on(unsigned note)
+{
+ for (const InstantiatedSpinner &is : button_spinners) {
+ if (is.spinner->hasFocus()) {
+ is.spinner->setValue(note);
+ is.spinner->selectAll();
+ }
+ }
+}
#include <sys/time.h>
#include "audio_mixer.h"
+#include "midi_mapper.h"
#include "mixer.h"
namespace Ui {
class QSpinBox;
class QTreeWidgetItem;
-class MIDIMappingDialog : public QDialog
+class MIDIMappingDialog : public QDialog, public ControllerReceiver
{
Q_OBJECT
int bank_field_number; // In MIDIMappingProto.
};
+ // ControllerReceiver interface. We only implement the raw events.
+ // All values are [0.0, 1.0].
+ void set_locut(float value) override {}
+ void set_limiter_threshold(float value) override {}
+ void set_makeup_gain(float value) override {}
+
+ void set_treble(unsigned bus_idx, float value) override {}
+ void set_mid(unsigned bus_idx, float value) override {}
+ void set_bass(unsigned bus_idx, float value) override {}
+ void set_gain(unsigned bus_idx, float value) override {}
+ void set_compressor_threshold(unsigned bus_idx, float value) override {}
+ void set_fader(unsigned bus_idx, float value) override {}
+
+ void toggle_locut(unsigned bus_idx) override {}
+ void toggle_auto_gain_staging(unsigned bus_idx) override {}
+ void toggle_compressor(unsigned bus_idx) override {}
+ void clear_peak(unsigned bus_idx) override {}
+
+ // Raw events; used for the editor dialog only.
+ void controller_changed(unsigned controller) override;
+ void note_on(unsigned note) override;
+
public slots:
void ok_clicked();
void cancel_clicked();
std::unique_ptr<MIDIMappingProto> construct_mapping_proto_from_ui();
-
Ui::MIDIMappingDialog *ui;
MIDIMapper *mapper;
+ ControllerReceiver *old_receiver;
// All controllers actually laid out on the grid (we need to store them
// so that we can move values back and forth between the controls and