23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package javax.sound.midi; |
26 package javax.sound.midi; |
27 |
27 |
28 import java.io.InputStream; |
|
29 import java.io.IOException; |
|
30 import java.util.Collections; |
28 import java.util.Collections; |
31 import java.util.HashMap; |
29 import java.util.HashMap; |
32 import java.util.Map; |
30 import java.util.Map; |
33 |
31 |
34 |
|
35 /** |
32 /** |
36 * A <code>MidiFileFormat</code> object encapsulates a MIDI file's |
33 * A {@code MidiFileFormat} object encapsulates a MIDI file's type, as well as |
37 * type, as well as its length and timing information. |
34 * its length and timing information. |
38 * |
35 * <p> |
39 * <p>A <code>MidiFileFormat</code> object can |
36 * A {@code MidiFileFormat} object can include a set of properties. A property |
40 * include a set of properties. A property is a pair of key and value: |
37 * is a pair of key and value: the key is of type {@code String}, the associated |
41 * the key is of type <code>String</code>, the associated property |
38 * property value is an arbitrary object. Properties specify additional |
42 * value is an arbitrary object. |
39 * informational meta data (like a author, or copyright). Properties are |
43 * Properties specify additional informational |
40 * optional information, and file reader and file writer implementations are not |
44 * meta data (like a author, or copyright). |
41 * required to provide or recognize properties. |
45 * Properties are optional information, and file reader and file |
42 * <p> |
46 * writer implementations are not required to provide or |
43 * The following table lists some common properties that should be used in |
47 * recognize properties. |
44 * implementations: |
48 * |
|
49 * <p>The following table lists some common properties that should |
|
50 * be used in implementations: |
|
51 * |
45 * |
52 * <table border=1> |
46 * <table border=1> |
53 <caption>MIDI File Format Properties</caption> |
47 <caption>MIDI File Format Properties</caption> |
54 * <tr> |
48 * <tr> |
55 * <th>Property key</th> |
49 * <th>Property key</th> |
81 * <td>{@link java.lang.String String}</td> |
75 * <td>{@link java.lang.String String}</td> |
82 * <td>an arbitrary text</td> |
76 * <td>an arbitrary text</td> |
83 * </tr> |
77 * </tr> |
84 * </table> |
78 * </table> |
85 * |
79 * |
|
80 * @author Kara Kytle |
|
81 * @author Florian Bomers |
86 * @see MidiSystem#getMidiFileFormat(java.io.File) |
82 * @see MidiSystem#getMidiFileFormat(java.io.File) |
87 * @see Sequencer#setSequence(java.io.InputStream stream) |
83 * @see Sequencer#setSequence(java.io.InputStream stream) |
88 * |
|
89 * @author Kara Kytle |
|
90 * @author Florian Bomers |
|
91 */ |
84 */ |
92 |
|
93 public class MidiFileFormat { |
85 public class MidiFileFormat { |
94 |
86 |
95 |
|
96 /** |
87 /** |
97 * Represents unknown length. |
88 * Represents unknown length. |
|
89 * |
98 * @see #getByteLength |
90 * @see #getByteLength |
99 * @see #getMicrosecondLength |
91 * @see #getMicrosecondLength |
100 */ |
92 */ |
101 public static final int UNKNOWN_LENGTH = -1; |
93 public static final int UNKNOWN_LENGTH = -1; |
102 |
94 |
103 |
|
104 /** |
95 /** |
105 * The type of MIDI file. |
96 * The type of MIDI file. |
106 */ |
97 */ |
107 protected int type; |
98 protected int type; |
108 |
99 |
130 /** |
121 /** |
131 * The duration of the MIDI file in microseconds. |
122 * The duration of the MIDI file in microseconds. |
132 */ |
123 */ |
133 protected long microsecondLength; |
124 protected long microsecondLength; |
134 |
125 |
135 |
126 /** |
136 /** The set of properties */ |
127 * The set of properties. |
|
128 */ |
137 private HashMap<String, Object> properties; |
129 private HashMap<String, Object> properties; |
138 |
130 |
139 |
131 /** |
140 /** |
132 * Constructs a {@code MidiFileFormat}. |
141 * Constructs a <code>MidiFileFormat</code>. |
133 * |
142 * |
134 * @param type the MIDI file type (0, 1, or 2) |
143 * @param type the MIDI file type (0, 1, or 2) |
135 * @param divisionType the timing division type (PPQ or one of the SMPTE |
144 * @param divisionType the timing division type (PPQ or one of the SMPTE types) |
136 * types) |
145 * @param resolution the timing resolution |
137 * @param resolution the timing resolution |
146 * @param bytes the length of the MIDI file in bytes, or UNKNOWN_LENGTH if not known |
138 * @param bytes the length of the MIDI file in bytes, or UNKNOWN_LENGTH if |
147 * @param microseconds the duration of the file in microseconds, or UNKNOWN_LENGTH if not known |
139 * not known |
|
140 * @param microseconds the duration of the file in microseconds, or |
|
141 * UNKNOWN_LENGTH if not known |
148 * @see #UNKNOWN_LENGTH |
142 * @see #UNKNOWN_LENGTH |
149 * @see Sequence#PPQ |
143 * @see Sequence#PPQ |
150 * @see Sequence#SMPTE_24 |
144 * @see Sequence#SMPTE_24 |
151 * @see Sequence#SMPTE_25 |
145 * @see Sequence#SMPTE_25 |
152 * @see Sequence#SMPTE_30DROP |
146 * @see Sequence#SMPTE_30DROP |
160 this.byteLength = bytes; |
154 this.byteLength = bytes; |
161 this.microsecondLength = microseconds; |
155 this.microsecondLength = microseconds; |
162 this.properties = null; |
156 this.properties = null; |
163 } |
157 } |
164 |
158 |
165 |
159 /** |
166 /** |
160 * Construct a {@code MidiFileFormat} with a set of properties. |
167 * Construct a <code>MidiFileFormat</code> with a set of properties. |
161 * |
168 * |
162 * @param type the MIDI file type (0, 1, or 2) |
169 * @param type the MIDI file type (0, 1, or 2) |
163 * @param divisionType the timing division type (PPQ or one of the SMPTE |
170 * @param divisionType the timing division type |
164 * types) |
171 * (PPQ or one of the SMPTE types) |
165 * @param resolution the timing resolution |
172 * @param resolution the timing resolution |
166 * @param bytes the length of the MIDI file in bytes, or UNKNOWN_LENGTH if |
173 * @param bytes the length of the MIDI file in bytes, |
167 * not known |
174 * or UNKNOWN_LENGTH if not known |
168 * @param microseconds the duration of the file in microseconds, or |
175 * @param microseconds the duration of the file in microseconds, |
169 * UNKNOWN_LENGTH if not known |
176 * or UNKNOWN_LENGTH if not known |
170 * @param properties a {@code Map<String,Object>} object with properties |
177 * @param properties a <code>Map<String,Object></code> object |
|
178 * with properties |
|
179 * |
|
180 * @see #UNKNOWN_LENGTH |
171 * @see #UNKNOWN_LENGTH |
181 * @see Sequence#PPQ |
172 * @see Sequence#PPQ |
182 * @see Sequence#SMPTE_24 |
173 * @see Sequence#SMPTE_24 |
183 * @see Sequence#SMPTE_25 |
174 * @see Sequence#SMPTE_25 |
184 * @see Sequence#SMPTE_30DROP |
175 * @see Sequence#SMPTE_30DROP |
190 long microseconds, Map<String, Object> properties) { |
181 long microseconds, Map<String, Object> properties) { |
191 this(type, divisionType, resolution, bytes, microseconds); |
182 this(type, divisionType, resolution, bytes, microseconds); |
192 this.properties = new HashMap<String, Object>(properties); |
183 this.properties = new HashMap<String, Object>(properties); |
193 } |
184 } |
194 |
185 |
195 |
|
196 |
|
197 /** |
186 /** |
198 * Obtains the MIDI file type. |
187 * Obtains the MIDI file type. |
|
188 * |
199 * @return the file's type (0, 1, or 2) |
189 * @return the file's type (0, 1, or 2) |
200 */ |
190 */ |
201 public int getType() { |
191 public int getType() { |
202 return type; |
192 return type; |
203 } |
193 } |
204 |
194 |
205 /** |
195 /** |
206 * Obtains the timing division type for the MIDI file. |
196 * Obtains the timing division type for the MIDI file. |
207 * |
197 * |
208 * @return the division type (PPQ or one of the SMPTE types) |
198 * @return the division type (PPQ or one of the SMPTE types) |
209 * |
|
210 * @see Sequence#Sequence(float, int) |
199 * @see Sequence#Sequence(float, int) |
211 * @see Sequence#PPQ |
200 * @see Sequence#PPQ |
212 * @see Sequence#SMPTE_24 |
201 * @see Sequence#SMPTE_24 |
213 * @see Sequence#SMPTE_25 |
202 * @see Sequence#SMPTE_25 |
214 * @see Sequence#SMPTE_30DROP |
203 * @see Sequence#SMPTE_30DROP |
217 */ |
206 */ |
218 public float getDivisionType() { |
207 public float getDivisionType() { |
219 return divisionType; |
208 return divisionType; |
220 } |
209 } |
221 |
210 |
222 |
211 /** |
223 /** |
212 * Obtains the timing resolution for the MIDI file. If the division type is |
224 * Obtains the timing resolution for the MIDI file. |
213 * PPQ, the resolution is specified in ticks per beat. For SMTPE timing, the |
225 * If the division type is PPQ, the resolution is specified in ticks per beat. |
214 * resolution is specified in ticks per frame. |
226 * For SMTPE timing, the resolution is specified in ticks per frame. |
|
227 * |
215 * |
228 * @return the number of ticks per beat (PPQ) or per frame (SMPTE) |
216 * @return the number of ticks per beat (PPQ) or per frame (SMPTE) |
229 * @see #getDivisionType |
217 * @see #getDivisionType |
230 * @see Sequence#getResolution() |
218 * @see Sequence#getResolution() |
231 */ |
219 */ |
232 public int getResolution() { |
220 public int getResolution() { |
233 return resolution; |
221 return resolution; |
234 } |
222 } |
235 |
223 |
236 |
|
237 /** |
224 /** |
238 * Obtains the length of the MIDI file, expressed in 8-bit bytes. |
225 * Obtains the length of the MIDI file, expressed in 8-bit bytes. |
|
226 * |
239 * @return the number of bytes in the file, or UNKNOWN_LENGTH if not known |
227 * @return the number of bytes in the file, or UNKNOWN_LENGTH if not known |
240 * @see #UNKNOWN_LENGTH |
228 * @see #UNKNOWN_LENGTH |
241 */ |
229 */ |
242 public int getByteLength() { |
230 public int getByteLength() { |
243 return byteLength; |
231 return byteLength; |
244 } |
232 } |
245 |
233 |
246 /** |
234 /** |
247 * Obtains the length of the MIDI file, expressed in microseconds. |
235 * Obtains the length of the MIDI file, expressed in microseconds. |
248 * @return the file's duration in microseconds, or UNKNOWN_LENGTH if not known |
236 * |
|
237 * @return the file's duration in microseconds, or UNKNOWN_LENGTH if not |
|
238 * known |
249 * @see Sequence#getMicrosecondLength() |
239 * @see Sequence#getMicrosecondLength() |
250 * @see #getByteLength |
240 * @see #getByteLength |
251 * @see #UNKNOWN_LENGTH |
241 * @see #UNKNOWN_LENGTH |
252 */ |
242 */ |
253 public long getMicrosecondLength() { |
243 public long getMicrosecondLength() { |
254 return microsecondLength; |
244 return microsecondLength; |
255 } |
245 } |
256 |
246 |
257 /** |
247 /** |
258 * Obtain an unmodifiable map of properties. |
248 * Obtain an unmodifiable map of properties. The concept of properties is |
259 * The concept of properties is further explained in |
249 * further explained in the {@link MidiFileFormat class description}. |
260 * the {@link MidiFileFormat class description}. |
250 * |
261 * |
251 * @return a {@code Map<String,Object>} object containing all properties. If |
262 * @return a <code>Map<String,Object></code> object containing |
252 * no properties are recognized, an empty map is returned. |
263 * all properties. If no properties are recognized, an empty map is |
|
264 * returned. |
|
265 * |
|
266 * @see #getProperty(String) |
253 * @see #getProperty(String) |
267 * @since 1.5 |
254 * @since 1.5 |
268 */ |
255 */ |
269 @SuppressWarnings("unchecked") // Cast of result of clone |
256 @SuppressWarnings("unchecked") // Cast of result of clone |
270 public Map<String,Object> properties() { |
257 public Map<String,Object> properties() { |
275 ret = (Map<String,Object>) (properties.clone()); |
262 ret = (Map<String,Object>) (properties.clone()); |
276 } |
263 } |
277 return Collections.unmodifiableMap(ret); |
264 return Collections.unmodifiableMap(ret); |
278 } |
265 } |
279 |
266 |
280 |
267 /** |
281 /** |
268 * Obtain the property value specified by the key. The concept of properties |
282 * Obtain the property value specified by the key. |
269 * is further explained in the {@link MidiFileFormat class description}. |
283 * The concept of properties is further explained in |
270 * <p> |
284 * the {@link MidiFileFormat class description}. |
271 * If the specified property is not defined for a particular file format, |
285 * |
272 * this method returns {@code null}. |
286 * <p>If the specified property is not defined for a |
273 * |
287 * particular file format, this method returns |
274 * @param key the key of the desired property |
288 * <code>null</code>. |
275 * @return the value of the property with the specified key, or {@code null} |
289 * |
276 * if the property does not exist |
290 * @param key the key of the desired property |
|
291 * @return the value of the property with the specified key, |
|
292 * or <code>null</code> if the property does not exist. |
|
293 * |
|
294 * @see #properties() |
277 * @see #properties() |
295 * @since 1.5 |
278 * @since 1.5 |
296 */ |
279 */ |
297 public Object getProperty(String key) { |
280 public Object getProperty(String key) { |
298 if (properties == null) { |
281 if (properties == null) { |
299 return null; |
282 return null; |
300 } |
283 } |
301 return properties.get(key); |
284 return properties.get(key); |
302 } |
285 } |
303 |
|
304 |
|
305 } |
286 } |