Package org.apache.cocoon.generation

Source Code of org.apache.cocoon.generation.XMidiGenerator

/*
* Copyright 1999-2002,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.generation;

import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.Map;

import org.apache.avalon.framework.parameters.ParameterException;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.components.midi.xmidi.ByteLen;
import org.apache.cocoon.components.midi.xmidi.Utils;
import org.apache.cocoon.components.midi.xmidi.Constants;
import org.apache.cocoon.components.source.SourceUtil;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceException;
import org.apache.excalibur.source.SourceNotFoundException;
import org.apache.excalibur.source.SourceValidity;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

/**
* Reads a standard MIDI file and generates SAX Events.
*
* The MIDI file parsing parts of this class are based on code from the XMidi project, written
* by  Peter Arthur Loeb (http://www.palserv.com/XMidi/) and used with permission.
* The warranty disclaimer of the MIT license (http://www.opensource.org/licenses/mit-license.html)
* applies to Peter Arthur Loeb's code.
*
* @author <a href="mailto:mark.leicester@energyintellect.com">Mark Leicester</a>
* @author <a href="mailto:peter@palserv.com">Peter Loeb</a>
*/

public class XMidiGenerator
    extends AbstractGenerator
    implements Parameterizable {

    /** The input source */
    protected Source inputSource;
    private boolean global_verbose;
    private boolean local_verbose;

    private static final boolean VERBOSE_DEFAULT = true;

    private boolean validateVerbosity(String verbose) {
        if (verbose.equalsIgnoreCase("TRUE")) {
            return true;
        } else if (verbose.equalsIgnoreCase("FALSE")) {
            return false;
        }
        return VERBOSE_DEFAULT;
    }

    public void parameterize(Parameters parameters) throws ParameterException {
        global_verbose =  validateVerbosity(parameters.getParameter(
                    "verbose",
                    String.valueOf(VERBOSE_DEFAULT)));
    }

    /**
     * Recycle this component.
     * All instance variables are set to <code>null</code>.
     */
    public void recycle() {
        if (null != this.inputSource) {
            super.resolver.release(this.inputSource);
            this.inputSource = null;
        }
        // Reinitialize variables
        initializeVariables();
        super.recycle();
    }

    /**
     * Setup the MIDI file generator.
     * Try to get the last modification date of the source for caching.
     */
    public void setup(SourceResolver resolver,
                      Map objectModel,
                      String src,
                      Parameters par)
    throws ProcessingException, SAXException, IOException {
        super.setup(resolver, objectModel, src, par);
        // Initialize lookup tables
        initializeLookupTables();
        try {
            this.inputSource = resolver.resolveURI(src);
        } catch (SourceException se) {
            throw SourceUtil.handle("Error resolving '" + src + "'.", se);
        }
        local_verbose =
            validateVerbosity(
                parameters.getParameter(
                    "verbose",
                    String.valueOf(global_verbose)));
    }

    /**
     * Generate the unique key.
     * This key must be unique inside the space of this component.
     *
     * @return The generated key hashes the src
     */
    public java.io.Serializable getKey() {
        return this.inputSource.getURI();
    }

    /**
     * Generate the validity object.
     *
     * @return The generated validity object or <code>null</code> if the
     *         component is currently not cacheable.
     */
    public SourceValidity getValidity() {
        return this.inputSource.getValidity();
    }

    /**
     * Generate XML data.
     */
    public void generate()
        throws IOException, SAXException, ProcessingException {
        try {
            if (getLogger().isDebugEnabled()) {
                getLogger().debug("Source " + super.source +
                                  " resolved to " + this.inputSource.getURI());
            }

            parseMIDI(this.inputSource);
        } catch (SAXException e) {
            SourceUtil.handleSAXException(this.inputSource.getURI(), e);
        }
    }

    private int midiFormat;
    private Hashtable ffHash;
    private String[] chanArray;
    private String[] fArray;
    private int numTracks;
    private int trkCount;
    private String[] notes;
    private int[] register;
    private Hashtable contHash;

    /**
     * @param source
     */
    private void parseMIDI(Source source)
    throws SAXException, SourceNotFoundException, IOException, ProcessingException {
        InputStream inputStream = source.getInputStream();

        AttributesImpl attr = new AttributesImpl();
        String text = "";
        this.contentHandler.startDocument();
        attr.addAttribute("", "VERSION", "VERSION", "CDATA", Constants.VERSION);
        this.contentHandler.startElement("", "XMidi", "XMidi", attr);

        boolean chunkFlag = true;
        while (chunkFlag) { // for each chunk
            byte[] hdr = new byte[8];

            int r;

            r = inputStream.read(hdr);
            if (r == -1) {
                chunkFlag = false;
                continue;
            }
            if (r < 8) {
                this.getLogger().debug("Getting header");
            }

            // get chunk id
            String cid = Utils.baToString(hdr, 0, 3);

            // get chunk length
            int len = Utils.baToInt(hdr, 4, 7);

            // get rest of chunk
            byte[] dta = new byte[len];
            r = inputStream.read(dta);
            if (r < len) {
                throw new ProcessingException("Getting data");
            }

            if (cid.equals("MThd")) {
                attr.clear();
                attr.addAttribute("", "LENGTH", "LENGTH", "CDATA", "" + len);
                attr.addAttribute("", "TYPE", "TYPE", "CDATA", cid);
                this.contentHandler.startElement("", "MThd", "MThd", attr);

                midiFormat = Utils.baToInt(dta, 0, 1);
                numTracks = Utils.baToInt(dta, 2, 3);
                String pnq = Utils.baToHex(dta, 4, 5);

                attr.clear();

                this.contentHandler.startElement("", "FORMAT", "FORMAT", attr);
                text = "" + midiFormat;
                this.contentHandler.characters(
                    text.toCharArray(),
                    0,
                    text.length());
                this.contentHandler.endElement("", "FORMAT", "FORMAT");

                this.contentHandler.startElement("", "TRACKS", "TRACKS", attr);
                text = "" + numTracks;
                this.contentHandler.characters(
                    text.toCharArray(),
                    0,
                    text.length());
                this.contentHandler.endElement("", "TRACKS", "TRACKS");

                this.contentHandler.startElement("", "PPNQ", "PPNQ", attr);
                text = pnq;
                this.contentHandler.characters(
                    text.toCharArray(),
                    0,
                    text.length());
                this.contentHandler.endElement("", "PPNQ", "PPNQ");

                this.contentHandler.endElement("", "MThd", "MThd");

            } else if (cid.equals("MTrk")) {
                trkCount++;
                if (trkCount > numTracks) {
                    throw new ProcessingException("too many tracks");
                }
                attr.clear();
                attr.addAttribute("", "LENGTH", "LENGTH", "CDATA", "" + len);
                attr.addAttribute("", "TYPE", "TYPE", "CDATA", cid);
                this.contentHandler.startElement("", "MTrk", "MTrk", attr);
                doTrack(dta, len);
                this.contentHandler.endElement("", "MTrk", "MTrk");
            } else {
                attr.clear();
                attr.addAttribute("", "LENGTH", "LENGTH", "CDATA", "" + len);
                attr.addAttribute("", "TYPE", "TYPE", "CDATA", cid);
                this.contentHandler.startElement("", "CHUNK", "CHUNK", attr);
                doHexData(dta, len);
                this.contentHandler.endElement("", "CHUNK", "CHUNK");
            }

        }

        this.contentHandler.endElement("", "XMidi", "XMidi");
        this.contentHandler.endDocument();
    }

    void initializeVariables() {
        numTracks = 0;
        trkCount = 0;
    }

    void initializeLookupTables() {
        ffHash = new Hashtable();
        ffHash.put("00", "Sequence Number");
        ffHash.put("01", "Text");
        ffHash.put("02", "Copyright");
        ffHash.put("03", "Sequence/Track Name");
        ffHash.put("04", "Instrument");
        ffHash.put("05", "Lyric");
        ffHash.put("06", "Marker");
        ffHash.put("07", "Cue Point");
        ffHash.put("20", "MIDI Channel");
        ffHash.put("21", "MIDI Port");
        ffHash.put("2F", "End of Track");
        ffHash.put("51", "Tempo");
        ffHash.put("54", "SMPTE Offset");
        ffHash.put("58", "Time Signature");
        ffHash.put("59", "Key Signature");
        ffHash.put("7F", "Proprietary Event");

        chanArray = new String[7];
        chanArray[0] = "Note Off";
        chanArray[1] = "Note On";
        chanArray[2] = "After Touch";
        chanArray[3] = "Control Change";
        chanArray[4] = "Program Change";
        chanArray[5] = "Channel Pressure";
        chanArray[6] = "Pitch Wheel";

        fArray = new String[16];
        fArray[0] = "SYSEX";
        fArray[1] = "MTC Quarter Frame Message";
        fArray[2] = "Song Position Pointer";
        fArray[3] = "Song Select";
        fArray[4] = "Undefined";
        fArray[5] = "Undefined";
        fArray[6] = "Tune Request";
        fArray[7] = "Unsupported";
        fArray[8] = "MIDI Clock";
        fArray[9] = "Undefined";
        fArray[10] = "MIDI Start";
        fArray[11] = "MIDI Continue";
        fArray[12] = "MIDI Stop";
        fArray[13] = "Undefined";
        fArray[14] = "Active Sense";
        fArray[15] = "NotUnderstood";

        contHash = new Hashtable();
        contHash.put("0", "Bank Select");
        contHash.put("1", "Modulation Wheel (coarse)");
        contHash.put("2", "Breath controller (coarse)");
        contHash.put("4", "Foot Pedal (coarse)");
        contHash.put("5", "Portamento Time (coarse)");
        contHash.put("6", "Data Entry (coarse)");
        contHash.put("7", "Volume (coarse)");
        contHash.put("8", "Balance (coarse)");
        contHash.put("10", "Pan position (coarse)");
        contHash.put("11", "Expression (coarse)");
        contHash.put("12", "Effect Control 1 (coarse)");
        contHash.put("13", "Effect Control 2 (coarse)");
        contHash.put("16", "General Purpose Slider 1");
        contHash.put("17", "General Purpose Slider 2");
        contHash.put("18", "General Purpose Slider 3");
        contHash.put("19", "General Purpose Slider 4");
        contHash.put("32", "Bank Select (fine)");
        contHash.put("33", "Modulation Wheel (fine)");
        contHash.put("34", "Breath controller (fine)");
        contHash.put("36", "Foot Pedal (fine)");
        contHash.put("37", "Portamento Time (fine)");
        contHash.put("38", "Data Entry (fine)");
        contHash.put("39", "Volume (fine)");
        contHash.put("40", "Balance (fine)");
        contHash.put("42", "Pan position (fine)");
        contHash.put("43", "Expression (fine)");
        contHash.put("44", "Effect Control 1 (fine)");
        contHash.put("45", "Effect Control 2 (fine)");
        contHash.put("64", "Hold Pedal (on/off)");
        contHash.put("65", "Portamento (on/off)");
        contHash.put("66", "Sustenuto Pedal (on/off)");
        contHash.put("67", "Soft Pedal (on/off)");
        contHash.put("68", "Legato Pedal (on/off)");
        contHash.put("69", "Hold 2 Pedal (on/off)");
        contHash.put("70", "Sound Variation");
        contHash.put("71", "Sound Timbre");
        contHash.put("72", "Sound Release Time");
        contHash.put("73", "Sound Attack Time");
        contHash.put("74", "Sound Brightness");
        contHash.put("75", "Sound Control 6");
        contHash.put("76", "Sound Control 7");
        contHash.put("77", "Sound Control 8");
        contHash.put("78", "Sound Control 9");
        contHash.put("79", "Sound Control 10");
        contHash.put("80", "General Purpose Button 1 (on/off)");
        contHash.put("81", "General Purpose Button 2 (on/off)");
        contHash.put("82", "General Purpose Button 3 (on/off)");
        contHash.put("83", "General Purpose Button 4 (on/off)");
        contHash.put("91", "Effects Level");
        contHash.put("92", "Tremulo Level");
        contHash.put("93", "Chorus Level");
        contHash.put("94", "Celeste Level");
        contHash.put("95", "Phaser Level");
        contHash.put("96", "Data Button increment");
        contHash.put("97", "Data Button decrement");
        contHash.put("98", "Non-registered Parameter (fine)");
        contHash.put("99", "Non-registered Parameter (coarse)");
        contHash.put("100", "Registered Parameter (fine)");
        contHash.put("101", "Registered Parameter (coarse)");
        contHash.put("120", "All Sound Off");
        contHash.put("121", "All Controllers Off");
        contHash.put("122", "Local Keyboard (on/off)");
        contHash.put("123", "All Notes Off");
        contHash.put("124", "Omni Mode Off");
        contHash.put("125", "Omni Mode On");
        contHash.put("126", "Mono Operation");
        contHash.put("127", "Poly Operation");

        notes = new String[128];
        register = new int[128];
        notes[0] = "C";
        register[0] = -5;
        notes[1] = "C#";
        register[1] = -5;
        notes[2] = "D";
        register[2] = -5;
        notes[3] = "Eb";
        register[3] = -5;
        notes[4] = "E";
        register[4] = -5;
        notes[5] = "F";
        register[5] = -5;
        notes[6] = "F#";
        register[6] = -5;
        notes[7] = "G";
        register[7] = -5;
        notes[8] = "Ab";
        register[8] = -5;
        notes[9] = "A";
        register[9] = -5;
        notes[10] = "Bb";
        register[10] = -5;
        notes[11] = "B";
        register[11] = -5;
        notes[12] = "C";
        register[12] = -4;
        notes[13] = "C#";
        register[13] = -4;
        notes[14] = "D";
        register[14] = -4;
        notes[15] = "Eb";
        register[15] = -4;
        notes[16] = "E";
        register[16] = -4;
        notes[17] = "F";
        register[17] = -4;
        notes[18] = "F#";
        register[18] = -4;
        notes[19] = "G";
        register[19] = -4;
        notes[20] = "Ab";
        register[20] = -4;
        notes[21] = "A";
        register[21] = -4;
        notes[22] = "Bb";
        register[22] = -4;
        notes[23] = "B";
        register[23] = -4;
        notes[24] = "C";
        register[24] = -3;
        notes[25] = "C#";
        register[25] = -3;
        notes[26] = "D";
        register[26] = -3;
        notes[27] = "Eb";
        register[27] = -3;
        notes[28] = "E";
        register[28] = -3;
        notes[29] = "F";
        register[29] = -3;
        notes[30] = "F#";
        register[30] = -3;
        notes[31] = "G";
        register[31] = -3;
        notes[32] = "Ab";
        register[32] = -3;
        notes[33] = "A";
        register[33] = -3;
        notes[34] = "Bb";
        register[34] = -3;
        notes[35] = "B";
        register[35] = -3;
        notes[36] = "C";
        register[36] = -2;
        notes[37] = "C#";
        register[37] = -2;
        notes[38] = "D";
        register[38] = -2;
        notes[39] = "Eb";
        register[39] = -2;
        notes[40] = "E";
        register[40] = -2;
        notes[41] = "F";
        register[41] = -2;
        notes[42] = "F#";
        register[42] = -2;
        notes[43] = "G";
        register[43] = -2;
        notes[44] = "Ab";
        register[44] = -2;
        notes[45] = "A";
        register[45] = -2;
        notes[46] = "Bb";
        register[46] = -2;
        notes[47] = "B";
        register[47] = -2;
        notes[48] = "C";
        register[48] = -1;
        notes[49] = "C#";
        register[49] = -1;
        notes[50] = "D";
        register[50] = -1;
        notes[51] = "Eb";
        register[51] = -1;
        notes[52] = "E";
        register[52] = -1;
        notes[53] = "F";
        register[53] = -1;
        notes[54] = "F#";
        register[54] = -1;
        notes[55] = "G";
        register[55] = -1;
        notes[56] = "Ab";
        register[56] = -1;
        notes[57] = "A";
        register[57] = -1;
        notes[58] = "Bb";
        register[58] = -1;
        notes[59] = "B";
        register[59] = -1;
        notes[60] = "C";
        register[60] = 0;
        notes[61] = "C#";
        register[61] = 0;
        notes[62] = "D";
        register[62] = 0;
        notes[63] = "Eb";
        register[63] = 0;
        notes[64] = "E";
        register[64] = 0;
        notes[65] = "F";
        register[65] = 0;
        notes[66] = "F#";
        register[66] = 0;
        notes[67] = "G";
        register[67] = 0;
        notes[68] = "Ab";
        register[68] = 0;
        notes[69] = "A";
        register[69] = 0;
        notes[70] = "Bb";
        register[70] = 0;
        notes[71] = "B";
        register[71] = 0;
        notes[72] = "C";
        register[72] = 1;
        notes[73] = "C#";
        register[73] = 1;
        notes[74] = "D";
        register[74] = 1;
        notes[75] = "Eb";
        register[75] = 1;
        notes[76] = "E";
        register[76] = 1;
        notes[77] = "F";
        register[77] = 1;
        notes[78] = "F#";
        register[78] = 1;
        notes[79] = "G";
        register[79] = 1;
        notes[80] = "Ab";
        register[80] = 1;
        notes[81] = "A";
        register[81] = 1;
        notes[82] = "Bb";
        register[82] = 1;
        notes[83] = "B";
        register[83] = 1;
        notes[84] = "C";
        register[84] = 2;
        notes[85] = "C#";
        register[85] = 2;
        notes[86] = "D";
        register[86] = 2;
        notes[87] = "Eb";
        register[87] = 2;
        notes[88] = "E";
        register[88] = 2;
        notes[89] = "F";
        register[89] = 2;
        notes[90] = "F#";
        register[90] = 2;
        notes[91] = "G";
        register[91] = 2;
        notes[92] = "Ab";
        register[92] = 2;
        notes[93] = "A";
        register[93] = 2;
        notes[94] = "Bb";
        register[94] = 2;
        notes[95] = "B";
        register[95] = 2;
        notes[96] = "C";
        register[96] = 3;
        notes[97] = "C#";
        register[97] = 3;
        notes[98] = "D";
        register[98] = 3;
        notes[99] = "Eb";
        register[99] = 3;
        notes[100] = "E";
        register[100] = 3;
        notes[101] = "F";
        register[101] = 3;
        notes[102] = "F#";
        register[102] = 3;
        notes[103] = "G";
        register[103] = 3;
        notes[104] = "Ab";
        register[104] = 3;
        notes[105] = "A";
        register[105] = 3;
        notes[106] = "Bb";
        register[106] = 3;
        notes[107] = "B";
        register[107] = 3;
        notes[108] = "C";
        register[108] = 4;
        notes[109] = "C#";
        register[109] = 4;
        notes[110] = "D";
        register[110] = 4;
        notes[111] = "Eb";
        register[111] = 4;
        notes[112] = "E";
        register[112] = 4;
        notes[113] = "F";
        register[113] = 4;
        notes[114] = "F#";
        register[114] = 4;
        notes[115] = "G";
        register[115] = 4;
        notes[116] = "Ab";
        register[116] = 4;
        notes[117] = "A";
        register[117] = 4;
        notes[118] = "Bb";
        register[118] = 4;
        notes[119] = "B";
        register[119] = 4;
        notes[120] = "C";
        register[120] = 5;
        notes[121] = "C#";
        register[121] = 5;
        notes[122] = "D";
        register[122] = 5;
        notes[123] = "Eb";
        register[123] = 5;
        notes[124] = "E";
        register[124] = 5;
        notes[125] = "F";
        register[125] = 5;
        notes[126] = "F#";
        register[126] = 5;
        notes[127] = "G";
        register[127] = 5;
    }

    /**
     * Add track data to DOM structure
    */
    void doTrack(byte[] dta, int len)
        throws SAXException, ProcessingException {
        AttributesImpl attr = new AttributesImpl();
        String text = "";

        boolean tFlag = true;
        int offset = 0;

        // initialize variables
        String edata = null;
        String snam = null;
        String nmData = "";
        String ctag = null;
        String ctagAttr[] = new String[4];
        String ctagAttrVal[] = new String[4];
        int ctagnum = 0;
        String cnum = null;
        String ctyp = null;
        int slen = 0;
        int chanType = 0;
        int hiName = 0;
        int status = 0;
        int noff = 0;
        String sval = null;
        boolean ecFlag = true; // assume edata
        boolean nFlag = true; // use slen for noff
        boolean firstTime = true;

        while (tFlag) {
            // do delta
            ByteLen bl = Utils.deltaToInt(dta, offset);
            offset += bl.len;
            String deltaLen = Utils.baToHex(bl.ba, 0, 3);

            nFlag = true; // assume simple (slen) offset
            // may or may not be status
            boolean statFlag = false;
            int first = Utils.baToInt(dta, offset, offset);
            this.getLogger().debug(
                "doTrack: in loop; deltaLen="
                    + deltaLen
                    + ", len="
                    + bl.len
                    + ", first="
                    + first);

            if ((first & 128) == 128) {
                // it is a status byte
                statFlag = true;
                sval = Utils.baToHex(dta, offset, offset);
                status = first;
                this.getLogger().debug("doTrack: have status: " + sval);
                if (status < 240 && status > 127) {
                    ecFlag = false;
                    chanType = (status - 128) / 16;
                    snam = chanArray[chanType];
                    ctyp = sval.substring(0, 1);
                    cnum = sval.substring(1, 2);
                } else {
                    ecFlag = true;
                    if (status > 239 && status < 256) {
                        hiName = status - 240;
                        snam = fArray[hiName];
                    } else {
                        throw new ProcessingException(
                            "Invalid status: " + status);
                    }
                }
                offset++;
            } else {
                this.getLogger().debug("doTrack: running status");
            }

            nmData = "";
            if (firstTime) {
                firstTime = false;
                if (!statFlag) {
                    throw new ProcessingException(
                        "first time, but no status; first = " + first);
                }
            }

            // offset points to the byte after the status
            // or first byte of "running status"

            attr.clear();
            attr.addAttribute("", "DTIME", "DTIME", "CDATA", "" + deltaLen);
            this.contentHandler.startElement("", "DELTA", "DELTA", attr);

            if (status > 127 && status < 144) {
                // note off
                slen = 2;
                // set up tag
                int pitch = Utils.baToInt(dta, offset, offset);
                int vel = Utils.baToInt(dta, offset + 1, offset + 1);
                ctag = "NOTE_OFF";
                ctagAttr[0] = "PITCH";
                ctagAttrVal[0] = "" + pitch;
                ctagAttr[1] = "VELOCITY";
                ctagAttrVal[1] = "" + vel;
                ctagnum = 2;
                if (local_verbose) {
                    ctagAttr[2] = "NAME";
                    ctagAttrVal[2] = notes[pitch];
                    ctagAttr[3] = "REGISTER";
                    ctagAttrVal[3] = "" + register[pitch];
                    ctagnum = 4;
                }
            } else if (status > 143 && status < 160) {
                // note on
                slen = 2;
                int pitch = Utils.baToInt(dta, offset, offset);
                int vel = Utils.baToInt(dta, offset + 1, offset + 1);
                ctag = "NOTE_ON";
                ctagAttr[0] = "PITCH";
                ctagAttrVal[0] = "" + pitch;
                ctagAttr[1] = "VELOCITY";
                ctagAttrVal[1] = "" + vel;
                ctagnum = 2;
                if (local_verbose) {
                    ctagAttr[2] = "NAME";
                    ctagAttrVal[2] = notes[pitch];
                    ctagAttr[3] = "REGISTER";
                    ctagAttrVal[3] = "" + register[pitch];
                    ctagnum = 4;
                }
            } else if (status > 159 && status < 176) {
                // after touch
                slen = 2;
                int pitch = Utils.baToInt(dta, offset, offset);
                int pres = Utils.baToInt(dta, offset + 1, offset + 1);
                ctag = "AFTER";
                ctagAttr[0] = "PITCH";
                ctagAttrVal[0] = "" + pitch;
                ctagAttr[1] = "PRESSURE";
                ctagAttrVal[1] = "" + pres;
                ctagnum = 2;
                if (local_verbose) {
                    ctagAttr[2] = "NAME";
                    ctagAttrVal[2] = notes[pitch];
                    ctagAttr[3] = "REGISTER";
                    ctagAttrVal[3] = "" + register[pitch];
                    ctagnum = 4;
                }
            } else if (status > 175 && status < 192) {
                // control change
                slen = 2;
                int contnum = Utils.baToInt(dta, offset, offset);
                int contval = Utils.baToInt(dta, offset + 1, offset + 1);
                ctag = "CONTROL";
                ctagAttr[0] = "NUMBER";
                ctagAttrVal[0] = "" + contnum;
                ctagAttr[1] = "VALUE";
                ctagAttrVal[1] = "" + contval;
                ctagnum = 2;
                if (local_verbose) {
                    ctagAttr[2] = "NAME";
                    ctagAttrVal[2] = (String) contHash.get("" + contnum);
                    ctagnum = 3;
                }
            } else if (status > 191 && status < 208) {
                // program (patch) change
                slen = 1;
                int patch = Utils.baToInt(dta, offset, offset);
                ctag = "PROGRAM";
                ctagAttr[0] = "NUMBER";
                ctagAttrVal[0] = "" + patch;
                ctagnum = 1;
            } else if (status > 207 && status < 224) {
                // channel pressure
                slen = 1;
                int pamt = Utils.baToInt(dta, offset, offset);
                ctag = "PRESSURE";
                ctagAttr[0] = "AMOUNT";
                ctagAttrVal[0] = "" + pamt;
                ctagnum = 1;
            } else if (status > 223 && status < 240) {
                // pitch wheel
                slen = 2;
                int pwamt = Utils.getPW(dta, offset);
                ctag = "WHEEL";
                ctagAttr[0] = "AMOUNT";
                ctagAttrVal[0] = "" + pwamt;
                ctagnum = 1;
            } else if (status == 240) {
                // sysex
                bl = Utils.deltaToInt(dta, offset);
                slen = Utils.baToInt(bl.ba, 0, 3);
                noff = bl.len;
                nFlag = false;
                edata =
                    Utils.baToHex(dta, offset + noff, offset + noff + slen - 1);
                noff += slen;
            } else if (status == 255) {
                // non midi (reset only in "live" midi")
                nmData = Utils.baToHex(dta, offset, offset);
                //            nmData = "SNMT=\""+nmDta+"\" ";
                snam = "non-MIDI";
                String nmNam = (String) ffHash.get(nmData);
                if (nmNam != null) {
                    snam += " - " + nmNam;
                } else {
                    snam += " - Unknown";
                }
                //            int nmt = baToInt(dta,offset+1,offset+1);
                bl = Utils.deltaToInt(dta, offset + 1);
                slen = Utils.baToInt(bl.ba, 0, 3);
                noff = bl.len + 1;
                nFlag = false;
                if (slen == 0) {
                    edata = "No data";
                } else {
                    edata =
                        Utils.baToHex(
                            dta,
                            offset + noff,
                            offset + noff + slen - 1);
                    noff += slen;
                }
                this.getLogger().debug(
                    "doTrack: status FF" + nmData + ", edata = " + edata);
            } else if (status == 241 || status == 243) {
                int tcv = dta[offset];
                Integer tc = new Integer(tcv);
                edata = tc.toString();
                slen = 1;
            } else if (status == 242) {
                int tcv = Utils.getPW(dta, offset);
                Integer tc = new Integer(tcv);
                edata = tc.toString();
                slen = 2;
            } else if (
                status == 246
                    || status == 248
                    || status == 250
                    || status == 251
                    || status == 252
                    || status == 254) {
                edata = "No data for " + snam;
                slen = 0;
            } else { // really unknown
                int ol = Utils.getNextHiOrd(dta, offset);
                edata = Utils.baToHex(dta, offset + 1, ol);
                ol -= offset + 1;
                slen = ol;
            }

            if (ecFlag) {
                if (statFlag) {
                    attr.clear();
                    attr.addAttribute("", "SLEN", "SLEN", "CDATA", "" + slen);
                    attr.addAttribute("", "SNAM", "SNAM", "CDATA", snam);
                    if (!nmData.equals("")) {
                        attr.addAttribute("", "SNMT", "SNMT", "CDATA", nmData);
                    }
                    attr.addAttribute("", "SVAL", "SVAL", "CDATA", sval);
                    this.contentHandler.startElement(
                        "",
                        "STATUS",
                        "STATUS",
                        attr);

                    attr.clear();
                    this.contentHandler.startElement(
                        "",
                        "EDATA",
                        "EDATA",
                        attr);
                    text = edata;
                    this.contentHandler.characters(
                        text.toCharArray(),
                        0,
                        text.length());
                    this.contentHandler.endElement("", "EDATA", "EDATA");

                    this.contentHandler.endElement("", "STATUS", "STATUS");
                } else {
                    attr.clear();
                    this.contentHandler.startElement(
                        "",
                        "EDATA",
                        "EDATA",
                        attr);
                    text = edata;
                    this.contentHandler.characters(
                        text.toCharArray(),
                        0,
                        text.length());
                    this.contentHandler.endElement("", "EDATA", "EDATA");
                }
            } else {

                if (statFlag) {
                    attr.clear();
                    attr.addAttribute("", "SLEN", "SLEN", "CDATA", "" + slen);
                    attr.addAttribute("", "SNAM", "SNAM", "CDATA", snam);
                    if (!nmData.equals("")) {
                        attr.addAttribute("", "SNMT", "SNMT", "CDATA", nmData);
                    }
                    attr.addAttribute("", "SVAL", "SVAL", "CDATA", sval);
                    this.contentHandler.startElement(
                        "",
                        "STATUS",
                        "STATUS",
                        attr);

                    attr.clear();
                    attr.addAttribute("", "NUMBER", "NUMBER", "CDATA", cnum);
                    attr.addAttribute("", "TYPE", "TYPE", "CDATA", ctyp);
                    this.contentHandler.startElement(
                        "",
                        "CHANNEL",
                        "CHANNEL",
                        attr);

                    attr.clear();
                    for (int c = 0; c < ctagnum; c++) {
                        attr.addAttribute(
                            "",
                            ctagAttr[c],
                            ctagAttr[c],
                            "CDATA",
                            ctagAttrVal[c]);
                    }
                    this.contentHandler.startElement("", ctag, ctag, attr);
                    this.contentHandler.endElement("", ctag, ctag);

                    this.contentHandler.endElement("", "CHANNEL", "CHANNEL");
                    this.contentHandler.endElement("", "STATUS", "STATUS");
                } else {
                    attr.clear();
                    attr.addAttribute("", "NUMBER", "NUMBER", "CDATA", cnum);
                    attr.addAttribute("", "TYPE", "TYPE", "CDATA", ctyp);
                    this.contentHandler.startElement(
                        "",
                        "CHANNEL",
                        "CHANNEL",
                        attr);

                    attr.clear();
                    for (int c = 0; c < ctagnum; c++) {
                        attr.addAttribute(
                            "",
                            ctagAttr[c],
                            ctagAttr[c],
                            "CDATA",
                            ctagAttrVal[c]);
                    }
                    this.contentHandler.startElement("", ctag, ctag, attr);
                    this.contentHandler.endElement("", ctag, ctag);

                    this.contentHandler.endElement("", "CHANNEL", "CHANNEL");
                }

            }

            this.contentHandler.endElement("", "DELTA", "DELTA");

            if (nFlag) {
                offset += slen;
            } else {
                offset += noff;
            }
            if (offset >= len) {
                tFlag = false;
            }
        }
    }

    /**
     * Write formatted hex data to file
     */
    void doHexData(byte[] dta, int len)
        throws ProcessingException, SAXException {
        AttributesImpl attr = new AttributesImpl();
        String text = "";

        this.contentHandler.startElement("", "HEXDATA", "HEXDATA", attr);

        StringBuffer bth = new StringBuffer("");
        int bpl = 32;
        int r = len % bpl;
        int n = len / bpl;
        for (int i = 0; i < n; i++) {
            int strt = i * bpl;
            bth.append(Utils.baToHex(dta, strt, strt + bpl - 1));
        }
        if (r > 0) {
            int strt = n * bpl;
            bth.append(Utils.baToHex(dta, strt, strt + r - 1));
        }

        text = bth.toString();
        this.contentHandler.characters(text.toCharArray(), 0, text.length());

        this.contentHandler.endElement("", "HEXDATA", "HEXDATA");
    }
}
TOP

Related Classes of org.apache.cocoon.generation.XMidiGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.