|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (C) 2000 Stefan Westerfeld
|
|
|
|
stefan@space.twc.de
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library 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
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* DISCLAIMER: The interfaces in artsmidi.idl (and the derived .cpp/.h files)
|
|
|
|
* DO NOT GUARANTEE BINARY COMPATIBILITY YET.
|
|
|
|
*
|
|
|
|
* They are intended for developers. You shouldn't expect that applications in
|
|
|
|
* binary form will be fully compatibile with further releases of these
|
|
|
|
* interfaces.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <artsflow.idl>
|
|
|
|
|
|
|
|
module Arts {
|
|
|
|
|
|
|
|
/* This is modelled somewhat after
|
|
|
|
- the AudioManager concept
|
|
|
|
- the aRts-0.3.4.1 MidiPort concept
|
|
|
|
- libtdemid
|
|
|
|
|
|
|
|
It adds timing as new feature compared to older implementation, and also
|
|
|
|
tries to do the full set of midi operations.
|
|
|
|
|
|
|
|
It's current state is "experimental", and "binary compatibility not kept".
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* an absolute timestamp
|
|
|
|
*/
|
|
|
|
struct TimeStamp {
|
|
|
|
long sec,usec;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* different status of a midi command
|
|
|
|
*/
|
|
|
|
enum MidiCommandStatus {
|
|
|
|
// Masks:
|
|
|
|
mcsCommandMask = 0xf0,
|
|
|
|
mcsChannelMask = 0x0f,
|
|
|
|
|
|
|
|
// Commands:
|
|
|
|
mcsNoteOff = 0x80,
|
|
|
|
mcsNoteOn = 0x90,
|
|
|
|
mcsKeyPressure = 0xa0,
|
|
|
|
mcsParameter = 0xb0,
|
|
|
|
mcsProgram = 0xc0,
|
|
|
|
mcsChannelPressure = 0xd0,
|
|
|
|
mcsPitchWheel = 0xe0
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the following are to be used once status is (mcsParameter|channel):
|
|
|
|
*/
|
|
|
|
enum MidiCommandParameter {
|
|
|
|
mcpSustain = 0x40,
|
|
|
|
mcpAllNotesOff = 0x7b
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* a midi command
|
|
|
|
*/
|
|
|
|
struct MidiCommand {
|
|
|
|
byte status;
|
|
|
|
byte data1;
|
|
|
|
byte data2;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* a midi event
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct MidiEvent {
|
|
|
|
TimeStamp time;
|
|
|
|
MidiCommand command;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* a midi port
|
|
|
|
*/
|
|
|
|
interface MidiPort {
|
|
|
|
/**
|
|
|
|
* the current absolute time (since the existence of the midi device)
|
|
|
|
*/
|
|
|
|
readonly attribute TimeStamp time;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the current play time
|
|
|
|
*
|
|
|
|
* Some midi devices, for instance synthetic audio devices, have a certain
|
|
|
|
* amount of internal buffering. This causes a time difference between
|
|
|
|
* where events are currently being rendered, which is the timestamp
|
|
|
|
* obtained by "time", and the events that the listener is hearing right
|
|
|
|
* now, which is this timestamp, the "playTime".
|
|
|
|
*/
|
|
|
|
readonly attribute TimeStamp playTime;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* processes a midi command
|
|
|
|
*/
|
|
|
|
oneway void processCommand(MidiCommand command);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* processes a midi event
|
|
|
|
*/
|
|
|
|
oneway void processEvent(MidiEvent event);
|
|
|
|
};
|
|
|
|
|
|
|
|
enum MidiClientDirection { mcdPlay, mcdRecord };
|
|
|
|
enum MidiClientType { mctDestination, mctApplication };
|
|
|
|
|
|
|
|
/**
|
|
|
|
* information about a midi client
|
|
|
|
*/
|
|
|
|
struct MidiClientInfo {
|
|
|
|
long ID;
|
|
|
|
sequence<long> connections;
|
|
|
|
|
|
|
|
MidiClientDirection direction;
|
|
|
|
MidiClientType type;
|
|
|
|
string title, autoRestoreID;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* a midi manager client
|
|
|
|
*/
|
|
|
|
interface MidiClient {
|
|
|
|
readonly attribute MidiClientInfo info;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* you can change the title of your client on the fly - everything else
|
|
|
|
* (besides the actual assignment) is static
|
|
|
|
*/
|
|
|
|
attribute string title;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* creates a new port through which the client can receive data from
|
|
|
|
* the midi manager
|
|
|
|
*/
|
|
|
|
void addInputPort(MidiPort port);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* creates a new port through which the client can send data to the
|
|
|
|
* midi manager
|
|
|
|
*/
|
|
|
|
MidiPort addOutputPort();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* removes a port
|
|
|
|
*/
|
|
|
|
void removePort(MidiPort port);
|
|
|
|
};
|
|
|
|
|
|
|
|
interface AudioSync;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* this synchronizes multiple midi clients - it also allows synchronization
|
|
|
|
* with audio events
|
|
|
|
*/
|
|
|
|
interface MidiSyncGroup {
|
|
|
|
/**
|
|
|
|
* adds a midi client to the synchronization group
|
|
|
|
*
|
|
|
|
* hint: during adding the client, the timestamps related to that
|
|
|
|
* client will jump
|
|
|
|
*/
|
|
|
|
void addClient(MidiClient client);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* deletes a midi client from the synchronization group
|
|
|
|
*/
|
|
|
|
void removeClient(MidiClient client);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* adds an AudioSync object to the synchronization group
|
|
|
|
*
|
|
|
|
* hint: during adding the AudioSync object, the timestamps related to
|
|
|
|
* that object might jump
|
|
|
|
*/
|
|
|
|
void addAudioSync(AudioSync audioSync);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* deletes an AudioSync object from the synchronization group
|
|
|
|
*/
|
|
|
|
void removeAudioSync(AudioSync audioSync);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Some general notes to the understanding of the midi manager. The midi
|
|
|
|
* manager has the task to intelligently assign applications to destinations.
|
|
|
|
*
|
|
|
|
* It is important to understand what it actually does to understand the
|
|
|
|
* distinction first, which is expressed through the "MidiClientType" of
|
|
|
|
* each client.
|
|
|
|
*
|
|
|
|
* APPLICATIONS: An application is a user visible application, that produces
|
|
|
|
* or records midi data. It is important for the understanding of an
|
|
|
|
* application, that an application actually *wants* to be supplied with
|
|
|
|
* data, or wants to get its data played. Thus, adding an application to
|
|
|
|
* the midi manager is an implicit request: "go and find a place where to
|
|
|
|
* put the events to (or get the events from)".
|
|
|
|
*
|
|
|
|
* Examples for applications would be games or midi players.
|
|
|
|
*
|
|
|
|
* DESTINATIONS: A destination is a system service that plays or supplies
|
|
|
|
* midi data. The characteristic here is that a destination is something
|
|
|
|
* that is there if you need it.
|
|
|
|
*
|
|
|
|
* Examples for destinations might be might be a hardware device or an
|
|
|
|
* emulation of a hardware device (such as a virtual sampler).
|
|
|
|
*
|
|
|
|
* So the process is as follows:
|
|
|
|
* - destinations register themselves at the midi manager, and provide
|
|
|
|
* system services in that way
|
|
|
|
*
|
|
|
|
* - when the user starts an application (such as a midi player), the midi
|
|
|
|
* manager's task is to assign it to a suitable destination
|
|
|
|
*
|
|
|
|
* - the user can interact with the process by changing the way applications
|
|
|
|
* are assigned to destinations - the midi manager will try to learn
|
|
|
|
* what the user wants, and next time do a better job while assigning
|
|
|
|
*
|
|
|
|
* To actually record or play some data, you need to register a client first,
|
|
|
|
* and after that, you can add Input or Output "MidiPort"s to your client,
|
|
|
|
* so that you can actually send or receive events with them.
|
|
|
|
*/
|
|
|
|
interface MidiManager { // SINGLETON: Arts_MidiManager
|
|
|
|
/**
|
|
|
|
* a list of clients
|
|
|
|
*/
|
|
|
|
readonly attribute sequence<MidiClientInfo> clients;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* add a client
|
|
|
|
*
|
|
|
|
* this creates a new MidiManagerClient
|
|
|
|
*/
|
|
|
|
MidiClient addClient(MidiClientDirection direction, MidiClientType type,
|
|
|
|
string title, string autoRestoreID);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* connect two clients
|
|
|
|
*/
|
|
|
|
void connect(long clientID, long destinationID);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* disconnect two clients
|
|
|
|
*/
|
|
|
|
void disconnect(long clientID, long destinationID);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* add a synchronization group
|
|
|
|
*
|
|
|
|
* this creates a new MidiSyncGroup
|
|
|
|
*/
|
|
|
|
MidiSyncGroup addSyncGroup();
|
|
|
|
};
|
|
|
|
|
|
|
|
interface MidiTest : MidiPort {
|
|
|
|
};
|
|
|
|
|
|
|
|
interface RawMidiPort : MidiPort {
|
|
|
|
attribute string device;
|
|
|
|
attribute boolean input, output;
|
|
|
|
attribute boolean running;
|
|
|
|
boolean open();
|
|
|
|
};
|
|
|
|
|
|
|
|
interface AlsaMidiGateway {
|
|
|
|
boolean rescan();
|
|
|
|
};
|
|
|
|
|
|
|
|
interface AlsaMidiPort : MidiPort {
|
|
|
|
attribute long client;
|
|
|
|
attribute long port;
|
|
|
|
boolean open();
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* EXPERIMENTAL interface for audio synchronization - this allows multiple
|
|
|
|
* objects to be started and stopped at a precisely defined timestamp
|
|
|
|
*/
|
|
|
|
interface AudioSync {
|
|
|
|
/**
|
|
|
|
* the current time
|
|
|
|
*/
|
|
|
|
readonly attribute TimeStamp time;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the current play time
|
|
|
|
*
|
|
|
|
* Since aRts has internal buffering, there is a time difference between
|
|
|
|
* where events are currently being rendered, which is the timestamp
|
|
|
|
* obtained by "time", and the events that the listener is hearing right
|
|
|
|
* now, which is this timestamp, the "playTime".
|
|
|
|
*/
|
|
|
|
readonly attribute TimeStamp playTime;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* queues calling synthModule.start() later
|
|
|
|
*
|
|
|
|
* (will keep a reference on the module until executed)
|
|
|
|
*/
|
|
|
|
void queueStart(SynthModule synthModule);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* queues calling synthModule.stop() later
|
|
|
|
*
|
|
|
|
* (will keep a reference on the module until executed)
|
|
|
|
*/
|
|
|
|
void queueStop(SynthModule synthModule);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomically executes all queued modification to the flow system
|
|
|
|
*/
|
|
|
|
void execute();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomically executes all queued modifications to the flow system
|
|
|
|
* at a given time
|
|
|
|
*/
|
|
|
|
void executeAt(TimeStamp timeStamp);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Midi Timer - can be used to provide timing for midi ports that have
|
|
|
|
* no "native" timing.
|
|
|
|
*/
|
|
|
|
interface MidiTimer
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* the current time
|
|
|
|
*/
|
|
|
|
readonly attribute TimeStamp time;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* this will put the event into an event queue and send it to the port
|
|
|
|
* once the time for the event has been reached
|
|
|
|
*/
|
|
|
|
oneway void queueEvent(MidiPort port, MidiEvent event);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Uses the system time (i.e. gettimeofday() and similar) to provide midi
|
|
|
|
* timing
|
|
|
|
*/
|
|
|
|
interface SystemMidiTimer : MidiTimer
|
|
|
|
{
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Uses the audio time (i.e. samples rendered to /dev/dsp) to provide midi
|
|
|
|
* timing
|
|
|
|
*/
|
|
|
|
interface AudioMidiTimer : MidiTimer
|
|
|
|
{
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|