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 javax.microedition.media.control;
027:
028: import javax.microedition.media.MediaException;
029:
030: /**
031: * <code>MIDIControl</code> provides access to MIDI rendering
032: * and transmitting devices.<p>
033: *
034: * Typical devices that are controlled with <code>MIDIControl</code>
035: * are internal synthesizers (software/hardware) or external
036: * hardware ports. Devices are virtual, i.e. even if there is only
037: * one physical synthesizer, all instances of <code>MIDIControl</code> seem
038: * to operate on its own synthesizer.<p>
039: *
040: * General functionality of this control is:
041: * <ol>
042: * <li>Querying current state of the device:
043: * <ul>
044: * <li>The programs that are currently assigned to each of the 16 channels</li>
045: * <li>Volume of each channel</li>
046: * </ul></li>
047: * <li>Querying the banks of the synthesizer:
048: * <ul>
049: * <li>Get a list of internal sound banks</li>
050: * <li>Get a list of custom sound banks</li>
051: * <li>Get the list of programs of a sound bank</li>
052: * <li>Get the name of a specific program</li>
053: * </ul></li>
054: * <li>Set the volume assigned to a channel</li>
055: * <li>Set the bank/program assigned to a channel</li>
056: * <li>Send short MIDI messages to the device</li>
057: * <li>Send long MIDI messages (system exclusive)</li>
058: * </ol>
059: *
060: * In Java Sound terms, <code>MIDIControl</code> combines
061: * methods and concepts of the interfaces Transmitter,
062: * Receiver, Synthesizer, MidiChannel, Soundbank, and Patch.<p>
063: *
064: * In this context, the following naming conventions are used:
065: * <ul>
066: * <li>A <i>program</i> refers to a single instrument. This is
067: * also known as a patch.</li>
068: * <li>A <i>bank</i> is short for sound bank. It contains up
069: * to 128 programs, numbered in the range from 0..127.</li>
070: * <li>An <i>internal bank</i> is provided by the software
071: * implementation or the hardware of the device.</li>
072: * <li>A <i>custom bank</i> is installed by an application,
073: * e.g. by loading an XMF meta file with an embedded bank.</li>
074: * </ul>
075: * <p>
076: * The conception of <code>MIDIControl</code> is based on scope and
077: * abstraction level:
078: * <ul>
079: * <li><code>MIDIControl</code> has methods that are specific
080: * to the device or renderer, and do not directly relate to a specific
081: * MIDI file or sequence to be played. However, as devices are virtual,
082: * MIDIControl's methods only operate on this virtual device.
083: * On the other hand, it is also
084: * possible to get an instance of <code>MIDIControl</code>
085: * without providing a sequence or MIDI file; this is done by
086: * specifying a magic Locator:<br>
087: * <br><code>
088: * try{
089: * <br> Player
090: * p = Manager.createPlayer(Manager.MIDI_DEVICE_LOCATOR);
091: * <br> MIDIControl
092: * synth = (MIDIControl)p.getControls("javax.microedition.media.control.MIDIControl");
093: * <br> } catch (MediaException e) {
094: * <br> }
095: * </code></li>
096: *
097: * <li><code>MIDIControl</code>'s methods can be considered
098: * advanced, low level functionality. This has 2 implications:
099: * <ol>
100: * <li><code>MIDIControl</code> is optional, i.e. no Player
101: * instance is required to provide an implementation of
102: * it</li>
103: * <li>Basic media or MIDI player applications will not need
104: * <code>MIDIControl</code>; {@link VolumeControl VolumeControl},
105: * {@link TempoControl TempoControl}, and {@link PitchControl PitchControl}
106: * are sufficient for basic needs.
107: * </li>
108: * </ol></li>
109: * </ul>
110: * <p>
111: * A useful function is "Panic": immediately turn off all
112: * sounds and notes. It can be implemented using the following code fragment:<br>
113: * <code>
114: * int CONTROL_ALL_SOUND_OFF = 0x78;<br>
115: * for (int channel = 0; channel < 16; channel++) {<br>
116: * shortMidiEvent(CONTROL_CHANGE | channel, CONTROL_ALL_SOUND_OFF, 0);<br>
117: * }<br>
118: * </code>
119: * <p>
120: * The implementation need not support the various query methods.
121: * This is a technical limitation, as the MIDI standard does not
122: * provide a standardized means to query the current program or
123: * the installed
124: * soundbanks. This especially applies to external MIDI ports.
125: * Optional methods must not be called if {@link #isBankQuerySupported isBankQuerySupported}
126: * returns false.
127: *
128: * @see javax.microedition.media.Player
129: * @see javax.microedition.media.control.RateControl
130: * @see javax.microedition.media.control.TempoControl
131: * @see javax.microedition.media.control.PitchControl
132: */
133:
134: public interface MIDIControl extends javax.microedition.media.Control {
135:
136: // constants for MIDI status (upper nibble of first byte)
137:
138: /**
139: * Command value for Note On message (0x90, or 144).
140: * To turn a note off, send a NOTE_ON message with 0
141: * velocity. Alternatively, a Note Off message (0x80)
142: * can be sent.
143: *
144: * @see #shortMidiEvent(int, int, int)
145: */
146: int NOTE_ON = 0x90; // 144
147:
148: /**
149: * Command value for Control Change message (0xB0, or 176).
150: * @see #shortMidiEvent(int, int, int)
151: */
152: int CONTROL_CHANGE = 0xB0; // 176
153:
154: // query device state
155:
156: /**
157: * Returns whether banks of the synthesizer can be queried.
158: * <p>
159: * If this functions returns true,
160: * then the following methods can be used to query banks:
161: * <ul>
162: * <li>{@link #getProgram(int) getProgram(int)}</li>
163: * <li>{@link #getBankList(boolean) getBankList(boolean)}</li>
164: * <li>{@link #getProgramList(int) getProgramList(int)}</li>
165: * <li>{@link #getProgramName(int, int) getProgramName(int, int)}</li>
166: * <li>{@link #getKeyName(int, int, int) getKeyName(int, int, int)}</li>
167: * </ul>
168: *
169: * @return true if this device supports querying of banks
170: */
171: boolean isBankQuerySupported();
172:
173: // send a Program Change short MIDI message, or
174: /**
175: * Returns program assigned to channel. It represents the current
176: * state of the channel. During playback of a MIDI file, the program
177: * may change due to program change events in the MIDI file.<p>
178: * To set a program for a channel,
179: * use setProgram(int, int, int).<p>
180: *
181: * The returned array is represented by an array {bank,program}.<p>
182: * If the device has not been initialized with a MIDI file, or the MIDI file
183: * does not contain a program change for this channel, an implementation
184: * specific default value is returned.<p>
185: *
186: * As there is no MIDI equivalent to this method, this method is
187: * optional, indicated by {@link #isBankQuerySupported isBankQuerySupported}.
188: * If it returns false, this function is not supported and throws an exception.
189: *
190: * @param channel 0-15
191: * @return program assigned to channel, represented by array {bank,program}.
192: * @exception IllegalArgumentException Thrown if <code>channel</code>
193: * is out of range.
194: * @exception IllegalStateException Thrown if the player has not been prefetched.
195: * @exception MediaException Thrown if querying of banks is not supported.
196: * @see #isBankQuerySupported
197: * @see #setProgram
198: */
199: int[] getProgram(int channel) throws MediaException;
200:
201: /**
202: * Get volume for the given channel. The return value is
203: * independent of the master volume, which is set and retrieved
204: * with {@link VolumeControl VolumeControl}.<p>
205: *
206: * As there is no MIDI equivalent to this method, the implementation
207: * may not always know the current volume for a given channel. In
208: * this case the return value is -1.
209: *
210: * @param channel 0-15
211: * @return channel volume, 0-127, or -1 if not known
212: * @exception IllegalArgumentException Thrown if <code>channel</code>
213: * is out of range.
214: * @exception IllegalStateException Thrown if the player has not been prefetched.
215: * @see #setChannelVolume(int, int)
216: */
217: int getChannelVolume(int channel);
218:
219: // set device state
220:
221: /**
222: * Set program of a channel. This sets the current program for the
223: * channel and may be overwritten during playback by events in a MIDI sequence.<p>
224: * It is a high level convenience function. Internally, these method calls are
225: * executed:<p>
226: * <code>
227: * shortMidiEvent(CONTROL_CHANGE | channel, CONTROL_BANK_CHANGE_MSB, bank >> 7);<br>
228: * shortMidiEvent(CONTROL_CHANGE | channel, CONTROL_BANK_CHANGE_LSB, bank & 0x7F);<br>
229: * shortMidiEvent(PROGRAM_CHANGE | channel, program, 0);
230: * </code><p>
231: *
232: * In order to use the default bank (the initial bank), set the bank parameter to -1.
233: * <p>
234: *
235: * In order to set a program without explicitly setting the bank,
236: * use the following call: <p>
237: * <code>
238: * shortMidiEvent(PROGRAM_CHANGE | channel, program, 0);
239: * </code><p>
240: *
241: * In both examples, the following constants are used:<p>
242: * <code>
243: * int PROGRAM_CHANGE = 0xC0;<br>
244: * int CONTROL_BANK_CHANGE_MSB = 0x00;<br>
245: * int CONTROL_BANK_CHANGE_LSB = 0x20;
246: * </code><p>
247: *
248: * @param channel 0-15
249: * @param bank 0-16383, or -1 for default bank
250: * @param program 0-127
251: * @exception IllegalArgumentException Thrown if any of the given
252: * parameters is out of range.
253: * @exception IllegalStateException Thrown if the player has not been prefetched.
254: * @see #getProgram
255: */
256: void setProgram(int channel, int bank, int program);
257:
258: /**
259: * Set volume for the given channel. To mute, set to 0.
260: * This sets the current volume for the
261: * channel and may be overwritten during playback by events in a MIDI sequence.<p>
262: * It is a high level convenience function. Internally, the following command
263: * is executed:<p>
264: * <code>
265: * shortMidiEvent(CONTROL_CHANGE | channel, CONTROL_MAIN_VOLUME, 0);
266: * </code><p>
267: * where this constant is used:<p>
268: * <code> int CONTROL_MAIN_VOLUME = 0x07</code><p>
269: *
270: * The channel volume is independent of the master volume, which
271: * is accessed with {@link VolumeControl VolumeControl}.
272: * Setting the channel volume does not modify the value of the master
273: * volume - and vice versa: changing the value of master volume does not
274: * change any channel's volume value.<br>
275: * The synthesizer
276: * mixes the output of up to 16 channels, each channel with its own
277: * channel volume. The master volume then controls the volume of the mix.
278: * Consequently, the effective output volume of a channel is the product
279: * of master volume and channel volume. <p>
280: *
281: * Setting the channel volume does not generate a
282: * {@link javax.microedition.media.PlayerListener#VOLUME_CHANGED VOLUME_CHANGED event}.
283: *
284: * @param channel 0-15
285: * @param volume 0-127
286: * @exception IllegalArgumentException Thrown if
287: * <code>channel</code> or <code>volume</code> is out of range.
288: * @exception IllegalStateException Thrown if the player has not been prefetched.
289: * @see #getChannelVolume
290: */
291: void setChannelVolume(int channel, int volume);
292:
293: // banks
294:
295: /**
296: * Returns list of installed banks.
297: * If the <code>custom</code> parameter is true, a list of custom banks is returned.
298: * Otherwise, a list of all banks (custom and internal) is returned.
299: * <p>
300: * As there is no MIDI equivalent to this method, this method is
301: * optional, indicated by {@link #isBankQuerySupported isBankQuerySupported}.
302: * If it returns false, this function is not supported and throws an exception.
303: *
304: * @param custom if set to true, returns list of custom banks.
305: * @return an array of all installed bank numbers.
306: * Each bank number is in the range of 0..16383
307: * @exception MediaException if this device does not support retrieval of
308: * banks
309: * @exception IllegalStateException Thrown if the player has not been prefetched.
310: * @see #isBankQuerySupported
311: */
312: int[] getBankList(boolean custom) throws MediaException;
313:
314: /**
315: * Given bank, get list of program numbers. If and only if
316: * this bank is not installed, an empty array is returned.<p>
317: *
318: * As there is no MIDI equivalent to this method, this method is
319: * optional, indicated by {@link #isBankQuerySupported isBankQuerySupported}.
320: * If it returns false, this function is not supported and throws an exception.
321: *
322: * @param bank 0..16383
323: * @return an array of programs defined in the given bank.
324: * Each program number is from 0..127.
325: * @exception IllegalArgumentException Thrown if <code>bank</code>
326: * is out of range.
327: * @exception MediaException Thrown if the device does not support
328: * retrieval of programs.
329: * @exception IllegalStateException Thrown if the player has not been prefetched.
330: * @see #setProgram
331: * @see #isBankQuerySupported
332: */
333: int[] getProgramList(int bank) throws MediaException;
334:
335: /**
336: * Given bank and program, get name of program.
337: * For space-saving reasons, an implementation may return an empty string.
338: * <p>
339: * As there is no MIDI equivalent to this method, this method is
340: * optional, indicated by {@link #isBankQuerySupported isBankQuerySupported}.
341: * If it returns false, this function is not supported and throws an exception.
342: *
343: * @param bank 0-16383
344: * @param prog 0-127
345: * @exception IllegalArgumentException Thrown if <code>bank</code>
346: * or <code>prog</code> is out of range.
347: * @exception MediaException Thrown if the bank or program is
348: * not installed (internal or custom), or if this device does not
349: * support retrieval of program names
350: * @exception IllegalStateException Thrown if the player has not been prefetched.
351: * @return name of the specified program, or empty string.
352: * @see #isBankQuerySupported
353: */
354: String getProgramName(int bank, int prog) throws MediaException;
355:
356: /**
357: * Given bank, program and key, get name of key.
358: * This method applies to key-mapped banks (i.e. percussive banks
359: * or effect banks) only.
360: * A return value of <code>null</code> means that the specified key
361: * is not mapped to a sound. For melodic banks,
362: * where each key (=note) produces the same sound at different pitch, this method
363: * always returns <code>null</code>.
364: * For space-saving reasons, an implementation may return an empty string
365: * instead of the key name. To find out which keys in a specific program
366: * are mapped to a sound, iterate through all keys (0-127) and compare
367: * the return value of <code>getKeyName</code> to non-<code>null</code>.
368: * <p>
369: * As there is no MIDI equivalent to this method, this method is
370: * optional, indicated by {@link #isBankQuerySupported isBankQuerySupported}.
371: * If it returns false, this function is not supported and throws an exception.
372: *
373: * @param bank 0-16383
374: * @param prog 0-127
375: * @param key 0-127
376: * @exception IllegalArgumentException Thrown if <code>bank</code>,
377: * <code>prog</code> or <code>key</code> is out of range.
378: * @exception MediaException Thrown if the bank or program is
379: * not installed (internal or custom), or if this device does not
380: * support retrieval of key names
381: * @exception IllegalStateException Thrown if the player has not been prefetched.
382: * @return name of the specified key, empty string, or <code>null</code> if
383: * the key is not mapped to a sound.
384: * @see #isBankQuerySupported
385: */
386: String getKeyName(int bank, int prog, int key)
387: throws MediaException;
388:
389: /**
390: * Sends a short MIDI event to the device.
391: * Short MIDI events consist of 1, 2, or 3 unsigned bytes.
392: * For non-realtime events, the first byte is split up into
393: * status (upper nibble, 0x80-0xF0) and channel (0x00-0x0F).
394: * For example, to send a <code>Note On</code> event on a given channel,
395: * use this line:<p>
396: * <code> shortMidiEvent(NOTE_ON | channel, note, velocity);</code><p>
397: * For events with less than 3 bytes, set the remaining data bytes to 0.<p>
398: *
399: * There is no guarantee that a specific
400: * implementation of a MIDI device supports all event types.
401: * Also, the MIDI protocol does not implement flow control and it is not
402: * guaranteed that an event reaches the destination.
403: * In both these cases, this method fails silently. <p>
404: *
405: * Static error checking is performed on the passed parameters. They have to
406: * specify a valid, complete MIDI event. Events with <code>type</code> < 0x80 are
407: * not valid MIDI events (-> running status). When an invalid event
408: * is encountered, an IllegalArgumentException is thrown.
409: *
410: * @param type 0x80..0xFF, excluding 0xF0 and 0xF7, which are reserved for system exclusive
411: * @param data1 for 2 and 3-byte events: first data byte, 0..127
412: * @param data2 for 3-byte events: second data byte, 0..127
413: * @exception IllegalArgumentException Thrown if one of the parameters
414: * is out of range.
415: * @exception IllegalStateException Thrown if the player has not been prefetched.
416: */
417: void shortMidiEvent(int type, int data1, int data2);
418:
419: /**
420: * Sends a long MIDI event to the device, typically a system exclusive message.
421: * This method passes the data directly to the receiving device.
422: * The data array's contents are not checked for validity.<p>
423: * It is possible to send short events, or even a series of short events
424: * with this method.<p>
425: *
426: * @param data array of the bytes to send
427: * @param offset start offset in data array
428: * @param length number of bytes to be sent
429: * @exception IllegalArgumentException Thrown if any one of the given
430: * parameters is not valid.
431: * @exception IllegalStateException Thrown if the player has not been prefetched.
432: * @return the number of bytes actually sent to the device or
433: * -1 if an error occurred
434: */
435: int longMidiEvent(byte[] data, int offset, int length);
436: }
|