OpenShot Audio Library | OpenShotAudio: juce_MidiDevices.cpp Source File

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
31 void 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
41 void MidiOutput::sendBlockOfMessages (const MidiBuffer& buffer,
42 double millisecondCounterToStartAt,
43 double samplesPerSecondForBuffer)
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
51 auto timeScaleFactor = 1000.0 / samplesPerSecondForBuffer;
52
53 const uint8* data;
54 int len, time;
55
56 for (MidiBuffer::Iterator i (buffer); i.getNextEvent (data, len, time);)
57 {
58 auto eventTime = millisecondCounterToStartAt + timeScaleFactor * time;
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
83 void 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
95 void MidiOutput::startBackgroundThread()
96{
97 startThread (9);
98}
99
100 void 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
juce::GenericScopedLock
Definition: juce_ScopedLock.h:55
juce::MidiBuffer::Iterator
Definition: juce_MidiBuffer.h:171
juce::MidiBuffer::Iterator::getNextEvent
bool getNextEvent(MidiMessage &result, int &samplePosition) noexcept
Definition: juce_MidiBuffer.cpp:219
juce::MidiBuffer
Definition: juce_MidiBuffer.h:43
juce::MidiMessage
Definition: juce_MidiMessage.h:35