net.sf.nmedit.nordmodular.Installer.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.nmedit.nordmodular.Installer.java

Source

/* Copyright (C) 2006 Christian Schneider
 * 
 * This file is part of Nomad.
 * 
 * Nomad 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 2 of the License, or
 * (at your option) any later version.
 * 
 * Nomad 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 Nomad; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package net.sf.nmedit.nordmodular;

import java.awt.Component;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.sound.midi.MidiDevice;

import net.sf.nmedit.jpatch.clavia.nordmodular.NMData;
import net.sf.nmedit.jpatch.clavia.nordmodular.NMPatch;
import net.sf.nmedit.jpatch.clavia.nordmodular.parser.PatchExporter;
import net.sf.nmedit.jpatch.clavia.nordmodular.parser.PatchFileWriter;
import net.sf.nmedit.jsynth.clavia.nordmodular.NordModular;
import net.sf.nmedit.jsynth.midi.MidiDescription;
import net.sf.nmedit.jsynth.midi.MidiID;
import net.sf.nmedit.jsynth.midi.MidiPlug;
import net.sf.nmedit.jtheme.ModulePane;
import net.sf.nmedit.nmutils.io.FileUtils;
import net.sf.nmedit.nomad.core.JPFUtil;
import net.sf.nmedit.nomad.core.Nomad;
import net.sf.nmedit.nomad.core.jpf.TempDir;
import net.sf.nmedit.nomad.core.menulayout.MLEntry;
import net.sf.nmedit.nomad.core.service.Service;
import net.sf.nmedit.nomad.core.service.initService.InitService;
import net.sf.nmedit.nomad.core.swing.ExtensionFilter;
import net.sf.nmedit.nomad.core.swing.document.DefaultDocumentManager;
import net.sf.nmedit.nomad.core.swing.document.Document;
import net.sf.nmedit.nomad.core.swing.explorer.ExplorerTree;
import net.sf.nmedit.nomad.core.swing.explorer.FileContext;
import net.sf.nmedit.nomad.core.swing.tabs.JTabbedPane2;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Installer implements InitService {

    // TempDir temp = new TempDir(this);
    public Class<? extends Service> getServiceClass() {
        return InitService.class;
    }

    public void init() {
        installPatches();
        readSynthConfiguration();

        NMContextData data = NMContextData.sharedInstance();
        NMData d = NMData.sharedInstance();

        ModulePane pane = ModulePane.getSharedInstance();
        pane.setModules(d.getModuleDescriptions());
        pane.setTheme(data.getJTContext());

        Nomad nomad = Nomad.sharedInstance();
        MLEntry mlKnobs = nomad.getMenuLayout().getEntry("nomad.menu.patch.knobs");

        DefaultDocumentManager dm = Nomad.sharedInstance().getDocumentManager();
        KnobController kc = new KnobController();
        dm.addListener(kc);
        mlKnobs.addActionListener(kc);

        loadLastSession();
    }

    public void shutdown() {

        saveCurrentSession();

        List<NordModular> synthList = new ArrayList<NordModular>();

        JTabbedPane2 tb = Nomad.sharedInstance().getSynthTabbedPane();

        for (int i = 0; i < tb.getTabCount(); i++) {
            Component c = tb.getComponentAt(i);
            if (c instanceof NMSynthDeviceContext) {
                synthList.add(((NMSynthDeviceContext) c).getSynthesizer());
            }
        }

        storeSynthConfiguration(synthList);

    }

    public void installPatches() {
        File pluginDir = JPFUtil.getPluginDirectory(this);
        File patches = new File(pluginDir, "patches/");
        TempDir tempDir = TempDir.generalTempDir();
        File userPatches = tempDir.getTempFile("patches");
        if (!userPatches.exists())
            FileUtils.copy(patches, userPatches);
        if (userPatches.exists()) {
            ExplorerTree explorerTree = Nomad.sharedInstance().getExplorer();
            FileContext libraryContext = new FileContext(explorerTree,
                    new ExtensionFilter("Nord Modular Patch", "pch", true), userPatches);
            libraryContext.setName("Library");
            libraryContext.setNailed(true);
            explorerTree.addRootNode(libraryContext, 0);
        }

    }

    private File getSessionFile(TempDir dir) {
        return dir.getTempFile("session.properties");
    }

    private void loadLastSession() {
        TempDir tmpDir = TempDir.forObject(this);
        File sessionFile = getSessionFile(tmpDir);

        if (!sessionFile.exists())
            return;

        Properties props = new Properties();
        InputStream in;
        try {
            in = new BufferedInputStream(new FileInputStream(sessionFile));
            try {
                props.load(in);
            } finally {
                in.close();
            }
        } catch (Exception e) {
            Log log = LogFactory.getLog(getClass());
            if (log.isDebugEnabled()) {
                log.debug("exception while loading session file", e);
            }

            e.printStackTrace();
            // ignore
            // delete corrupt session file
            sessionFile.delete();
            return;
        }

        loadSessionFromProperties(tmpDir, props);

    }

    private static final String SESSION_PATCHCOUNT = "session.patchcount";

    private void loadSessionFromProperties(TempDir tmpDir, Properties props) {
        String PCountString = props.getProperty(SESSION_PATCHCOUNT);
        if (PCountString == null)
            return;

        int patchcount;
        try {
            patchcount = Integer.parseInt(PCountString);
        } catch (NumberFormatException e) {
            Log log = LogFactory.getLog(getClass());
            if (log.isDebugEnabled()) {
                log.debug("exception while loading session file", e);
            }

            return;
        }

        for (int i = 0; i < patchcount; i++) {
            File sourceFile = null;
            String keySourceFile = getSourceFileKey(i);
            String sourceFileString = props.getProperty(keySourceFile);
            if (sourceFileString != null)
                sourceFile = new File(sourceFileString);
            File tmpFile = getPatchTmpFile(tmpDir, i);
            String title = props.getProperty(getTitleKey(i));
            NMPatch patch = tryOpenSessionPatch(tmpFile, sourceFile, title);
        }

    }

    private String getTitleKey(int index) {
        return "patch." + index + ".title";
    }

    private String getSourceFileKey(int index) {
        return "patch." + index + ".sourcefile";
    }

    private File getPatchTmpFile(TempDir tmpDir, int index) {
        return tmpDir.getTempFile("temp_" + index + ".pch");
    }

    private NMPatch tryOpenSessionPatch(File file, File sourceFile, String title) {
        if (!file.exists())
            return null;
        return NmFileService.openPatch(file, sourceFile, title, false);
    }

    private void saveCurrentSession() {
        DefaultDocumentManager dm = Nomad.sharedInstance().getDocumentManager();

        List<NMPatch> patches = new ArrayList<NMPatch>();

        for (Document doc : dm.getDocuments()) {
            if (doc instanceof PatchDocument) {
                patches.add(((PatchDocument) doc).getPatch());
            }
        }

        TempDir tmpDir = TempDir.forObject(this);

        Properties props = new Properties();
        int pcount = 0;

        for (NMPatch patch : patches) {
            File saveAs = getPatchTmpFile(tmpDir, pcount);

            try {
                OutputStream out = new BufferedOutputStream(new FileOutputStream(saveAs));

                PatchFileWriter pfw = new PatchFileWriter(out);
                PatchExporter export = new PatchExporter();
                export.export(patch, pfw);

                out.flush();
                out.close();
            } catch (Exception e) {
                Log log = LogFactory.getLog(getClass());
                if (log.isDebugEnabled()) {
                    log.debug("exception while storing session file", e);
                }

                e.printStackTrace();
                continue;
            }

            // tmp file written
            File sourceFile = patch.getFile();
            if (sourceFile != null)
                props.put(getSourceFileKey(pcount), sourceFile.getAbsolutePath());
            else {
                // source file unknown, since patch file contains no title we have to remember it
                String name = patch.getName();
                if (name != null)
                    props.put(getTitleKey(pcount), name);
            }
            pcount++;
        }

        props.put(SESSION_PATCHCOUNT, String.valueOf(pcount));

        File sessionFile = getSessionFile(tmpDir);

        try {
            OutputStream out = new BufferedOutputStream(new FileOutputStream(sessionFile));
            props.store(out, "generated file - do not edit manually");
            out.close();
        } catch (Exception e) {
            Log log = LogFactory.getLog(getClass());
            if (log.isDebugEnabled()) {
                log.debug("exception while storing session file", e);
            }

            e.printStackTrace();
            // ignore   
        }

    }

    private void readSynthConfiguration() {
        Properties properties = new Properties();

        InputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(getSynthPropertyFile()));
            properties.load(in);
        } catch (IOException e) {
            // ignore
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }

        readSynthConfiguration(properties);
    }

    private void readSynthConfiguration(Properties properties) {
        int count = str2int(properties.getProperty("nordmodular.count"), 0);

        if (count > 100) {
            count = 10; // just in case the number messed up
        }

        if (count <= 0)
            return;

        for (int i = 0; i < count; i++) {
            String prefix = "nordmodular." + i + ".";

            String name = properties.getProperty(prefix + "name");

            MidiDescription in = readMidiInfo(properties, prefix + "midi.in.", true);
            MidiDescription out = readMidiInfo(properties, prefix + "midi.out.", false);

            MidiPlug pin = in == null ? null : new MidiPlug(in);
            MidiPlug pout = out == null ? null : new MidiPlug(out);

            NewNordModularService.newSynth(name, pin, pout);
        }
    }

    private MidiDescription readMidiInfo(Properties properties, String prefix, boolean input) {
        int id = str2int(properties.getProperty(prefix + "id"), -1);
        String name = properties.getProperty(prefix + "name");
        String vendor = properties.getProperty(prefix + "vendor");
        String version = properties.getProperty(prefix + "version");
        String description = properties.getProperty(prefix + "description");
        int isInput = str2boolean(properties.getProperty(prefix + "input"));

        if (isInput < 0 || ((isInput == 1) != input))
            return null;

        return new MidiDescription(name, vendor, version, description, isInput, id);
    }

    private int str2boolean(String value) {
        try {
            return Boolean.parseBoolean(value) ? 1 : 0;
        } catch (NumberFormatException e) {
            return -1;
        }
    }

    private int str2int(String value, int alt) {
        if (value == null)
            return alt;

        try {
            return Integer.parseInt(value.trim());
        } catch (NumberFormatException e) {
            return alt;
        }
    }

    private void storeSynthConfiguration(List<NordModular> synthList) {
        MidiID midiID = new MidiID();

        Properties properties = new Properties();
        properties.put("nordmodular.count", Integer.toString(synthList.size()));
        for (int i = 0; i < synthList.size(); i++) {
            String prefix = "nordmodular." + i + ".";
            NordModular synth = synthList.get(i);
            properties.put(prefix + "name", synth.getName());
            putMidiInfo(properties, prefix + "midi.in.", synth.getPCInPort().getPlug(), midiID, true);
            putMidiInfo(properties, prefix + "midi.out.", synth.getPCOutPort().getPlug(), midiID, false);
        }

        OutputStream out = null;

        try {
            out = new BufferedOutputStream(new FileOutputStream(getSynthPropertyFile()));

            properties.store(out, "generated file, do not edit");
        } catch (IOException e) {
            // ignore
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
    }

    private void putMidiInfo(Properties properties, String prefix, MidiPlug plug, MidiID midiID, boolean input) {
        if (plug == null)
            return;
        MidiDevice.Info info = plug.getDeviceInfo();
        if (info == null)
            return;

        properties.put(prefix + "id", Integer.toString(midiID.getID(info)));
        properties.put(prefix + "name", info.getName());
        properties.put(prefix + "vendor", info.getVendor());
        properties.put(prefix + "version", info.getVersion());
        properties.put(prefix + "description", info.getDescription());
        properties.put(prefix + "input", Boolean.toString(input));
    }

    private File getSynthPropertyFile() {
        return TempDir.forObject(this).getTempFile("synth.properties");
    }

}