mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-23 01:44:22 +00:00
First check-in of the "jucequake": a major re-organisation of the library to break it up into modules. For more details about this, see the website forum..
This commit is contained in:
parent
1a21c89755
commit
b70e0a28d2
1527 changed files with 90380 additions and 396643 deletions
|
|
@ -1,444 +0,0 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-11 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// (This file gets included by juce_linux_NativeCode.cpp, rather than being
|
||||
// compiled on its own).
|
||||
#if JUCE_INCLUDED_FILE
|
||||
#if JUCE_ALSA
|
||||
|
||||
//==============================================================================
|
||||
namespace
|
||||
{
|
||||
snd_seq_t* iterateMidiDevices (const bool forInput,
|
||||
StringArray& deviceNamesFound,
|
||||
const int deviceIndexToOpen)
|
||||
{
|
||||
snd_seq_t* returnedHandle = nullptr;
|
||||
snd_seq_t* seqHandle = nullptr;
|
||||
|
||||
if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT
|
||||
: SND_SEQ_OPEN_OUTPUT, 0) == 0)
|
||||
{
|
||||
snd_seq_system_info_t* systemInfo = nullptr;
|
||||
snd_seq_client_info_t* clientInfo = nullptr;
|
||||
|
||||
if (snd_seq_system_info_malloc (&systemInfo) == 0)
|
||||
{
|
||||
if (snd_seq_system_info (seqHandle, systemInfo) == 0
|
||||
&& snd_seq_client_info_malloc (&clientInfo) == 0)
|
||||
{
|
||||
int numClients = snd_seq_system_info_get_cur_clients (systemInfo);
|
||||
|
||||
while (--numClients >= 0 && returnedHandle == 0)
|
||||
{
|
||||
if (snd_seq_query_next_client (seqHandle, clientInfo) == 0)
|
||||
{
|
||||
snd_seq_port_info_t* portInfo;
|
||||
if (snd_seq_port_info_malloc (&portInfo) == 0)
|
||||
{
|
||||
int numPorts = snd_seq_client_info_get_num_ports (clientInfo);
|
||||
const int client = snd_seq_client_info_get_client (clientInfo);
|
||||
|
||||
snd_seq_port_info_set_client (portInfo, client);
|
||||
snd_seq_port_info_set_port (portInfo, -1);
|
||||
|
||||
while (--numPorts >= 0)
|
||||
{
|
||||
if (snd_seq_query_next_port (seqHandle, portInfo) == 0
|
||||
&& (snd_seq_port_info_get_capability (portInfo)
|
||||
& (forInput ? SND_SEQ_PORT_CAP_READ
|
||||
: SND_SEQ_PORT_CAP_WRITE)) != 0)
|
||||
{
|
||||
deviceNamesFound.add (snd_seq_client_info_get_name (clientInfo));
|
||||
|
||||
if (deviceNamesFound.size() == deviceIndexToOpen + 1)
|
||||
{
|
||||
const int sourcePort = snd_seq_port_info_get_port (portInfo);
|
||||
const int sourceClient = snd_seq_client_info_get_client (clientInfo);
|
||||
|
||||
if (sourcePort != -1)
|
||||
{
|
||||
if (forInput)
|
||||
{
|
||||
snd_seq_set_client_name (seqHandle, "Juce Midi Input");
|
||||
|
||||
const int portId = snd_seq_create_simple_port (seqHandle, "Juce Midi In Port",
|
||||
SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
|
||||
SND_SEQ_PORT_TYPE_MIDI_GENERIC);
|
||||
|
||||
snd_seq_connect_from (seqHandle, portId, sourceClient, sourcePort);
|
||||
}
|
||||
else
|
||||
{
|
||||
snd_seq_set_client_name (seqHandle, "Juce Midi Output");
|
||||
|
||||
const int portId = snd_seq_create_simple_port (seqHandle, "Juce Midi Out Port",
|
||||
SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ,
|
||||
SND_SEQ_PORT_TYPE_MIDI_GENERIC);
|
||||
|
||||
snd_seq_connect_to (seqHandle, portId, sourceClient, sourcePort);
|
||||
}
|
||||
|
||||
returnedHandle = seqHandle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snd_seq_port_info_free (portInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snd_seq_client_info_free (clientInfo);
|
||||
}
|
||||
|
||||
snd_seq_system_info_free (systemInfo);
|
||||
}
|
||||
|
||||
if (returnedHandle == 0)
|
||||
snd_seq_close (seqHandle);
|
||||
}
|
||||
|
||||
deviceNamesFound.appendNumbersToDuplicates (true, true);
|
||||
|
||||
return returnedHandle;
|
||||
}
|
||||
|
||||
snd_seq_t* createMidiDevice (const bool forInput, const String& deviceNameToOpen)
|
||||
{
|
||||
snd_seq_t* seqHandle = nullptr;
|
||||
|
||||
if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT
|
||||
: SND_SEQ_OPEN_OUTPUT, 0) == 0)
|
||||
{
|
||||
snd_seq_set_client_name (seqHandle,
|
||||
(deviceNameToOpen + (forInput ? " Input" : " Output")).toUTF8());
|
||||
|
||||
const int portId
|
||||
= snd_seq_create_simple_port (seqHandle,
|
||||
forInput ? "in"
|
||||
: "out",
|
||||
forInput ? (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)
|
||||
: (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ),
|
||||
forInput ? SND_SEQ_PORT_TYPE_APPLICATION
|
||||
: SND_SEQ_PORT_TYPE_MIDI_GENERIC);
|
||||
|
||||
if (portId < 0)
|
||||
{
|
||||
snd_seq_close (seqHandle);
|
||||
seqHandle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return seqHandle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class MidiOutputDevice
|
||||
{
|
||||
public:
|
||||
MidiOutputDevice (MidiOutput* const midiOutput_,
|
||||
snd_seq_t* const seqHandle_)
|
||||
:
|
||||
midiOutput (midiOutput_),
|
||||
seqHandle (seqHandle_),
|
||||
maxEventSize (16 * 1024)
|
||||
{
|
||||
jassert (seqHandle != 0 && midiOutput != 0);
|
||||
snd_midi_event_new (maxEventSize, &midiParser);
|
||||
}
|
||||
|
||||
~MidiOutputDevice()
|
||||
{
|
||||
snd_midi_event_free (midiParser);
|
||||
snd_seq_close (seqHandle);
|
||||
}
|
||||
|
||||
void sendMessageNow (const MidiMessage& message)
|
||||
{
|
||||
if (message.getRawDataSize() > maxEventSize)
|
||||
{
|
||||
maxEventSize = message.getRawDataSize();
|
||||
snd_midi_event_free (midiParser);
|
||||
snd_midi_event_new (maxEventSize, &midiParser);
|
||||
}
|
||||
|
||||
snd_seq_event_t event;
|
||||
snd_seq_ev_clear (&event);
|
||||
|
||||
snd_midi_event_encode (midiParser,
|
||||
message.getRawData(),
|
||||
message.getRawDataSize(),
|
||||
&event);
|
||||
|
||||
snd_midi_event_reset_encode (midiParser);
|
||||
|
||||
snd_seq_ev_set_source (&event, 0);
|
||||
snd_seq_ev_set_subs (&event);
|
||||
snd_seq_ev_set_direct (&event);
|
||||
|
||||
snd_seq_event_output (seqHandle, &event);
|
||||
snd_seq_drain_output (seqHandle);
|
||||
}
|
||||
|
||||
private:
|
||||
MidiOutput* const midiOutput;
|
||||
snd_seq_t* const seqHandle;
|
||||
snd_midi_event_t* midiParser;
|
||||
int maxEventSize;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiOutputDevice);
|
||||
};
|
||||
|
||||
StringArray MidiOutput::getDevices()
|
||||
{
|
||||
StringArray devices;
|
||||
iterateMidiDevices (false, devices, -1);
|
||||
return devices;
|
||||
}
|
||||
|
||||
int MidiOutput::getDefaultDeviceIndex()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
MidiOutput* MidiOutput::openDevice (int deviceIndex)
|
||||
{
|
||||
MidiOutput* newDevice = nullptr;
|
||||
|
||||
StringArray devices;
|
||||
snd_seq_t* const handle = iterateMidiDevices (false, devices, deviceIndex);
|
||||
|
||||
if (handle != 0)
|
||||
{
|
||||
newDevice = new MidiOutput();
|
||||
newDevice->internal = new MidiOutputDevice (newDevice, handle);
|
||||
}
|
||||
|
||||
return newDevice;
|
||||
}
|
||||
|
||||
MidiOutput* MidiOutput::createNewDevice (const String& deviceName)
|
||||
{
|
||||
MidiOutput* newDevice = nullptr;
|
||||
|
||||
snd_seq_t* const handle = createMidiDevice (false, deviceName);
|
||||
|
||||
if (handle != 0)
|
||||
{
|
||||
newDevice = new MidiOutput();
|
||||
newDevice->internal = new MidiOutputDevice (newDevice, handle);
|
||||
}
|
||||
|
||||
return newDevice;
|
||||
}
|
||||
|
||||
MidiOutput::~MidiOutput()
|
||||
{
|
||||
delete static_cast <MidiOutputDevice*> (internal);
|
||||
}
|
||||
|
||||
void MidiOutput::sendMessageNow (const MidiMessage& message)
|
||||
{
|
||||
static_cast <MidiOutputDevice*> (internal)->sendMessageNow (message);
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class MidiInputThread : public Thread
|
||||
{
|
||||
public:
|
||||
MidiInputThread (MidiInput* const midiInput_,
|
||||
snd_seq_t* const seqHandle_,
|
||||
MidiInputCallback* const callback_)
|
||||
: Thread ("Juce MIDI Input"),
|
||||
midiInput (midiInput_),
|
||||
seqHandle (seqHandle_),
|
||||
callback (callback_)
|
||||
{
|
||||
jassert (seqHandle != 0 && callback != 0 && midiInput != 0);
|
||||
}
|
||||
|
||||
~MidiInputThread()
|
||||
{
|
||||
snd_seq_close (seqHandle);
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
const int maxEventSize = 16 * 1024;
|
||||
snd_midi_event_t* midiParser;
|
||||
|
||||
if (snd_midi_event_new (maxEventSize, &midiParser) >= 0)
|
||||
{
|
||||
HeapBlock <uint8> buffer (maxEventSize);
|
||||
|
||||
const int numPfds = snd_seq_poll_descriptors_count (seqHandle, POLLIN);
|
||||
struct pollfd* const pfd = (struct pollfd*) alloca (numPfds * sizeof (struct pollfd));
|
||||
|
||||
snd_seq_poll_descriptors (seqHandle, pfd, numPfds, POLLIN);
|
||||
|
||||
while (! threadShouldExit())
|
||||
{
|
||||
if (poll (pfd, numPfds, 500) > 0)
|
||||
{
|
||||
snd_seq_event_t* inputEvent = nullptr;
|
||||
|
||||
snd_seq_nonblock (seqHandle, 1);
|
||||
|
||||
do
|
||||
{
|
||||
if (snd_seq_event_input (seqHandle, &inputEvent) >= 0)
|
||||
{
|
||||
// xxx what about SYSEXes that are too big for the buffer?
|
||||
const int numBytes = snd_midi_event_decode (midiParser, buffer, maxEventSize, inputEvent);
|
||||
|
||||
snd_midi_event_reset_decode (midiParser);
|
||||
|
||||
if (numBytes > 0)
|
||||
{
|
||||
const MidiMessage message ((const uint8*) buffer,
|
||||
numBytes,
|
||||
Time::getMillisecondCounter() * 0.001);
|
||||
|
||||
|
||||
callback->handleIncomingMidiMessage (midiInput, message);
|
||||
}
|
||||
|
||||
snd_seq_free_event (inputEvent);
|
||||
}
|
||||
}
|
||||
while (snd_seq_event_input_pending (seqHandle, 0) > 0);
|
||||
|
||||
snd_seq_free_event (inputEvent);
|
||||
}
|
||||
}
|
||||
|
||||
snd_midi_event_free (midiParser);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
MidiInput* const midiInput;
|
||||
snd_seq_t* const seqHandle;
|
||||
MidiInputCallback* const callback;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiInputThread);
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
MidiInput::MidiInput (const String& name_)
|
||||
: name (name_),
|
||||
internal (0)
|
||||
{
|
||||
}
|
||||
|
||||
MidiInput::~MidiInput()
|
||||
{
|
||||
stop();
|
||||
delete static_cast <MidiInputThread*> (internal);
|
||||
}
|
||||
|
||||
void MidiInput::start()
|
||||
{
|
||||
static_cast <MidiInputThread*> (internal)->startThread();
|
||||
}
|
||||
|
||||
void MidiInput::stop()
|
||||
{
|
||||
static_cast <MidiInputThread*> (internal)->stopThread (3000);
|
||||
}
|
||||
|
||||
int MidiInput::getDefaultDeviceIndex()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
StringArray MidiInput::getDevices()
|
||||
{
|
||||
StringArray devices;
|
||||
iterateMidiDevices (true, devices, -1);
|
||||
return devices;
|
||||
}
|
||||
|
||||
MidiInput* MidiInput::openDevice (int deviceIndex, MidiInputCallback* callback)
|
||||
{
|
||||
MidiInput* newDevice = nullptr;
|
||||
|
||||
StringArray devices;
|
||||
snd_seq_t* const handle = iterateMidiDevices (true, devices, deviceIndex);
|
||||
|
||||
if (handle != 0)
|
||||
{
|
||||
newDevice = new MidiInput (devices [deviceIndex]);
|
||||
newDevice->internal = new MidiInputThread (newDevice, handle, callback);
|
||||
}
|
||||
|
||||
return newDevice;
|
||||
}
|
||||
|
||||
MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallback* callback)
|
||||
{
|
||||
MidiInput* newDevice = nullptr;
|
||||
|
||||
snd_seq_t* const handle = createMidiDevice (true, deviceName);
|
||||
|
||||
if (handle != 0)
|
||||
{
|
||||
newDevice = new MidiInput (deviceName);
|
||||
newDevice->internal = new MidiInputThread (newDevice, handle, callback);
|
||||
}
|
||||
|
||||
return newDevice;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#else
|
||||
|
||||
// (These are just stub functions if ALSA is unavailable...)
|
||||
|
||||
StringArray MidiOutput::getDevices() { return StringArray(); }
|
||||
int MidiOutput::getDefaultDeviceIndex() { return 0; }
|
||||
MidiOutput* MidiOutput::openDevice (int) { return nullptr; }
|
||||
MidiOutput* MidiOutput::createNewDevice (const String&) { return nullptr; }
|
||||
MidiOutput::~MidiOutput() {}
|
||||
void MidiOutput::sendMessageNow (const MidiMessage&) {}
|
||||
|
||||
MidiInput::MidiInput (const String& name_) : name (name_), internal (0) {}
|
||||
MidiInput::~MidiInput() {}
|
||||
void MidiInput::start() {}
|
||||
void MidiInput::stop() {}
|
||||
int MidiInput::getDefaultDeviceIndex() { return 0; }
|
||||
StringArray MidiInput::getDevices() { return StringArray(); }
|
||||
MidiInput* MidiInput::openDevice (int, MidiInputCallback*) { return nullptr; }
|
||||
MidiInput* MidiInput::createNewDevice (const String&, MidiInputCallback*) { return nullptr; }
|
||||
|
||||
#endif
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue