001: /*
002: *
003: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
004: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License version
008: * 2 only, as published by the Free Software Foundation.
009: *
010: * This program is distributed in the hope that it will be useful, but
011: * WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * General Public License version 2 for more details (a copy is
014: * included at /legal/license.txt).
015: *
016: * You should have received a copy of the GNU General Public License
017: * version 2 along with this work; if not, write to the Free Software
018: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
022: * Clara, CA 95054 or visit www.sun.com if you need additional
023: * information or have any questions.
024: */
025:
026: package com.sun.mmedia;
027:
028: import com.sun.mmedia.DirectPlayer;
029:
030: import javax.microedition.media.*;
031: import javax.microedition.media.control.*;
032:
033: /**
034: * Implement all of MIDI related controls like :
035: * MIDIControl, RateControl, PitchControl, TempoControl
036: */
037: class DirectMIDIControl implements MIDIControl, RateControl,
038: PitchControl, TempoControl, DirectControls {
039:
040: // MIDIControl
041: private native void nSetChannelVolume(int handle, int channel,
042: int volume);
043:
044: private native int nGetChannelVolume(int handle, int channel);
045:
046: private native void nSetProgram(int handle, int channel, int bank,
047: int program);
048:
049: private native void nShortMidiEvent(int handle, int type,
050: int data1, int data2);
051:
052: private native int nLongMidiEvent(int handle, byte[] data,
053: int offset, int length);
054:
055: // RateControl
056: private native int nGetMaxRate(int handle);
057:
058: private native int nGetMinRate(int handle);
059:
060: private native int nSetRate(int handle, int rate);
061:
062: private native int nGetRate(int handle);
063:
064: // PitchControl
065: private native int nGetMaxPitch(int handle);
066:
067: private native int nGetMinPitch(int handle);
068:
069: private native int nSetPitch(int handle, int pitch);
070:
071: private native int nGetPitch(int handle);
072:
073: // TempoControl
074: private native int nGetTempo(int handle);
075:
076: private native int nSetTempo(int handle, int tempo);
077:
078: // Bank Query
079: private native boolean nIsBankQuerySupported(int handle);
080:
081: private native int nGetBankList(int handle, boolean custom,
082: int[] list);
083:
084: private native int nGetKeyName(int handle, int bank, int prog,
085: int key, byte[] keyname);
086:
087: private native int nGetProgramName(int handle, int bank, int prog,
088: byte[] progname);
089:
090: private native int nGetProgramList(int handle, int bank,
091: int[] proglist);
092:
093: private native int nGetProgram(int handle, int channel,
094: int[] program);
095:
096: DirectMIDIControl(DirectPlayer p) {
097: _player = p;
098: }
099:
100: // Private //////////////////////////////////////////////////////////
101:
102: private void checkState() {
103: if (_player.state < Player.PREFETCHED) {
104: throw new IllegalStateException("Not prefetched");
105: }
106: }
107:
108: private void checkChannel(int channel) {
109: if (channel < 0 || channel > 15) {
110: throw new IllegalArgumentException(
111: "Channel is out of range");
112: }
113: }
114:
115: private void checkVolume(int volume) {
116: if (volume < 0 || volume > 127) {
117: throw new IllegalArgumentException("Volume is out of range");
118: }
119: }
120:
121: private void checkType(int type) {
122: if (type < 0x80 || type > 0xFF || type == 0xF0 || type == 0xF7) {
123: throw new IllegalArgumentException("Type is out of range");
124: }
125: }
126:
127: private void checkData(int data) {
128: if (data < 0 || data > 127) {
129: throw new IllegalArgumentException("Data is out of range");
130: }
131: }
132:
133: private void checkLongMidiEvent(byte[] data, int offset, int length) {
134: if (data == null) {
135: throw new IllegalArgumentException(
136: "Data is null for long MIDI event ");
137: } else if ((offset >= data.length) || (offset < 0)) {
138: if (data.length != 0) {
139: throw new IllegalArgumentException(
140: "Invalid offset for long MIDI event");
141: }
142: } else if ((length > data.length) || (length < 0)) {
143: throw new IllegalArgumentException(
144: "Length is out of range for long MIDI event");
145: }
146: }
147:
148: private void checkProgram(int program) {
149: if (program < 0 || program > 127) {
150: throw new IllegalArgumentException(
151: "Program is out of range");
152: }
153: }
154:
155: private void checkBank(int bank) {
156: if (bank < 0 || bank > 16383) {
157: throw new IllegalArgumentException("Bank is out of range");
158: }
159: }
160:
161: // DirectControls ////////////////////////////////////////////////////
162:
163: public synchronized void playerStarted() {
164: if (_cachedRate != -1) {
165: // NOTE - MMAPI SPEC is not clear about this
166: // set cached rate at enter playing state
167: nSetRate(_player.hNative, _cachedRate);
168: _cachedRate = -1;
169: }
170: }
171:
172: public synchronized void playerStopped() {
173: }
174:
175: public synchronized void playerClosed() {
176: _player = null;
177: }
178:
179: // MIDIControl ///////////////////////////////////////////////////////
180:
181: public synchronized boolean isBankQuerySupported() {
182: return nIsBankQuerySupported(_player.hNative);
183: }
184:
185: public synchronized int[] getProgram(int channel)
186: throws MediaException {
187:
188: checkState();
189: checkChannel(channel);
190:
191: int[] p = new int[2];
192:
193: int len = nGetProgram(_player.hNative, channel, p);
194: if (len < 0)
195: throw new MediaException("GetProgram failure");
196:
197: return p;
198: }
199:
200: public synchronized int[] getBankList(boolean custom)
201: throws MediaException {
202:
203: checkState();
204:
205: int[] bl1 = new int[20];
206:
207: int len = nGetBankList(_player.hNative, custom, bl1);
208: if (len < 0)
209: throw new MediaException("BankList failure");
210:
211: int[] bl2 = new int[len];
212:
213: for (int i = 0; i < len; i++)
214: bl2[i] = bl1[i];
215:
216: return bl2;
217: }
218:
219: public synchronized String getKeyName(int bank, int prog, int key)
220: throws MediaException {
221:
222: checkState();
223: checkBank(bank);
224: checkProgram(prog);
225:
226: if ((key < 0) || (key > 127))
227: throw new IllegalArgumentException("key out of range");
228:
229: byte[] str = new byte[64];
230:
231: int len = nGetKeyName(_player.hNative, bank, prog, key, str);
232: if (len < 0)
233: throw new MediaException("KeyName failure");
234:
235: return new String(str, 0, len);
236: }
237:
238: public synchronized String getProgramName(int bank, int prog)
239: throws MediaException {
240:
241: checkState();
242: checkBank(bank);
243: checkProgram(prog);
244:
245: byte[] str = new byte[64];
246:
247: int len = nGetProgramName(_player.hNative, bank, prog, str);
248: if (len < 0)
249: throw new MediaException("ProgramName failure");
250:
251: return new String(str, 0, len);
252: }
253:
254: public synchronized int[] getProgramList(int bank)
255: throws MediaException {
256:
257: checkState();
258: checkBank(bank);
259:
260: int[] pl1 = new int[200];
261:
262: int len = nGetProgramList(_player.hNative, bank, pl1);
263: if (len < 0)
264: throw new MediaException("ProgramList failure");
265:
266: int[] pl2 = new int[len];
267:
268: for (int i = 0; i < len; i++)
269: pl2[i] = pl1[i];
270:
271: return pl2;
272: }
273:
274: public synchronized void setChannelVolume(int channel, int volume) {
275: checkState();
276: checkChannel(channel);
277: checkVolume(volume);
278:
279: if (_player != null && _player.hNative != 0) {
280: nSetChannelVolume(_player.hNative, channel, volume);
281: }
282: }
283:
284: public synchronized int getChannelVolume(int channel) {
285: checkState();
286: checkChannel(channel);
287:
288: if (_player != null && _player.hNative != 0) {
289: return nGetChannelVolume(_player.hNative, channel);
290: } else {
291: return -1;
292: }
293: }
294:
295: public synchronized void setProgram(int channel, int bank,
296: int program) {
297: checkState();
298: checkChannel(channel);
299:
300: if (bank != -1)
301: checkBank(bank);
302: checkProgram(program);
303:
304: if (_player != null && _player.hNative != 0) {
305: nSetProgram(_player.hNative, channel, bank, program);
306: }
307: }
308:
309: public synchronized void shortMidiEvent(int type, int data1,
310: int data2) {
311: checkState();
312: checkType(type);
313: checkData(data1);
314: checkData(data2);
315:
316: if (_player != null && _player.hNative != 0) {
317: nShortMidiEvent(_player.hNative, type, data1, data2);
318: }
319: }
320:
321: public synchronized int longMidiEvent(byte[] data, int offset,
322: int length) {
323: checkState();
324: checkLongMidiEvent(data, offset, length);
325:
326: if (_player != null && _player.hNative != 0) {
327: return nLongMidiEvent(_player.hNative, data, offset, length);
328: } else {
329: return -1;
330: }
331: }
332:
333: // RateControl ///////////////////////////////////////////////////////
334:
335: //
336: // SPEC:
337: // If the Player is already started, setRate will immediately take effect.
338: // Q - How about the other case?
339: //
340: public synchronized int setRate(int millirate) {
341: if (_player == null)
342: return 0;
343:
344: int max = getMaxRate();
345: int min = getMinRate();
346:
347: if (millirate > max) {
348: millirate = max;
349: } else if (millirate < min) {
350: millirate = min;
351: }
352:
353: if (_player.state >= Player.STARTED) {
354: _cachedRate = -1;
355: return nSetRate(_player.hNative, millirate);
356: } else {
357: _cachedRate = millirate;
358: return millirate;
359: }
360: }
361:
362: public synchronized int getRate() {
363: if (_player != null && _player.hNative != 0) {
364: return _cachedRate == -1 ? nGetRate(_player.hNative)
365: : _cachedRate;
366: } else {
367: return 0;
368: }
369: }
370:
371: public synchronized int getMaxRate() {
372: if (_player != null && _player.hNative != 0) {
373: return nGetMaxRate(_player.hNative);
374: } else {
375: return 0;
376: }
377: }
378:
379: public synchronized int getMinRate() {
380: if (_player != null && _player.hNative != 0) {
381: return nGetMinRate(_player.hNative);
382: } else {
383: return 0;
384: }
385: }
386:
387: // PitchControl //////////////////////////////////////////////////////
388:
389: public synchronized int setPitch(int millisemitones) {
390: int max = getMaxPitch();
391: int min = getMinPitch();
392:
393: if (millisemitones > max) {
394: millisemitones = max;
395: } else if (millisemitones < min) {
396: millisemitones = min;
397: }
398:
399: if (_player != null && _player.hNative != 0) {
400: return nSetPitch(_player.hNative, millisemitones);
401: } else {
402: return 0;
403: }
404: }
405:
406: public synchronized int getPitch() {
407: if (_player != null && _player.hNative != 0) {
408: return nGetPitch(_player.hNative);
409: } else {
410: return 0;
411: }
412: }
413:
414: public synchronized int getMaxPitch() {
415: if (_player != null && _player.hNative != 0) {
416: return nGetMaxPitch(_player.hNative);
417: } else {
418: return 0;
419: }
420: }
421:
422: public synchronized int getMinPitch() {
423: if (_player != null && _player.hNative != 0) {
424: return nGetMinPitch(_player.hNative);
425: } else {
426: return 0;
427: }
428: }
429:
430: // TempoControl //////////////////////////////////////////////////////
431:
432: public synchronized int setTempo(int millitempo) {
433: if (millitempo < 0) {
434: millitempo = 0;
435: }
436:
437: if (_player != null && _player.hNative != 0) {
438: return nSetTempo(_player.hNative, millitempo);
439: } else {
440: return 0;
441: }
442: }
443:
444: public synchronized int getTempo() {
445: if (_player != null && _player.hNative != 0) {
446: return nGetTempo(_player.hNative);
447: } else {
448: return 0;
449: }
450: }
451:
452: //////////////////////////////////////////////////////////////////////
453:
454: private DirectPlayer _player;
455: private int _cachedRate = -1;
456: };
|