Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

protocols: implement a remote control protocol based on MIDI #125

Merged
merged 1 commit into from
Dec 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions cmake/libremidi.examples.cmake
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
macro(setup_example _example)
target_link_libraries(${_example} PRIVATE libremidi)
target_link_libraries("${_example}" PRIVATE libremidi)
endmacro()

macro(add_example _example)
add_executable(${_example} examples/${_example}.cpp)
setup_example(${_example})
string(REPLACE "/" "_" _exampleName "${_example}")
add_executable("${_exampleName}" "examples/${_example}.cpp")
setup_example("${_exampleName}")
endmacro()

macro(add_backend_example _example)
add_executable(${_example} examples/backends/${_example}.cpp)
setup_example(${_example})
add_executable("${_example}" "examples/backends/${_example}.cpp")
setup_example("${_example}")
endmacro()

add_example(midiobserve)
Expand All @@ -27,6 +28,8 @@ add_example(minimal)
add_example(midi2_echo)
add_example(rawmidiin)

add_example(protocols/remote_control)

if(LIBREMIDI_NI_MIDI2)
add_example(midi2_interop)
endif()
Expand Down
99 changes: 99 additions & 0 deletions examples/protocols/remote_control.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include <libremidi/libremidi.hpp>
#include <libremidi/protocols/remote_control.hpp>

#if __has_include(<magic_enum_all.hpp>)
#include <magic_enum_all.hpp>
#else
#include <iomanip>
#include <iostream>
#include <sstream>
namespace magic_enum
{
std::string enum_name(auto cmd)
{
std::stringstream ss;
ss << "0x" << std::setbase(16) << static_cast<uint32_t>(cmd);
return ss.str();
}
}
#endif

#include <chrono>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <thread>

int main()
{
auto api = libremidi::API::ALSA_SEQ;
libremidi::observer observer{{.track_any = true}, api};
if (observer.get_input_ports().empty())
return 1;
if (observer.get_output_ports().empty())
return 1;

libremidi::input_port ip;
libremidi::output_port op;

// Tested with https://github.com/NicoG60/TouchMCU
for (auto& p : observer.get_input_ports())
if (p.port_name == "TouchOSC")
ip = p;
for (auto& p : observer.get_output_ports())
if (p.port_name == "TouchOSC")
op = p;

if (ip.port_name.empty() || op.port_name.empty())
{
std::cerr << "No device found !";
return 1;
}

// Create the midi out port
libremidi::midi_out midi_out{{}, api};

// Set-up the remote control API.
// Here we only do some logging, this is where commands sqall be handled.
libremidi::remote_control_processor rcp{{.midi_out = [&](libremidi::message&& msg) {
midi_out.send_message(msg);
}, .on_command = [](libremidi::remote_control_protocol::mixer_command cmd, bool pressed) {
std::cerr << "command: " << magic_enum::enum_name(cmd) << " -> "
<< (pressed ? "pressed" : "released") << "\n";
}, .on_control = [](libremidi::remote_control_protocol::mixer_control ctl, int v) {
std::cerr << "control: " << magic_enum::enum_name(ctl) << " -> " << v << "\n";
}, .on_fader = [](libremidi::remote_control_protocol::fader f, uint16_t v) {
std::cerr << "fader: " << magic_enum::enum_name(f) << " -> " << v << "\n";
}}};

// Initialize the midi in port
libremidi::midi_in midi_in{
{.on_message = [&](const libremidi::message& message) { rcp.on_midi(message); }}, api};

// Open the ports
if (auto err = midi_in.open_port(ip); err != stdx::error{})
err.throw_exception();

if (auto err = midi_out.open_port(op); err != stdx::error{})
err.throw_exception();

// Start communication
rcp.start();

// Blast messages :)
using proto = libremidi::remote_control_protocol;
unsigned i = 0;
for (;;)
{
std::this_thread::sleep_for(std::chrono::milliseconds(50));

std::time_t result = std::time(nullptr);
auto ctime = std::localtime(&result);
rcp.update_timecode(ctime->tm_hour, ctime->tm_min, ctime->tm_sec, 0);
rcp.update_lcd(std::string(1, '\0' + i % 127), i % 112);
rcp.fader(static_cast<proto::fader>(i % 8), (200 * i) % 16384);
i++;
}

return 0;
}
Loading
Loading