1 /*
2  * Copyright (C) 2019-2020 Rerrah
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use,
8  * copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following
11  * conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 #pragma once
27 #include "RtMidi/RtMidi.hpp"
28 #include <string>
29 #include <vector>
30 #include <memory>
31 #include <mutex>
32 #include <cstdint>
33 
34 class MidiInterface
35 {
36 public:
37 	static MidiInterface &instance();
38 	~MidiInterface();
39 
40 private:
41 	MidiInterface();
42 
43 public:
44 	RtMidi::Api currentApi() const;
45 	std::string currentApiName() const;
46 	std::vector<std::string> getAvailableApi() const;
47 	bool switchApi(std::string api, std::string* errDetail = nullptr);
48 	bool switchApi(RtMidi::Api api, std::string* errDetail = nullptr);	// Use internal
49 	bool supportsVirtualPort() const;
50 	bool supportsVirtualPort(std::string api) const;
51 	std::vector<std::string> getRealInputPorts();
52 	std::vector<std::string> getRealInputPorts(const std::string& api);
53 
54 	void closeInputPort();
55 	bool openInputPort(unsigned port, std::string* errDetail = nullptr);
56 	bool openInputPortByName(const std::string &portName, std::string* errDetail = nullptr);
57 
58 	typedef void (InputHandler)(double, const uint8_t *, size_t, void *);
59 	void installInputHandler(InputHandler *handler, void *userData);
60 	void uninstallInputHandler(InputHandler *handler, void *userData);
61 
62 private:
63 	static void onMidiInput(double timestamp, std::vector<unsigned char> *message, void *userData);
64 
65 	std::unique_ptr<RtMidiIn> inputClient_;
66 	bool hasOpenInputPort_;
67 	std::mutex inputHandlersMutex_;
68 	std::vector<std::pair<InputHandler *, void *>> inputHandlers_;
69 
70 	static std::unique_ptr<MidiInterface> instance_;
71 };
72