MIDI2LR 6.1.0.0
MIDI2LR is an application that interfaces MIDI controllers with Lightroom 6+/CC Classic. It processes MIDI input into develop parameter updates and photo actions, and sends MIDI output when parameters are changed for motorized feedback (on controllers that have motorized faders). A listing of available LightRoom commands is in the Wiki. Assistance on the code and design is welcome.
Loading...
Searching...
No Matches
MidiReceiver Class Referencefinal

#include <MIDIReceiver.h>

+ Inheritance diagram for MidiReceiver:

Public Member Functions

 MidiReceiver (const MidiReceiver &other)=delete
 
 MidiReceiver (Devices &devices)
 
 MidiReceiver (MidiReceiver &&other)=delete
 
 ~MidiReceiver ()=default
 
template<class T >
void AddCallback (_In_ T *const object, _In_ void(T::*const mf)(rsj::MidiMessage))
 
MidiReceiveroperator= (const MidiReceiver &other)=delete
 
MidiReceiveroperator= (MidiReceiver &&other)=delete
 
void RescanDevices ()
 
void Start ()
 
void Stop ()
 

Private Member Functions

void DispatchCcMessage (const std::pair< rsj::MidiMessage, juce::MidiInput * > &popped)
 
void DispatchMessages ()
 
void DispatchNoteOnPwMessage (const std::pair< rsj::MidiMessage, juce::MidiInput * > &popped) const
 
void handleIncomingMidiMessage (juce::MidiInput *device, const juce::MidiMessage &message) override
 
void InitDevices ()
 
void TryToOpen ()
 

Private Attributes

std::vector< std::function< void(rsj::MidiMessage)> > callbacks_
 
Devicesdevices_
 
std::future< void > dispatch_messages_future_
 
std::map< juce::MidiInput *, NrpnFilterfilters_ {}
 
std::vector< std::unique_ptr< juce::MidiInput > > input_devices_
 
rsj::ConcurrentQueue< std::pair< rsj::MidiMessage, juce::MidiInput * > > messages_
 

Constructor & Destructor Documentation

◆ MidiReceiver() [1/3]

MidiReceiver::MidiReceiver ( Devices devices)
inlineexplicit
37: devices_(devices) {}
Devices & devices_
Definition MIDIReceiver.h:67

◆ ~MidiReceiver()

MidiReceiver::~MidiReceiver ( )
default

◆ MidiReceiver() [2/3]

MidiReceiver::MidiReceiver ( const MidiReceiver other)
delete

◆ MidiReceiver() [3/3]

MidiReceiver::MidiReceiver ( MidiReceiver &&  other)
delete

Member Function Documentation

◆ AddCallback()

