11namespace tracktion {
inline namespace engine
19 :
AudioIODevice (
"Hosted Device",
"Hosted Device"), audioIf (aif), onDestroy (onDestroy_)
28 juce::StringArray getOutputChannelNames()
override {
return audioIf.getOutputChannelNames(); }
29 juce::StringArray getInputChannelNames()
override {
return audioIf.getInputChannelNames(); }
32 int getDefaultBufferSize()
override {
return audioIf.parameters.
blockSize; }
36 double sampleRate,
int bufferSizeSamples)
override
38 ignoreUnused (inputChannels, outputChannels, sampleRate, bufferSizeSamples);
42 void close()
override {}
55 bool isOpen()
override {
return true; }
56 bool isPlaying()
override {
return true; }
58 int getCurrentBitDepth()
override {
return 16; }
59 int getOutputLatencyInSamples()
override {
return 0; }
60 int getInputLatencyInSamples()
override {
return 0; }
61 bool hasControlPanel()
const override {
return false; }
62 bool showControlPanel()
override {
return false; }
63 bool setAudioPreprocessingEnabled (
bool)
override {
return false; }
64 int getCurrentBufferSizeSamples()
override {
return audioIf.parameters.
blockSize; }
65 double getCurrentSampleRate()
override {
return audioIf.parameters.
sampleRate; }
83 if (callback !=
nullptr)
92 void settingsChanged()
94 if (callback !=
nullptr)
109 : AudioIODeviceType (
"Hosted Device"), audioIf (aif)
114 if (audioIf.deviceType ==
this)
115 audioIf.deviceType =
nullptr;
118 void scanForDevices()
override {}
119 juce::StringArray getDeviceNames (
bool =
false)
const override {
return {
"Hosted Device" }; }
120 int getDefaultDeviceIndex (
bool)
const override {
return 0; }
122 bool hasSeparateInputsAndOutputs()
const override {
return false; }
129 ptr->devices.removeFirstMatchingValue (d);
131 devices.add (device);
137 for (
auto device : devices)
138 device->processBlock (buffer);
141 void settingsChanged()
143 for (
auto device : devices)
144 device->settingsChanged();
165 audioIf.midiInputs.removeFirstMatchingValue (
this);
170 return virtualMidiDevice;
175 return new HostedMidiInputDeviceInstance (*
this, epc);
178 void loadProps()
override
180 auto n = engine.
getPropertyStorage().getXmlPropertyItem (SettingID::midiin, getName());
181 MidiInputDevice::loadMidiProps (n.get());
184 void saveProps()
override
188 MidiInputDevice::saveMidiProps (n);
197 MidiInputDevice::handleIncomingMidiMessage (nullptr, mm.getMessage());
202 for (
auto instance : instances)
203 if (auto hostedInstance = dynamic_cast<HostedMidiInputDeviceInstance*> (instance))
204 hostedInstance->processBlock (pendingMidiMessages);
206 pendingMidiMessages.
clear();
209 using MidiInputDevice::handleIncomingMidiMessage;
213 pendingMidiMessages.
addEvent (m, 0);
217 void closeDevice()
override {}
221 class HostedMidiInputDeviceInstance :
public MidiInputDeviceInstanceBase
224 HostedMidiInputDeviceInstance (HostedMidiInputDevice& owner_, EditPlaybackContext& epc)
225 : MidiInputDeviceInstanceBase (owner_, epc)
236 for (
auto mmm : midi)
238 const auto blockStreamTime = tracktion::graph::sampleToTime (mmm.samplePosition, sampleRate);
240 auto msg = mmm.getMessage();
241 msg.setTimeStamp (globalStreamTime + blockStreamTime);
242 handleIncomingMidiMessage (std::move (msg));
247 const double sampleRate =
context.getSampleRate();
249 HostedMidiInputDevice& getHostedMidiInputDevice()
const {
return static_cast<HostedMidiInputDevice&
> (
owner); }
253 HostedAudioDeviceInterface& audioIf;
270 audioIf.midiOutputs.removeFirstMatchingValue (
this);
275 return new HostedMidiOutputDeviceInstance (*
this, epc);
280 for (
auto m : toSend)
282 auto t = m.getTimeStamp() * audioIf.parameters.
sampleRate;
283 midi.addEvent (m,
int (t));
291 toSend.addMidiMessage (message, 0, MidiMessageArray::notMPE);
292 toSend.sortByTimestamp();
307 const auto deltaTime = -editTime - outputDevice.getDeviceDelay();
308 outputDevice.toSend.mergeFromAndClearWithOffset (mma, deltaTime.inSeconds());
320HostedAudioDeviceInterface::HostedAudioDeviceInterface (
Engine& e)
325void HostedAudioDeviceInterface::initialise (
const Parameters& p)
332 if (deviceType ==
nullptr)
333 for (
auto device : dm.deviceManager.getAvailableDeviceTypes())
335 deviceType = hostedAudioDeviceType;
338 if (deviceType ==
nullptr)
344 dm.deviceManager.setCurrentAudioDeviceType (
"Hosted Device",
true);
346 jassert (dm.deviceManager.getCurrentAudioDeviceType() ==
"Hosted Device");
347 jassert (dm.deviceManager.getCurrentDeviceTypeObject() == deviceType);
349 for (
int i = 0; i < dm.getNumWaveOutDevices(); i++)
350 if (
auto wo = dm.getWaveOutDevice (i))
351 wo->setEnabled (
true);
353 for (
int i = 0; i < dm.getNumWaveInDevices(); i++)
354 if (
auto wi = dm.getWaveInDevice (i))
355 wi->setStereoPair (
false);
357 for (
int i = 0; i < dm.getNumWaveInDevices(); i++)
359 if (
auto wi = dm.getWaveInDevice (i))
362 wi->setEnabled (
true);
367void HostedAudioDeviceInterface::prepareToPlay (
double sampleRate,
int blockSize)
374 || maxChannels != newMaxChannels)
376 maxChannels = newMaxChannels;
380 if (deviceType !=
nullptr)
381 deviceType->settingsChanged();
387 for (
auto input : midiInputs)
388 if (auto hostedInput = dynamic_cast<HostedMidiInputDevice*> (input))
389 hostedInput->processBlock (midi);
393 if (deviceType !=
nullptr)
394 deviceType->processBlock (buffer);
396 for (
auto output : midiOutputs)
397 if (auto hostedOutput = dynamic_cast<HostedMidiOutputDevice*> (output))
398 hostedOutput->processBlock (midi);
427 if (i < parameters.outputNames.
size())
428 res.
add (parameters.outputNames[i]);
436MidiOutputDevice* HostedAudioDeviceInterface::createMidiOutput()
438 auto device =
new HostedMidiOutputDevice (*
this);
439 midiOutputs.add (device);
443MidiInputDevice* HostedAudioDeviceInterface::createMidiInput()
445 auto device =
new HostedMidiInputDevice (*
this);
446 midiInputs.add (device);
int getNumChannels() const noexcept
int getNumSamples() const noexcept
const Type *const * getArrayOfReadPointers() const noexcept
Type *const * getArrayOfWritePointers() noexcept
virtual void audioDeviceIOCallbackWithContext(const float *const *inputChannelData, int numInputChannels, float *const *outputChannelData, int numOutputChannels, int numSamples, const AudioIODeviceCallbackContext &context)
virtual void audioDeviceAboutToStart(AudioIODevice *device)=0
virtual void audioDeviceStopped()=0
AudioIODevice(const String &deviceName, const String &typeName)
BigInteger & setRange(int startBit, int numBits, bool shouldBeSet)
bool addEvent(const MidiMessage &midiMessage, int sampleNumber)
int size() const noexcept
void add(String stringToAdd)
double getCurrentStreamTime() const noexcept
Returns the current block's stream time.
Engine & engine
A reference to the Engine.
The Engine is the central class for all tracktion sessions.
PropertyStorage & getPropertyStorage() const
Returns the PropertyStorage user settings customisable XML file.
DeviceManager & getDeviceManager() const
Returns the DeviceManager instance for handling audio / MIDI devices.
The HostedAudioDeviceInterface allows an application or plugin to pass audio and midi buffers to the ...
double sampleRate
Expected sample rate.
static bool isHostedMidiInputDevice(const MidiInputDevice &)
Returns true if the MidiInput device is a HostedMidiInputDevice.
int outputChannels
Number of audio output channels.
int inputChannels
Number of audio input channels.
int blockSize
Expected block size.
juce::StringArray inputNames
Names of your audio channels.
#define TRANS(stringLiteral)
#define JUCE_DECLARE_WEAK_REFERENCEABLE(Class)
Represents a position in real-life time.