Updated project dependencies
[stereo.git] / MemphisDJ / src / music / PlaybackQueue.java
blob5e39da033f802a2b48adaa92669dd55f74cf6938
1 package music;
3 import interfaces.collection.AbstractCollection;
4 import interfaces.collection.Collection;
5 import interfaces.collection.Source;
7 import java.util.ArrayList;
8 import java.util.HashSet;
9 import java.util.Iterator;
10 import java.util.LinkedList;
11 import java.util.List;
12 import java.util.Set;
14 import notification.AbstractEventGenerator;
15 import notification.QueueListener;
17 class PlaybackQueue extends AbstractEventGenerator<QueueListener>
18 implements interfaces.PlaybackQueue, Source.Listener {
20 public static final int RECENT = 5;
21 public static final int QUEUED = 10;
23 private Source<? extends Track> source;
25 private volatile Track current;
26 private volatile int position;
27 private LinkedList<Track> queued;
28 private LinkedList<Track> recent;
30 public PlaybackQueue(Source<? extends Track> source) {
31 queued = new LinkedList<Track>();
32 recent = new LinkedList<Track>();
34 this.source = source;
35 source.registerListener(this);
38 public synchronized void next() {
40 System.out.println("queue: next");
42 if (current != null) {
43 recent.addLast(current);
44 while (recent.size() > RECENT) {
45 recent.removeFirst();
49 while (queued.size() < QUEUED && source.hasNext()) {
50 queued.addLast(source.next());
53 if (!queued.isEmpty()) {
54 current = queued.removeFirst();
55 position++;
56 notifyQueueChanged();
58 else {
59 notifyQueueEmpty();
63 public synchronized void prev() {
65 System.out.println("queue: prev");
67 if (!recent.isEmpty()) {
69 if (current != null) {
70 queued.addFirst(current);
71 position--;
74 current = recent.removeLast();
76 notifyQueueChanged();
80 public synchronized void clear() {
81 queued.clear();
83 System.out.println("queue cleared");
85 notifyQueueChanged();
88 public synchronized void enqueue(List<? extends Track> tracks) {
89 queued.addAll(tracks);
91 notifyQueueChanged();
94 public synchronized boolean hasSongs() {
95 return !queued.isEmpty();
98 public synchronized void added(Iterable<? extends Track> tracks) {
100 System.out.println("songs added: updating queue");
102 boolean empty = queued.isEmpty() && current == null;
104 while (queued.size() < QUEUED && source.hasNext()) {
105 queued.addLast(source.next());
106 System.out.println("added " + queued.getLast());
109 if (!queued.isEmpty() && empty) {
110 if (empty) notifyTracksAvailable();
111 else notifyQueueChanged();
115 public synchronized void removed(Set<? extends Track> tracks) {
117 boolean changed = false;
119 for (Iterator<Track> it = recent.iterator(); it.hasNext();) {
120 if (tracks.contains(it.next())) {
121 it.remove();
122 changed = true;
125 if (current != null && tracks.contains(current)) {
126 current = null;
127 changed = true;
129 for (Iterator<Track> it = queued.iterator(); it.hasNext();) {
130 if (tracks.contains(it.next())) {
131 it.remove();
132 changed = true;
136 if (!changed) return;
138 if (current == null) {
139 next();
142 if (current == null) {
143 notifyQueueEmpty();
145 else {
146 notifyQueueChanged();
150 protected synchronized void remove(Track t) {
151 recent.remove(t);
152 if (current == t) current = null;
153 queued.remove(t);
156 public synchronized Track current() {
157 return current;
160 public synchronized int position() {
161 return position;
164 public synchronized Collection<? extends Track> playlist() {
166 //TODO create collection
167 List<Track> tracks = new ArrayList<Track>();
168 tracks.addAll(recent);
169 if (current != null) tracks.add(current);
170 tracks.addAll(queued);
172 return new PlaybackQueueCollection(tracks);
175 public synchronized void setSource(Source<? extends Track> source) {
177 this.source.removeListener(this);
179 Set<Track> removed = new HashSet<Track>();
180 for (Track t: this.source.tracks()) {
181 removed.add(t);
184 this.source.registerListener(this);
185 this.source = source;
187 for (Track t: this.source.tracks()) {
188 removed.remove(t);
191 removed(removed);
194 protected void notifyQueueEmpty() {
195 System.out.println("queue empty");
196 for (QueueListener l: super.listeners()) {
197 l.queueEmpty();
201 protected void notifyTracksAvailable() {
202 System.out.println("tracks available");
203 for (QueueListener l: super.listeners()) {
204 l.tracksAvailable();
208 protected void notifyQueueChanged() {
209 System.out.println("queue changed");
210 for (QueueListener l: super.listeners()) {
211 l.queueChanged();
215 private class PlaybackQueueCollection extends AbstractCollection<Track> {
217 private final List<Track> tracks;
218 private final Iterator<Track> trackIt;
220 public PlaybackQueueCollection(List<Track> tracks) {
221 super(Collection.QUEUE_ID, Collection.QUEUE_PERSISTENT_ID);
222 this.tracks = tracks;
223 this.trackIt = tracks.iterator();
226 public boolean hasNext() {
227 return trackIt.hasNext();
230 public Track next() {
231 return trackIt.next();
234 public int editStatus() {
235 return GENERATED;
238 public Iterable<? extends Track> tracks() {
239 return tracks;
242 public Iterator<Track> iterator() {
243 return tracks.iterator();
246 public int id() {
247 return source.id();
250 public long persistentId() {
251 return source.persistentId();
254 public boolean isRoot() {
255 // TODO Auto-generated method stub
256 return false;
259 public String name() {
260 return source.name();
263 public Collection<Track> parent() {
264 return null;
267 public int size() {
268 return tracks.size();