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