Skip to content

Commit a484baf

Browse files
committed
Add bn and various.
1 parent 8319a9c commit a484baf

18 files changed

+903
-806
lines changed

.github/workflows/ci.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ jobs:
2525
- name: macOS-14/Xcode/Debug
2626
build_type: Debug
2727
generator: Xcode
28-
os: macos-14
28+
os: macos-15
2929
package: TGZ
3030

3131
- name: macOS-14/Xcode/Release
3232
build_type: Release
3333
generator: Xcode
34-
os: macos-14
34+
os: macos-15
3535
package: TGZ
3636

3737
# Ubuntu builds

demo/CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
add_subdirectory(ci_discovery)
1+
add_subdirectory(ci_create_discovery)
22
add_subdirectory(ci_dispatcher)
3-
add_subdirectory(dispatcher_function)
3+
add_subdirectory(ump_dispatcher_function)
44
add_subdirectory(midi1_to_ump)
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
add_executable(demo_ci_create_discovery ci_create_discovery.cpp)
2+
target_link_libraries(demo_ci_create_discovery PRIVATE midi2)
3+
setup_target(demo_ci_create_discovery)
4+
add_test(NAME demo_ci_create_discovery COMMAND demo_ci_create_discovery)
5+

demo/ci_discovery/ci_discovery.cpp demo/ci_create_discovery/ci_create_discovery.cpp

+16-8
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,39 @@
66
//
77
//===------------------------------------------------------------------------------------===//
88

9+
#include <array>
910
#include <cstddef>
1011
#include <cstdlib>
1112
#include <format>
1213
#include <iostream>
1314
#include <iterator>
15+
#include <ranges>
1416
#include <vector>
1517

1618
#include "midi2/ci_create_message.hpp"
1719
#include "midi2/ci_types.hpp"
1820
#include "midi2/utils.hpp"
1921

