New Class to handle UI
[juce-lv2.git] / juce / source / src / audio / midi / juce_MidiOutput.cpp
blob6c01aad41c6a5a10d3daec3d4afbb9b272320aa0
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../core/juce_StandardHeader.h"
28 BEGIN_JUCE_NAMESPACE
30 #include "juce_MidiOutput.h"
31 #include "../../core/juce_Time.h"
34 //==============================================================================
35 struct MidiOutput::PendingMessage
37 PendingMessage (const void* const data, const int len, const double timeStamp)
38 : message (data, len, timeStamp)
41 MidiMessage message;
42 PendingMessage* next;
45 MidiOutput::MidiOutput()
46 : Thread ("midi out"),
47 internal (nullptr),
48 firstMessage (nullptr)
52 void MidiOutput::sendBlockOfMessages (const MidiBuffer& buffer,
53 const double millisecondCounterToStartAt,
54 double samplesPerSecondForBuffer)
56 // You've got to call startBackgroundThread() for this to actually work..
57 jassert (isThreadRunning());
59 // this needs to be a value in the future - RTFM for this method!
60 jassert (millisecondCounterToStartAt > 0);
62 const double timeScaleFactor = 1000.0 / samplesPerSecondForBuffer;
64 MidiBuffer::Iterator i (buffer);
66 const uint8* data;
67 int len, time;
69 while (i.getNextEvent (data, len, time))
71 const double eventTime = millisecondCounterToStartAt + timeScaleFactor * time;
73 PendingMessage* const m = new PendingMessage (data, len, eventTime);
75 const ScopedLock sl (lock);
77 if (firstMessage == nullptr || firstMessage->message.getTimeStamp() > eventTime)
79 m->next = firstMessage;
80 firstMessage = m;
82 else
84 PendingMessage* mm = firstMessage;
86 while (mm->next != nullptr && mm->next->message.getTimeStamp() <= eventTime)
87 mm = mm->next;
89 m->next = mm->next;
90 mm->next = m;
94 notify();
97 void MidiOutput::clearAllPendingMessages()
99 const ScopedLock sl (lock);
101 while (firstMessage != nullptr)
103 PendingMessage* const m = firstMessage;
104 firstMessage = firstMessage->next;
105 delete m;
109 void MidiOutput::startBackgroundThread()
111 startThread (9);
114 void MidiOutput::stopBackgroundThread()
116 stopThread (5000);
119 void MidiOutput::run()
121 while (! threadShouldExit())
123 uint32 now = Time::getMillisecondCounter();
124 uint32 eventTime = 0;
125 uint32 timeToWait = 500;
127 PendingMessage* message;
130 const ScopedLock sl (lock);
131 message = firstMessage;
133 if (message != nullptr)
135 eventTime = roundToInt (message->message.getTimeStamp());
137 if (eventTime > now + 20)
139 timeToWait = eventTime - (now + 20);
140 message = nullptr;
142 else
144 firstMessage = message->next;
149 if (message != nullptr)
151 if (eventTime > now)
153 Time::waitForMillisecondCounter (eventTime);
155 if (threadShouldExit())
156 break;
159 if (eventTime > now - 200)
160 sendMessageNow (message->message);
162 delete message;
164 else
166 jassert (timeToWait < 1000 * 30);
167 wait (timeToWait);
171 clearAllPendingMessages();
175 END_JUCE_NAMESPACE