CorsixTH engine (the C++ part)
Open source implementation of Theme Hospital
Loading...
Searching...
No Matches
midi_player.h
Go to the documentation of this file.
1/*
2Copyright (c) 2025 Stephen Baker
3
4Permission is hereby granted, free of charge, to any person obtaining a copy of
5this software and associated documentation files (the "Software"), to deal in
6the Software without restriction, including without limitation the rights to
7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8of the Software, and to permit persons to whom the Software is furnished to do
9so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all
12copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20SOFTWARE.
21*/
22
23#ifndef CORSIX_TH_MIDI_PLAYER_H
24#define CORSIX_TH_MIDI_PLAYER_H
25
26#include "config.h"
27
28#ifdef WITH_MIDI_DEVICE
29#include <rtmidi/RtMidi.h>
30
31#include <atomic>
32#include <climits>
33#include <condition_variable>
34#include <memory>
35#include <optional>
36#include <queue>
37#include <string>
38#include <thread>
39#include <vector>
40
41struct playback_state;
42
46constexpr unsigned int midi_virtual_port_index = UINT_MAX;
47
51const char* const midi_external_port_name = "midi_out";
52
58class open_midi_port {
59 public:
66 open_midi_port(RtMidiOut& midi_out, unsigned int port)
67 : midi_out(midi_out), port(port) {
68 if (port == midi_virtual_port_index) {
69 midi_out.openVirtualPort(midi_external_port_name);
70 } else {
71 midi_out.openPort(port, midi_external_port_name);
72 }
73 }
74 open_midi_port(const open_midi_port&) = delete;
75 open_midi_port& operator=(const open_midi_port&) = delete;
76 open_midi_port(const open_midi_port&&) = delete;
77 open_midi_port& operator=(const open_midi_port&&) = delete;
78
82 ~open_midi_port() { midi_out.closePort(); }
83
87 bool is_virtual() const { return port == midi_virtual_port_index; }
88
92 unsigned int get_port() const { return port; }
93
94 private:
96 RtMidiOut& midi_out;
97
99 unsigned int port;
100};
101
105enum class player_command {
107 stop,
108
110 pause,
111
113 resume,
114
117 set_volume,
118
120 noop
121};
122
128class player_command_queue {
129 public:
134 void push(player_command command);
135
145 player_command pop(bool blocking);
146
150 void clear();
151
152 private:
154 std::mutex mut{};
155
157 std::queue<player_command> queue{};
158
160 std::condition_variable cv{};
161};
162
166class midi_player {
167 public:
194 midi_player(std::string_view api, std::string_view port_name,
195 bool use_master_volume_sysex);
196 midi_player(const midi_player&) = delete;
197 midi_player& operator=(const midi_player&) = delete;
198 ~midi_player();
199
203 static std::vector<std::string> api_list();
204
208 std::vector<std::string> port_list() const;
209
215 void set_port(std::string_view port_name);
216
221 void set_volume(double volume);
222
228 void play_xmi(const unsigned char* xmi_data, size_t xmi_length);
229
235 void stop();
236
240 void pause();
241
245 void resume();
246
247 private:
253 void open_default_port();
254
262 bool is_port_open() const;
263
270 static void init_playback(playback_state& state);
271
278 static void playback_loop(playback_state&& state);
279
281 std::unique_ptr<RtMidiOut> midi_out;
282
284 std::optional<open_midi_port> port;
285
287 std::thread playback_thread{};
288
290 player_command_queue command_queue{};
291
293 std::atomic<double> volume{1.0};
294
297 bool use_master_volume_sysex{false};
298
300 std::mutex midi_out_mutex{};
301};
302
303#else // WITH_MIDI_DEVICE
304
305class midi_player {};
306
307#endif // WITH_MIDI_DEVICE
308
309#endif // CORSIX_TH_MIDI_PLAYER_H
Definition midi_player.h:305