Path: blob/master/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_MidiOut.c
41152 views
/*1* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425//#define USE_ERROR26//#define USE_TRACE2728#if USE_PLATFORM_MIDI_OUT == TRUE2930#include "PLATFORM_API_MacOSX_MidiUtils.h"3132char* MIDI_OUT_GetErrorStr(INT32 err) {33return (char *) MIDI_Utils_GetErrorMsg((int) err);34}353637INT32 MIDI_OUT_GetNumDevices() {38return MIDI_Utils_GetNumDevices(MIDI_OUT);39}404142INT32 MIDI_OUT_GetDeviceName(INT32 deviceID, char *name, UINT32 nameLength) {43return MIDI_Utils_GetDeviceName(MIDI_OUT, deviceID, name, nameLength);44}454647INT32 MIDI_OUT_GetDeviceVendor(INT32 deviceID, char *name, UINT32 nameLength) {48return MIDI_Utils_GetDeviceVendor(MIDI_OUT, deviceID, name, nameLength);49}505152INT32 MIDI_OUT_GetDeviceDescription(INT32 deviceID, char *name, UINT32 nameLength) {53return MIDI_Utils_GetDeviceDescription(MIDI_OUT, deviceID, name, nameLength);54}555657INT32 MIDI_OUT_GetDeviceVersion(INT32 deviceID, char *name, UINT32 nameLength) {58return MIDI_Utils_GetDeviceVersion(MIDI_OUT, deviceID, name, nameLength);59}606162/* *************************** MidiOutDevice implementation ***************************************** */6364INT32 MIDI_OUT_OpenDevice(INT32 deviceID, MidiDeviceHandle** handle) {65TRACE1("MIDI_OUT_OpenDevice: deviceID: %d\n", (int) deviceID);66/* queue sizes are ignored for MIDI_OUT only (uses STREAMS) */67return MIDI_Utils_OpenDevice(MIDI_OUT, deviceID, (MacMidiDeviceHandle**) handle, 0, 0, 0);68}6970INT32 MIDI_OUT_CloseDevice(MidiDeviceHandle* handle) {71TRACE0("MIDI_OUT_CloseDevice\n");7273// issue a "SUSTAIN OFF" message to each MIDI channel, 0 to 15.74// "CONTROL CHANGE" is 176, "SUSTAIN CONTROLLER" is 64, and the value is 0.75// $$fb 2002-04-04: It is responsability of the application developer to76// leave the device in a consistent state. So I put this in comments77/*78for (channel = 0; channel < 16; channel++)79MIDI_OUT_SendShortMessage(deviceHandle, (unsigned char)(176 + channel),80(unsigned char)64, (unsigned char)0, (UINT32)-1);81*/82return MIDI_Utils_CloseDevice((MacMidiDeviceHandle*) handle);83}848586INT64 MIDI_OUT_GetTimeStamp(MidiDeviceHandle* handle) {87return MIDI_Utils_GetTimeStamp((MacMidiDeviceHandle*) handle);88}899091INT32 MIDI_OUT_SendShortMessage(MidiDeviceHandle* handle, UINT32 packedMsg, UINT32 timestamp) {92OSStatus err = noErr;9394TRACE2("> MIDI_OUT_SendShortMessage %x, time: %d\n", (uint) packedMsg, (int) timestamp);95if (!handle) {96ERROR0("< ERROR: MIDI_OUT_SendShortMessage: handle is NULL\n");97return MIDI_INVALID_HANDLE;98}99100MacMidiDeviceHandle* macHandle = (MacMidiDeviceHandle*) handle;101UInt8 mBuffers[100];102MIDIPacketList* packetList = (MIDIPacketList*) mBuffers;103MIDIPacket* packet;104UINT32 nData;105Byte data[3] = {packedMsg & 0xFF, (packedMsg >> 8) & 0xFF, (packedMsg >> 16) & 0xFF};106bool byteIsInvalid = FALSE;107108packet = MIDIPacketListInit(packetList);109switch (data[0] & 0xF0) {110case 0x80: // Note off111case 0x90: // Note on112case 0xA0: // Aftertouch113case 0xB0: // Controller114case 0xE0: // Pitch wheel115nData = 3;116break;117118case 0xC0: // Program change119case 0xD0: // Channel pressure120nData = 2;121break;122123case 0xF0: {124// System common message125switch (data[0]) {126case 0xF0:127case 0xF7:128// System exclusive129fprintf(stderr, "%s: %d->internal error: sysex message status=0x%X while sending short message\n",130__FILE__, __LINE__, data[0]);131byteIsInvalid = TRUE;132break;133134case 0xF1: // MTC quarter frame message135//fprintf(stderr, ">>>MIDI_OUT_SendShortMessage: MTC quarter frame message....\n");136nData = 2;137break;138case 0xF3: // Song select139//fprintf(stderr, ">>>MIDI_OUT_SendShortMessage: Song select....\n");140nData = 2;141break;142143case 0xF2: // Song position pointer144//fprintf(stderr, ">>>MIDI_OUT_SendShortMessage: Song position pointer....\n");145nData = 3;146break;147148case 0xF6: // Tune request149//fprintf(stderr, ">>>MIDI_OUT_SendShortMessage: Tune request....\n");150nData = 1;151break;152153default:154// Invalid message155fprintf(stderr, "%s: %d->Invalid message: message status=0x%X while sending short message\n",156__FILE__, __LINE__, data[0]);157byteIsInvalid = TRUE;158break;159}160break;161}162163default:164// This can't happen, but handle it anyway.165fprintf(stderr, "%s: %d->Invalid message: message status=0x%X while sending short message\n",166__FILE__, __LINE__, data[0]);167byteIsInvalid = TRUE;168break;169}170171if (byteIsInvalid) return -1;172173MIDIPacketListAdd(packetList, sizeof(mBuffers), packet, 0, nData, data);174err = MIDISend(macHandle->port, (MIDIEndpointRef) (intptr_t) handle->deviceHandle, packetList);175176MIDI_CHECK_ERROR;177TRACE0("< MIDI_OUT_SendShortMessage\n");178return (err == noErr ? MIDI_SUCCESS : -1);179}180181182INT32 MIDI_OUT_SendLongMessage(MidiDeviceHandle* handle, UBYTE* data, UINT32 size, UINT32 timestamp) {183OSStatus err = noErr;184185TRACE2("> MIDI_OUT_SendLongMessage size %d, time: %d\n", (int) size, (int) timestamp);186if (!handle || !data) {187ERROR0("< ERROR: MIDI_OUT_SendLongMessage: handle, or data is NULL\n");188return MIDI_INVALID_HANDLE;189}190if (size == 0) {191return MIDI_SUCCESS;192}193194MacMidiDeviceHandle* macHandle = (MacMidiDeviceHandle*) handle;195UInt8 mBuffers[8196];196MIDIPacketList* packetList = (MIDIPacketList*) mBuffers;197MIDIPacket* packet = NULL;198UINT32 remaining = size;199UINT32 increment = 512;200UINT32 nData;201202handle->isWaiting = TRUE;203204while (remaining > 0) {205206if (packet == NULL) {207packet = MIDIPacketListInit(packetList);208}209210if (remaining > increment) {211nData = increment;212} else {213nData = remaining;214}215216// Copies the bytes to our current packet.217if ((packet = MIDIPacketListAdd(packetList, sizeof(mBuffers), packet, 0, nData, (const Byte*) data)) == NULL) {218// Packet list is full, send it.219err = MIDISend(macHandle->port, (MIDIEndpointRef) (intptr_t) handle->deviceHandle, packetList);220if (err != noErr) {221break;222}223} else {224// Moves the data pointer to the next segment.225data += nData;226remaining -= nData;227packet = MIDIPacketNext(packet);228}229}230231MIDI_CHECK_ERROR;232handle->isWaiting = FALSE;233TRACE0("< MIDI_OUT_SendLongMessage\n");234return (err == noErr ? MIDI_SUCCESS : -1);235}236237#endif /* USE_PLATFORM_MIDI_OUT */238239240