#ifndef MIDISERVICES_H
#define MIDISERVICES_H

#include <CoreServices/CoreServices.h>
#include <CoreFoundation/CoreFoundation.h>
#include <stddef.h>
#include <APPLE/CoreMIDI/MIDIServices.h>

#ifdef __cplusplus
extern "C" {
#endif

/*MIDIEndpointRef


A MIDI source or destination, owned by an entity. 
typedef struct OpaqueMIDIEndpoint * MIDIEndpointRef;  
Discussion 

Derives from MIDIObjectRef, owned by a MIDIEntityRef, unless it is a virtual endpoint, in which case there is no owning entity. 

Entities have any number of MIDIEndpointRef's, sources and destinations of 16-channel MIDI streams.*/
typedef struct OpaqueMIDIEndpoint * MIDIEndpointRef;  

/*MIDIPortRef


A MIDI connection port owned by a client. 
typedef struct OpaqueMIDIPort * MIDIPortRef;  
Discussion 

Derives from MIDIObjectRef, owned by a MIDIClientRef. 

A MIDIPortRef, which may be an input port or output port, is an object through which a client may communicate with any number of MIDI sources or destinations.*/
typedef struct OpaqueMIDIPort * MIDIPortRef; 

/*MIDIClientRef


An object maintaining per-client state. 
typedef struct OpaqueMIDIClient * MIDIClientRef;  
Discussion 

Derives from MIDIObjectRef, does not have an owner object. 

To use CoreMIDI, an application creates a MIDIClientRef, to which it can add MIDIPortRef's, through which it can send and receive MIDI.*/
typedef struct OpaqueMIDIClient * MIDIClientRef;  

/*MIDIObjectRef


The base class of many CoreMIDI objects. 
typedef void * MIDIObjectRef;  
Discussion 

MIDIObject is the base class for many of the objects in CoreMIDI. They have properties, and often an "owner" object, from which they inherit any properties they do not themselves have. 

Developers may add their own private properties, whose names must begin with their company's inverted domain name, as in Java package names, but with underscores instead of dots, e.g.: com_apple_APrivateAppleProperty*/
typedef void * MIDIObjectRef;  

/*MIDITimeStamp


A host clock time. 
typedef UInt64 MIDITimeStamp;  
Discussion 

A host clock time representing the time of an event, as returned by mach_absolute_time() or UpTime(). 

Since MIDI applications will tend to do a fair amount of math with the times of events, it's more convenient to use a UInt64 than an AbsoluteTime. 

See CoreAudio/HostTime.h.*/
typedef UInt64 MIDITimeStamp;  

/*MIDIPacket


A collection of simultaneous MIDI events.
struct MIDIPacket { 
    MIDITimeStamp timeStamp; 
    UInt16 length; 
    Byte data[256]; 
};  
Fields
timeStamp
The time at which the events occurred, if receiving MIDI, or, if sending MIDI, the time at which the events are to be played. Zero means "now." The time stamp applies to the first MIDI byte in the packet.
length
The number of valid MIDI bytes which follow, in data. (It may be larger than 256 bytes if the packet is dynamically allocated.)
data
A variable-length stream of MIDI messages. Running status is not allowed. In the case of system-exclusive messages, a packet may only contain a single message, or portion of one, with no other MIDI events. 

The MIDI messages in the packet must always be complete, except for system-exclusive. 

(This is declared to be 256 bytes in length so clients don't have to create custom data structures in simple situations.)*/

struct MIDIPacket { 
    MIDITimeStamp timeStamp; 
    UInt16 length; 
    Byte data[256]; 
};  
typedef struct MIDIPacket MIDIPacket;

/*
MIDIPacketList


A list of MIDI events being received from, or being sent to, one endpoint. 
struct MIDIPacketList { 
    UInt32 numPackets; 
    MIDIPacket packet[1]; 
};  
Fields
numPackets
The number of MIDIPackets in the list.
packet
An open-ended array of variable-length MIDIPackets.
Discussion 

The timestamps in the packet list must be in ascending order. 

Note that the packets in the list, while defined as an array, may not be accessed as an array, since they are variable-length. To iterate through the packets in a packet list, use a loop such as: 
MIDIPacket *packet = &packetList->packet[0];
  for (int i = 0; i < packetList->numPackets; ++i) {
    ...
    packet = MIDIPacketNext(packet);
  }*/
struct MIDIPacketList { 
    UInt32 numPackets; 
    MIDIPacket packet[1]; 
};  

typedef struct MIDIPacketList			MIDIPacketList;

/*MIDINotificationMessageID


Signifies the type of a MIDINotification.
enum { // MIDINotificationMessageID 
    kMIDIMsgSetupChanged = 1, 
    kMIDIMsgObjectAdded = 2, 
    kMIDIMsgObjectRemoved = 3, 
    kMIDIMsgPropertyChanged = 4, 
    kMIDIMsgThruConnectionsChanged = 5, 
    kMIDIMsgSerialPortOwnerChanged = 6, 
    kMIDIMsgIOError = 7 
};  
Constants
kMIDIMsgSetupChanged
Some aspect of the current MIDISetup has changed. No data. Should ignore this message if messages 2-6 are handled.
kMIDIMsgObjectAdded
A device, entity or endpoint was added. Structure is MIDIObjectAddRemoveNotification. New for CoreMIDI 1.3.
kMIDIMsgObjectRemoved
A device, entity or endpoint was removed. Structure is MIDIObjectAddRemoveNotification. New for CoreMIDI 1.3.
kMIDIMsgPropertyChanged
An object's property was changed. Structure is MIDIObjectPropertyChangeNotification. New for CoreMIDI 1.3.
kMIDIMsgThruConnectionsChanged
A persistent MIDI Thru connection was created or destroyed. No data. New for CoreMIDI 1.3.
kMIDIMsgSerialPortOwnerChanged
A persistent MIDI Thru connection was created or destroyed. No data. New for CoreMIDI 1.3.
kMIDIMsgIOError
A driver I/O error occurred.*/
enum { // MIDINotificationMessageID 
    kMIDIMsgSetupChanged = 1, 
    kMIDIMsgObjectAdded = 2, 
    kMIDIMsgObjectRemoved = 3, 
    kMIDIMsgPropertyChanged = 4, 
    kMIDIMsgThruConnectionsChanged = 5, 
    kMIDIMsgSerialPortOwnerChanged = 6, 
    kMIDIMsgIOError = 7 
};


/*MIDINotification


A message describing a system state change. 
struct MIDINotification { 
    MIDINotificationMessageID messageID; 
    ByteCount messageSize; 
    // additional data may follow, depending on messageID 
};  
Fields
messageID
type of message
messageSize
size of the entire message, including messageID and messageSize
Discussion 

A MIDINotification is a structure passed to a MIDINotifyProc, when CoreMIDI wishes to inform a client of a change in the state of the system.*/
struct MIDINotification { 
    MIDINotificationMessageID messageID; 
    ByteCount messageSize; 
    // additional data may follow, depending on messageID 
};  
typedef struct MIDINotification MIDINotification;

/*MIDINotifyProc


A callback function for notifying clients of state changes. 
typedef void (*MIDINotifyProc)(
    const MIDINotification *message,
    void *refCon);  
Parameters
message
A structure containing information about what changed.
refCon
The client's refCon passed to MIDIClientCreate.
Discussion 

This callback function is called when some aspect of the current MIDI setup changes. It is called on the runloop (thread) on which MIDIClientCreate was first called.*/
typedef void (*MIDINotifyProc)(
    const MIDINotification *message,
    void *refCon);  

/*MIDIReadProc


A function receiving MIDI input. 
typedef void (*MIDIReadProc)(
    const MIDIPacketList *pktlist,
    void *readProcRefCon,
    void *srcConnRefCon);  
Parameters
pktlist
The incoming MIDI message(s).
readProcRefCon
The refCon you passed to MIDIInputPortCreate or MIDIDestinationCreate
srcConnRefCon
A refCon you passed to MIDIPortConnectSource, which identifies the source of the data.
Discussion 

This is a callback function through which a client receives incoming MIDI messages. 

A MIDIReadProc function pointer is passed to the MIDIInputPortCreate and MIDIDestinationCreate functions. The CoreMIDI framework will create a high-priority receive thread on your client's behalf, and from that thread, your MIDIReadProc will be called when incoming MIDI messages arrive. Because this function is called from a separate thread, be aware of the synchronization issues when accessing data in this callback.*/
typedef void (*MIDIReadProc)(
    const MIDIPacketList *pktlist,
    void *readProcRefCon,
    void *srcConnRefCon);  

//func

/*kMIDIPropertyName

extern const CFStringRef kMIDIPropertyName;  
Discussion 

device/entity/endpoint property, string 

Devices, entities, and endpoints may all have names. The recommended way to display an endpoint's name is to ask for the endpoint name, and display only that name if it is unique. If it is non-unique, prepend the device name. 

A setup editor may allow the user to set the names of both driver-owned and external devices.*/
extern const CFStringRef kMIDIPropertyName;  

/*MIDIPacketNext


Advances a MIDIPacket pointer to the MIDIPacket which immediately follows it in memory if it is part of a MIDIPacketList.
extern MIDIPacket * MIDIPacketNext(
    MIDIPacket *pkt );  
Parameters
pkt
A pointer to a MIDIPacket in a MIDIPacketList. 

Return Value

The subsequent packet in the MIDIPacketList. 

Discussion 

This is implemented as a macro for efficiency and to avoid const problems.*/
extern MIDIPacket * MIDIPacketNext(
    MIDIPacket *pkt ); 

/*MIDIClientCreate


Creates a MIDIClient object.
extern OSStatus MIDIClientCreate(
    CFStringRef name, 
    MIDINotifyProc notifyProc, 
    void *notifyRefCon, 
    MIDIClientRef *outClient );  
Parameters
name
The client's name.
notifyProc
An optional (may be NULL) callback function through which the client will receive notifications of changes to the system.
notifyRefCon
A refCon passed back to notifyRefCon
outClient
On successful return, points to the newly-created MIDIClientRef.
Return Value

An OSStatus result code. 

Discussion 

Note that notifyProc will always be called on the run loop which was current when MIDIClientCreate was first called. 

Availability
Introduced in Mac OS X v10.0.*/
extern OSStatus MIDIClientCreate(
    CFStringRef name, 
    MIDINotifyProc notifyProc, 
    void *notifyRefCon, 
    MIDIClientRef *outClient );  


/*MIDIObjectGetStringProperty


Gets an object's string-type property.
extern OSStatus MIDIObjectGetStringProperty(
    MIDIObjectRef obj, 
    CFStringRef propertyID, 
    CFStringRef *str );  
Parameters
obj
The object whose property is to be returned.
propertyID
Name of the property to return.
str
On successful return, the value of the property.
Return Value

An OSStatus result code. 

Discussion 

(See the MIDIObjectRef documentation for information about properties.) 
Availability
Introduced in Mac OS X v10.0.*/
extern OSStatus MIDIObjectGetStringProperty(
    MIDIObjectRef obj, 
    CFStringRef propertyID, 
    CFStringRef *str ); 

/*MIDIPacketListInit


Prepares a MIDIPacketList to be built up dynamically.
extern MIDIPacket * MIDIPacketListInit(
    MIDIPacketList *pktlist );  
Parameters
pktlist
The packet list to be initialized. 

Return Value

A pointer to the first MIDIPacket in the packet list. 
Availability
Introduced in Mac OS X v10.0.*/
extern MIDIPacket * MIDIPacketListInit(
    MIDIPacketList *pktlist ); 

/*MIDISend


Sends MIDI to a destination.
extern OSStatus MIDISend(
    MIDIPortRef port, 
    MIDIEndpointRef dest, 
    const MIDIPacketList *pktlist );  
Parameters
port
The output port through which the MIDI is to be sent.
dest
The destination to receive the events.
pktlist
The MIDI events to be sent.
Return Value

An OSStatus result code. 

Discussion 

Events with future timestamps are scheduled for future delivery. CoreMIDI performs any needed MIDI merging. 
Availability
Introduced in Mac OS X v10.0.*/
extern OSStatus MIDISend(
    MIDIPortRef port, 
    MIDIEndpointRef dest, 
    const MIDIPacketList *pktlist );  

/*MIDIPacketListAdd


Adds a MIDI event to a MIDIPacketList.
extern MIDIPacket * MIDIPacketListAdd(
    MIDIPacketList *pktlist, 
    ByteCount listSize, 
    MIDIPacket *curPacket, 
    MIDITimeStamp time, 
    ByteCount nData, 
    const Byte *data);  
Parameters
pktlist
The packet list to which the event is to be added.
listSize
The size, in bytes, of the packet list.
curPacket
A packet pointer returned by a previous call to MIDIPacketListInit or MIDIPacketListAdd for this packet list.
time
The new event's time.
nData
The length of the new event, in bytes.
data
The new event. May be a single MIDI event, or a partial sys-ex event. Running status is not permitted.
Return Value

Returns null if there was not room in the packet for the event; otherwise returns a packet pointer which should be passed as curPacket in a subsequent call to this function. 

Discussion 

The maximum size of a packet list is 65536 bytes. Large sysex messages must be sent in smaller packet lists. 
Availability
Introduced in Mac OS X v10.0.*/
extern MIDIPacket * MIDIPacketListAdd(
    MIDIPacketList *pktlist, 
    ByteCount listSize, 
    MIDIPacket *curPacket, 
    MIDITimeStamp time, 
    ByteCount nData, 
    const Byte *data);  

/*MIDIClientDispose


Disposes a MIDIClient object.
extern OSStatus MIDIClientDispose(
    MIDIClientRef client );  
Parameters
client
The client to dispose.
Return Value

An OSStatus result code. 

Discussion 

It is not essential to call this function; the CoreMIDI framework will automatically dispose all MIDIClients when an application terminates. 
Availability
Introduced in Mac OS X v10.0.*/

extern OSStatus MIDIClientDispose(
    MIDIClientRef client );  

/*MIDIInputPortCreate


Creates an input port through which the client may receive incoming MIDI messages from any MIDI source.
extern OSStatus MIDIInputPortCreate(
    MIDIClientRef client, 
    CFStringRef portName, 
    MIDIReadProc readProc, 
    void *refCon, 
    MIDIPortRef *outPort );  
Parameters
client
The client to own the newly-created port.
portName
The name of the port.
readProc
The MIDIReadProc which will be called with incoming MIDI, from sources connected to this port.
refCon
The refCon passed to readHook.
outPort
On successful return, points to the newly-created MIDIPort.
Return Value

An OSStatus result code. 

Discussion 

After creating a port, use MIDIPortConnectSource to establish an input connection from any number of sources to your port. 

readProc will be called on a separate high-priority thread owned by CoreMIDI. 
Availability
Introduced in Mac OS X v10.0.*/
extern OSStatus MIDIInputPortCreate(
    MIDIClientRef client, 
    CFStringRef portName, 
    MIDIReadProc readProc, 
    void *refCon, 
    MIDIPortRef *outPort );  


/*MIDIGetDestination


Returns one of the destinations in the system.
extern MIDIEndpointRef MIDIGetDestination(
    ItemCount destIndex0 );  
Parameters
destIndex0
The index (0...MIDIGetNumberOfDestinations()-1) of the destination to return
Return Value

A reference to a destination, or NULL if an error occurred. 
Availability
Introduced in Mac OS X v10.0.*/
extern MIDIEndpointRef MIDIGetDestination(
    ItemCount destIndex0 );  

/*MIDIPortConnectSource


Establishes a connection from a source to a client's input port.
extern OSStatus MIDIPortConnectSource(
    MIDIPortRef port, 
    MIDIEndpointRef source, 
    void *connRefCon );  
Parameters
port
The port to which to create the connection. This port's readProc is called with incoming MIDI from the source.
source
The source from which to create the connection.
connRefCon
This refCon is passed to the MIDIReadProc, as a way to identify the source.
Return Value

An OSStatus result code. 

Availability
Introduced in Mac OS X v10.0.*/
extern OSStatus MIDIPortConnectSource(
    MIDIPortRef port, 
    MIDIEndpointRef source, 
    void *connRefCon );  

/*MIDIGetSource


Returns one of the sources in the system.
extern MIDIEndpointRef MIDIGetSource(
    ItemCount sourceIndex0 );  
Parameters
sourceIndex0
The index (0...MIDIGetNumberOfSources()-1) of the source to return
Return Value

A reference to a source, or NULL if an error occurred. 
Availability
Introduced in Mac OS X v10.0.*/
extern MIDIEndpointRef MIDIGetSource(
    ItemCount sourceIndex0 );

/*MIDIOutputPortCreate


Creates an output port through which the client may send outgoing MIDI messages to any MIDI destination.
extern OSStatus MIDIOutputPortCreate(
    MIDIClientRef client, 
    CFStringRef portName, 
    MIDIPortRef *outPort );  
Parameters
client
The client to own the newly-created port
portName
The name of the port.
outPort
On successful return, points to the newly-created MIDIPort.
Return Value

An OSStatus result code. 

Discussion 

Output ports provide a mechanism for MIDI merging. CoreMIDI assumes that each output port will be responsible for sending only a single MIDI stream to each destination, although a single port may address all of the destinations in the system. 

Multiple output ports are only necessary when an application is capable of directing multiple simultaneous MIDI streams to the same destination. 
Availability
Introduced in Mac OS X v10.0.*/
extern OSStatus MIDIOutputPortCreate(
    MIDIClientRef client, 
    CFStringRef portName, 
    MIDIPortRef *outPort );  

/*MIDIGetNumberOfSources


Returns the number of sources in the system.
extern ItemCount MIDIGetNumberOfSources();  
Return Value

The number of sources in the system, or 0 if an error occurred. 
Availability
Introduced in Mac OS X v10.0.*/
extern ItemCount MIDIGetNumberOfSources();  

/*MIDIGetNumberOfDestinations


Returns the number of destinations in the system.
extern ItemCount MIDIGetNumberOfDestinations();  
Return Value

The number of destinations in the system, or 0 if an error occurred. 
Availability
Introduced in Mac OS X v10.0.*/
extern ItemCount MIDIGetNumberOfDestinations();  

#ifdef __cplusplus
}
#endif
#endif