Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_MidiUtils.c
41149 views
1
/*
2
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
/*
27
**
28
** Overview:
29
** Implementation of the functions used for both MIDI in and MIDI out.
30
**
31
** Java package com.sun.media.sound defines the AbstractMidiDevice class
32
** which encapsulates functionalities shared by both MidiInDevice and
33
** MidiOutDevice classes in the same package.
34
**
35
** The Java layer classes MidiInDevice and MidiOutDevice in turn map to
36
** the MIDIEndpointRef data type in the CoreMIDI framework, which
37
** represents a source or destination for a standard 16-channel MIDI data
38
** stream.
39
*/
40
/*****************************************************************************/
41
42
//#define USE_ERROR
43
//#define USE_TRACE
44
45
#if (USE_PLATFORM_MIDI_IN == TRUE) || (USE_PLATFORM_MIDI_OUT == TRUE)
46
47
#include "PLATFORM_API_MacOSX_MidiUtils.h"
48
#include <pthread.h>
49
#include <assert.h>
50
51
// Constant character string definitions of CoreMIDI's corresponding error codes.
52
53
static const char* strMIDIInvalidClient =
54
"An invalid MIDIClientRef was passed.";
55
static const char* strMIDIInvalidPort =
56
"An invalid MIDIPortRef was passed.";
57
static const char* strMIDIWrongEndpointType =
58
"A source endpoint was passed to a function expecting a destination, or vice versa.";
59
static const char* strMIDINoConnection =
60
"Attempt to close a non-existant connection.";
61
static const char* strMIDIUnknownEndpoint =
62
"An invalid MIDIEndpointRef was passed.";
63
static const char* strMIDIUnknownProperty =
64
"Attempt to query a property not set on the object.";
65
static const char* strMIDIWrongPropertyType =
66
"Attempt to set a property with a value not of the correct type.";
67
static const char* strMIDINoCurrentSetup =
68
"Internal error; there is no current MIDI setup object.";
69
static const char* strMIDIMessageSendErr =
70
"Communication with MIDIServer failed.";
71
static const char* strMIDIServerStartErr =
72
"Unable to start MIDIServer.";
73
static const char* strMIDISetupFormatErr =
74
"Unable to read the saved state.";
75
static const char* strMIDIWrongThread =
76
"A driver is calling a non-I/O function in the server from a thread other than"
77
"the server's main thread.";
78
static const char* strMIDIObjectNotFound =
79
"The requested object does not exist.";
80
static const char* strMIDIIDNotUnique =
81
"Attempt to set a non-unique kMIDIPropertyUniqueID on an object.";
82
83
static const char* midi_strerror(int err) {
84
/*
85
@enum Error Constants
86
@abstract The error constants unique to Core MIDI.
87
@discussion These are the error constants that are unique to Core MIDI. Note that Core MIDI
88
functions may return other codes that are not listed here.
89
*/
90
const char* strerr;
91
92
switch (err) {
93
case kMIDIInvalidClient:
94
strerr = strMIDIInvalidClient;
95
break;
96
case kMIDIInvalidPort:
97
strerr = strMIDIInvalidPort;
98
break;
99
case kMIDIWrongEndpointType:
100
strerr = strMIDIWrongEndpointType;
101
break;
102
case kMIDINoConnection:
103
strerr = strMIDINoConnection;
104
break;
105
case kMIDIUnknownEndpoint:
106
strerr = strMIDIUnknownEndpoint;
107
break;
108
case kMIDIUnknownProperty:
109
strerr = strMIDIUnknownProperty;
110
break;
111
case kMIDIWrongPropertyType:
112
strerr = strMIDIWrongPropertyType;
113
break;
114
case kMIDINoCurrentSetup:
115
strerr = strMIDINoCurrentSetup;
116
break;
117
case kMIDIMessageSendErr:
118
strerr = strMIDIMessageSendErr;
119
break;
120
case kMIDIServerStartErr:
121
strerr = strMIDIServerStartErr;
122
break;
123
case kMIDISetupFormatErr:
124
strerr = strMIDISetupFormatErr;
125
break;
126
case kMIDIWrongThread:
127
strerr = strMIDIWrongThread;
128
break;
129
case kMIDIObjectNotFound:
130
strerr = strMIDIObjectNotFound;
131
break;
132
case kMIDIIDNotUnique:
133
strerr = strMIDIIDNotUnique;
134
break;
135
default:
136
strerr = "Unknown error.";
137
break;
138
}
139
return strerr;
140
}
141
142
const char* MIDI_Utils_GetErrorMsg(int err) {
143
return midi_strerror(err);
144
}
145
146
147
void MIDI_Utils_PrintError(int err) {
148
#ifdef USE_ERROR
149
const char* s = MIDI_Utils_GetErrorMsg(err);
150
if (s != NULL) {
151
fprintf(stderr, "%s\n", s);
152
}
153
#endif
154
}
155
156
157
// Note direction is either MIDI_IN or MIDI_OUT.
158
INT32 MIDI_Utils_GetNumDevices(int direction) {
159
int num_endpoints;
160
if (direction == MIDI_IN) {
161
num_endpoints = MIDIGetNumberOfSources();
162
//fprintf(stdout, "MIDIGetNumberOfSources() returns %d\n", num_endpoints);
163
} else if (direction == MIDI_OUT) {
164
num_endpoints = MIDIGetNumberOfDestinations();
165
//printf(stdout, "MIDIGetNumberOfDestinations() returns %d\n", num_endpoints);
166
} else {
167
assert((direction == MIDI_IN || direction == MIDI_OUT));
168
num_endpoints = 0;
169
}
170
return (INT32) num_endpoints;
171
}
172
173
// Wraps calls to CFStringGetCStringPtr and CFStringGetCString to make sure
174
// we extract the c characters into the buffer and null-terminate it.
175
static void CFStringExtractCString(CFStringRef cfs, char* buffer, UINT32 bufferSize, CFStringEncoding encoding) {
176
const char* ptr = CFStringGetCStringPtr(cfs, encoding);
177
if (ptr) {
178
strlcpy(buffer, ptr, bufferSize);
179
} else {
180
if (! CFStringGetCString(cfs, buffer, bufferSize, encoding)) {
181
// There's an error in conversion, make sure we null-terminate the buffer.
182
buffer[bufferSize - 1] = '\0';
183
}
184
}
185
}
186
187
//
188
// @see com.sun.media.sound.AbstractMidiDeviceProvider.getDeviceInfo().
189
static int getEndpointProperty(int direction, INT32 deviceID, char *buffer, int bufferLength, CFStringRef propertyID) {
190
191
if (deviceID < 0) {
192
return MIDI_INVALID_DEVICEID;
193
}
194
195
MIDIEndpointRef endpoint;
196
197
if (direction == MIDI_IN) {
198
endpoint = MIDIGetSource(deviceID);
199
} else if (direction == MIDI_OUT) {
200
endpoint = MIDIGetDestination(deviceID);
201
} else {
202
return MIDI_INVALID_ARGUMENT;
203
}
204
205
if (!endpoint) {
206
return MIDI_INVALID_DEVICEID;
207
}
208
209
int status = MIDI_SUCCESS;
210
if (propertyID == kMIDIPropertyDriverVersion) {
211
SInt32 driverVersion;
212
status = MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyDriverVersion, &driverVersion);
213
if (status != MIDI_SUCCESS) return status;
214
snprintf(buffer,
215
bufferLength,
216
"%d",
217
(int) driverVersion);
218
}
219
else {
220
CFStringRef pname;
221
status = MIDIObjectGetStringProperty(endpoint, propertyID, &pname);
222
if (status != MIDI_SUCCESS) return status;
223
CFStringExtractCString(pname, buffer, bufferLength, 0);
224
}
225
return MIDI_ERROR_NONE;
226
}
227
228
// A simple utility which encapsulates CoreAudio's HostTime APIs.
229
// It returns the current host time in nanoseconds which when subtracted from
230
// a previous getCurrentTimeInNanos() result produces the delta in nanos.
231
static UInt64 getCurrentTimeInNanos() {
232
UInt64 hostTime = AudioGetCurrentHostTime();
233
UInt64 nanos = AudioConvertHostTimeToNanos(hostTime);
234
return nanos;
235
}
236
237
238
INT32 MIDI_Utils_GetDeviceName(int direction, INT32 deviceID, char *name, UINT32 bufferLength) {
239
return getEndpointProperty(direction, deviceID, name, bufferLength, kMIDIPropertyName);
240
}
241
242
243
INT32 MIDI_Utils_GetDeviceVendor(int direction, INT32 deviceID, char *name, UINT32 bufferLength) {
244
return getEndpointProperty(direction, deviceID, name, bufferLength, kMIDIPropertyManufacturer);
245
}
246
247
248
INT32 MIDI_Utils_GetDeviceDescription(int direction, INT32 deviceID, char *name, UINT32 bufferLength) {
249
return getEndpointProperty(direction, deviceID, name, bufferLength, kMIDIPropertyDisplayName);
250
}
251
252
253
INT32 MIDI_Utils_GetDeviceVersion(int direction, INT32 deviceID, char *name, UINT32 bufferLength) {
254
return getEndpointProperty(direction, deviceID, name, bufferLength, kMIDIPropertyDriverVersion);
255
}
256
257
258
static MIDIClientRef client = (MIDIClientRef) 0;
259
static MIDIPortRef inPort = (MIDIPortRef) 0;
260
static MIDIPortRef outPort = (MIDIPortRef) 0;
261
262
// Each MIDIPacket can contain more than one midi messages.
263
// This function processes the packet and adds the messages to the specified message queue.
264
// @see also src/share/native/com/sun/media/sound/PlatformMidi.h.
265
static void processMessagesForPacket(const MIDIPacket* packet, MacMidiDeviceHandle* handle) {
266
const UInt8* data;
267
UInt16 length;
268
UInt8 byte;
269
UInt8 pendingMessageStatus;
270
UInt8 pendingData[2];
271
UInt16 pendingDataIndex, pendingDataLength;
272
UINT32 packedMsg;
273
MIDITimeStamp ts = packet->timeStamp;
274
275
pendingMessageStatus = 0;
276
pendingDataIndex = pendingDataLength = 0;
277
278
data = packet->data;
279
length = packet->length;
280
while (length--) {
281
bool byteIsInvalid = FALSE;
282
283
byte = *data++;
284
packedMsg = byte;
285
286
if (byte >= 0xF8) {
287
// Each RealTime Category message (ie, Status of 0xF8 to 0xFF) consists of only 1 byte, the Status.
288
// Except that 0xFD is an invalid status code.
289
//
290
// 0xF8 -> Midi clock
291
// 0xF9 -> Midi tick
292
// 0xFA -> Midi start
293
// 0xFB -> Midi continue
294
// 0xFC -> Midi stop
295
// 0xFE -> Active sense
296
// 0xFF -> Reset
297
if (byte == 0xFD) {
298
byteIsInvalid = TRUE;
299
} else {
300
pendingDataLength = 0;
301
}
302
} else {
303
if (byte < 0x80) {
304
// Not a status byte -- check our history.
305
if (handle->readingSysExData) {
306
CFDataAppendBytes(handle->readingSysExData, &byte, 1);
307
308
} else if (pendingDataIndex < pendingDataLength) {
309
pendingData[pendingDataIndex] = byte;
310
pendingDataIndex++;
311
312
if (pendingDataIndex == pendingDataLength) {
313
// This message is now done -- do the final processing.
314
if (pendingDataLength == 2) {
315
packedMsg = pendingMessageStatus | pendingData[0] << 8 | pendingData[1] << 16;
316
} else if (pendingDataLength == 1) {
317
packedMsg = pendingMessageStatus | pendingData[0] << 8;
318
} else {
319
fprintf(stderr, "%s: %d->internal error: pendingMessageStatus=0x%X, pendingDataLength=%d\n",
320
__FILE__, __LINE__, pendingMessageStatus, pendingDataLength);
321
byteIsInvalid = TRUE;
322
}
323
pendingDataLength = 0;
324
}
325
} else {
326
// Skip this byte -- it is invalid.
327
byteIsInvalid = TRUE;
328
}
329
} else {
330
if (handle->readingSysExData /* && (byte == 0xF7) */) {
331
// We have reached the end of system exclusive message -- send it finally.
332
const UInt8* bytes = CFDataGetBytePtr(handle->readingSysExData);
333
CFIndex size = CFDataGetLength(handle->readingSysExData);
334
MIDI_QueueAddLong(handle->h.queue,
335
(UBYTE*) bytes,
336
(UINT32) size,
337
0, // Don't care, windowish porting only.
338
(INT64) (AudioConvertHostTimeToNanos(ts) + 500) / 1000,
339
TRUE);
340
CFRelease(handle->readingSysExData);
341
handle->readingSysExData = NULL;
342
}
343
344
pendingMessageStatus = byte;
345
pendingDataLength = 0;
346
pendingDataIndex = 0;
347
348
switch (byte & 0xF0) {
349
case 0x80: // Note off
350
case 0x90: // Note on
351
case 0xA0: // Aftertouch
352
case 0xB0: // Controller
353
case 0xE0: // Pitch wheel
354
pendingDataLength = 2;
355
break;
356
357
case 0xC0: // Program change
358
case 0xD0: // Channel pressure
359
pendingDataLength = 1;
360
break;
361
362
case 0xF0: {
363
// System common message
364
switch (byte) {
365
case 0xF0:
366
// System exclusive
367
// Allocates a CFMutableData reference to accumulate the SysEx data until EOX (0xF7) is reached.
368
handle->readingSysExData = CFDataCreateMutable(NULL, 0);
369
break;
370
371
case 0xF7:
372
// System exclusive ends--already handled above.
373
// But if this is showing up outside of sysex, it's invalid.
374
byteIsInvalid = TRUE;
375
break;
376
377
case 0xF1: // MTC quarter frame message
378
case 0xF3: // Song select
379
pendingDataLength = 1;
380
break;
381
382
case 0xF2: // Song position pointer
383
pendingDataLength = 2;
384
break;
385
386
case 0xF6: // Tune request
387
pendingDataLength = 0;
388
break;
389
390
default:
391
// Invalid message
392
byteIsInvalid = TRUE;
393
break;
394
}
395
break;
396
}
397
398
default:
399
// This can't happen, but handle it anyway.
400
byteIsInvalid = TRUE;
401
break;
402
}
403
}
404
}
405
if (byteIsInvalid) continue;
406
407
// If the byte is valid and pendingDataLength is 0, we are ready to send the message.
408
if (pendingDataLength == 0) {
409
MIDI_QueueAddShort(handle->h.queue, packedMsg, (INT64) (AudioConvertHostTimeToNanos(ts) + 500) / 1000, TRUE);
410
}
411
}
412
}
413
414
static void midiReadProc(const MIDIPacketList* packetList, void* refCon, void* connRefCon) {
415
unsigned int i;
416
const MIDIPacket* packet;
417
MacMidiDeviceHandle* handle = (MacMidiDeviceHandle*) connRefCon;
418
419
packet = packetList->packet;
420
for (i = 0; i < packetList->numPackets; ++i) {
421
processMessagesForPacket(packet, handle);
422
packet = MIDIPacketNext(packet);
423
}
424
425
// Notify the waiting thread that there's data available.
426
if (handle) {
427
MIDI_SignalConditionVariable(handle->h.platformData);
428
}
429
}
430
431
static void midiInit() {
432
if (client) {
433
return;
434
}
435
436
OSStatus err = noErr;
437
438
err = MIDIClientCreate(CFSTR("MIDI Client"), NULL, NULL, &client);
439
if (err != noErr) { goto Exit; }
440
441
// This just creates an input port through which the client may receive
442
// incoming MIDI messages from any MIDI source.
443
err = MIDIInputPortCreate(client, CFSTR("MIDI Input Port"), midiReadProc, NULL, &inPort);
444
if (err != noErr) { goto Exit; }
445
446
err = MIDIOutputPortCreate(client, CFSTR("MIDI Output Port"), &outPort);
447
if (err != noErr) { goto Exit; }
448
449
Exit:
450
if (err != noErr) {
451
const char* s = MIDI_Utils_GetErrorMsg(err);
452
if (s != NULL) {
453
printf("%s\n", s);
454
}
455
}
456
}
457
458
459
INT32 MIDI_Utils_OpenDevice(int direction, INT32 deviceID, MacMidiDeviceHandle** handle,
460
int num_msgs, int num_long_msgs,
461
size_t lm_size)
462
{
463
midiInit();
464
465
int err = MIDI_ERROR_NONE;
466
MIDIEndpointRef endpoint = (MIDIEndpointRef) 0;
467
468
TRACE0("MIDI_Utils_OpenDevice\n");
469
470
(*handle) = (MacMidiDeviceHandle*) malloc(sizeof(MacMidiDeviceHandle));
471
if (!(*handle)) {
472
ERROR0("ERROR: MIDI_Utils_OpenDevice: out of memory\n");
473
return MIDI_OUT_OF_MEMORY;
474
}
475
memset(*handle, 0, sizeof(MacMidiDeviceHandle));
476
477
// Create the infrastructure for MIDI in/out, and after that,
478
// get the device's endpoint.
479
if (direction == MIDI_IN) {
480
// Create queue and the pthread condition variable.
481
(*handle)->h.queue = MIDI_CreateQueue(num_msgs);
482
(*handle)->h.platformData = MIDI_CreateConditionVariable();
483
if (!(*handle)->h.queue || !(*handle)->h.platformData) {
484
ERROR0("< ERROR: MIDI_IN_OpenDevice: could not create queue or condition variable\n");
485
free(*handle);
486
(*handle) = NULL;
487
return MIDI_OUT_OF_MEMORY;
488
}
489
endpoint = MIDIGetSource(deviceID);
490
(*handle)->port = inPort;
491
} else if (direction == MIDI_OUT) {
492
endpoint = MIDIGetDestination(deviceID);
493
(*handle)->port = outPort;
494
}
495
496
if (!endpoint) {
497
// An error occurred.
498
free(*handle);
499
return MIDI_INVALID_DEVICEID;
500
}
501
(*handle)->h.deviceHandle = (void*) (intptr_t) endpoint;
502
(*handle)->h.startTime = getCurrentTimeInNanos();
503
(*handle)->direction = direction;
504
(*handle)->deviceID = deviceID;
505
506
TRACE0("MIDI_Utils_OpenDevice: succeeded\n");
507
return err;
508
}
509
510
511
INT32 MIDI_Utils_CloseDevice(MacMidiDeviceHandle* handle) {
512
int err = MIDI_ERROR_NONE;
513
bool midiIn = (handle->direction == MIDI_IN);
514
515
TRACE0("> MIDI_Utils_CloseDevice\n");
516
if (!handle) {
517
ERROR0("< ERROR: MIDI_Utils_CloseDevice: handle is NULL\n");
518
return MIDI_INVALID_HANDLE;
519
}
520
if (!handle->h.deviceHandle) {
521
ERROR0("< ERROR: MIDI_Utils_CloseDevice: native handle is NULL\n");
522
return MIDI_INVALID_HANDLE;
523
}
524
handle->isStarted = FALSE;
525
handle->h.deviceHandle = NULL;
526
527
if (midiIn) {
528
if (handle->h.queue != NULL) {
529
MidiMessageQueue* queue = handle->h.queue;
530
handle->h.queue = NULL;
531
MIDI_DestroyQueue(queue);
532
}
533
if (handle->h.platformData) {
534
MIDI_DestroyConditionVariable(handle->h.platformData);
535
}
536
}
537
free(handle);
538
539
TRACE0("< MIDI_Utils_CloseDevice: succeeded\n");
540
return err;
541
}
542
543
544
INT32 MIDI_Utils_StartDevice(MacMidiDeviceHandle* handle) {
545
OSStatus err = noErr;
546
547
if (!handle || !handle->h.deviceHandle) {
548
ERROR0("ERROR: MIDI_Utils_StartDevice: handle or native is NULL\n");
549
return MIDI_INVALID_HANDLE;
550
}
551
552
// Clears all the events from the queue.
553
MIDI_QueueClear(handle->h.queue);
554
555
if (!handle->isStarted) {
556
/* set the flag that we can now receive messages */
557
handle->isStarted = TRUE;
558
559
if (handle->direction == MIDI_IN) {
560
// The handle->h.platformData field contains the (pthread_cond_t*)
561
// associated with the source of the MIDI input stream, and is
562
// used in the CoreMIDI's callback to signal the arrival of new
563
// data.
564
//
565
// Similarly, handle->h.queue is used in the CoreMDID's callback
566
// to dispatch the incoming messages to the appropriate queue.
567
//
568
err = MIDIPortConnectSource(inPort, (MIDIEndpointRef) (intptr_t) (handle->h.deviceHandle), (void*) handle);
569
} else if (handle->direction == MIDI_OUT) {
570
// Unschedules previous-sent packets.
571
err = MIDIFlushOutput((MIDIEndpointRef) (intptr_t) handle->h.deviceHandle);
572
}
573
574
MIDI_CHECK_ERROR;
575
}
576
return MIDI_SUCCESS; /* don't fail */
577
}
578
579
580
INT32 MIDI_Utils_StopDevice(MacMidiDeviceHandle* handle) {
581
OSStatus err = noErr;
582
583
if (!handle || !handle->h.deviceHandle) {
584
ERROR0("ERROR: MIDI_Utils_StopDevice: handle or native handle is NULL\n");
585
return MIDI_INVALID_HANDLE;
586
}
587
588
if (handle->isStarted) {
589
/* set the flag that we don't want to receive messages anymore */
590
handle->isStarted = FALSE;
591
592
if (handle->direction == MIDI_IN) {
593
err = MIDIPortDisconnectSource(inPort, (MIDIEndpointRef) (intptr_t) (handle->h.deviceHandle));
594
} else if (handle->direction == MIDI_OUT) {
595
// Unschedules previously-sent packets.
596
err = MIDIFlushOutput((MIDIEndpointRef) (intptr_t) handle->h.deviceHandle);
597
}
598
599
MIDI_CHECK_ERROR;
600
}
601
return MIDI_SUCCESS;
602
}
603
604
605
INT64 MIDI_Utils_GetTimeStamp(MacMidiDeviceHandle* handle) {
606
607
if (!handle || !handle->h.deviceHandle) {
608
ERROR0("ERROR: MIDI_Utils_GetTimeStamp: handle or native handle is NULL\n");
609
return (INT64) -1; /* failure */
610
}
611
612
UInt64 delta = getCurrentTimeInNanos() - handle->h.startTime;
613
return (INT64) ((delta + 500) / 1000);
614
}
615
616
617
/***************************************************************************/
618
/* Condition Variable Support for Mac OS X Port */
619
/* */
620
/* This works with the Native Locking Support defined below. We are using */
621
/* POSIX pthread_cond_t/pthread_mutex_t to do locking and synchronization. */
622
/* */
623
/* For MidiDeviceHandle* handle, the mutex reference is stored as handle-> */
624
/* queue->lock while the condition variabale reference is stored as handle */
625
/* ->platformData. */
626
/***************************************************************************/
627
628
// Called from Midi_Utils_Opendevice(...) to create a condition variable
629
// used to synchronize between the receive thread created by the CoreMIDI
630
// and the Java-initiated MidiInDevice run loop.
631
void* MIDI_CreateConditionVariable() {
632
pthread_cond_t* cond = (pthread_cond_t*) malloc(sizeof(pthread_cond_t));
633
pthread_cond_init(cond, NULL);
634
return (void*) cond;
635
}
636
637
void MIDI_DestroyConditionVariable(void* cond) {
638
while (pthread_cond_destroy((pthread_cond_t*) cond) == EBUSY) {
639
pthread_cond_broadcast((pthread_cond_t*) cond);
640
sched_yield();
641
}
642
return;
643
}
644
645
// Called from MIDI_IN_GetMessage(...) to wait for MIDI messages to become
646
// available via delivery from the CoreMIDI receive thread
647
void MIDI_WaitOnConditionVariable(void* cond, void* lock) {
648
if (cond && lock) {
649
pthread_mutex_lock(lock);
650
pthread_cond_wait((pthread_cond_t*) cond, (pthread_mutex_t*) lock);
651
pthread_mutex_unlock(lock);
652
}
653
return;
654
}
655
656
// Called from midiReadProc(...) to notify the waiting thread to unblock on
657
// the condition variable.
658
void MIDI_SignalConditionVariable(void* cond) {
659
if (cond) {
660
pthread_cond_signal((pthread_cond_t*) cond);
661
}
662
return;
663
}
664
665
666
/**************************************************************************/
667
/* Native Locking Support */
668
/* */
669
/* @see src/share/natve/com/sun/media/sound/PlatformMidi.c which contains */
670
/* utility functions for platform midi support where the section of code */
671
/* for MessageQueue implementation calls out to these functions. */
672
/**************************************************************************/
673
674
void* MIDI_CreateLock() {
675
pthread_mutex_t* lock = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
676
pthread_mutex_init(lock, NULL);
677
TRACE0("MIDI_CreateLock\n");
678
return (void *)lock;
679
}
680
681
void MIDI_DestroyLock(void* lock) {
682
if (lock) {
683
pthread_mutex_destroy((pthread_mutex_t*) lock);
684
free(lock);
685
TRACE0("MIDI_DestroyLock\n");
686
}
687
}
688
689
void MIDI_Lock(void* lock) {
690
if (lock) {
691
pthread_mutex_lock((pthread_mutex_t*) lock);
692
}
693
}
694
695
void MIDI_Unlock(void* lock) {
696
if (lock) {
697
pthread_mutex_unlock((pthread_mutex_t*) lock);
698
}
699
}
700
701
702
#endif // USE_PLATFORM_MIDI_IN || USE_PLATFORM_MIDI_OUT
703
704