Files
2026-08-16 18:24:52 +07:00

207 lines
5.8 KiB
Plaintext

//-----------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Helpers
// Filename : public.sdk/source/vst/interappaudio/MidiIO.mm
// Created by : Steinberg, 09/2013.
// Description : VST 3 InterAppAudio
// Flags : clang-format SMTGSequencer
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------
#import "MidiIO.h"
#import <CoreMIDI/MIDINetworkSession.h>
namespace Steinberg {
namespace Vst {
namespace InterAppAudio {
//-----------------------------------------------------------------------------
MidiIO& MidiIO::instance ()
{
static MidiIO gInstance;
return gInstance;
}
//-----------------------------------------------------------------------------
MidiIO::MidiIO () = default;
//-----------------------------------------------------------------------------
MidiIO::~MidiIO ()
{
setEnabled (false);
}
//-----------------------------------------------------------------------------
void MidiIO::addProcessor (IMidiProcessor* processor)
{
midiProcessors.push_back (processor);
}
//-----------------------------------------------------------------------------
void MidiIO::removeProcessor (IMidiProcessor* processor)
{
auto it = std::find (midiProcessors.begin (), midiProcessors.end (), processor);
if (it != midiProcessors.end ())
{
midiProcessors.erase (it);
}
}
//-----------------------------------------------------------------------------
bool MidiIO::isEnabled () const
{
return client != 0;
}
//-----------------------------------------------------------------------------
bool MidiIO::setEnabled (bool state)
{
if (state)
{
if (client)
return true;
OSStatus err;
NSString* name = [[NSBundle mainBundle] bundleIdentifier];
if ((err =
MIDIClientCreate ((__bridge CFStringRef)name, notifyProc, this, &client) != noErr))
return false;
if ((err = MIDIInputPortCreate (client, CFSTR ("Input"), readProc, this, &inputPort) !=
noErr))
{
MIDIClientDispose (client);
client = 0;
return false;
}
name = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleDisplayName"];
if ((err = MIDIDestinationCreate (client, (__bridge CFStringRef)name, readProc, this,
&destPort) != noErr))
{
MIDIPortDispose (inputPort);
inputPort = 0;
MIDIClientDispose (client);
client = 0;
return false;
}
}
else
{
if (client == 0)
return true;
disconnectSources ();
MIDIEndpointDispose (destPort);
destPort = 0;
MIDIPortDispose (inputPort);
inputPort = 0;
MIDIClientDispose (client);
client = 0;
}
return true;
}
//-----------------------------------------------------------------------------
void MidiIO::setMidiNetworkEnabled (bool state)
{
if (inputPort && isMidiNetworkEnabled () != state)
{
if (!state)
{
MIDIPortDisconnectSource (inputPort,
[MIDINetworkSession defaultSession].sourceEndpoint);
}
[MIDINetworkSession defaultSession].enabled = state;
if (state)
{
MIDIPortConnectSource (inputPort, [MIDINetworkSession defaultSession].sourceEndpoint,
0);
}
}
}
//-----------------------------------------------------------------------------
bool MidiIO::isMidiNetworkEnabled () const
{
return [MIDINetworkSession defaultSession].isEnabled;
}
//-----------------------------------------------------------------------------
void MidiIO::setMidiNetworkPolicy (MIDINetworkConnectionPolicy policy)
{
[MIDINetworkSession defaultSession].connectionPolicy = policy;
}
//-----------------------------------------------------------------------------
MIDINetworkConnectionPolicy MidiIO::getMidiNetworkPolicy () const
{
return [MIDINetworkSession defaultSession].connectionPolicy;
}
//-----------------------------------------------------------------------------
void MidiIO::onInput (const MIDIPacketList* pktlist)
{
const MIDIPacket* packet = &pktlist->packet[0];
for (UInt32 i = 0; i < pktlist->numPackets; i++)
{
for (auto processor : midiProcessors)
{
processor->onMIDIEvent (packet->data[0], packet->data[1], packet->data[2], 0, false);
}
packet = MIDIPacketNext (packet);
}
}
//-----------------------------------------------------------------------------
void MidiIO::onSourceAdded (MIDIObjectRef source)
{
connectedSources.push_back ((MIDIEndpointRef)source);
MIDIPortConnectSource (inputPort, (MIDIEndpointRef)source, NULL);
}
//-----------------------------------------------------------------------------
void MidiIO::disconnectSources ()
{
for (auto source : connectedSources)
MIDIPortDisconnectSource (inputPort, source);
connectedSources.clear ();
}
//-----------------------------------------------------------------------------
void MidiIO::onSetupChanged ()
{
disconnectSources ();
ItemCount numSources = MIDIGetNumberOfSources ();
for (ItemCount i = 0; i < numSources; i++)
{
onSourceAdded (MIDIGetSource (i));
}
}
//-----------------------------------------------------------------------------
void MidiIO::readProc (const MIDIPacketList* pktlist, void* readProcRefCon, void* srcConnRefCon)
{
MidiIO* io = static_cast<MidiIO*> (readProcRefCon);
io->onInput (pktlist);
}
//-----------------------------------------------------------------------------
void MidiIO::notifyProc (const MIDINotification* message, void* refCon)
{
if (message->messageID == kMIDIMsgSetupChanged)
{
MidiIO* mio = (MidiIO*)refCon;
mio->onSetupChanged ();
}
}
}
}
} // namespaces