/* * CraftBook Copyright (C) 2010-2017 sk89q <http://www.sk89q.com> * CraftBook Copyright (C) 2011-2017 me4502 <http://www.me4502.com> * CraftBook Copyright (C) Contributors * * 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 com.sk89q.craftbook.core.util.jinglenote; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class StringJingleSequencer implements JingleSequencer { private int delay; private boolean isPlaying; private boolean playedBefore = false; private List<Note> song; private Set<JingleNotePlayer> players = new HashSet<>(); public StringJingleSequencer(String tune, int delay) { this.delay = delay; song = parseTune(tune); } @Override public void run() throws InterruptedException { if(song == null) { return; } isPlaying = true; playedBefore = true; int position = 0; while (position < song.size() && isPlaying && !players.isEmpty()) { for (JingleNotePlayer player : players) { player.play(song.get(position)); } position++; Thread.sleep(delay * 50L); //Delay ticks means x * 50L to get to millis. } isPlaying = false; } private static ArrayList<Note> parseTune(String tune) { if (tune == null) return null; ArrayList<Note> musicKeys = new ArrayList<>(); byte instrument = -1; for (int i = 0; i < tune.length(); i++) { char first = tune.charAt(i); if (first >= '0' && first <= '9') { // instrument? instrument = getTypeFromChar(first); } else if (i + 1 < tune.length()) { // note? if (instrument == -1) return null; int pitch = getPitchFromChar(first); boolean skip = false; if (pitch == -1) { switch (first) { case '-': case ' ': skip = true; break; default: return null; } } int octave; try { octave = Integer.parseInt(Character.toString(tune.charAt(i + 1))); } catch (NumberFormatException e) { octave = 2; } if (skip) { musicKeys.add(new Note(Instrument.PIANO, (byte) 0, 0)); } else { if (octave < 2) octave = 2; pitch += (octave - 2) * 12; if (pitch < 0) pitch = 0; else if (pitch > 24) pitch = 24; musicKeys.add(new Note(Instrument.toMCSound(instrument), (byte) pitch, 60F)); } i++; } } if (musicKeys.size() == 0) return null; return musicKeys; } private static byte getTypeFromChar(char type) { byte instrument = -1; switch (type) { case '9': case '8': case '7': case '0': instrument = 0; break; case '1': instrument = 1; break; case '2': instrument = 2; break; case '3': instrument = 3; break; case '4': instrument = 4; break; case '5': instrument = 5; break; case '6': instrument = 6; break; } return instrument; } private static int getPitchFromChar(char charPitch) { int pitch = 0; switch (charPitch) { case 'f': pitch++; case 'e': pitch++; case 'D': pitch++; case 'd': pitch++; case 'C': pitch++; case 'c': pitch++; case 'b': pitch++; case 'A': pitch++; case 'a': pitch++; case 'G': pitch++; case 'g': pitch++; case 'F': break; default: pitch = -1; break; } return pitch; } @Override public void stop() { isPlaying = false; } @Override public boolean isPlaying () { return isPlaying; } @Override public boolean hasPlayedBefore () { return playedBefore; } @Override public void stop (JingleNotePlayer player) { players.remove(player); } @Override public void play (JingleNotePlayer player) { players.add(player); if(!playedBefore) try { run(); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public Set<JingleNotePlayer> getPlayers () { return players; } }