summaryrefslogtreecommitdiff
path: root/libs/backends/portaudio/winmmemidi_output_device.h
blob: 8c4d4d0c903d9e6b2c168f92b40903b3d7261a6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
 * Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef WINMME_MIDI_OUTPUT_DEVICE_H
#define WINMME_MIDI_OUTPUT_DEVICE_H

#include <windows.h>
#include <mmsystem.h>

#include <stdint.h>
#include <pthread.h>

#include <string>

#include <boost/scoped_ptr.hpp>

#include <pbd/ringbuffer.h>

namespace ARDOUR {

class WinMMEMidiOutputDevice {
public:
	WinMMEMidiOutputDevice (int index);

	~WinMMEMidiOutputDevice ();

	bool enqueue_midi_event (uint64_t rel_event_time_us,
	                         const uint8_t* data,
	                         const size_t size);

	bool start ();
	bool stop ();

	void set_enabled (bool enable);
	bool get_enabled ();

	std::string name () const { return m_name; }

private: // Methods
	bool open (UINT index, std::string& error_msg);
	bool close (std::string& error_msg);

	bool set_device_name (UINT index);

	std::string get_error_string (MMRESULT error_code);

	bool start_midi_output_thread ();
	bool stop_midi_output_thread ();

	bool signal (HANDLE semaphore);
	bool wait (HANDLE semaphore);

	static void* midi_output_thread (void*);
	void midi_output_thread ();

	bool wait_for_microseconds (int64_t us);

	static void CALLBACK winmm_output_callback (HMIDIOUT handle,
	                                            UINT msg,
	                                            DWORD_PTR instance,
	                                            DWORD_PTR midi_data,
	                                            DWORD_PTR timestamp);

	void midi_output_callback (UINT msg, DWORD_PTR data, DWORD_PTR timestamp);

private: // Data
	HMIDIOUT m_handle;

	HANDLE m_queue_semaphore;
	HANDLE m_sysex_semaphore;

	HANDLE m_timer;

	bool m_started;
	bool m_enabled;

	std::string m_name;

	pthread_t m_output_thread_handle;

	bool m_thread_running;
	bool m_thread_quit;

	boost::scoped_ptr<RingBuffer<uint8_t> > m_midi_buffer;
};

} // namespace ARDOUR

#endif // WINMME_MIDI_OUTPUT_DEVICE_H