Skip to content

Commit

Permalink
[core] Enable more conversion cases when creating midi_in objects
Browse files Browse the repository at this point in the history
  • Loading branch information
jcelerier committed Sep 10, 2024
1 parent bebe74a commit 83ea9de
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 5 deletions.
2 changes: 1 addition & 1 deletion include/libremidi/api-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ typedef enum libremidi_api
WINDOWS_MIDI_SERVICES, /*!< Windows API for MIDI 2.0. Requires Windows 11 */
KEYBOARD_UMP, /*!< Computer keyboard input */

DUMMY /*!< A compilable but non-functional API. */
DUMMY = 0xFFFF /*!< A compilable but non-functional API. */
} libremidi_api;

#if __cplusplus
Expand Down
15 changes: 15 additions & 0 deletions include/libremidi/api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <libremidi/api-c.h>
#include <libremidi/config.hpp>

#include <any>
#include <string_view>
#include <vector>

Expand Down Expand Up @@ -30,6 +31,9 @@ LIBREMIDI_EXPORT std::vector<libremidi::API> available_apis() noexcept;
*/
LIBREMIDI_EXPORT std::vector<libremidi::API> available_ump_apis() noexcept;

LIBREMIDI_EXPORT
libremidi::API midi_api(const std::any& conf);

//! A static function to determine the current version.
LIBREMIDI_EXPORT std::string_view get_version() noexcept;

Expand All @@ -40,6 +44,17 @@ LIBREMIDI_EXPORT std::string_view get_api_display_name(libremidi::API api);
//! Look-up an API through its name
LIBREMIDI_EXPORT libremidi::API get_compiled_api_by_name(std::string_view api);

inline constexpr bool is_midi1(libremidi::API api)
{
return (static_cast<int>(api) >= 0x1 && static_cast<int>(api) < 0x1000)
|| api == libremidi::API::DUMMY;
}

inline constexpr bool is_midi2(libremidi::API api)
{
return static_cast<int>(api) >= 0x1000;
}

namespace midi1
{
//! Returns the default MIDI 1.0 backend to use for the target OS.
Expand Down
15 changes: 14 additions & 1 deletion include/libremidi/libremidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,20 @@ LIBREMIDI_INLINE libremidi::API get_compiled_api_by_name(std::string_view name)
midi2::for_all_backends([&](auto b) { apis.push_back(b.API); });
return apis;
}

LIBREMIDI_INLINE
libremidi::API midi_api(const std::any& conf)
{
libremidi::API ret = libremidi::API::UNSPECIFIED;
midi_any::for_all_backends([&]<typename T>(T) {
if (std::any_cast<typename T::midi_in_configuration>(&conf)
|| std::any_cast<typename T::midi_out_configuration>(&conf)
|| std::any_cast<typename T::midi_observer_configuration>(&conf))
{
ret = T::API;
}
});
return ret;
}
LIBREMIDI_INLINE
std::any midi_in_configuration_for(libremidi::API api)
{
Expand Down
39 changes: 36 additions & 3 deletions include/libremidi/midi_in.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,47 @@ make_midi1_in(const input_configuration& base_conf, const std::any& api_conf)
{
return make_midi1_in(base_conf);
}
else if (auto api = std::any_cast<libremidi::API>(&api_conf))
else if (auto api_p = std::any_cast<libremidi::API>(&api_conf))
{
return make_midi_in(base_conf, midi_in_configuration_for(*api), midi1::available_backends);
if (*api_p == libremidi::API::UNSPECIFIED)
{
if (auto backend = make_midi_in(
base_conf, midi_in_configuration_for(libremidi::midi1::default_api()),
midi1::available_backends))
return backend;

auto c2 = convert_midi1_to_midi2_input_configuration(base_conf);
if (auto backend = make_midi_in(
c2, midi_in_configuration_for(libremidi::midi2::default_api()),
midi2::available_backends))
return backend;
}
else if (is_midi1(*api_p))
{
// all good
return make_midi_in(base_conf, midi_in_configuration_for(*api_p), midi1::available_backends);
}
else if (is_midi2(*api_p))
{
auto c2 = convert_midi1_to_midi2_input_configuration(base_conf);
return make_midi_in(c2, midi_in_configuration_for(*api_p), midi2::available_backends);
}
}
else
{
return make_midi_in(base_conf, api_conf, midi1::available_backends);
const auto api = libremidi::midi_api(api_conf);
if (libremidi::is_midi1(api))
{
return make_midi_in(base_conf, api_conf, midi1::available_backends);
}
else if (libremidi::is_midi2(api))
{
auto c2 = convert_midi1_to_midi2_input_configuration(base_conf);
return make_midi_in(c2, api_conf, midi2::available_backends);
}
}

return std::make_unique<midi_in_dummy>(input_configuration{}, dummy_configuration{});
}

/// MIDI 1 constructors
Expand Down

0 comments on commit 83ea9de

Please sign in to comment.