/* * ASAPApplet.java - ASAP applet * * Copyright (C) 2007-2009 Piotr Fusik * * This file is part of ASAP (Another Slight Atari Player), * see http://asap.sourceforge.net * * ASAP 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. * * ASAP 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 ASAP; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ import java.applet.Applet; import java.awt.Color; import java.awt.Graphics; import java.io.InputStream; import java.io.IOException; import java.net.URL; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import netscape.javascript.JSObject; import net.sf.asap.ASAP; import net.sf.asap.ASAP_ModuleInfo; public class ASAPApplet extends Applet implements Runnable { private final ASAP asap = new ASAP(); private int song; private SourceDataLine line; private boolean running; private boolean paused; private static final int BITS_PER_SAMPLE = 16; private int defaultPlaybackTime = -1; private int loopPlaybackTime = -1; private static final int ONCE = -2; // for loopPlaybackTime private Color background; private Color foreground; public void update(Graphics g) { if (running) paint(g); else super.update(g); } public void paint(Graphics g) { if (!running) return; int channels = 4 * asap.getModuleInfo().channels; int channelWidth = getWidth() / channels; int totalHeight = getHeight(); int unitHeight = totalHeight / 15; for (int i = 0; i < channels; i++) { int height = asap.getPokeyChannelVolume(i) * unitHeight; g.setColor(background); g.fillRect(i * channelWidth, 0, channelWidth, totalHeight - height); g.setColor(foreground); g.fillRect(i * channelWidth, totalHeight - height, channelWidth, height); } /* ASAP_ModuleInfo module_info = asap.getModuleInfo(); g.drawString("Author: " + module_info.author, 10, 20); g.drawString("Name: " + module_info.name, 10, 40); g.drawString("Date: " + module_info.date, 10, 60); if (module_info.songs > 1) g.drawString("Song " + (song + 1) + " of " + module_info.songs, 10, 80); */ } public void run() { byte[] buffer = new byte[8192]; int len; do { synchronized (asap) { len = asap.generate(buffer, BITS_PER_SAMPLE); } synchronized (this) { while (paused) { try { wait(); } catch (InterruptedException e) { return; } } } line.write(buffer, 0, len); repaint(); } while (len == buffer.length && running); if (running) { String js = getParameter("onPlaybackEnd"); if (js != null) JSObject.getWindow(this).eval(js); running = false; } repaint(); } public void setPlaybackTime(String defaultPlaybackTime, String loopPlaybackTime) { this.defaultPlaybackTime = ASAP.parseDuration(defaultPlaybackTime); if ("ONCE".equals(loopPlaybackTime)) this.loopPlaybackTime = ONCE; else this.loopPlaybackTime = ASAP.parseDuration(loopPlaybackTime); } public void play(String filename, int song) { byte[] module; int module_len = 0; try { InputStream is = new URL(getDocumentBase(), filename).openStream(); module = new byte[ASAP.MODULE_MAX]; for (;;) { int i = is.read(module, module_len, ASAP.MODULE_MAX - module_len); if (i <= 0) break; module_len += i; } is.close(); } catch (IOException e) { showStatus("ERROR LOADING " + filename); return; } ASAP_ModuleInfo module_info; synchronized (asap) { asap.load(filename, module, module_len); module_info = asap.getModuleInfo(); if (song < 0) song = module_info.default_song; int duration = module_info.durations[song]; if (duration < 0) duration = defaultPlaybackTime; else if (module_info.loops[song] && loopPlaybackTime != ONCE) duration = loopPlaybackTime; asap.playSong(song, duration); } AudioFormat format = new AudioFormat(ASAP.SAMPLE_RATE, BITS_PER_SAMPLE, module_info.channels, BITS_PER_SAMPLE != 8, false); try { line = (SourceDataLine) AudioSystem.getLine(new DataLine.Info(SourceDataLine.class, format)); line.open(format); } catch (LineUnavailableException e) { showStatus("ERROR OPENING AUDIO"); return; } line.start(); if (!running) { running = true; new Thread(this).start(); } synchronized (this) { paused = false; notify(); } repaint(); } private Color getColor(String parameter, Color defaultColor) { String s = getParameter(parameter); if (s == null || s.length() == 0) return defaultColor; if (s.charAt(0) == '#') s = s.substring(1); return new Color(Integer.parseInt(s, 16)); } public void start() { setPlaybackTime(getParameter("defaultPlaybackTime"), getParameter("loopPlaybackTime")); background = getColor("background", Color.BLACK); setBackground(background); foreground = getColor("foreground", Color.GREEN); String filename = getParameter("file"); if (filename == null) return; int song = -1; String s = getParameter("song"); if (s == null || s.length() == 0) song = -1; else song = Integer.parseInt(s); play(filename, song); } public void stop() { running = false; } public synchronized boolean togglePause() { paused = !paused; if (!paused) notify(); return paused; } public String getAuthor() { return asap.getModuleInfo().author; } public String getName() { return asap.getModuleInfo().name; } public String getDate() { return asap.getModuleInfo().date; } }