OpenShot Audio Library | OpenShotAudio 0.3.2
Loading...
Searching...
No Matches
juce_MidiDevices.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26MidiOutput::MidiOutput (const String& deviceName, const String& deviceIdentifier)
27 : Thread ("midi out"), deviceInfo (deviceName, deviceIdentifier)
28{
29}
30
31void MidiOutput::sendBlockOfMessagesNow (const MidiBuffer& buffer)
32{
33 MidiBuffer::Iterator i (buffer);
34 MidiMessage message;
35 int samplePosition; // Note: Not actually used, so no need to initialise.
36
37 while (i.getNextEvent (message, samplePosition))
38 sendMessageNow (message);
39}
40
41void MidiOutput::sendBlockOfMessages (const MidiBuffer& buffer,
44{
45 // You've got to call startBackgroundThread() for this to actually work..
46 jassert (isThreadRunning());
47
48 // this needs to be a value in the future - RTFM for this method!
49 jassert (millisecondCounterToStartAt > 0);
50
52
53 const uint8* data;
54 int len, time;
55
56 for (MidiBuffer::Iterator i (buffer); i.getNextEvent (data, len, time);)
57 {
59 auto* m = new PendingMessage (data, len, eventTime);
60
61 const ScopedLock sl (lock);
62
63 if (firstMessage == nullptr || firstMessage->message.getTimeStamp() > eventTime)
64 {
65 m->next = firstMessage;
66 firstMessage = m;
67 }
68 else
69 {
70 auto* mm = firstMessage;
71
72 while (mm->next != nullptr && mm->next->message.getTimeStamp() <= eventTime)
73 mm = mm->next;
74
75 m->next = mm->next;
76 mm->next = m;
77 }
78 }
79
80 notify();
81}
82
83void MidiOutput::clearAllPendingMessages()
84{
85 const ScopedLock sl (lock);
86
87 while (firstMessage != nullptr)
88 {
89 auto* m = firstMessage;
90 firstMessage = firstMessage->next;
91 delete m;
92 }
93}
94
95void MidiOutput::startBackgroundThread()
96{
97 startThread (9);
98}
99
100void MidiOutput::stopBackgroundThread()
101{
102 stopThread (5000);
103}
104
105void MidiOutput::run()
106{
107 while (! threadShouldExit())
108 {
109 auto now = Time::getMillisecondCounter();
110 uint32 eventTime = 0;
111 uint32 timeToWait = 500;
112
113 PendingMessage* message;
114
115 {
116 const ScopedLock sl (lock);
117 message = firstMessage;
118
119 if (message != nullptr)
120 {
121 eventTime = (uint32) roundToInt (message->message.getTimeStamp());
122
123 if (eventTime > now + 20)
124 {
125 timeToWait = eventTime - (now + 20);
126 message = nullptr;
127 }
128 else
129 {
130 firstMessage = message->next;
131 }
132 }
133 }
134
135 if (message != nullptr)
136 {
137 std::unique_ptr<PendingMessage> messageDeleter (message);
138
139 if (eventTime > now)
140 {
141 Time::waitForMillisecondCounter (eventTime);
142
143 if (threadShouldExit())
144 break;
145 }
146
147 if (eventTime > now - 200)
148 sendMessageNow (message->message);
149 }
150 else
151 {
152 jassert (timeToWait < 1000 * 30);
153 wait ((int) timeToWait);
154 }
155 }
156
157 clearAllPendingMessages();
158}
159
160} // namespace juce
bool getNextEvent(MidiMessage &result, int &samplePosition) noexcept