1 /* 2 * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.sound.midi; 27 28 import java.util.Collections; 29 import java.util.HashMap; 30 import java.util.Map; 31 32 /** 33 * A {@code MidiFileFormat} object encapsulates a MIDI file's type, as well as 34 * its length and timing information. 35 * <p> 36 * A {@code MidiFileFormat} object can include a set of properties. A property 37 * is a pair of key and value: the key is of type {@code String}, the associated 38 * property value is an arbitrary object. Properties specify additional 39 * informational meta data (like a author, or copyright). Properties are 40 * optional information, and file reader and file writer implementations are not 41 * required to provide or recognize properties. 42 * <p> 43 * The following table lists some common properties that should be used in 44 * implementations: 45 * 46 * <table class="striped"> 47 * <caption>MIDI File Format Properties</caption> 48 * <thead> 49 * <tr> 50 * <th scope="col">Property key 51 * <th scope="col">Value type 52 * <th scope="col">Description 53 * </thead> 54 * <tbody> 55 * <tr> 56 * <th scope="row">"author" 57 * <td>{@link String String} 58 * <td>name of the author of this file 59 * <tr> 60 * <th scope="row">"title" 61 * <td>{@link String String} 62 * <td>title of this file 63 * <tr> 64 * <th scope="row">"copyright" 65 * <td>{@link String String} 66 * <td>copyright message 67 * <tr> 68 * <th scope="row">"date" 69 * <td>{@link java.util.Date Date} 70 * <td>date of the recording or release 71 * <tr> 72 * <th scope="row">"comment" 73 * <td>{@link String String} 74 * <td>an arbitrary text 75 * </tbody> 76 * </table> 77 * 78 * @author Kara Kytle 79 * @author Florian Bomers 80 * @see MidiSystem#getMidiFileFormat(java.io.File) 81 * @see Sequencer#setSequence(java.io.InputStream stream) 82 */ 83 public class MidiFileFormat { 84 85 /** 86 * Represents unknown length. 87 * 88 * @see #getByteLength 89 * @see #getMicrosecondLength 90 */ 91 public static final int UNKNOWN_LENGTH = -1; 92 93 /** 94 * The type of MIDI file. 95 */ 96 protected int type; 97 98 /** 99 * The division type of the MIDI file. 100 * 101 * @see Sequence#PPQ 102 * @see Sequence#SMPTE_24 103 * @see Sequence#SMPTE_25 104 * @see Sequence#SMPTE_30DROP 105 * @see Sequence#SMPTE_30 106 */ 107 protected float divisionType; 108 109 /** 110 * The timing resolution of the MIDI file. 111 */ 112 protected int resolution; 113 114 /** 115 * The length of the MIDI file in bytes. 116 */ 117 protected int byteLength; 118 119 /** 120 * The duration of the MIDI file in microseconds. 121 */ 122 protected long microsecondLength; 123 124 /** 125 * The set of properties. 126 */ 127 private HashMap<String, Object> properties; 128 129 /** 130 * Constructs a {@code MidiFileFormat}. 131 * 132 * @param type the MIDI file type (0, 1, or 2) 133 * @param divisionType the timing division type (PPQ or one of the SMPTE 134 * types) 135 * @param resolution the timing resolution 136 * @param bytes the length of the MIDI file in bytes, or 137 * {@link #UNKNOWN_LENGTH} if not known 138 * @param microseconds the duration of the file in microseconds, or 139 * {@link #UNKNOWN_LENGTH} if not known 140 * @see #UNKNOWN_LENGTH 141 * @see Sequence#PPQ 142 * @see Sequence#SMPTE_24 143 * @see Sequence#SMPTE_25 144 * @see Sequence#SMPTE_30DROP 145 * @see Sequence#SMPTE_30 146 */ 147 public MidiFileFormat(int type, float divisionType, int resolution, int bytes, long microseconds) { 148 149 this.type = type; 150 this.divisionType = divisionType; 151 this.resolution = resolution; 152 this.byteLength = bytes; 153 this.microsecondLength = microseconds; 154 this.properties = null; 155 } 156 157 /** 158 * Construct a {@code MidiFileFormat} with a set of properties. 159 * 160 * @param type the MIDI file type (0, 1, or 2) 161 * @param divisionType the timing division type (PPQ or one of the SMPTE 162 * types) 163 * @param resolution the timing resolution 164 * @param bytes the length of the MIDI file in bytes, or 165 * {@code UNKNOWN_LENGTH} if not known 166 * @param microseconds the duration of the file in microseconds, or 167 * {@code UNKNOWN_LENGTH} if not known 168 * @param properties a {@code Map<String,Object>} object with properties 169 * @see #UNKNOWN_LENGTH 170 * @see Sequence#PPQ 171 * @see Sequence#SMPTE_24 172 * @see Sequence#SMPTE_25 173 * @see Sequence#SMPTE_30DROP 174 * @see Sequence#SMPTE_30 175 * @since 1.5 176 */ 177 public MidiFileFormat(int type, float divisionType, 178 int resolution, int bytes, 179 long microseconds, Map<String, Object> properties) { 180 this(type, divisionType, resolution, bytes, microseconds); 181 this.properties = new HashMap<>(properties); 182 } 183 184 /** 185 * Obtains the MIDI file type. 186 * 187 * @return the file's type (0, 1, or 2) 188 */ 189 public int getType() { 190 return type; 191 } 192 193 /** 194 * Obtains the timing division type for the MIDI file. 195 * 196 * @return the division type (PPQ or one of the SMPTE types) 197 * @see Sequence#Sequence(float, int) 198 * @see Sequence#PPQ 199 * @see Sequence#SMPTE_24 200 * @see Sequence#SMPTE_25 201 * @see Sequence#SMPTE_30DROP 202 * @see Sequence#SMPTE_30 203 * @see Sequence#getDivisionType() 204 */ 205 public float getDivisionType() { 206 return divisionType; 207 } 208 209 /** 210 * Obtains the timing resolution for the MIDI file. If the division type is 211 * PPQ, the resolution is specified in ticks per beat. For SMTPE timing, the 212 * resolution is specified in ticks per frame. 213 * 214 * @return the number of ticks per beat (PPQ) or per frame (SMPTE) 215 * @see #getDivisionType 216 * @see Sequence#getResolution() 217 */ 218 public int getResolution() { 219 return resolution; 220 } 221 222 /** 223 * Obtains the length of the MIDI file, expressed in 8-bit bytes. 224 * 225 * @return the number of bytes in the file, or {@code UNKNOWN_LENGTH} if not 226 * known 227 * @see #UNKNOWN_LENGTH 228 */ 229 public int getByteLength() { 230 return byteLength; 231 } 232 233 /** 234 * Obtains the length of the MIDI file, expressed in microseconds. 235 * 236 * @return the file's duration in microseconds, or {@code UNKNOWN_LENGTH} if 237 * not known 238 * @see Sequence#getMicrosecondLength() 239 * @see #getByteLength 240 * @see #UNKNOWN_LENGTH 241 */ 242 public long getMicrosecondLength() { 243 return microsecondLength; 244 } 245 246 /** 247 * Obtain an unmodifiable map of properties. The concept of properties is 248 * further explained in the {@link MidiFileFormat class description}. 249 * 250 * @return a {@code Map<String,Object>} object containing all properties. If 251 * no properties are recognized, an empty map is returned. 252 * @see #getProperty(String) 253 * @since 1.5 254 */ 255 @SuppressWarnings("unchecked") // Cast of result of clone 256 public Map<String,Object> properties() { 257 Map<String,Object> ret; 258 if (properties == null) { 259 ret = new HashMap<>(0); 260 } else { 261 ret = (Map<String,Object>) (properties.clone()); 262 } 263 return Collections.unmodifiableMap(ret); 264 } 265 266 /** 267 * Obtain the property value specified by the key. The concept of properties 268 * is further explained in the {@link MidiFileFormat class description}. 269 * <p> 270 * If the specified property is not defined for a particular file format, 271 * this method returns {@code null}. 272 * 273 * @param key the key of the desired property 274 * @return the value of the property with the specified key, or {@code null} 275 * if the property does not exist 276 * @see #properties() 277 * @since 1.5 278 */ 279 public Object getProperty(String key) { 280 if (properties == null) { 281 return null; 282 } 283 return properties.get(key); 284 } 285 }