Use portaudio error codes in the PortaudioIO class.
[ardour.git] / libs / backends / portaudio / winmmemidi_output_device.h
1 /*
2  * Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #ifndef WINMME_MIDI_OUTPUT_DEVICE_H
20 #define WINMME_MIDI_OUTPUT_DEVICE_H
21
22 #include <windows.h>
23 #include <mmsystem.h>
24
25 #include <stdint.h>
26 #include <pthread.h>
27
28 #include <string>
29
30 #include <boost/scoped_ptr.hpp>
31
32 #include <pbd/ringbuffer.h>
33
34 namespace ARDOUR {
35
36 class WinMMEMidiOutputDevice {
37 public:
38         WinMMEMidiOutputDevice (int index);
39
40         ~WinMMEMidiOutputDevice ();
41
42         bool enqueue_midi_event (uint64_t rel_event_time_us,
43                                  const uint8_t* data,
44                                  const size_t size);
45
46         bool start ();
47         bool stop ();
48
49         void set_enabled (bool enable);
50         bool get_enabled ();
51
52         std::string name () const { return m_name; }
53
54 private: // Methods
55         bool open (UINT index, std::string& error_msg);
56         bool close (std::string& error_msg);
57
58         bool set_device_name (UINT index);
59
60         std::string get_error_string (MMRESULT error_code);
61
62         bool start_midi_output_thread ();
63         bool stop_midi_output_thread ();
64
65         bool signal (HANDLE semaphore);
66         bool wait (HANDLE semaphore);
67
68         static void* midi_output_thread (void*);
69         void midi_output_thread ();
70
71         bool wait_for_microseconds (int64_t us);
72
73         static void CALLBACK winmm_output_callback (HMIDIOUT handle,
74                                                     UINT msg,
75                                                     DWORD_PTR instance,
76                                                     DWORD_PTR midi_data,
77                                                     DWORD_PTR timestamp);
78
79         void midi_output_callback (UINT msg, DWORD_PTR data, DWORD_PTR timestamp);
80
81 private: // Data
82         HMIDIOUT m_handle;
83
84         HANDLE m_queue_semaphore;
85         HANDLE m_sysex_semaphore;
86
87         HANDLE m_timer;
88
89         bool m_started;
90         bool m_enabled;
91
92         std::string m_name;
93
94         pthread_t m_output_thread_handle;
95
96         bool m_thread_running;
97         bool m_thread_quit;
98
99         boost::scoped_ptr<RingBuffer<uint8_t> > m_midi_buffer;
100 };
101
102 } // namespace ARDOUR
103
104 #endif // WINMME_MIDI_OUTPUT_DEVICE_H