This repository contains MadHelix itself, along with compiled libraries with its dependencies.
Clone
HTTPS:
git clone https://vervis.peers.community/repos/ZEkyo
SSH:
git clone USERNAME@vervis.peers.community:ZEkyo
Branches
Tags
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();
}
});
}
}