Source code: irate/client/PlayThread.java
1 // Copyright 2003 Anthony Jones, Taras
2
3 package irate.client;
4
5 import irate.common.Track;
6 import irate.common.UpdateListener;
7
8 import java.io.*;
9 import java.util.*;
10
11 public class PlayThread extends Thread {
12
13 private Track currentTrack;
14 private Track nextTrack;
15 private Player player;
16 private PlayerList playerList;
17 private PlayListManager playListManager;
18 private Vector updateListeners = new Vector();
19 private Speech speech = new Speech();
20 private boolean speaking;
21 private boolean toKeepPlaying;
22
23 public PlayThread(PlayListManager playListManager, PlayerList playerList) {
24 this.playListManager = playListManager;
25 this.playerList = playerList;
26 }
27
28 public boolean isSpeechSupported() {
29 return speech.isSupported();
30 }
31
32 public void run() {
33 while (true) {
34 playTrack();
35 }
36 }
37
38 private void playFile(File file) throws Exception {
39 player = playerList.getPlayer(playListManager.getTrackDatabase().getPlayer());
40 try {
41 player.play(file);
42 }
43 catch (PlayerException e) {
44 e.printStackTrace();
45 }
46 finally {
47 // Without this, RoboJock can't talk because it fights with the
48 // Java player over the sound device.
49 player.close();
50 }
51 }
52
53 public synchronized void play(Track track) {
54 nextTrack = track;
55 reject();
56 }
57
58 private void playTrack() {
59 try {
60 synchronized (this) {
61 speaking = playListManager.getTrackDatabase().isRoboJockEnabled();
62 // If a next track has been chosen by the user, use that, otherwise
63 // pick one intelligently.
64 currentTrack =
65 nextTrack != null ? nextTrack : playListManager.chooseTrack();
66 toKeepPlaying = true;
67 nextTrack = null;
68 }
69
70 if (currentTrack != null) {
71 notifyUpdateListeners();
72 File file = currentTrack.getFile();
73 if (file.exists()) {
74 if (speaking) {
75 try {
76 speech.say(
77 (currentTrack.isRated() ? "" : "Unrated. ")
78 + currentTrack.getTitle()
79 + " by "
80 + currentTrack.getArtist());
81 }
82 catch (Exception e) {
83 e.printStackTrace();
84 }
85 finally {
86 speaking = false;
87 }
88 }
89 if (toKeepPlaying) {
90 playFile(file);
91 if (toKeepPlaying) {
92 currentTrack.incNoOfTimesPlayed();
93 playListManager.getTrackDatabase().incNoOfPlays();
94 }
95 }
96 }
97 else
98 speaking = false;
99 }
100 }
101 catch (Exception e) {
102 e.printStackTrace();
103 }
104 finally {
105 try {
106 sleep(500);
107 }
108 catch (InterruptedException e) {
109 }
110 }
111 }
112
113 public Track getCurrentTrack() {
114 return currentTrack;
115 }
116
117 public synchronized void reject() {
118 // It must not be paused if you want to reject a track.
119 setPaused(false);
120
121 // Clear the toKeepPlaying flag to instruct the play thread to co-operatively stop.
122 toKeepPlaying = false;
123 if (player != null)
124 player.close();
125
126 // Stop RoboJock if it's talking.
127 if (speech != null && speaking)
128 speech.abort();
129 }
130
131 public void setRating(int rating) {
132 currentTrack.setRating(rating);
133 }
134
135 public void setPaused(boolean paused) {
136 if (player != null)
137 player.setPaused(paused);
138 }
139
140 public boolean isPaused() {
141 if (player == null)
142 return false;
143 return player.isPaused();
144 }
145
146 public void addUpdateListener(UpdateListener updateListener) {
147 updateListeners.add(updateListener);
148 }
149
150 private void notifyUpdateListeners() {
151 for (int i = 0; i < updateListeners.size(); i++) {
152 UpdateListener updateListener = (UpdateListener) updateListeners.elementAt(i);
153 updateListener.actionPerformed();
154 }
155 }
156 }