/*
*
* Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package com.sun.mmedia;
import com.sun.mmedia.DirectPlayer;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
/**
* Implement all of MIDI related controls like :
* MIDIControl, RateControl, PitchControl, TempoControl
*/
class DirectMIDIControl implements
MIDIControl, RateControl, PitchControl, TempoControl, DirectControls {
// MIDIControl
private native void nSetChannelVolume(int handle, int channel, int volume);
private native int nGetChannelVolume(int handle, int channel);
private native void nSetProgram(int handle, int channel, int bank, int program);
private native void nShortMidiEvent(int handle, int type, int data1, int data2);
private native int nLongMidiEvent(int handle, byte[] data, int offset, int length);
// RateControl
private native int nGetMaxRate(int handle);
private native int nGetMinRate(int handle);
private native int nSetRate(int handle, int rate);
private native int nGetRate(int handle);
// PitchControl
private native int nGetMaxPitch(int handle);
private native int nGetMinPitch(int handle);
private native int nSetPitch(int handle, int pitch);
private native int nGetPitch(int handle);
// TempoControl
private native int nGetTempo(int handle);
private native int nSetTempo(int handle, int tempo);
// Bank Query
private native boolean nIsBankQuerySupported(int handle);
private native int nGetBankList(int handle, boolean custom, int[] list);
private native int nGetKeyName(int handle, int bank, int prog, int key, byte[] keyname);
private native int nGetProgramName(int handle, int bank, int prog, byte[] progname);
private native int nGetProgramList(int handle, int bank, int[] proglist);
private native int nGetProgram(int handle, int channel, int[] program);
DirectMIDIControl(DirectPlayer p) {
_player = p;
}
// Private //////////////////////////////////////////////////////////
private void checkState() {
if (_player.state < Player.PREFETCHED) {
throw new IllegalStateException("Not prefetched");
}
}
private void checkChannel(int channel) {
if (channel < 0 || channel > 15) {
throw new IllegalArgumentException("Channel is out of range");
}
}
private void checkVolume(int volume) {
if (volume < 0 || volume > 127) {
throw new IllegalArgumentException("Volume is out of range");
}
}
private void checkType(int type) {
if (type < 0x80 || type > 0xFF || type == 0xF0 || type == 0xF7) {
throw new IllegalArgumentException("Type is out of range");
}
}
private void checkData(int data) {
if (data < 0 || data > 127) {
throw new IllegalArgumentException("Data is out of range");
}
}
private void checkLongMidiEvent(byte[] data, int offset, int length) {
if (data == null) {
throw new IllegalArgumentException("Data is null for long MIDI event ");
} else if ((offset >= data.length) || (offset < 0)) {
if (data.length != 0) {
throw new IllegalArgumentException("Invalid offset for long MIDI event");
}
} else if ((length > data.length) || (length < 0)) {
throw new IllegalArgumentException("Length is out of range for long MIDI event");
}
}
private void checkProgram(int program) {
if (program < 0 || program > 127) {
throw new IllegalArgumentException("Program is out of range");
}
}
private void checkBank(int bank) {
if (bank < 0 || bank > 16383) {
throw new IllegalArgumentException("Bank is out of range");
}
}
// DirectControls ////////////////////////////////////////////////////
public synchronized void playerStarted() {
if (_cachedRate != -1) {
// NOTE - MMAPI SPEC is not clear about this
// set cached rate at enter playing state
nSetRate(_player.hNative, _cachedRate);
_cachedRate = -1;
}
}
public synchronized void playerStopped() {
}
public synchronized void playerClosed() {
_player = null;
}
// MIDIControl ///////////////////////////////////////////////////////
public synchronized boolean isBankQuerySupported() {
return nIsBankQuerySupported(_player.hNative);
}
public synchronized int[] getProgram(int channel) throws MediaException {
checkState();
checkChannel(channel);
int[] p = new int[2];
int len = nGetProgram(_player.hNative, channel, p);
if(len < 0) throw new MediaException("GetProgram failure");
return p;
}
public synchronized int[] getBankList(boolean custom) throws MediaException {
checkState();
int[] bl1 = new int[20];
int len = nGetBankList(_player.hNative, custom, bl1);
if(len < 0) throw new MediaException("BankList failure");
int[] bl2 = new int[len];
for(int i=0; i<len; i++)
bl2[i] = bl1[i];
return bl2;
}
public synchronized String getKeyName(int bank, int prog, int key) throws MediaException {
checkState();
checkBank(bank);
checkProgram(prog);
if((key < 0) || (key > 127))
throw new IllegalArgumentException("key out of range");
byte[] str = new byte[64];
int len = nGetKeyName(_player.hNative, bank, prog, key, str);
if(len < 0) throw new MediaException("KeyName failure");
return new String(str, 0, len);
}
public synchronized String getProgramName(int bank, int prog) throws MediaException {
checkState();
checkBank(bank);
checkProgram(prog);
byte[] str = new byte[64];
int len = nGetProgramName(_player.hNative, bank, prog, str);
if(len < 0) throw new MediaException("ProgramName failure");
return new String(str, 0, len);
}
public synchronized int[] getProgramList(int bank) throws MediaException {
checkState();
checkBank(bank);
int[] pl1 = new int[200];
int len = nGetProgramList(_player.hNative, bank, pl1);
if(len < 0) throw new MediaException("ProgramList failure");
int[] pl2 = new int[len];
for(int i=0; i<len; i++)
pl2[i] = pl1[i];
return pl2;
}
public synchronized void setChannelVolume(int channel, int volume) {
checkState();
checkChannel(channel);
checkVolume(volume);
if (_player != null && _player.hNative != 0) {
nSetChannelVolume(_player.hNative, channel, volume);
}
}
public synchronized int getChannelVolume(int channel) {
checkState();
checkChannel(channel);
if (_player != null && _player.hNative != 0) {
return nGetChannelVolume(_player.hNative, channel);
} else {
return -1;
}
}
public synchronized void setProgram(int channel, int bank, int program) {
checkState();
checkChannel(channel);
if(bank != -1) checkBank(bank);
checkProgram(program);
if (_player != null && _player.hNative != 0) {
nSetProgram(_player.hNative, channel, bank, program);
}
}
public synchronized void shortMidiEvent(int type, int data1, int data2) {
checkState();
checkType(type);
checkData(data1);
checkData(data2);
if (_player != null && _player.hNative != 0) {
nShortMidiEvent(_player.hNative, type, data1, data2);
}
}
public synchronized int longMidiEvent(byte[] data, int offset, int length) {
checkState();
checkLongMidiEvent(data, offset, length);
if (_player != null && _player.hNative != 0) {
return nLongMidiEvent(_player.hNative, data, offset, length);
} else {
return -1;
}
}
// RateControl ///////////////////////////////////////////////////////
//
// SPEC:
// If the Player is already started, setRate will immediately take effect.
// Q - How about the other case?
//
public synchronized int setRate(int millirate) {
if (_player == null)
return 0;
int max = getMaxRate();
int min = getMinRate();
if (millirate > max) {
millirate = max;
} else if (millirate < min) {
millirate = min;
}
if (_player.state >= Player.STARTED) {
_cachedRate = -1;
return nSetRate(_player.hNative, millirate);
} else {
_cachedRate = millirate;
return millirate;
}
}
public synchronized int getRate() {
if (_player != null && _player.hNative != 0) {
return _cachedRate == -1 ? nGetRate(_player.hNative) : _cachedRate;
} else {
return 0;
}
}
public synchronized int getMaxRate() {
if (_player != null && _player.hNative != 0) {
return nGetMaxRate(_player.hNative);
} else {
return 0;
}
}
public synchronized int getMinRate() {
if (_player != null && _player.hNative != 0) {
return nGetMinRate(_player.hNative);
} else {
return 0;
}
}
// PitchControl //////////////////////////////////////////////////////
public synchronized int setPitch(int millisemitones) {
int max = getMaxPitch();
int min = getMinPitch();
if (millisemitones > max) {
millisemitones = max;
} else if (millisemitones < min) {
millisemitones = min;
}
if (_player != null && _player.hNative != 0) {
return nSetPitch(_player.hNative, millisemitones);
} else {
return 0;
}
}
public synchronized int getPitch() {
if (_player != null && _player.hNative != 0) {
return nGetPitch(_player.hNative);
} else {
return 0;
}
}
public synchronized int getMaxPitch() {
if (_player != null && _player.hNative != 0) {
return nGetMaxPitch(_player.hNative);
} else {
return 0;
}
}
public synchronized int getMinPitch() {
if (_player != null && _player.hNative != 0) {
return nGetMinPitch(_player.hNative);
} else {
return 0;
}
}
// TempoControl //////////////////////////////////////////////////////
public synchronized int setTempo(int millitempo) {
if (millitempo < 0) {
millitempo = 0;
}
if (_player != null && _player.hNative != 0) {
return nSetTempo(_player.hNative, millitempo);
} else {
return 0;
}
}
public synchronized int getTempo() {
if (_player != null && _player.hNative != 0) {
return nGetTempo(_player.hNative);
} else {
return 0;
}
}
//////////////////////////////////////////////////////////////////////
private DirectPlayer _player;
private int _cachedRate = -1;
};
|