OpenShot Library | libopenshot-audio 0.2.0
juce_MidiOutput.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
27{
28 PendingMessage (const void* data, int len, double timeStamp)
29 : message (data, len, timeStamp)
30 {}
31
32 MidiMessage message;
33 PendingMessage* next;
34};
35
36MidiOutput::MidiOutput (const String& deviceName)
37 : Thread ("midi out"), name (deviceName)
38{
39}
40
42{
43 MidiBuffer::Iterator i (buffer);
44 MidiMessage message;
45 int samplePosition; // Note: Not actually used, so no need to initialise.
46
47 while (i.getNextEvent (message, samplePosition))
48 sendMessageNow (message);
49}
50
54{
55 // You've got to call startBackgroundThread() for this to actually work..
56 jassert (isThreadRunning());
57
58 // this needs to be a value in the future - RTFM for this method!
59 jassert (millisecondCounterToStartAt > 0);
60
62
63 const uint8* data;
64 int len, time;
65
66 for (MidiBuffer::Iterator i (buffer); i.getNextEvent (data, len, time);)
67 {
69 auto* m = new PendingMessage (data, len, eventTime);
70
71 const ScopedLock sl (lock);
72
73 if (firstMessage == nullptr || firstMessage->message.getTimeStamp() > eventTime)
74 {
75 m->next = firstMessage;
76 firstMessage = m;
77 }
78 else
79 {
80 auto* mm = firstMessage;
81
82 while (mm->next != nullptr && mm->next->message.getTimeStamp() <= eventTime)
83 mm = mm->next;
84
85 m->next = mm->next;
86 mm->next = m;
87 }
88 }
89
90 notify();
91}
92
94{
95 const ScopedLock sl (lock);
96
97 while (firstMessage != nullptr)
98 {
99 auto* m = firstMessage;
100 firstMessage = firstMessage->next;
101 delete m;
102 }
103}
104
109
111{
112 stopThread (5000);
113}
114
115void MidiOutput::run()
116{
117 while (! threadShouldExit())
118 {
120 uint32 eventTime = 0;
121 uint32 timeToWait = 500;
122
123 PendingMessage* message;
124
125 {
126 const ScopedLock sl (lock);
127 message = firstMessage;
128
129 if (message != nullptr)
130 {
131 eventTime = (uint32) roundToInt (message->message.getTimeStamp());
132
133 if (eventTime > now + 20)
134 {
135 timeToWait = eventTime - (now + 20);
136 message = nullptr;
137 }
138 else
139 {
140 firstMessage = message->next;
141 }
142 }
143 }
144
145 if (message != nullptr)
146 {
147 std::unique_ptr<PendingMessage> messageDeleter (message);
148
149 if (eventTime > now)
150 {
152
153 if (threadShouldExit())
154 break;
155 }
156
157 if (eventTime > now - 200)
158 sendMessageNow (message->message);
159 }
160 else
161 {
162 jassert (timeToWait < 1000 * 30);
163 wait ((int) timeToWait);
164 }
165 }
166
168}
169
170} // namespace juce
Holds a resizable array of primitive or copy-by-value objects.
Definition juce_Array.h:60
Used to iterate through the events in a MidiBuffer.
bool getNextEvent(MidiMessage &result, int &samplePosition) noexcept
Retrieves a copy of the next event from the buffer.
Holds a sequence of time-stamped midi events.
Encapsulates a MIDI message.
double getTimeStamp() const noexcept
Returns the timestamp associated with this message.
void sendBlockOfMessagesNow(const MidiBuffer &buffer)
Sends out a sequence of MIDI messages immediately.
void stopBackgroundThread()
Stops the background thread, and clears any pending midi events.
void clearAllPendingMessages()
Gets rid of any midi messages that had been added by sendBlockOfMessages().
void startBackgroundThread()
Starts up a background thread so that the device can send blocks of data.
void sendMessageNow(const MidiMessage &message)
Sends out a MIDI message immediately.
void sendBlockOfMessages(const MidiBuffer &buffer, double millisecondCounterToStartAt, double samplesPerSecondForBuffer)
This lets you supply a block of messages that will be sent out at some point in the future.
The JUCE String class!
Definition juce_String.h:43
Encapsulates a thread.
Definition juce_Thread.h:47
void startThread()
Starts the thread running.
bool wait(int timeOutMilliseconds) const
Suspends the execution of this thread until either the specified timeout period has elapsed,...
bool threadShouldExit() const
Checks whether the thread has been told to stop running.
bool stopThread(int timeOutMilliseconds)
Attempts to stop the thread running.
void notify() const
Wakes up the thread.
bool isThreadRunning() const
Returns true if the thread is currently active.
static void waitForMillisecondCounter(uint32 targetTime) noexcept
Waits until the getMillisecondCounter() reaches a given value.
static uint32 getMillisecondCounter() noexcept
Returns the number of millisecs since a fixed event (usually system startup).