#include "midi_mapper.h"
-#include "audio_mixer.h"
-#include "midi_mapping.pb.h"
-
#include <alsa/asoundlib.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <assert.h>
+#include <errno.h>
#include <fcntl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/text_format.h>
+#include <pthread.h>
+#include <poll.h>
+#include <stdint.h>
+#include <stdio.h>
#include <sys/eventfd.h>
-
+#include <unistd.h>
+#include <algorithm>
#include <functional>
#include <thread>
+#include "audio_mixer.h"
+#include "midi_mapping.pb.h"
+
using namespace google::protobuf;
using namespace std;
using namespace std::placeholders;
{
should_quit_fd = eventfd(/*initval=*/0, /*flags=*/0);
assert(should_quit_fd != -1);
- refresh_highlights();
}
MIDIMapper::~MIDIMapper()
{
should_quit = true;
const uint64_t one = 1;
- write(should_quit_fd, &one, sizeof(one));
+ if (write(should_quit_fd, &one, sizeof(one)) != sizeof(one)) {
+ perror("write(should_quit_fd)");
+ exit(1);
+ }
midi_thread.join();
close(should_quit_fd);
}
void MIDIMapper::thread_func()
{
+ pthread_setname_np(pthread_self(), "MIDIMapper");
+
snd_seq_t *seq;
int err;
if (err < 0) {
if (err == -EINTR) continue;
if (err == -EAGAIN) break;
+ if (err == -ENOSPC) {
+ fprintf(stderr, "snd_seq_event_input: Some events were lost.\n");
+ continue;
+ }
fprintf(stderr, "snd_seq_event_input: %s\n", snd_strerror(err));
return;
}
lock_guard<mutex> lock(mu);
switch (event->type) {
case SND_SEQ_EVENT_CONTROLLER: {
- printf("Controller %d changed to %d\n", event->data.control.param, event->data.control.value);
-
const int controller = event->data.control.param;
const float value = map_controller_to_float(event->data.control.value);
receiver->note_on(note);
- printf("Note: %d\n", note);
-
for (size_t bus_idx = 0; bus_idx < size_t(mapping_proto->bus_mapping_size()); ++bus_idx) {
const MIDIMappingBusProto &bus_mapping = mapping_proto->bus_mapping(bus_idx);
if (bus_mapping.has_prev_bank() &&
bind(&ControllerReceiver::toggle_compressor, receiver, _1));
match_button(note, MIDIMappingBusProto::kClearPeakFieldNumber, MIDIMappingProto::kClearPeakBankFieldNumber,
bind(&ControllerReceiver::clear_peak, receiver, _1));
+ match_button(note, MIDIMappingBusProto::kToggleMuteFieldNumber, MIDIMappingProto::kClearPeakBankFieldNumber,
+ bind(&ControllerReceiver::toggle_mute, receiver, _1));
match_button(note, MIDIMappingBusProto::kToggleLimiterFieldNumber, MIDIMappingProto::kToggleLimiterBankFieldNumber,
bind(&ControllerReceiver::toggle_limiter, receiver));
match_button(note, MIDIMappingBusProto::kToggleAutoMakeupGainFieldNumber, MIDIMappingProto::kToggleAutoMakeupGainBankFieldNumber,
bind(&ControllerReceiver::toggle_auto_makeup_gain, receiver));
+ break;
}
case SND_SEQ_EVENT_PORT_START:
subscribe_to_port_lock_held(seq, event->data.addr);
void MIDIMapper::subscribe_to_port_lock_held(snd_seq_t *seq, const snd_seq_addr_t &addr)
{
- // Client 0 is basically the system; ignore it.
- if (addr.client == 0) {
+ // Client 0 (SNDRV_SEQ_CLIENT_SYSTEM) is basically the system; ignore it.
+ // MIDI through (SNDRV_SEQ_CLIENT_DUMMY) echoes back what we give it, so ignore that, too.
+ if (addr.client == 0 || addr.client == 14) {
+ return;
+ }
+
+ // Don't listen to ourselves.
+ if (addr.client == snd_seq_client_id(seq)) {
return;
}
bus_idx, MIDIMappingBusProto::kCompressorThresholdFieldNumber, MIDIMappingProto::kCompressorThresholdBankFieldNumber));
receiver->highlight_fader(bus_idx, has_active_controller(
bus_idx, MIDIMappingBusProto::kFaderFieldNumber, MIDIMappingProto::kFaderBankFieldNumber));
+ receiver->highlight_mute(bus_idx, has_active_controller(
+ bus_idx, MIDIMappingBusProto::kToggleMuteFieldNumber, MIDIMappingProto::kToggleMuteBankFieldNumber));
receiver->highlight_toggle_locut(bus_idx, has_active_controller(
bus_idx, MIDIMappingBusProto::kToggleLocutFieldNumber, MIDIMappingProto::kToggleLocutBankFieldNumber));
receiver->highlight_toggle_auto_gain_staging(bus_idx, has_active_controller(
}
unsigned num_buses = min<unsigned>(global_audio_mixer->num_buses(), mapping_proto->bus_mapping_size());
for (unsigned bus_idx = 0; bus_idx < num_buses; ++bus_idx) {
+ if (global_audio_mixer->get_mute(bus_idx)) {
+ activate_lights(bus_idx, MIDIMappingBusProto::kIsMutedFieldNumber, &active_lights);
+ }
if (global_audio_mixer->get_locut_enabled(bus_idx)) {
activate_lights(bus_idx, MIDIMappingBusProto::kLocutIsOnFieldNumber, &active_lights);
}