1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-10-19 17:11:12 +02:00

Extensive changes to improve NoteTrack display and (some) editing, NoteTrack playback via MIDI, and Midi-to-Audio alignment.

This commit is contained in:
rbdannenberg
2010-09-18 21:02:36 +00:00
parent f6327602e8
commit a1f0e5ed5b
96 changed files with 5679 additions and 3566 deletions

View File

@@ -57,21 +57,29 @@
#define MIDI_EOX 0xf7
#define MIDI_STATUS_MASK 0x80
static MIDIClientRef client = NULL; /* Client handle to the MIDI server */
static MIDIPortRef portIn = NULL; /* Input port handle */
static MIDIPortRef portOut = NULL; /* Output port handle */
// "Ref"s are pointers on 32-bit machines and ints on 64 bit machines
// NULL_REF is our representation of either 0 or NULL
#ifdef __LP64__
#define NULL_REF 0
#else
#define NULL_REF NULL
#endif
static MIDIClientRef client = NULL_REF; /* Client handle to the MIDI server */
static MIDIPortRef portIn = NULL_REF; /* Input port handle */
static MIDIPortRef portOut = NULL_REF; /* Output port handle */
extern pm_fns_node pm_macosx_in_dictionary;
extern pm_fns_node pm_macosx_out_dictionary;
typedef struct midi_macosxcm_struct {
unsigned long sync_time; /* when did we last determine delta? */
PmTimestamp sync_time; /* when did we last determine delta? */
UInt64 delta; /* difference between stream time and real time in ns */
UInt64 last_time; /* last output time */
int first_message; /* tells midi_write to sychronize timestamps */
int sysex_mode; /* middle of sending sysex */
unsigned long sysex_word; /* accumulate data when receiving sysex */
unsigned int sysex_byte_count; /* count how many received */
uint32_t sysex_word; /* accumulate data when receiving sysex */
uint32_t sysex_byte_count; /* count how many received */
char error[PM_HOST_ERROR_MSG_LEN];
char callback_error[PM_HOST_ERROR_MSG_LEN];
Byte packetBuffer[PACKET_BUFFER_SIZE];
@@ -81,7 +89,7 @@ typedef struct midi_macosxcm_struct {
MIDITimeStamp sysex_timestamp; /* timestamp to use with sysex data */
/* allow for running status (is running status possible here? -rbd): -cpr */
unsigned char last_command;
long last_msg_length;
int32_t last_msg_length;
} midi_macosxcm_node, *midi_macosxcm_type;
/* private function declarations */
@@ -92,7 +100,7 @@ char* cm_get_full_endpoint_name(MIDIEndpointRef endpoint);
static int
midi_length(long msg)
midi_length(int32_t msg)
{
int status, high, low;
static int high_lengths[] = {
@@ -235,7 +243,7 @@ readProc(const MIDIPacketList *newPackets, void *refCon, void *connRefCon)
PmEvent event;
MIDIPacket *packet;
unsigned int packetIndex;
unsigned long now;
uint32_t now;
unsigned int status;
#ifdef CM_DEBUG
@@ -260,9 +268,9 @@ readProc(const MIDIPacketList *newPackets, void *refCon, void *connRefCon)
packet->length); */
for (packetIndex = 0; packetIndex < newPackets->numPackets; packetIndex++) {
/* Set the timestamp and dispatch this message */
event.timestamp =
event.timestamp = (PmTimestamp) /* explicit conversion */ (
(AudioConvertHostTimeToNanos(packet->timeStamp) - m->delta) /
(UInt64) 1000000;
(UInt64) 1000000);
status = packet->data[0];
/* process packet as sysex data if it begins with MIDI_SYSEX, or
MIDI_EOX or non-status byte with no running status */
@@ -303,9 +311,8 @@ midi_in_open(PmInternal *midi, void *driverInfo)
/* time_get does not take a parameter, so coerce */
midi->time_proc = (PmTimeProcPtr) Pt_Time;
}
endpoint = (MIDIEndpointRef) descriptors[midi->device_id].descriptor;
if (endpoint == NULL) {
endpoint = (MIDIEndpointRef) (long) descriptors[midi->device_id].descriptor;
if (endpoint == NULL_REF) {
return pmInvalidDeviceId;
}
@@ -333,7 +340,7 @@ midi_in_open(PmInternal *midi, void *driverInfo)
pm_hosterror = macHostError;
sprintf(pm_hosterror_text,
"Host error %ld: MIDIPortConnectSource() in midi_in_open()",
macHostError);
(long) macHostError);
midi->descriptor = NULL;
pm_free(m);
return pmHostError;
@@ -353,8 +360,8 @@ midi_in_close(PmInternal *midi)
if (!m) return pmBadPtr;
endpoint = (MIDIEndpointRef) descriptors[midi->device_id].descriptor;
if (endpoint == NULL) {
endpoint = (MIDIEndpointRef) (long) descriptors[midi->device_id].descriptor;
if (endpoint == NULL_REF) {
pm_hosterror = pmBadPtr;
}
@@ -364,7 +371,7 @@ midi_in_close(PmInternal *midi)
pm_hosterror = macHostError;
sprintf(pm_hosterror_text,
"Host error %ld: MIDIPortDisconnectSource() in midi_in_close()",
macHostError);
(long) macHostError);
err = pmHostError;
}
@@ -421,12 +428,12 @@ midi_abort(PmInternal *midi)
PmError err = pmNoError;
OSStatus macHostError;
MIDIEndpointRef endpoint =
(MIDIEndpointRef) descriptors[midi->device_id].descriptor;
(MIDIEndpointRef) (long) descriptors[midi->device_id].descriptor;
macHostError = MIDIFlushOutput(endpoint);
if (macHostError != noErr) {
pm_hosterror = macHostError;
sprintf(pm_hosterror_text,
"Host error %ld: MIDIFlushOutput()", macHostError);
"Host error %ld: MIDIFlushOutput()", (long) macHostError);
err = pmHostError;
}
return err;
@@ -439,7 +446,7 @@ midi_write_flush(PmInternal *midi, PmTimestamp timestamp)
OSStatus macHostError;
midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor;
MIDIEndpointRef endpoint =
(MIDIEndpointRef) descriptors[midi->device_id].descriptor;
(MIDIEndpointRef) (long) descriptors[midi->device_id].descriptor;
assert(m);
assert(endpoint);
if (m->packet != NULL) {
@@ -454,7 +461,7 @@ send_packet_error:
pm_hosterror = macHostError;
sprintf(pm_hosterror_text,
"Host error %ld: MIDISend() in midi_write()",
macHostError);
(long) macHostError);
return pmHostError;
}
@@ -476,7 +483,12 @@ send_packet(PmInternal *midi, Byte *message, unsigned int messageLength,
/* out of space, send the buffer and start refilling it */
/* make midi->packet non-null to fool midi_write_flush into sending */
m->packet = (MIDIPacket *) 4;
if ((err = midi_write_flush(midi, timestamp)) != pmNoError) return err;
/* timestamp is 0 because midi_write_flush ignores timestamp since
* timestamps are already in packets. The timestamp parameter is here
* because other API's need it. midi_write_flush can be called
* from system-independent code that must be cross-API.
*/
if ((err = midi_write_flush(midi, 0)) != pmNoError) return err;
m->packet = MIDIPacketListInit(m->packetList);
assert(m->packet); /* if this fails, it's a programming error */
m->packet = MIDIPacketListAdd(m->packetList, sizeof(m->packetBuffer),
@@ -491,8 +503,8 @@ send_packet(PmInternal *midi, Byte *message, unsigned int messageLength,
static PmError
midi_write_short(PmInternal *midi, PmEvent *event)
{
long when = event->timestamp;
long what = event->message;
PmTimestamp when = event->timestamp;
PmMessage what = event->message;
MIDITimeStamp timestamp;
UInt64 when_ns;
midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor;
@@ -659,9 +671,9 @@ CFStringRef EndpointName(MIDIEndpointRef endpoint, bool isExternal)
CFRelease(str);
}
MIDIEntityRef entity = NULL;
MIDIEntityRef entity = NULL_REF;
MIDIEndpointGetEntity(endpoint, &entity);
if (entity == NULL)
if (entity == NULL_REF)
// probably virtual
return result;
@@ -675,9 +687,9 @@ CFStringRef EndpointName(MIDIEndpointRef endpoint, bool isExternal)
}
}
// now consider the device's name
MIDIDeviceRef device = NULL;
MIDIDeviceRef device = NULL_REF;
MIDIEntityGetDevice(entity, &device);
if (device == NULL)
if (device == NULL_REF)
return result;
str = NULL;
@@ -722,17 +734,17 @@ static CFStringRef ConnectedEndpointName(MIDIEndpointRef endpoint)
CFMutableStringRef result = CFStringCreateMutable(NULL, 0);
CFStringRef str;
OSStatus err;
int i;
long i;
// Does the endpoint have connections?
CFDataRef connections = NULL;
int nConnected = 0;
long nConnected = 0;
bool anyStrings = false;
err = MIDIObjectGetDataProperty(endpoint, kMIDIPropertyConnectionUniqueID, &connections);
if (connections != NULL) {
// It has connections, follow them
// Concatenate the names of all connected devices
nConnected = CFDataGetLength(connections) / sizeof(MIDIUniqueID);
nConnected = CFDataGetLength(connections) / (int32_t) sizeof(MIDIUniqueID);
if (nConnected) {
const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections));
for (i = 0; i < nConnected; ++i, ++pid) {
@@ -901,7 +913,7 @@ PmError pm_macosxcm_init(void)
/* Iterate over the MIDI input devices */
for (i = 0; i < numInputs; i++) {
endpoint = MIDIGetSource(i);
if (endpoint == NULL) {
if (endpoint == NULL_REF) {
continue;
}
@@ -911,13 +923,13 @@ PmError pm_macosxcm_init(void)
/* Register this device with PortMidi */
pm_add_device("CoreMIDI", cm_get_full_endpoint_name(endpoint),
TRUE, (void*)endpoint, &pm_macosx_in_dictionary);
TRUE, (void *) (long) endpoint, &pm_macosx_in_dictionary);
}
/* Iterate over the MIDI output devices */
for (i = 0; i < numOutputs; i++) {
endpoint = MIDIGetDestination(i);
if (endpoint == NULL) {
if (endpoint == NULL_REF) {
continue;
}
@@ -927,20 +939,22 @@ PmError pm_macosxcm_init(void)
/* Register this device with PortMidi */
pm_add_device("CoreMIDI", cm_get_full_endpoint_name(endpoint),
FALSE, (void*)endpoint, &pm_macosx_out_dictionary);
FALSE, (void *) (long) endpoint,
&pm_macosx_out_dictionary);
}
return pmNoError;
error_return:
pm_hosterror = macHostError;
sprintf(pm_hosterror_text, "Host error %ld: %s\n", macHostError, error_text);
sprintf(pm_hosterror_text, "Host error %ld: %s\n", (long) macHostError,
error_text);
pm_macosxcm_term(); /* clear out any opened ports */
return pmHostError;
}
void pm_macosxcm_term(void)
{
if (client != NULL) MIDIClientDispose(client);
if (portIn != NULL) MIDIPortDispose(portIn);
if (portOut != NULL) MIDIPortDispose(portOut);
if (client != NULL_REF) MIDIClientDispose(client);
if (portIn != NULL_REF) MIDIPortDispose(portIn);
if (portOut != NULL_REF) MIDIPortDispose(portOut);
}