22+
using namespace midi2::ci::literals;
23+
2024
int main() {
25+
constexpr auto my_muid = midi2::ci::muid{0x01234567U}; // Use a proper random number!
2126
constexpr std::size_t buffer_size = 256;
2227
constexpr midi2::ci::header header{
23-
.device_id = 0x7F, .version = 2, .remote_muid = 0, .local_muid = midi2::ci::broadcast_muid};
24-
constexpr midi2::ci::discovery_reply discovery{.manufacturer = {0x12, 0x23, 0x34},
25-
.family = 0x1779,
26-
.model = 0x2B5D,
27-
.version = {0x4E, 0x3C, 0x2A, 0x18},
28-
.capability = 0x7F,
29-
.max_sysex_size = buffer_size,
30-
.output_path_id = 0};
28+
.device_id = 0_b7, .version = 2_b7, .remote_muid = my_muid, .local_muid = midi2::ci::broadcast_muid};
29+
constexpr midi2::ci::discovery_reply discovery{.manufacturer = {0x12_b7, 0x23_b7, 0x34_b7},
30+
.family = 0x1779_b14,
31+
.model = 0x2B5D_b14,
32+
.version = {0x01_b7, 0x00_b7, 0x00_b7, 0x00_b7},
33+
.capability = 0x7F_b7,
34+
.max_sysex_size = midi2::ci::b28{buffer_size},
35+
.output_path_id = 0_b7};
3136
std::array<std::byte, buffer_size> message{};
37+
// NOLINTNEXTLINE(llvm-qualified-auto,readability-qualified-auto)
3238
auto const first = std::begin(message);
39+
// NOLINTNEXTLINE(llvm-qualified-auto,readability-qualified-auto)
3340
auto const last = std::end(message);
41+
// NOLINTNEXTLINE(llvm-qualified-auto,readability-qualified-auto)
3442
auto const pos = midi2::ci::create_message(first, last, header, discovery);
3543
if (pos == last) {
3644
std::cerr << "Buffer too small\n";

demo/ci_discovery/CMakeLists.txt

-5
This file was deleted.

demo/ci_dispatcher/ci_dispatcher.cpp

+66-36
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,91 @@
1+
//===-- Demo CI Message Dispatch ----------------------------------------------*- C++ -*-===//
2+
//
3+
// midi2 library under the MIT license.
4+
// See https://github.com/paulhuggett/AM_MIDI2.0Lib/blob/main/LICENSE for license information.
5+
// SPDX-License-Identifier: MIT
6+
//
7+
//===------------------------------------------------------------------------------------===//
8+
19
#include "midi2/ci_dispatcher.hpp"
210

311
#include <array>
412
#include <cstdlib>
5-
#include <ctime>
613
#include <format>
714
#include <iostream>
8-
#include <random>
9-
#include <ranges>
15+
#include <type_traits>
1016

11-
namespace {
17+
using namespace midi2::ci::literals;
1218

13-
template <std::ranges::input_range Range> std::string as_string(Range const &range) {
14-
std::string result;
15-
char const *separator = "";
16-
for (auto const v : range) {
17-
result += std::format("{}0x{:X}", separator, v);
18-
separator = ", ";
19+
// A formatter for arrays of 7-bit integer values (b7). These will be represented to
20+
// comma-separated hex values.
21+
template <std::size_t Size, typename CharT> struct std::formatter<std::array<midi2::ci::b7, Size>, CharT> {
22+
constexpr auto parse(auto &parse_ctx) const { return parse_ctx.begin(); }
23+
auto format(std::array<midi2::ci::b7, Size> const &arr, auto &format_ctx) const {
24+
// NOLINTNEXTLINE(llvm-qualified-auto,readability-qualified-auto)
25+
auto out = format_ctx.out();
26+
char const *separator = "";
27+
for (auto const value : arr) {
28+
out = std::format_to(out, "{}0x{:X}", separator, value);
29+
separator = ",";
30+
}
31+
return out;
1932
}
20-
return result;
33+
};
34+
35+
namespace {
36+
// Display the header fields
37+
void print_header(std::ostream &os, midi2::ci::header const &h) {
38+
os << std::format("device-id=0x{:X}\nversion=0x{:X}\n", h.device_id, h.version)
39+
<< std::format("remote-MUID=0x{:X}\nlocal-MUID=0x{:X}\n\n", h.remote_muid, h.local_muid);
40+
}
41+
// Display the discovery data fields
42+
void print_discovery(std::ostream &os, midi2::ci::discovery const &d) {
43+
os << std::format("manufacturer={}\nfamily=0x{:X}\nmodel=0x{:X}\n", d.manufacturer, d.family, d.model)
44+
<< std::format("version={}\ncapability=0x{:X}\n", d.version, d.capability)
45+
<< std::format("max-sysex-size=0x{:X}\noutput-path-id=0x{:X}\n", d.max_sysex_size, d.output_path_id);
2146
}
2247

23-
} // end anonymous namespace
48+
// We must pass a “context” to the dispatcher, which will be forwarded to each of the dispatcher's callbacks.
49+
// The context lets message handlers share state but we don’t need that here, so a struct with no members will suffice.
50+
struct context {};
2451

25-
int main() {
26-
// Generate a random local MUID.
27-
std::mt19937 engine{std::random_device{}()};
28-
std::uniform_int_distribution<std::uint32_t> distribution;
29-
auto const local_muid = distribution(engine) % midi2::ci::max_user_muid;
52+
// Normally, these typedefs are not necessary: just use auto! However,
53+
// they are included here for clarity.
54+
constexpr auto buffer_size = std::size_t{256};
55+
using function_config = midi2::ci::function_config<context, buffer_size>;
56+
static_assert(std::is_same_v<std::remove_cvref_t<decltype(function_config::buffer_size)>, std::size_t>);
57+
using dispatcher = midi2::ci::ci_dispatcher<function_config>;
3058

31-
struct context {};
59+
dispatcher setup_ci_dispatcher(midi2::ci::muid const my_muid) {
3260
// Create a CI dispatcher instance using std::function<> for all of its handler functions.
33-
auto dispatcher = midi2::ci::make_function_dispatcher(context{});
61+
auto dispatcher = midi2::ci::make_function_dispatcher<context, buffer_size>();
3462
auto &config = dispatcher.config();
35-
// Register a handler for checking whether a message is address to this MUID.
63+
64+
// Register a handler for checking whether a message is addressed to this receiver.
3665
config.system.on_check_muid(
37-
[&local_muid](context, std::uint8_t /*group*/, std::uint32_t const muid) { return local_muid == muid; });
66+
[my_muid](context, std::uint8_t /*group*/, midi2::ci::muid const m) { return m == my_muid; });
67+
3868
// Register a handler for Discovery messages.
39-
config.management.on_discovery([](context, midi2::ci::header const &hdr, midi2::ci::discovery const &d) {
40-
// Display the header fields
41-
std::cout << std::format("device-id=0x{:X}\nversion=0x{:X}\n", hdr.device_id, hdr.version)
42-
<< std::format("remote-MUID=0x{:08X}\nlocal-MUID=0x{:08X}\n\n", hdr.remote_muid, hdr.local_muid);
43-
44-
// Display the discovery data fields
45-
std::cout << std::format("manufacturer=[{}]\nfamily=0x{:X}\nmodel=0x{:X}\n", as_string(d.manufacturer), d.family,
46-
d.model)
47-
<< std::format("version=[{}]\n", as_string(d.version))
48-
<< std::format("capability=0x{:X}\nmax-sysex-size=0x{:X}\noutput-path-id=0x{:X}\n", d.capability,
49-
d.max_sysex_size, d.output_path_id);
69+
config.management.on_discovery([](context, midi2::ci::header const &h, midi2::ci::discovery const &d) {
70+
print_header(std::cout, h);
71+
print_discovery(std::cout, d);
5072
// Send a reply to this message...
5173
});
74+
return dispatcher;
75+
}
76+
} // end anonymous namespace
77+
78+
int main() {
79+
constexpr auto my_muid = midi2::ci::muid{0x01234567U}; // Use a proper random number!
80+
constexpr auto my_group = std::uint8_t{0};
81+
constexpr auto device_id = 0_b7;
82+
auto dispatcher = setup_ci_dispatcher(my_muid);
5283

84+
// A system exclusive message containing a CI discovery request.
5385
constexpr std::array message{0x7E, 0x7F, 0x0D, 0x70, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7F,
5486
0x7F, 0x7F, 0x7F, 0x12, 0x23, 0x34, 0x79, 0x2E, 0x5D, 0x56,
55-
0x4E, 0x3C, 0x2A, 0x18, 0x7F, 0x00, 0x02, 0x00, 0x00, 0x71};
56-
constexpr auto group = std::uint8_t{0};
57-
constexpr auto device_id = std::byte{0};
58-
dispatcher.start(group, device_id);
87+
0x01, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x02, 0x00, 0x00, 0x00};
88+
dispatcher.start(my_group, device_id);
5989
for (auto const b : message) {
6090
dispatcher.processMIDICI(static_cast<std::byte>(b));
6191
}

demo/dispatcher_function/CMakeLists.txt

-4
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
add_executable(demo_ump_dispatcher_function ump_dispatcher_function.cpp)
2+
target_link_libraries(demo_ump_dispatcher_function PRIVATE midi2)
3+
setup_target(demo_ump_dispatcher_function)
4+
add_test(NAME demo-ump-dispatcher-function COMMAND demo_ump_dispatcher_function)

include/midi2/ci_create_message.hpp

+12-12
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ template <> struct type_to_packed<discovery_reply> {
3737
using v1 = packed::discovery_reply_v1;
3838
using v2 = packed::discovery_reply_v2;
3939
};
40-
template <> struct type_to_packed<endpoint_info> {
41-
static constexpr auto id = message::endpoint_info;
42-
using v1 = packed::endpoint_info_v1;
43-
using v2 = packed::endpoint_info_v1;
40+
template <> struct type_to_packed<endpoint> {
41+
static constexpr auto id = message::endpoint;
42+
using v1 = packed::endpoint_v1;
43+
using v2 = packed::endpoint_v1;
4444
};
45-
template <> struct type_to_packed<endpoint_info_reply> {
46-
static constexpr auto id = message::endpoint_info_reply;
45+
template <> struct type_to_packed<endpoint_reply> {
46+
static constexpr auto id = message::endpoint_reply;
4747
};
4848
template <> struct type_to_packed<invalidate_muid> {
4949
static constexpr auto id = message::invalidate_muid;
@@ -242,7 +242,7 @@ struct trivial_sentinel {
242242

243243
template <typename T, std::output_iterator<std::byte> O, std::sentinel_for<O> S>
244244
constexpr O create_message(O first, S const last, header const &hdr, T const &t) {
245-
if (hdr.version == 1) {
245+
if (hdr.version == b7{1U}) {
246246
using v1_type = details::type_to_packed<T>::v1;
247247
if constexpr (!std::is_same_v<v1_type, details::not_available>) {
248248
first = details::write_header_body<v1_type>(first, last, hdr, t);
@@ -253,12 +253,12 @@ constexpr O create_message(O first, S const last, header const &hdr, T const &t)
253253
}
254254

255255
template <std::output_iterator<std::byte> O, std::sentinel_for<O> S>
256-
constexpr O create_message(O first, S const last, header const &hdr, endpoint_info_reply const &reply) {
257-
first = details::write_header(first, last, hdr, details::type_to_packed<endpoint_info_reply>::id);
258-
auto const v1 = static_cast<packed::endpoint_info_reply_v1>(reply);
256+
constexpr O create_message(O first, S const last, header const &hdr, endpoint_reply const &reply) {
257+
first = details::write_header(first, last, hdr, details::type_to_packed<endpoint_reply>::id);
258+
auto const v1 = static_cast<packed::endpoint_reply_v1>(reply);
259259
static_assert(std::is_trivially_copyable_v<decltype(v1)> && alignof(decltype(v1)) == 1);
260260
return details::write_packed_with_tail(first, last, std::bit_cast<std::byte const *>(&v1),
261-
offsetof(packed::endpoint_info_reply_v1, data), reply.information);
261+
offsetof(packed::endpoint_reply_v1, data), reply.information);
262262
}
263263

264264
template <std::output_iterator<std::byte> O, std::sentinel_for<O> S>
@@ -273,7 +273,7 @@ constexpr O create_message(O first, S const last, header const &hdr, struct ack
273273
template <std::output_iterator<std::byte> O, std::sentinel_for<O> S>
274274
constexpr O create_message(O first, S last, header const &hdr, struct nak const &nak) {
275275
first = details::write_header(first, last, hdr, details::type_to_packed<struct nak>::id);
276-
if (hdr.version == 1) {
276+
if (hdr.version == b7{1U}) {
277277
return first;
278278
}
279279
auto const v2 = static_cast<packed::nak_v2>(nak);

0 commit comments

Comments
 (0)