This repository contains MadHelix itself, along with compiled libraries with its dependencies.

[[ 🗃 ^ZEkyo madhelix ]] :: [📥 Inbox] [📤 Outbox] [🐤 Followers] [🤝 Collaborators] [🛠 Commits]

Clone

HTTPS: git clone https://vervis.peers.community/repos/ZEkyo

SSH: git clone USERNAME@vervis.peers.community:ZEkyo

Branches

Tags

v0.0.1 :: src / org / ultrasonicmadness / ultrasonichelix /

UltrasonicHelix.java

/*
 * UltrasonicHelix is a Java Swing-based GUI frontend for SoundHelix.
 * Copyright (C) 2017 UltrasonicMadness
 *
 * 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 org.ultrasonicmadness.ultrasonichelix;

// Assorted imports
import java.io.File;
import java.net.URL;
import java.util.Random;

// SoundHelix
import com.soundhelix.misc.SongContext;
import com.soundhelix.util.SongUtils;

// AWT widgets
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;

// Swing widgets
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

// Other Swing modules
import javax.swing.SwingUtilities;

// UltrasonicHelix imports
import org.ultrasonicmadness.ultrasonichelix.dialogs.AboutBox;
import org.ultrasonicmadness.ultrasonichelix.panels.ControlsPanel;
import org.ultrasonicmadness.ultrasonichelix.panels.OptionsPanel;
import org.ultrasonicmadness.ultrasonichelix.panels.StatusPanel;
import org.ultrasonicmadness.ultrasonichelix.utils.PathUtils;

public class UltrasonicHelix {
    
    // SoundHelix
    private File stylesDir; // Styles directory
    private SongContext currentSong; // Current song being played
    private boolean startHelix; // If this is set to true, SoundHelix will be called to play the specified music and it will be set back to false.
    private boolean helixPlaying; // Set to true while SoundHelix is playing music, false otherwise.
    
    // Main 3 panels: status, options, controls
    private StatusPanel statusPanel;
    private OptionsPanel optionsPanel;
    private ControlsPanel controlsPanel;
    
    // SoundHelix thread.
    private Thread soundHelix = new Thread(new Runnable() {
        public void run() {
            // This thread runs as long as UltrasonicHelix does.
            while (true) {
                if (startHelix) {
                    // Since this command has been started, set this to false so it isn't started repeatedly.
                    startHelix = false;
                    helixPlaying = true;
                    
                    statusPanel.setStatus("Loading SoundHelix");
                    
                    // The buttons don't function at this time, so disable them while SoundHelix loads.
                    controlsPanel.setControlsEnabled(false);
                    
                    try {
                        // If a song name is specified, use it, otherwise generate a random number and use it.
                        if (optionsPanel.getCurrentSongName() != null &&
                            !optionsPanel.getCurrentSongName().equals("")) {
                            currentSong = SongUtils.generateSong(
                                new URL("file://" + stylesDir.toString() +
                                    File.separator +
                                    optionsPanel.getCurrentStyleName() +
                                    ".xml"
                                ),
                                optionsPanel.getCurrentSongName()
                            );
                        } else {
                            // This is the same way SoundHelix uses the random number generator.
                            currentSong = SongUtils.generateSong(
                                new URL("file://" + stylesDir.toString() +
                                    File.separator +
                                    optionsPanel.getCurrentStyleName() +
                                    ".xml"
                                ),
                                new Random().nextLong()
                            );
                        }
                        
                        // Update song and style information
                        statusPanel.setStatus("Playing",
                            currentSong.getSongName(), "Style",
                            optionsPanel.getCurrentStyleName()
                        );
                        
                        // Now SoundHelix has loaded, enable the buttons again
                        controlsPanel.setControlsEnabled(true);
                        
                        // Play the song
                        currentSong.getPlayer().play(currentSong);
                    } catch (Exception x) { // In case SoundHelix encounters a problem
                        JOptionPane.showMessageDialog(null,
                            x.getMessage().toString(), "SoundHelix Error",
                            JOptionPane.ERROR_MESSAGE
                        );
                        
                        // In case an error has occured, enable the buttons again
                        controlsPanel.setControlsEnabled(true);
                    } catch (NoClassDefFoundError r) { // In case SoundHelix.jar is not found
                        JOptionPane.showMessageDialog(null,
                            "Cannot find module " + r.getMessage(), "Error",
                            JOptionPane.ERROR_MESSAGE
                        );
                        
                        // In case an error has occured, enable the buttons again
                        controlsPanel.setControlsEnabled(true);
                    }
                    
                    // The song has finished at this point, so update variables and status accordingly.
                    helixPlaying = false;
                    statusPanel.setStatus("Ready");
                } else {
                    // Without this, the thread does not respond to startHelix being set to true.
                    // There is probably a much better way to do this.
                    System.out.print("");
                }
            }
        }
    });
    
    public UltrasonicHelix() {
        // Initialize variables
        stylesDir = new File(PathUtils.getStylesDirPath());
        startHelix = false;
        helixPlaying = false;
        
        // Initialize status, options and control panels
        statusPanel = new StatusPanel();
        optionsPanel = new OptionsPanel();
        controlsPanel = new ControlsPanel();
        
        // Declare and initialize main frame and panel
        JFrame mainWindow = new JFrame("UltrasonicHelix");
        JPanel mainPanel = new JPanel();
        
        // Assume program is ready for now, error checking is carried out below.
        statusPanel.setStatus("Ready");
        
        // Start SoundHelix thread
        soundHelix.setDaemon(true); // Closes SoundHelix if UltrasonicHelix is closed.
        soundHelix.start();
        
        // Set panel layout
        mainPanel.setLayout(new GridBagLayout());
        
        // Set up constraints
        GridBagConstraints mainConstraints = new GridBagConstraints();
        mainConstraints.fill = GridBagConstraints.HORIZONTAL;
        
        // Add panels
        mainConstraints.gridy = 0;
        mainPanel.add(statusPanel, mainConstraints);
        
        mainConstraints.gridy = 1;
        mainPanel.add(optionsPanel, mainConstraints);
        
        mainConstraints.gridy = 2;
        mainPanel.add(controlsPanel, mainConstraints);
        
        // If no styles are found, disable the buttons and display an alert.
        if (stylesDir.list() == null || stylesDir.list().length == 0) {
            statusPanel.setStatus("No styles available.");
            controlsPanel.setControlsEnabled(false);
            
            JOptionPane.showMessageDialog(null,
                "No .xml files found in the styles directory",
                "Error",
                JOptionPane.ERROR_MESSAGE
            );
        }
        
        // Add action listeners to buttons
        controlsPanel.addPlayAction(e -> {
            playSong();
        });
        
        controlsPanel.addStopAction(e -> {
            stopSong();
        });
        
        controlsPanel.addAboutAction(e -> {
            AboutBox.show();
        });
        
        // Set up main window
        mainWindow.add(mainPanel);
        mainWindow.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        mainWindow.setResizable(false);
        mainWindow.pack();
        mainWindow.setVisible(true);
    }
    
    public void playSong() {
        stopSong(); // Without this, the next song won't play until the last one is finished.
        startHelix = true; // Signals to the SoundHelix thread to start
    }
    
    public void stopSong() {
        if (helixPlaying) {
            currentSong.getPlayer().abortPlay();
        }
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new UltrasonicHelix();
            }
        });
    }
}

[See repo JSON]