20 snd_seq_client_info_t& cinfo, snd_seq_port_info_t& pinfo);
28 [[nodiscard]] std::string_view
getName()
const override;
33 const std::vector<uint8_t>& message, EmuTime::param time)
override;
35 template<
typename Archive>
36 void serialize(Archive& ar,
unsigned version);
44 snd_midi_event_t* event_parser;
55 snd_seq_client_info_t& cinfo, snd_seq_port_info_t& pinfo)
58 , destClient(snd_seq_port_info_get_client(&pinfo))
59 , destPort(snd_seq_port_info_get_port(&pinfo))
60 , name(snd_seq_client_info_get_name(&cinfo))
61 , desc(snd_seq_port_info_get_name(&pinfo))
83 void MidiOutALSA::connect()
85 sourcePort = snd_seq_create_simple_port(
86 &seq,
"MIDI out pluggable",
87 0, SND_SEQ_PORT_TYPE_MIDI_GENERIC);
90 "Failed to create ALSA port: ", snd_strerror(sourcePort));
93 int err = snd_seq_connect_to(&seq, sourcePort, destClient, destPort);
95 snd_seq_delete_simple_port(&seq, sourcePort);
97 "Failed to connect to ALSA port "
98 "(", destClient,
':', destPort,
")"
99 ": ", snd_strerror(err));
107 void MidiOutALSA::disconnect()
109 snd_midi_event_free(event_parser);
110 snd_seq_disconnect_to(&seq, sourcePort, destClient, destPort);
111 snd_seq_delete_simple_port(&seq, sourcePort);
127 const std::vector<uint8_t>& message, EmuTime::param )
130 snd_seq_ev_clear(&ev);
133 snd_seq_ev_set_source(&ev, sourcePort);
134 snd_seq_ev_set_subs(&ev);
137 long encodeLen = snd_midi_event_encode(
138 event_parser, message.data(), message.size(), &ev);
140 std::cerr <<
"Error encoding MIDI message of type "
141 << std::hex << int(message[0]) << std::dec
142 <<
": " << snd_strerror(encodeLen) <<
'\n';
145 if (ev.type == SND_SEQ_EVENT_NONE) {
146 std::cerr <<
"Incomplete MIDI message of type "
147 << std::hex << int(message[0]) << std::dec <<
'\n';
152 snd_seq_ev_set_direct(&ev);
153 int err = snd_seq_event_output(&seq, &ev);
155 std::cerr <<
"Error sending MIDI event: "
156 << snd_strerror(err) <<
'\n';
158 snd_seq_drain_output(&seq);
161 template<
typename Archive>
164 if constexpr (Archive::IS_LOADER) {
174 std::unique_ptr<MidiSessionALSA> MidiSessionALSA::instance;
182 int err = snd_seq_open(&seq,
"default", SND_SEQ_OPEN_DUPLEX, 0);
185 "Could not open sequencer: ", snd_strerror(err));
188 snd_seq_set_client_name(seq,
"openMSX");
191 instance->scanClients(controller);
194 MidiSessionALSA::MidiSessionALSA(snd_seq_t& seq_)
209 snd_seq_client_info_t* cinfo;
210 snd_seq_client_info_alloca(&cinfo);
211 snd_seq_client_info_set_client(cinfo, -1);
212 while (snd_seq_query_next_client(&seq, cinfo) >= 0) {
213 int client = snd_seq_client_info_get_client(cinfo);
214 if (client == SND_SEQ_CLIENT_SYSTEM) {
220 snd_seq_port_info_t* pinfo;
221 snd_seq_port_info_alloca(&pinfo);
222 snd_seq_port_info_set_client(pinfo, client);
223 snd_seq_port_info_set_port(pinfo, -1);
224 while (snd_seq_query_next_port(&seq, pinfo) >= 0) {
225 unsigned int type = snd_seq_port_info_get_type(pinfo);
226 if (!(type & SND_SEQ_PORT_TYPE_MIDI_GENERIC)) {
229 constexpr
unsigned int wrcaps =
230 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE;
231 if ((snd_seq_port_info_get_capability(pinfo) & wrcaps) == wrcaps) {
void printError(std::string_view message)
Represents something you can plug devices into.
void serialize(Archive &ar, unsigned version)
MidiOutALSA & operator=(const MidiOutALSA &)=delete
MidiOutALSA(snd_seq_t &seq, snd_seq_client_info_t &cinfo, snd_seq_port_info_t &pinfo)
MidiOutALSA(const MidiOutALSA &)=delete
void plugHelper(Connector &connector, EmuTime::param time) override
std::string_view getName() const override
Name used to identify this pluggable.
void recvMessage(const std::vector< uint8_t > &message, EmuTime::param time) override
Called when a full MIDI message is ready to be sent.
void unplugHelper(EmuTime::param time) override
std::string_view getDescription() const override
Description for this pluggable.
Pluggable that connects an MSX MIDI out port to a host MIDI device.
static constexpr size_t MAX_MESSAGE_SIZE
The limit for the amount of data we'll put into one MIDI message.
Lists ALSA MIDI ports we can connect to.
static void registerAll(PluggingController &controller, CliComm &cliComm)
Thrown when a plug action fails.
Central administration of Connectors and Pluggables.
void registerPluggable(std::unique_ptr< Pluggable > pluggable)
Add a Pluggable to the registry.
This file implemented 3 utility functions:
REGISTER_POLYMORPHIC_INITIALIZER(Pluggable, CassettePlayer, "CassettePlayer")
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)