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