Path: blob/master/src/java.desktop/share/classes/com/sun/media/sound/MidiOutDevice.java
41161 views
/*1* Copyright (c) 1999, 2019, 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*/2425package com.sun.media.sound;2627import javax.sound.midi.MidiMessage;28import javax.sound.midi.MidiUnavailableException;29import javax.sound.midi.Receiver;30import javax.sound.midi.ShortMessage;3132/**33* MidiOutDevice class representing functionality of MidiOut devices.34*35* @author David Rivas36* @author Kara Kytle37* @author Florian Bomers38*/39final class MidiOutDevice extends AbstractMidiDevice {4041MidiOutDevice(AbstractMidiDeviceProvider.Info info) {42super(info);43}4445@Override46protected synchronized void implOpen() throws MidiUnavailableException {47int index = ((AbstractMidiDeviceProvider.Info)getDeviceInfo()).getIndex();48id = nOpen(index); // can throw MidiUnavailableException49if (id == 0) {50throw new MidiUnavailableException("Unable to open native device");51}52}5354@Override55protected synchronized void implClose() {56// prevent further action57long oldId = id;58id = 0;5960super.implClose();6162// close the device63nClose(oldId);64}6566@Override67public long getMicrosecondPosition() {68long timestamp = -1;69if (isOpen()) {70timestamp = nGetTimeStamp(id);71}72return timestamp;73}7475/** Returns if this device supports Receivers.76This implementation always returns true.77@return true, if the device supports Receivers, false otherwise.78*/79@Override80protected boolean hasReceivers() {81return true;82}8384@Override85protected Receiver createReceiver() {86return new MidiOutReceiver();87}8889final class MidiOutReceiver extends AbstractReceiver {9091@Override92void implSend(final MidiMessage message, final long timeStamp) {93final int length = message.getLength();94final int status = message.getStatus();95if (length <= 3 && status != 0xF0 && status != 0xF7) {96int packedMsg;97if (message instanceof ShortMessage) {98if (message instanceof FastShortMessage) {99packedMsg = ((FastShortMessage) message).getPackedMsg();100} else {101ShortMessage msg = (ShortMessage) message;102packedMsg = (status & 0xFF)103| ((msg.getData1() & 0xFF) << 8)104| ((msg.getData2() & 0xFF) << 16);105}106} else {107packedMsg = 0;108byte[] data = message.getMessage();109if (length>0) {110packedMsg = data[0] & 0xFF;111if (length>1) {112/* We handle meta messages here. The message113system reset (FF) doesn't get until here,114because it's length is only 1. So if we see115a status byte of FF, it's sure that we116have a Meta message. */117if (status == 0xFF) {118return;119}120packedMsg |= (data[1] & 0xFF) << 8;121if (length>2) {122packedMsg |= (data[2] & 0xFF) << 16;123}124}125}126}127nSendShortMessage(id, packedMsg, timeStamp);128} else {129final byte[] data;130if (message instanceof FastSysexMessage) {131data = ((FastSysexMessage) message).getReadOnlyMessage();132} else {133data = message.getMessage();134}135final int dataLength = Math.min(length, data.length);136if (dataLength > 0) {137nSendLongMessage(id, data, dataLength, timeStamp);138}139}140}141142/** shortcut for the Sun implementation */143synchronized void sendPackedMidiMessage(int packedMsg, long timeStamp) {144if (isOpen() && id != 0) {145nSendShortMessage(id, packedMsg, timeStamp);146}147}148} // class MidiOutReceiver149150private native long nOpen(int index) throws MidiUnavailableException;151private native void nClose(long id);152153private native void nSendShortMessage(long id, int packedMsg, long timeStamp);154private native void nSendLongMessage(long id, byte[] data, int size, long timeStamp);155private native long nGetTimeStamp(long id);156157} // class MidiOutDevice158159160