template<class T >
void MidiReceiver::AddCallback ( _In_ T *const  object,
_In_ void(T::*)(rsj::MidiMessage mf 
)
inline
50 {
51 if (object && mf) { callbacks_.emplace_back(std::bind_front(mf, object)); }
52 }
std::vector< std::function< void(rsj::MidiMessage)> > callbacks_
Definition MIDIReceiver.h:70

◆ DispatchCcMessage()

void MidiReceiver::DispatchCcMessage ( const std::pair< rsj::MidiMessage, juce::MidiInput * > &  popped)
private
137{
138 try {
139 if (const auto result {filters_[popped.second](popped.first)}; result.is_nrpn) {
140 if (result.is_ready) {
141 const rsj::MidiMessage nrpn_message {
142 rsj::MessageType::kCc, popped.first.channel, result.control, result.value};
143 for (const auto& cb : callbacks_) { cb(nrpn_message); }
144 }
145 }
146 else {
147 for (const auto& cb : callbacks_) { cb(popped.first); }
148 }
149 }
150 catch (const std::exception& e) {
152 throw;
153 }
154}
std::map< juce::MidiInput *, NrpnFilter > filters_
Definition MIDIReceiver.h:69
void ExceptionResponse(gsl::czstring id, gsl::czstring fu, const std::exception &e) noexcept
Definition MidiUtilities.h:123
int channel
Definition MidiUtilities.h:125

◆ DispatchMessages()

void MidiReceiver::DispatchMessages ( )
private
169{
170 try {
171 for (auto popped {messages_.pop()}; popped.first != kTerminate; popped = messages_.pop()) {
172#ifdef _WIN32
173 SetThreadExecutionState(0x00000002UL | 0x00000001UL);
174#endif
175 switch (popped.first.message_type_byte) {
177 DispatchCcMessage(popped);
178 break;
182 break;
188 break; /* no action if other type of MIDI message */
189 }
190 }
191 }
192 catch (const std::exception& e) {
194 throw;
195 }
196}
void DispatchCcMessage(const std::pair< rsj::MidiMessage, juce::MidiInput * > &popped)
Definition MIDIReceiver.cpp:136
void DispatchNoteOnPwMessage(const std::pair< rsj::MidiMessage, juce::MidiInput * > &popped) const
Definition MIDIReceiver.cpp:156
rsj::ConcurrentQueue< std::pair< rsj::MidiMessage, juce::MidiInput * > > messages_
Definition MIDIReceiver.h:68
T pop()
Definition Concurrency.h:180

◆ DispatchNoteOnPwMessage()

void MidiReceiver::DispatchNoteOnPwMessage ( const std::pair< rsj::MidiMessage, juce::MidiInput * > &  popped) const
private
158{
159 try {
160 for (const auto& cb : callbacks_) { cb(popped.first); }
161 }
162 catch (const std::exception& e) {
164 throw;
165 }
166}

◆ handleIncomingMidiMessage()

void MidiReceiver::handleIncomingMidiMessage ( juce::MidiInput *  device,
const juce::MidiMessage &  message 
)
inlineoverrideprivate
57 {
58 messages_.push({rsj::MidiMessage(message), device});
59 }
void push(const T &value)
Definition Concurrency.h:152

◆ InitDevices()

void MidiReceiver::InitDevices ( )
private
110{
111 using namespace std::literals::chrono_literals;
112 try {
113 rsj::Log("Trying to open input devices.");
114 TryToOpen();
115 if (input_devices_.empty()) /* encountering errors first try on MacOS */
116 {
117 rsj::Log("Retrying to open input devices.");
118 std::this_thread::sleep_for(20ms);
119 rsj::Log("20ms sleep for open input devices.");
120 TryToOpen();
121 if (input_devices_.empty()) /* encountering errors second try on MacOS */
122 {
123 rsj::Log("Retrying second time to open input devices.");
124 std::this_thread::sleep_for(80ms);
125 rsj::Log("80ms sleep for open input devices.");
126 TryToOpen();
127 }
128 }
129 }
130 catch (const std::exception& e) {
132 throw;
133 }
134}
void TryToOpen()
Definition MIDIReceiver.cpp:84
std::vector< std::unique_ptr< juce::MidiInput > > input_devices_
Definition MIDIReceiver.h:71
void Log(const juce::String &info, const std::source_location &location=std::source_location::current()) noexcept
Definition Misc.cpp:131

◆ operator=() [1/2]

MidiReceiver & MidiReceiver::operator= ( const MidiReceiver other)
delete

◆ operator=() [2/2]

MidiReceiver & MidiReceiver::operator= ( MidiReceiver &&  other)
delete

◆ RescanDevices()

void MidiReceiver::RescanDevices ( )
67{
68 try {
69 for (const auto& dev : input_devices_) {
70 dev->stop();
71 rsj::Log(fmt::format(FMT_STRING("Stopped input device {}."),
72 dev->getName().toStdString()));
73 }
74 input_devices_.clear();
75 rsj::Log("Cleared input devices.");
76 }
77 catch (const std::exception& e) {
79 throw;
80 }
81 InitDevices(); /* initdevices has own try catch block */
82}
void InitDevices()
Definition MIDIReceiver.cpp:109

◆ Start()

void MidiReceiver::Start ( )
40{
41 try {
43 dispatch_messages_future_ = std::async(std::launch::async, [this] {
44 rsj::LabelThread(MIDI2LR_UC_LITERAL("MidiReceiver dispatch messages thread"));
45 MIDI2LR_FAST_FLOATS;
47 });
48 }
49 catch (const std::exception& e) {
51 throw;
52 }
53}
void DispatchMessages()
Definition MIDIReceiver.cpp:168
std::future< void > dispatch_messages_future_
Definition MIDIReceiver.h:72
void LabelThread(gsl::czstring threadname)
Definition Misc.cpp:48

◆ Stop()

void MidiReceiver::Stop ( )
56{
57 for (const auto& dev : input_devices_) {
58 dev->stop();
59 rsj::Log(fmt::format(FMT_STRING("Stopped input device {}."), dev->getName().toStdString()));
60 }
61 if (const auto remaining {messages_.clear_count_push({kTerminate, nullptr})}) {
62 rsj::Log(fmt::format(FMT_STRING("{} left in queue in MidiReceiver StopRunning."), remaining));
63 }
64}
size_type clear_count_push(const T &value)
Definition Concurrency.h:246

◆ TryToOpen()

void MidiReceiver::TryToOpen ( )
private
85{
86 try {
87 const auto available_devices {juce::MidiInput::getAvailableDevices()};
88 for (const auto& device : available_devices) {
89 if (auto open_device {juce::MidiInput::openDevice(device.identifier, this)}) {
90 if (devices_.EnabledOrNew(open_device->getDeviceInfo(), "input")) {
91 open_device->start();
92 rsj::Log(fmt::format(FMT_STRING("Opened input device {}."),
93 open_device->getName().toStdString()));
94 input_devices_.push_back(std::move(open_device));
95 }
96 else {
97 rsj::Log(fmt::format(FMT_STRING("Ignored input device {}."),
98 open_device->getName().toStdString()));
99 }
100 }
101 }
102 }
103 catch (const std::exception& e) {
105 throw;
106 }
107}
bool EnabledOrNew(const juce::MidiDeviceInfo &info, const juce::String &io)
Definition Devices.cpp:152

Member Data Documentation

◆ callbacks_

std::vector<std::function<void(rsj::MidiMessage)> > MidiReceiver::callbacks_
private

◆ devices_

Devices& MidiReceiver::devices_
private

◆ dispatch_messages_future_

std::future<void> MidiReceiver::dispatch_messages_future_
private

◆ filters_

std::map<juce::MidiInput*, NrpnFilter> MidiReceiver::filters_ {}
private
69{};

◆ input_devices_

std::vector<std::unique_ptr<juce::MidiInput> > MidiReceiver::input_devices_
private

◆ messages_

rsj::ConcurrentQueue<std::pair<rsj::MidiMessage, juce::MidiInput*> > MidiReceiver::messages_
private

The documentation for this class was generated from the following files: