com.foudroyantfactotum.mod.fousarchive.midi.MidiDetails.java Source code

Java tutorial

Introduction

Here is the source code for com.foudroyantfactotum.mod.fousarchive.midi.MidiDetails.java

Source

/*
 * Fou's Archive - A Minecraft Mod
 * Copyright (c) 2016 Foudroyant Factotum
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.foudroyantfactotum.mod.fousarchive.midi;

import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;
import gnu.trove.map.hash.TObjectByteHashMap;

import javax.annotation.Nonnull;
import javax.sound.midi.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

public class MidiDetails {
    /*
    /music_category:       Piano_Roll
    /title:                Stumbling
    /subtitle:             Fox Trot
    /roll_manufacturer:    Broadway
    /roll_brand:           Broadway Word Roll
    /roll_number:          1080
    /roll_class:           88
    /performer:            Vanderhaak, William
    /composer:             Confrey
    /composition_date:     1922
    /roll_tempo:           80
    /song_type:            Foxtrot, Novelty Ragtime
    /roll_condition:       Excellent
    /roll_authenticity:    Original
    /roll_copyright:       Allans (9d Royalty Stamp)
    */

    public static final MidiDetails NO_DETAILS = new MidiDetails();

    private final String[] elem;

    private final String title;
    private final String subtitle;
    private final String rollManufacturer;
    private final String rollBrand;
    private final String rollNumber;
    private final String rollClass;
    private final String performer;
    private final String composer;
    private final String compositionDate;
    private final String rollTempo;
    private final String songType;
    private final String rollCondition;
    private final String rollAuthenticity;
    private final String rollCopyright;

    private final long maxTicks;

    private static final String[] tags = { "/title:", "/subtitle:", "/roll_manufacturer:", "/roll_brand:",
            "/roll_number:", "/roll_class:", "/performer:", "/composer:", "/composition_date:", "/roll_tempo:",
            "/song_type:", "/roll_condition:", "/roll_authenticity:", "/roll_copyright:" };

    private static final TObjectByteHashMap<String> ctt = new TObjectByteHashMap<>(tags.length);
    private static final String[] cTags = cleanTags();

    private static String[] cleanTags() {
        final String[] t = new String[tags.length];

        for (int i = 0; i < t.length; ++i) {
            t[i] = tags[i].substring(1, tags[i].length() - 1);
            ctt.put(t[i], (byte) i);
        }

        return t;
    }

    private MidiDetails() {
        this(new String[14], 1);
    }

    private MidiDetails(String[] result, long maxTicks) {
        this.title = result[0];
        this.subtitle = result[1];
        this.rollManufacturer = result[2];
        this.rollBrand = result[3];
        this.rollNumber = result[4];
        this.rollClass = result[5];
        this.performer = result[6];
        this.composer = result[7];
        this.compositionDate = result[8];
        this.rollTempo = result[9];
        this.songType = result[10];
        this.rollCondition = result[11];
        this.rollAuthenticity = result[12];
        this.rollCopyright = result[13];

        this.maxTicks = maxTicks;

        this.elem = result;
    }

    @Nonnull
    public static MidiDetails getMidiDetails(InputStream stream) throws IOException {
        final String[] result = new String[tags.length];

        final Sequence sequence;

        try {
            sequence = MidiSystem.getSequence(stream);
        } catch (InvalidMidiDataException e) {
            return NO_DETAILS;
        }

        for (Track track : sequence.getTracks()) {
            for (int i = 0; i < track.size(); i++) {
                final MidiEvent event = track.get(i);
                final MidiMessage midimsg = event.getMessage();

                if (midimsg instanceof MetaMessage) {
                    final MetaMessage msg = (MetaMessage) midimsg;
                    final String meta = new String(msg.getData());

                    for (int tgi = 0; tgi < tags.length; ++tgi) {
                        final String tag = tags[tgi];

                        if (meta.startsWith(tag)) {
                            result[tgi] = meta.substring(tag.length()).trim();
                            break;
                        }
                    }
                }
            }
        }

        if (result[0] == null || result[7] == null)
            return NO_DETAILS;

        return new MidiDetails(result, sequence.getTickLength());
    }

    public String getSimpleDetails() {
        return String.format("\u201C%s\u201D by %s", title, composer);
    }

    public String getLongDetails() {
        return String.format("%s \u00A7o#%s\u00A77 class %s\n" + "\u00A76Manufacturer:\u00A77 %s\n"
                + "\u00A76Performer:\u00A77 %s\n" + "\u00A76Composer:\u00A77 %s (%s)\n" + "\u00A76(c)\u00A77 %s",
                rollBrand, rollNumber, rollClass, rollManufacturer, performer, composer, compositionDate,
                rollCopyright);
    }

    public ImmutableMap<String, String> toMap() {
        final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();

        for (int i = 0; i < cTags.length; ++i) {
            if (elem[i] != null)
                builder.put(cTags[i], elem[i]);
        }

        builder.put("maxTicks", String.valueOf(maxTicks));

        return builder.build();
    }

    public static MidiDetails fromMap(ImmutableMap<String, String> map) {
        final String[] elem = new String[tags.length + 1];

        for (Map.Entry<String, String> entry : map.entrySet())
            if (ctt.containsKey(entry.getKey()))
                elem[ctt.get(entry.getKey())] = entry.getValue();

        if (elem[0] == null || elem[7] == null)
            return null;

        return new MidiDetails(elem, Long.parseLong(map.get("maxTicks")));
    }

    public String getTitle() {
        return title;
    }

    public String getSubtitle() {
        return subtitle;
    }

    public String getRollManufacturer() {
        return rollManufacturer;
    }

    public String getRollBrand() {
        return rollBrand;
    }

    public String getRollNumber() {
        return rollNumber;
    }

    public String getRollClass() {
        return rollClass;
    }

    public String getPerformer() {
        return performer;
    }

    public String getComposer() {
        return composer;
    }

    public String getCompositionDate() {
        return compositionDate;
    }

    public String getRollTempo() {
        return rollTempo;
    }

    public String getSongType() {
        return songType;
    }

    public String getRollCondition() {
        return rollCondition;
    }

    public String getRollAuthenticity() {
        return rollAuthenticity;
    }

    public String getRollCopyright() {
        return rollCopyright;
    }

    public long getMaxTicks() {
        return maxTicks;
    }

    @Override
    public String toString() {
        return Objects.toStringHelper(this).add("title", title).add("subtitle", subtitle)
                .add("rollManufacturer", rollManufacturer).add("rollBrand", rollBrand).add("rollNumber", rollNumber)
                .add("rollClass", rollClass).add("performer", performer).add("composer", composer)
                .add("compositionDate", compositionDate).add("rollTempo", rollTempo).add("songType", songType)
                .add("rollCondition", rollCondition).add("rollAuthenticity", rollAuthenticity)
                .add("rollCopyright", rollCopyright).add("maxTicks", maxTicks).toString();
    }

    public static MidiDetails simpleMD(@Nonnull String name, @Nonnull String composer) {
        final String[] str = new String[tags.length];
        str[0] = name;
        str[7] = composer;

        return new MidiDetails(str, 1);
    }
}