com.maccasoft.composer.TextExportDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.maccasoft.composer.TextExportDialog.java

Source

/*
 * Copyright (c) 2016 Marco Maccaferri and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Marco Maccaferri - initial API and implementation
 */

package com.maccasoft.composer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class TextExportDialog extends Dialog {

    Button spin;
    Button clang;
    Text text;
    Label size;

    Font font;
    byte[] data;

    public TextExportDialog(Shell parentShell) {
        super(parentShell);
        setBlockOnOpen(true);
    }

    @Override
    protected void configureShell(Shell newShell) {
        super.configureShell(newShell);
        newShell.setText("Song Export");
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout(1, false);
        layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
        layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
        layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
        layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
        applyDialogFont(composite);

        if ("win32".equals(SWT.getPlatform())) { //$NON-NLS-1$
            font = new Font(Display.getDefault(), "Courier New", 10, SWT.NONE); //$NON-NLS-1$
        } else {
            font = new Font(Display.getDefault(), "mono", 10, SWT.NONE); //$NON-NLS-1$
        }

        Composite container = new Composite(composite, SWT.NONE);
        GridLayout gridLayout = new GridLayout(2, false);
        gridLayout.marginWidth = gridLayout.marginHeight = 0;
        container.setLayout(gridLayout);
        spin = new Button(container, SWT.RADIO);
        spin.setText("Spin");
        spin.setSelection(true);
        spin.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                updateTextDump();
                text.setFocus();
            }
        });
        clang = new Button(container, SWT.RADIO);
        clang.setText("C Array");
        clang.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                updateTextDump();
                text.setFocus();
            }
        });

        text = new Text(composite, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
        text.setFont(font);
        text.setLayoutData(new GridData(convertWidthInCharsToPixels(80), convertHeightInCharsToPixels(25)));

        text.addDisposeListener(new DisposeListener() {

            @Override
            public void widgetDisposed(DisposeEvent e) {
                font.dispose();
            }
        });
        text.setFocus();

        size = new Label(composite, SWT.NONE);
        size.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));

        updateTextDump();

        return composite;
    }

    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
    }

    public void setSongData(byte[] data) {
        this.data = data;
    }

    void updateTextDump() {
        StringBuilder sb = new StringBuilder();
        try {
            if (spin.getSelection()) {
                displaySpin(sb);
            } else {
                displayC(sb);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        text.setText(sb.toString());
        size.setText(String.format("%d bytes", data.length));
    }

    void displaySpin(StringBuilder sb) {
        int c;
        Map<Integer, Integer> init = new HashMap<Integer, Integer>();
        List<Integer> instruments = new ArrayList<Integer>();
        List<Integer> patterns = new ArrayList<Integer>();

        int i = 0;

        sb.append("DAT\n\nmusic\n");
        sb.append(String.format("    byte    $%02X, $%02X ' flag\n\n", data[i], data[i + 1]));
        i += 2;

        c = 0;
        while (i < data.length) {
            int v = (data[i] & 0xFF) | ((data[i + 1] & 0xFF) << 8);
            sb.append(String.format("    byte    $%02X, $%02X", data[i], data[i + 1]));
            i += 2;
            if (v == 0) {
                sb.append(" ' end of instrument pointers\n\n");
                break;
            } else {
                instruments.add(v);
                sb.append(String.format(" ' instrument %d\n", c++));
            }
        }

        for (c = 0; c < 8; c++) {
            sb.append(String.format("    byte    $%02X, $%02X ' channel %d\n", data[i], data[i + 1], c));
            int v = (data[i] & 0xFF) | ((data[i + 1] & 0xFF) << 8);
            if (v != 0) {
                init.put(v, c);
            }
            i += 2;
        }

        if ((i % 4) != 0) {
            sb.append("    byte    ");
            sb.append(String.format("$%02X", data[i++]));
            while ((i % 4) != 0) {
                sb.append(String.format(", $%02X", data[i++]));
            }
            sb.append(" ' align to 4-bytes boundary\n");
        }

        sb.append("\n    ' pattern pointers\n");

        while (i < data.length) {
            sb.append(String.format("    byte    $%02X, $%02X, $%02X, $%02X", data[i], data[i + 1], data[i + 2],
                    data[i + 3]));

            Integer ch = init.get(i - 2);
            if (ch != null) {
                sb.append(" ' channel " + ch);
            }
            sb.append("\n");

            if (data[i] == (byte) 0xFF && data[i + 1] == (byte) 0xFF && data[i + 2] == (byte) 0xFF
                    && data[i + 3] == (byte) 0xFF) {
                break;
            }

            int v = (data[i] & 0xFF) | ((data[i + 1] & 0xFF) << 8);
            patterns.add(v & 0x7FFF);
            i += 4;
        }
        i += 4;

        sb.append("\n    ' instruments\n");

        int addr = i - 2;
        while (i < data.length && !patterns.contains(addr)) {
            sb.append(String.format("    byte    $%02X, $%02X, $%02X, $%02X", data[i], data[i + 1], data[i + 2],
                    data[i + 3]));
            sb.append(String.format(", $%02X, $%02X, $%02X, $%02X", data[i + 4], data[i + 5], data[i + 6],
                    data[i + 7]));
            if (instruments.contains(addr)) {
                sb.append(String.format(" ' instrument %d", instruments.indexOf(addr)));
            }
            sb.append("\n");
            i += 8;
            addr += 8;
        }

        sb.append("\n    ' patterns\n");

        StringBuilder pb = new StringBuilder();
        while (i < data.length) {
            if (patterns.contains(addr)) {
                if (pb.length() != 0) {
                    sb.append(pb);
                    sb.append("\n");
                }
                pb = new StringBuilder("    byte    ");
            }
            if (pb.length() > 12) {
                pb.append(", ");
            }
            pb.append(String.format("$%02X", data[i++]));
            addr++;
        }
        if (pb.length() != 0) {
            sb.append(pb);
            sb.append("\n");
        }

        text.setText(sb.toString());
    }

    void displayC(StringBuilder sb) {
        int c;
        Map<Integer, Integer> init = new HashMap<Integer, Integer>();
        List<Integer> instruments = new ArrayList<Integer>();
        List<Integer> patterns = new ArrayList<Integer>();

        int i = 0;

        sb.append("uint8_t music[] = {\n");
        sb.append(String.format("    0x%02X, 0x%02X, // flag\n\n", data[i], data[i + 1]));
        i += 2;

        c = 0;
        while (i < data.length) {
            int v = (data[i] & 0xFF) | ((data[i + 1] & 0xFF) << 8);
            sb.append(String.format("    0x%02X, 0x%02X,", data[i], data[i + 1]));
            i += 2;
            if (v == 0) {
                sb.append(" // end of instrument pointers\n\n");
                break;
            } else {
                instruments.add(v);
                sb.append(String.format(" // instrument %d\n", c++));
            }
        }

        for (c = 0; c < 8; c++) {
            sb.append(String.format("    0x%02X, 0x%02X, // channel %d\n", data[i], data[i + 1], c));
            int v = (data[i] & 0xFF) | ((data[i + 1] & 0xFF) << 8);
            if (v != 0) {
                init.put(v, c);
            }
            i += 2;
        }

        if ((i % 4) != 0) {
            sb.append("    ");
            sb.append(String.format("0x%02X,", data[i++]));
            while ((i % 4) != 0) {
                sb.append(String.format(" 0x%02X,", data[i++]));
            }
            sb.append(" // align to 4-bytes boundary\n");
        }

        sb.append("\n    // pattern pointers\n");

        while (i < data.length) {
            sb.append(String.format("    0x%02X, 0x%02X, 0x%02X, 0x%02X,", data[i], data[i + 1], data[i + 2],
                    data[i + 3]));

            Integer ch = init.get(i - 2);
            if (ch != null) {
                sb.append(" // channel " + ch);
            }
            sb.append("\n");

            if (data[i] == (byte) 0xFF && data[i + 1] == (byte) 0xFF && data[i + 2] == (byte) 0xFF
                    && data[i + 3] == (byte) 0xFF) {
                break;
            }

            int v = (data[i] & 0xFF) | ((data[i + 1] & 0xFF) << 8);
            patterns.add(v & 0x7FFF);
            i += 4;
        }
        i += 4;

        sb.append("\n    // instruments\n");

        int addr = i - 2;
        while (i < data.length && !patterns.contains(addr)) {
            sb.append(String.format("    0x%02X, 0x%02X, 0x%02X, 0x%02X,", data[i], data[i + 1], data[i + 2],
                    data[i + 3]));
            sb.append(String.format(" 0x%02X, 0x%02X, 0x%02X, 0x%02X,", data[i + 4], data[i + 5], data[i + 6],
                    data[i + 7]));
            if (instruments.contains(addr)) {
                sb.append(String.format(" // instrument %d", instruments.indexOf(addr)));
            }
            sb.append("\n");
            i += 8;
            addr += 8;
        }

        sb.append("\n    // patterns\n");

        StringBuilder pb = new StringBuilder();
        while (i < data.length) {
            if (patterns.contains(addr)) {
                if (pb.length() != 0) {
                    sb.append(pb);
                    sb.append("\n");
                }
                pb = new StringBuilder("    ");
            }
            if (pb.length() > 4) {
                pb.append(" ");
            }
            pb.append(String.format("0x%02X,", data[i++]));
            addr++;
        }
        if (pb.length() != 0) {
            sb.append(pb);
            sb.append("\n");
        }

        sb.append("};\n");

        text.setText(sb.toString());
    }
}