working on win32 uwp! and libremidi update

This commit is contained in:
Sebastian @ HfG
2024-10-28 19:24:18 +01:00
parent 06cb6d8319
commit 1e3755148c
106 changed files with 8474 additions and 2198 deletions
@@ -0,0 +1,70 @@
#pragma once
// clang-format off
#define NOMINMAX 1
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#include <mmsystem.h>
// clang-format on
#include <libremidi/error.hpp>
namespace libremidi
{
struct winmm_error_domain : public stdx::error_domain
{
public:
constexpr winmm_error_domain() noexcept
: error_domain{{0xa32b080ac770514eULL, 0xef59a407f921da43ULL}}
{
}
stdx::string_ref name() const noexcept override { return "winmm"; }
bool equivalent(const stdx::error& lhs, const stdx::error& rhs) const noexcept override
{
if (lhs.domain() == rhs.domain())
return error_cast<int>(lhs) == error_cast<int>(rhs);
return false;
}
stdx::string_ref message(const stdx::error& e) const noexcept override
{
switch (error_cast<int>(e))
{
case MMSYSERR_NOERROR: return "No error";
case MMSYSERR_ERROR: return "Error";
case MMSYSERR_BADDEVICEID: return "Bad device ID";
case MMSYSERR_NOTENABLED: return "Not enabled";
case MMSYSERR_ALLOCATED: return "Allocated";
case MMSYSERR_INVALHANDLE: return "Invalid handle";
case MMSYSERR_NODRIVER: return "No driver";
case MMSYSERR_NOMEM: return "No memory";
case MMSYSERR_NOTSUPPORTED: return "Not supported";
case MMSYSERR_BADERRNUM: return "Bad errnum";
case MMSYSERR_INVALFLAG: return "Invalid flag";
case MMSYSERR_INVALPARAM: return "Invalid parameter";
case MMSYSERR_HANDLEBUSY: return "Handle busy";
case MMSYSERR_INVALIDALIAS: return "Invalid alias";
case MMSYSERR_BADDB: return "Bad database";
case MMSYSERR_KEYNOTFOUND: return "Key not found";
case MMSYSERR_READERROR: return "Read error";
case MMSYSERR_WRITEERROR: return "Write error";
case MMSYSERR_DELETEERROR: return "Delete error";
case MMSYSERR_VALNOTFOUND: return "Value not found";
case MMSYSERR_NODRIVERCB: return "No driver callback";
case MMSYSERR_MOREDATA: return "More data";
}
return "Unknown error code";
}
};
inline stdx::error from_mmerr(int ret) noexcept
{
static constexpr winmm_error_domain domain;
return {ret, domain};
}
}
+5 -12
View File
@@ -1,15 +1,8 @@
#pragma once
#define NOMINMAX 1
#define WIN32_LEAN_AND_MEAN 1
#include <libremidi/backends/winmm/error_domain.hpp>
#include <libremidi/detail/midi_api.hpp>
#include <algorithm>
// clang-format off
#include <windows.h>
#include <mmsystem.h>
// clang-format on
namespace libremidi
{
@@ -44,10 +37,10 @@ inline std::string ConvertToUTF8(const TCHAR* str)
// Next functions add the portNumber to the name so that
// the device's names are sure to be listed with individual names
// even when they have the same brand name
inline void MakeUniqueInPortName(std::string& deviceName, unsigned int portNumber)
inline void MakeUniqueInPortName(std::string& deviceName, std::size_t portNumber)
{
int x = 1;
for (unsigned int i = 0; i < portNumber; i++)
for (std::size_t i = 0; i < portNumber; i++)
{
MIDIINCAPS deviceCaps;
midiInGetDevCaps(i, &deviceCaps, sizeof(MIDIINCAPS));
@@ -61,10 +54,10 @@ inline void MakeUniqueInPortName(std::string& deviceName, unsigned int portNumbe
deviceName += std::to_string(x);
}
inline void MakeUniqueOutPortName(std::string& deviceName, unsigned int portNumber)
inline void MakeUniqueOutPortName(std::string& deviceName, std::size_t portNumber)
{
int x = 1;
for (unsigned int i = 0; i < portNumber; i++)
for (std::size_t i = 0; i < portNumber; i++)
{
MIDIOUTCAPS deviceCaps;
midiOutGetDevCaps(i, &deviceCaps, sizeof(MIDIOUTCAPS));
+35 -52
View File
@@ -22,20 +22,17 @@ public:
explicit midi_in_winmm(input_configuration&& conf, winmm_input_configuration&& apiconf)
: configuration{std::move(conf), std::move(apiconf)}
{
// We'll issue a warning here if no devices are available but not
// throw an error since the user can plugin something later.
if (midiInGetNumDevs() == 0)
{
warning(
configuration, "midi_in_winmm::initialize: no MIDI input devices currently available.");
}
if (!InitializeCriticalSectionAndSpinCount(&(this->_mutex), 0x00000400))
{
warning(
libremidi_handle_error(
configuration,
"midi_in_winmm::initialize: InitializeCriticalSectionAndSpinCount failed.");
"InitializeCriticalSectionAndSpinCount failed.");
this->client_open_ = std::errc::too_many_files_open;
return;
}
this->client_open_ = stdx::error{};
}
~midi_in_winmm() override
@@ -43,35 +40,22 @@ public:
// Close a connection if it exists.
midi_in_winmm::close_port();
DeleteCriticalSection(&(this->_mutex));
}
bool open_virtual_port(std::string_view) override
{
warning(configuration, "midi_in_winmm: open_virtual_port unsupported");
return false;
}
void set_client_name(std::string_view) override
{
warning(configuration, "midi_in_winmm: set_client_name unsupported");
}
void set_port_name(std::string_view) override
{
warning(configuration, "midi_in_winmm: set_port_name unsupported");
if(this->client_open_ == stdx::error{})
DeleteCriticalSection(&(this->_mutex));
}
libremidi::API get_current_api() const noexcept override { return libremidi::API::WINDOWS_MM; }
bool do_open(unsigned int portNumber)
stdx::error do_open(std::size_t portNumber)
{
MMRESULT result = midiInOpen(
&this->inHandle, portNumber, std::bit_cast<DWORD_PTR>(&midiInputCallback),
std::bit_cast<DWORD_PTR>(this), CALLBACK_FUNCTION);
if (result != MMSYSERR_NOERROR)
{
error<driver_error>(
configuration, "midi_in_winmm::open_port: error creating Windows MM MIDI input port.");
return false;
libremidi_handle_error(
configuration, "error creating Windows MM MIDI input port.");
return from_mmerr(result);
}
// Allocate and init the sysex buffers.
@@ -90,11 +74,11 @@ public:
{
midiInClose(this->inHandle);
this->inHandle = nullptr;
error<driver_error>(
libremidi_handle_error(
configuration,
"midi_in_winmm::open_port: error starting Windows MM MIDI input port "
"error starting Windows MM MIDI input port "
"(PrepareHeader).");
return false;
return from_mmerr(result);
}
// Register the buffer.
@@ -103,11 +87,11 @@ public:
{
midiInClose(this->inHandle);
this->inHandle = nullptr;
error<driver_error>(
libremidi_handle_error(
configuration,
"midi_in_winmm::open_port: error starting Windows MM MIDI input port "
"error starting Windows MM MIDI input port "
"(AddBuffer).");
return false;
return from_mmerr(result);
}
}
@@ -117,15 +101,15 @@ public:
{
midiInClose(this->inHandle);
this->inHandle = nullptr;
error<driver_error>(
configuration, "midi_in_winmm::open_port: error starting Windows MM MIDI input port.");
return false;
libremidi_handle_error(
configuration, "error starting Windows MM MIDI input port.");
return from_mmerr(result);
}
return true;
return stdx::error{};
}
bool open_port(const input_port& p, std::string_view) override
stdx::error open_port(const input_port& p, std::string_view) override
{
observer_winmm obs{{}, winmm_observer_configuration{}};
auto ports = obs.get_input_ports();
@@ -142,12 +126,12 @@ public:
if (p.port_name == port.port_name)
return do_open(port.port);
}
error<invalid_parameter_error>(
configuration, "midi_in_winmm::open_port: port not found: " + p.port_name);
return false;
libremidi_handle_error(
configuration, "port not found: " + p.port_name);
return std::errc::invalid_argument;
}
void close_port() override
stdx::error close_port() override
{
if (connected_)
{
@@ -170,9 +154,9 @@ public:
if (res != MMSYSERR_NOERROR)
{
warning(
libremidi_handle_warning(
configuration,
"midi_in_winmm::open_port: error closing Windows MM MIDI input "
"error closing Windows MM MIDI input "
"port (midiInUnprepareHeader).");
continue;
}
@@ -187,6 +171,7 @@ public:
this->inHandle = nullptr;
LeaveCriticalSection(&(this->_mutex));
}
return stdx::error{};
}
private:
@@ -255,8 +240,7 @@ private:
const auto* sysex = reinterpret_cast<MIDIHDR*>(midiMessage);
if(inputStatus == MIM_LONGERROR)
{
self.m_processing.message.bytes.clear();
self.m_processing.state = self.m_processing.main;
self.m_processing.reset();
}
else if (!self.configuration.ignore_sysex)
{
@@ -286,10 +270,9 @@ private:
LeaveCriticalSection(&(self._mutex));
if (result != MMSYSERR_NOERROR)
{
#if defined(__LIBREMIDI_DEBUG__)
std::cerr << "\nmidi_in::midiInputCallback: error sending sysex to "
"Midi device!!\n\n";
#endif
LIBREMIDI_LOG(
"error sending sysex to "
"Midi device!!");
}
}
}
+31 -48
View File
@@ -1,6 +1,7 @@
#pragma once
#include <libremidi/backends/winmm/config.hpp>
#include <libremidi/backends/winmm/helpers.hpp>
#include <libremidi/backends/winmm/observer.hpp>
#include <libremidi/detail/midi_out.hpp>
namespace libremidi
@@ -20,55 +21,34 @@ public:
midi_out_winmm(output_configuration&& conf, winmm_output_configuration&& apiconf)
: configuration{std::move(conf), std::move(apiconf)}
{
// We'll issue a warning here if no devices are available but not
// throw an error since the user can plug something in later.
if (midiOutGetNumDevs() == 0)
{
warning(
configuration,
"midi_out_winmm::initialize: no MIDI output devices currently "
"available.");
}
this->client_open_ = stdx::error{};
}
~midi_out_winmm() override
{
// Close a connection if it exists.
midi_out_winmm::close_port();
}
bool open_virtual_port(std::string_view) override
{
warning(configuration, "midi_out_winmm: open_virtual_port unsupported");
return false;
}
void set_client_name(std::string_view) override
{
warning(configuration, "midi_out_winmm: set_client_name unsupported");
}
void set_port_name(std::string_view) override
{
warning(configuration, "midi_out_winmm: set_port_name unsupported");
this->client_open_ = std::errc::not_connected;
}
libremidi::API get_current_api() const noexcept override { return libremidi::API::WINDOWS_MM; }
[[nodiscard]] bool do_open(unsigned int portNumber)
[[nodiscard]] stdx::error do_open(unsigned int portNumber)
{
MMRESULT result = midiOutOpen(&this->outHandle, portNumber, 0, 0, CALLBACK_NULL);
if (result != MMSYSERR_NOERROR)
{
error<driver_error>(
libremidi_handle_error(
configuration,
"midi_out_winmm::open_port: error creating Windows MM MIDI output "
"error creating Windows MM MIDI output "
"port.");
return false;
return from_mmerr(result);
}
return true;
return stdx::error{};
}
bool open_port(const output_port& p, std::string_view) override
stdx::error open_port(const output_port& p, std::string_view) override
{
observer_winmm obs{{}, winmm_observer_configuration{}};
auto ports = obs.get_output_ports();
@@ -85,29 +65,30 @@ public:
if (p.port_name == port.port_name)
return do_open(port.port);
}
error<invalid_parameter_error>(
configuration, "midi_out_winmm::open_port: port not found: " + p.port_name);
return false;
libremidi_handle_error(
configuration, "port not found: " + p.port_name);
return std::errc::invalid_argument;
}
void close_port() override
stdx::error close_port() override
{
if (this->outHandle)
midiOutClose(this->outHandle);
this->outHandle = nullptr;
connected_ = false;
return stdx::error{};
}
void send_message(const unsigned char* message, size_t size) override
stdx::error send_message(const unsigned char* message, size_t size) override
{
if (!connected_)
return;
return std::errc::not_connected;
if (size == 0)
{
warning(configuration, "midi_out_winmm::send_message: message argument is empty!");
return;
libremidi_handle_warning(configuration, "message argument is empty!");
return std::errc::invalid_argument;
}
if (message[0] == 0xF0)
@@ -126,18 +107,18 @@ public:
auto result = midiOutPrepareHeader(this->outHandle, &sysex, sizeof(MIDIHDR));
if (result != MMSYSERR_NOERROR)
{
error<driver_error>(
configuration, "midi_out_winmm::send_message: error preparing sysex header.");
return;
libremidi_handle_error(
configuration, "error preparing sysex header.");
return from_mmerr(result);
}
// Send the message.
result = midiOutLongMsg(this->outHandle, &sysex, sizeof(MIDIHDR));
if (result != MMSYSERR_NOERROR)
{
error<driver_error>(
configuration, "midi_out_winmm::send_message: error sending sysex message.");
return;
libremidi_handle_error(
configuration, "error sending sysex message.");
return from_mmerr(result);
}
// Unprepare the buffer and MIDIHDR.
@@ -152,11 +133,11 @@ public:
// Make sure the message size isn't too big.
if (size > 3)
{
warning(
libremidi_handle_warning(
configuration,
"midi_out_winmm::send_message: message size is greater than 3 bytes "
"message size is greater than 3 bytes "
"(and not sysex)!");
return;
return std::errc::message_size;
}
// Pack MIDI bytes into double word.
@@ -167,10 +148,12 @@ public:
auto result = midiOutShortMsg(this->outHandle, packet);
if (result != MMSYSERR_NOERROR)
{
error<driver_error>(
configuration, "midi_out_winmm::send_message: error sending MIDI message.");
libremidi_handle_error(
configuration, "error sending MIDI message.");
return from_mmerr(result);
}
}
return stdx::error{};
}
private: