/*
 * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.media.sound;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.SequenceInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.EOFException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.BufferedInputStream;
import java.net.URL;
import java.net.MalformedURLException;

import javax.sound.midi.MidiFileFormat;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MetaMessage;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.Sequence;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.SysexMessage;
import javax.sound.midi.Track;
import javax.sound.midi.spi.MidiFileReader;



/**
 * MIDI file reader.
 *
 * @author Kara Kytle
 * @author Jan Borgersen
 * @author Florian Bomers
 */

public class StandardMidiFileReader extends MidiFileReader {

    private static final int MThd_MAGIC = 0x4d546864;  // 'MThd'

    private static final int MIDI_TYPE_0 = 0;
    private static final int MIDI_TYPE_1 = 1;

    private static final int bisBufferSize = 1024; // buffer size in buffered input streams

    /**
     * MIDI parser types
     */
    private static final int types[] = {
        MIDI_TYPE_0,
        MIDI_TYPE_1
    };

    public MidiFileFormat getMidiFileFormat(InputStream stream) throws InvalidMidiDataException, IOException {
        return getMidiFileFormatFromStream(stream, MidiFileFormat.UNKNOWN_LENGTH, null);
    }

    // $$fb 2002-04-17: part of fix for 4635286: MidiSystem.getMidiFileFormat() returns format having invalid length
    private MidiFileFormat getMidiFileFormatFromStream(InputStream stream, int fileLength, SMFParser smfParser) throws InvalidMidiDataException, IOException {
        int maxReadLength = 16;
        int duration = MidiFileFormat.UNKNOWN_LENGTH;
        DataInputStream dis;

        if (stream instanceof DataInputStream) {
            dis = (DataInputStream) stream;
        } else {
            dis = new DataInputStream(stream);
        }
        if (smfParser == null) {
            dis.mark(maxReadLength);
        } else {
            smfParser.stream = dis;
        }

        int type;
        int numtracks;
        float divisionType;
        int resolution;

        try {
            int magic = dis.readInt();
            if( !(magic == MThd_MAGIC) ) {
                // not MIDI
                throw new InvalidMidiDataException("not a valid MIDI file");
            }

            // read header length
            int bytesRemaining = dis.readInt() - 6;
            type = dis.readShort();
            numtracks = dis.readShort();
            int timing = dis.readShort();

            // decipher the timing code
            if (timing > 0) {
                // tempo based timing.  value is ticks per beat.
                divisionType = Sequence.PPQ;
                resolution = timing;
            } else {
                // SMPTE based timing.  first decipher the frame code.
                int frameCode = (-1 * timing) >> 8;
                switch(frameCode) {
                case 24:
                    divisionType = Sequence.SMPTE_24;
                    break;
                case 25:
                    divisionType = Sequence.SMPTE_25;
                    break;
                case 29:
                    divisionType = Sequence.SMPTE_30DROP;
                    break;
                case 30:
                    divisionType = Sequence.SMPTE_30;
                    break;
                default:
                    throw new InvalidMidiDataException("Unknown frame code: " + frameCode);
                }
                // now determine the timing resolution in ticks per frame.
                resolution = timing & 0xFF;
            }
            if (smfParser != null) {
                // remainder of this chunk
                dis.skip(bytesRemaining);
                smfParser.tracks = numtracks;
            }
        } finally {
            // if only reading the file format, reset the stream
            if (smfParser == null) {
                dis.reset();
            }
        }
        MidiFileFormat format = new MidiFileFormat(type, divisionType, resolution, fileLength, duration);
        return format;
    }


    public MidiFileFormat getMidiFileFormat(URL url) throws InvalidMidiDataException, IOException {
        InputStream urlStream = url.openStream(); // throws IOException
        BufferedInputStream bis = new BufferedInputStream( urlStream, bisBufferSize );
        MidiFileFormat fileFormat = null;
        try {
            fileFormat = getMidiFileFormat( bis ); // throws InvalidMidiDataException
        } finally {
            bis.close();
        }
        return fileFormat;
    }


    public MidiFileFormat getMidiFileFormat(File file) throws InvalidMidiDataException, IOException {
        FileInputStream fis = new FileInputStream(file); // throws IOException
        BufferedInputStream bis = new BufferedInputStream(fis, bisBufferSize);

        // $$fb 2002-04-17: part of fix for 4635286: MidiSystem.getMidiFileFormat() returns format having invalid length
        long length = file.length();
        if (length > Integer.MAX_VALUE) {
            length = MidiFileFormat.UNKNOWN_LENGTH;
        }
        MidiFileFormat fileFormat = null;
        try {
            fileFormat = getMidiFileFormatFromStream(bis, (int) length, null);
        } finally {
            bis.close();
        }
        return fileFormat;
    }


    public Sequence getSequence(InputStream stream) throws InvalidMidiDataException, IOException {
        SMFParser smfParser = new SMFParser();
        MidiFileFormat format = getMidiFileFormatFromStream(stream,
                                                            MidiFileFormat.UNKNOWN_LENGTH,
                                                            smfParser);

        // must be MIDI Type 0 or Type 1
        if ((format.getType() != 0) && (format.getType() != 1)) {
            throw new InvalidMidiDataException("Invalid or unsupported file type: "  + format.getType());
        }

        // construct the sequence object
        Sequence sequence = new Sequence(format.getDivisionType(), format.getResolution());

        // for each track, go to the beginning and read the track events
        for (int i = 0; i < smfParser.tracks; i++) {
            if (smfParser.nextTrack()) {
                smfParser.readTrack(sequence.createTrack());
            } else {
                break;
            }
        }
        return sequence;
    }



    public Sequence getSequence(URL url) throws InvalidMidiDataException, IOException {
        InputStream is = url.openStream();  // throws IOException
        is = new BufferedInputStream(is, bisBufferSize);
        Sequence seq = null;
        try {
            seq = getSequence(is);
        } finally {
            is.close();
        }
        return seq;
    }


    public Sequence getSequence(File file) throws InvalidMidiDataException, IOException {
        InputStream is = new FileInputStream(file); // throws IOException
        is = new BufferedInputStream(is, bisBufferSize);
        Sequence seq = null;
        try {
            seq = getSequence(is);
        } finally {
            is.close();
        }
        return seq;
    }
}

//=============================================================================================================

/**
 * State variables during parsing of a MIDI file
 */
class SMFParser {
    private static final int MTrk_MAGIC = 0x4d54726b;  // 'MTrk'

    // set to true to not allow corrupt MIDI files tombe loaded
    private static final boolean STRICT_PARSER = false;

    private static final boolean DEBUG = false;

    int tracks;                       // number of tracks
    DataInputStream stream;   // the stream to read from

    private int trackLength = 0;  // remaining length in track
    private byte[] trackData = null;
    private int pos = 0;

    public SMFParser() {
    }

    private int readUnsigned() throws IOException {
        return trackData[pos++] & 0xFF;
    }

    private void read(byte[] data) throws IOException {
        System.arraycopy(trackData, pos, data, 0, data.length);
        pos += data.length;
    }

    private long readVarInt() throws IOException {
        long value = 0; // the variable-lengh int value
        int currentByte = 0;
        do {
            currentByte = trackData[pos++] & 0xFF;
            value = (value << 7) + (currentByte & 0x7F);
        } while ((currentByte & 0x80) != 0);
        return value;
    }

    private int readIntFromStream() throws IOException {
        try {
            return stream.readInt();
        } catch (EOFException eof) {
            throw new EOFException("invalid MIDI file");
        }
    }

    boolean nextTrack() throws IOException, InvalidMidiDataException {
        int magic;
        trackLength = 0;
        do {
            // $$fb 2003-08-20: fix for 4910986: MIDI file parser breaks up on http connection
            if (stream.skipBytes(trackLength) != trackLength) {
                if (!STRICT_PARSER) {
                    return false;
                }
                throw new EOFException("invalid MIDI file");
            }
            magic = readIntFromStream();
            trackLength = readIntFromStream();
        } while (magic != MTrk_MAGIC);
        if (!STRICT_PARSER) {
            if (trackLength < 0) {
                return false;
            }
        }
        // now read track in a byte array
        trackData = new byte[trackLength];
        try {
            // $$fb 2003-08-20: fix for 4910986: MIDI file parser breaks up on http connection
            stream.readFully(trackData);
        } catch (EOFException eof) {
            if (!STRICT_PARSER) {
                return false;
            }
            throw new EOFException("invalid MIDI file");
        }
        pos = 0;
        return true;
    }

    private boolean trackFinished() {
        return pos >= trackLength;
    }

    void readTrack(Track track) throws IOException, InvalidMidiDataException {
        try {
            // reset current tick to 0
            long tick = 0;

            // reset current status byte to 0 (invalid value).
            // this should cause us to throw an InvalidMidiDataException if we don't
            // get a valid status byte from the beginning of the track.
            int status = 0;
            boolean endOfTrackFound = false;

            while (!trackFinished() && !endOfTrackFound) {
                MidiMessage message;

                int data1 = -1;         // initialize to invalid value
                int data2 = 0;

                // each event has a tick delay and then the event data.

                // first read the delay (a variable-length int) and update our tick value
                tick += readVarInt();

                // check for new status
                int byteValue = readUnsigned();

                if (byteValue >= 0x80) {
                    status = byteValue;
                } else {
                    data1 = byteValue;
                }

                switch (status & 0xF0) {
                case 0x80:
                case 0x90:
                case 0xA0:
                case 0xB0:
                case 0xE0:
                    // two data bytes
                    if (data1 == -1) {
                        data1 = readUnsigned();
                    }
                    data2 = readUnsigned();
                    message = new FastShortMessage(status | (data1 << 8) | (data2 << 16));
                    break;
                case 0xC0:
                case 0xD0:
                    // one data byte
                    if (data1 == -1) {
                        data1 = readUnsigned();
                    }
                    message = new FastShortMessage(status | (data1 << 8));
                    break;
                case 0xF0:
                    // sys-ex or meta
                    switch(status) {
                    case 0xF0:
                    case 0xF7:
                        // sys ex
                        int sysexLength = (int) readVarInt();
                        byte[] sysexData = new byte[sysexLength];
                        read(sysexData);

                        SysexMessage sysexMessage = new SysexMessage();
                        sysexMessage.setMessage(status, sysexData, sysexLength);
                        message = sysexMessage;
                        break;

                    case 0xFF:
                        // meta
                        int metaType = readUnsigned();
                        int metaLength = (int) readVarInt();

                        byte[] metaData = new byte[metaLength];
                        read(metaData);

                        MetaMessage metaMessage = new MetaMessage();
                        metaMessage.setMessage(metaType, metaData, metaLength);
                        message = metaMessage;
                        if (metaType == 0x2F) {
                            // end of track means it!
                            endOfTrackFound = true;
                        }
                        break;
                    default:
                        throw new InvalidMidiDataException("Invalid status byte: " + status);
                    } // switch sys-ex or meta
                    break;
                default:
                    throw new InvalidMidiDataException("Invalid status byte: " + status);
                } // switch
                track.add(new MidiEvent(message, tick));
            } // while
        } catch (ArrayIndexOutOfBoundsException e) {
            if (DEBUG) e.printStackTrace();
            // fix for 4834374
            throw new EOFException("invalid MIDI file");
        }
    }

}
