001: package org.millstone.examples.stoneplayer;
002:
003: import java.util.LinkedList;
004: import java.util.Iterator;
005: import java.util.Random;
006: import java.util.Set;
007: import java.io.File;
008: import javazoom.jl.player.*;
009:
010: /** Jukebox implementing a shared playlist and standard playing interface.
011: *
012: * @author IT Mill Ltd
013: */
014: public class Jukebox implements Runnable {
015:
016: private static LinkedList playList = new LinkedList();
017: private static Song current = null;
018: private static Player player;
019: private static Thread playerThread;
020: private static Random rand;
021: private static boolean playing = false;
022: private static LinkedList listeners = new LinkedList();
023:
024: /** Get iterator for iterating trough songs in playlist. */
025: public Iterator getPlayListIterator() {
026: return playList.iterator();
027: }
028:
029: /** Add set of files toplaylist.
030: * @param files Set of files
031: */
032: public void addToPlayList(Set files) {
033: Object[] f = files.toArray();
034: for (int i = 0; i < f.length; i++)
035: addToPlayList((File) f[i]);
036: }
037:
038: /** Add new MP3-file to playlist.
039: * @param file MP3-file or directory to be added to playlist
040: */
041: public void addToPlayList(File file) {
042: if (file.isFile()
043: && file.getName().toLowerCase().endsWith(".mp3"))
044: playList.add(new Song(file));
045: else if (file.isDirectory()) {
046: File[] f = file.listFiles();
047: for (int i = 0; i < f.length; i++)
048: addToPlayList(f[i]);
049: }
050: playlistChange();
051: if (current == null && size() > 0) {
052: current = (Song) playList.getFirst();
053: stateChange();
054: }
055: }
056:
057: /** Remove a song from the playlist.
058: * @param song Song to be removed from the list.
059: */
060: public void removeFromPlayList(Song song) {
061: if (song == current)
062: next();
063: playList.remove(song);
064: playlistChange();
065: }
066:
067: /** Remove a song from the playlist.
068: * @param song Song to be removed from the list.
069: */
070: public void clearPlayList() {
071: if (isPlaying())
072: stop();
073: playList.clear();
074: current = null;
075: playlistChange();
076: }
077:
078: /** Start playing.
079: */
080: public synchronized void play() {
081: if (size() > 0) {
082: if (current == null)
083: current = (Song) playList.getFirst();
084:
085: // Stop if currently playing
086: playing = false;
087: if (player != null)
088: player.close();
089: while (playerThread != null && playerThread.isAlive()) {
090: playerThread.interrupt();
091: try {
092: wait(2);
093: } catch (java.lang.InterruptedException e) {
094: System.out
095: .println("Interrupted exception at player.");
096: }
097: }
098:
099: // Start playing current
100: playerThread = new Thread(this );
101: playing = true;
102: playerThread.start();
103: }
104: stateChange();
105: }
106:
107: /** Stop playing.
108: */
109: public synchronized void stop() {
110: playing = false;
111: if (playerThread != null) {
112: if (player != null) {
113: player.close();
114: player = null;
115: }
116: while (playerThread.isAlive()) {
117: playerThread.interrupt();
118: try {
119: wait(2);
120: } catch (java.lang.InterruptedException e) {
121: System.out
122: .println("Interrupted exception at player.");
123: }
124: }
125: playerThread = null;
126: }
127: stateChange();
128: }
129:
130: /** Move to next song in playlist.
131: */
132: public void next() {
133: if (current != null) {
134: int index = playList.indexOf(current);
135: if (index < playList.size() - 1) {
136: current = (Song) playList.get(index + 1);
137: if (isPlaying())
138: play();
139: } else {
140: current = null;
141: if (size() > 0)
142: current = (Song) playList.getFirst();
143: stop();
144: }
145: } else if (isPlaying())
146: play();
147: playlistChange();
148: }
149:
150: /** Move to previous song in playlist.
151: */
152: public void prev() {
153: if (current != null) {
154: int index = playList.indexOf(current);
155: if (index > 0)
156: current = (Song) playList.get(index - 1);
157: }
158: if (isPlaying())
159: play();
160: playlistChange();
161: }
162:
163: /** Move to random song in playlist.
164: */
165: public void random() {
166: if (size() > 0) {
167: if (rand == null)
168: rand = new Random();
169: int index = rand.nextInt(size());
170: current = (Song) playList.get(index);
171: if (isPlaying())
172: play();
173: playlistChange();
174: }
175: }
176:
177: public void run() {
178: while (playing) {
179: try {
180: AudioDevice audioDev = FactoryRegistry.systemRegistry()
181: .createAudioDevice();
182: player = new Player(current.getStream(), audioDev);
183: player.play();
184: player.close();
185: } catch (java.lang.Exception e) {
186: System.out.println("Exception at player:" + e);
187: playing = false;
188: }
189:
190: if (playing) {
191: int index = playList.indexOf(current);
192: if (index < playList.size() - 1) {
193: current = (Song) playList.get(index + 1);
194: stateChange();
195: } else
196: playing = false;
197: }
198: }
199: }
200:
201: /** Get the currently playing song */
202: public Song getCurrentSong() {
203: return current;
204: }
205:
206: /** Get the currently playing song */
207: public void setCurrentSong(Song song) {
208: if (song != null) {
209: if (!playList.contains(song))
210: playList.addLast(song);
211: if (current != song) {
212: current = song;
213: play();
214: }
215: } else
216: stop();
217: }
218:
219: /** Is the player active */
220: public boolean isPlaying() {
221: return playing;
222: }
223:
224: /** Get the number of songs in playlist */
225: public int size() {
226: return playList.size();
227: }
228:
229: /** Get the current song index */
230: public int getCurrentSongIndex() {
231: if (current != null)
232: return playList.indexOf(current);
233: else
234: return -1;
235: }
236:
237: /** Add jukebox listener for this jukebox */
238: public void addListener(JukeboxListener listener) {
239: listeners.add(listener);
240: }
241:
242: /** Remove jukebox listener from this jukebox */
243: public void removeListener(JukeboxListener listener) {
244: listeners.remove(listener);
245: }
246:
247: /** Emit jukebox state change (if the state have really changed) */
248: private void stateChange() {
249: for (Iterator i = listeners.iterator(); i.hasNext();)
250: ((JukeboxListener) i.next()).jukeboxStateChanged(this );
251: }
252:
253: /** Emit jukebox playlist change */
254: private void playlistChange() {
255: for (Iterator i = listeners.iterator(); i.hasNext();)
256: ((JukeboxListener) i.next()).jukeboxPlaylistChanged(this );
257: }
258:
259: /** Get the playlist */
260: public LinkedList getPlayList() {
261: return playList;
262: }
263: }
264:
265: /* This Millstone sample code is public domain. *
266: * For more information see www.millstone.org. */
|