1#include "PlayList.h"
2
3#include <OS.h>
4
5#include <stdlib.h>
6#include <string.h>
7
8//#define DEBUG_PLAYLIST
9
10#ifdef DEBUG_PLAYLIST
11#include <stdio.h>
12#define STRACE(x) printf x
13#else
14#define STRACE(x) /* nothing */
15#endif
16
17
18PlayList::PlayList(int16 count, int16 start)
19	:
20	fTrackCount(count),
21	fTrackIndex(0),
22	fStartingTrack(start),
23	fRandom(false),
24	fLoop(false)
25{
26	STRACE(("PlayList(count=%d,start=%d)\n",count,start));
27
28	srand(real_time_clock_usecs());
29
30	if (fTrackCount < 0)
31		fTrackCount = 0;
32	else if (fTrackCount > 500)
33		fTrackCount = 500;
34
35	if (fStartingTrack >= fTrackCount)
36		fStartingTrack = fTrackCount - 1;
37
38	if (fStartingTrack < 1)
39		fStartingTrack = 1;
40
41	memset(fTrackList, -1, 500);
42
43	Unrandomize();
44}
45
46
47void
48PlayList::SetTrackCount(const int16 &count)
49{
50	fLocker.Lock();
51
52	STRACE(("PlayList::SetTrackCount(%d)\n",count));
53
54	if (count <= 0) {
55		fTrackCount = 0;
56		fTrackIndex = 0;
57	}
58	else if (count > 500)
59		fTrackCount = 500;
60	else
61		fTrackCount = count;
62
63	memset(fTrackList, -1, 500);
64	SetShuffle(IsShuffled());
65
66	fLocker.Unlock();
67}
68
69
70void
71PlayList::SetStartingTrack(const int16 &start)
72{
73	fLocker.Lock();
74
75	STRACE(("PlayList::SetStartingTrack(%d)\n",start));
76
77	fStartingTrack = start;
78
79	fLocker.Unlock();
80}
81
82
83void
84PlayList::Rewind()
85{
86	STRACE(("PlayList::Rewind()\n"));
87	fLocker.Lock();
88
89	fTrackIndex = 0;
90
91	fLocker.Unlock();
92}
93
94
95void
96PlayList::SetShuffle(const bool &random)
97{
98	STRACE(("PlayList::SetShuffle(%s)\n", random ? "random" : "sequential"));
99	fLocker.Lock();
100
101	if (random)
102		Randomize();
103	else
104		Unrandomize();
105
106	fRandom = random;
107
108	fLocker.Unlock();
109}
110
111
112void
113PlayList::SetLoop(const bool &loop)
114{
115	STRACE(("PlayList::SetLoop(%s)\n", loop ? "loop" : "non-loop"));
116	fLocker.Lock();
117
118	fLoop = loop;
119
120	fLocker.Unlock();
121}
122
123
124void
125PlayList::SetCurrentTrack(const int16 &track)
126{
127	STRACE(("PlayList::SetCurrentTrack(%d)\n",track));
128
129	if (track < 0 || track > fTrackCount)
130		return;
131
132	fLocker.Lock();
133
134	for (int16 i = 0; i < fTrackCount; i++) {
135		if (fTrackList[i] == track) {
136			fTrackIndex = i;
137			break;
138		}
139	}
140
141	fLocker.Unlock();
142}
143
144
145int16
146PlayList::GetCurrentTrack()
147{
148	fLocker.Lock();
149
150	int16 value = fTrackList[fTrackIndex];
151//	STRACE(("PlayList::GetCurrentTrack()=%d\n",value));
152
153	fLocker.Unlock();
154	return value;
155}
156
157
158int16
159PlayList::GetNextTrack()
160{
161	fLocker.Lock();
162
163	if (fTrackCount < 1) {
164		fLocker.Unlock();
165		STRACE(("PlayList::GetNextTrack()=-1 (no tracks)\n"));
166		return -1;
167	}
168
169	if (fTrackIndex > (fTrackCount - fStartingTrack)) {
170		if (fLoop)
171			fTrackIndex = 0;
172		else {
173			fLocker.Unlock();
174			STRACE(("PlayList::GetNextTrack()=-1 (track index out of range)\n"));
175			return -1;
176		}
177	}
178	else
179		fTrackIndex++;
180
181	int16 value = fTrackList[fTrackIndex];
182	STRACE(("PlayList::GetNextTrack()=%d\n",value));
183
184	fLocker.Unlock();
185	return value;
186}
187
188
189int16
190PlayList::GetPreviousTrack()
191{
192	fLocker.Lock();
193
194	if (fTrackCount < 1) {
195		fLocker.Unlock();
196		STRACE(("PlayList::GetPreviousTrack()=-1 (no tracks)\n"));
197		return -1;
198	}
199
200	if (fTrackIndex == 0) {
201		if (fLoop)
202			fTrackIndex = (fTrackCount - fStartingTrack);
203		else {
204			fLocker.Unlock();
205			STRACE(("PlayList::GetPreviousTrack()=-1 (track index out of range)\n"));
206			return -1;
207		}
208	}
209	else
210		fTrackIndex--;
211
212	int16 value = fTrackList[fTrackIndex];
213	STRACE(("PlayList::GetPreviousTrack()=%d\n",value));
214	fLocker.Unlock();
215	return value;
216}
217
218
219int16
220PlayList::GetLastTrack()
221{
222	fLocker.Lock();
223
224	if (fTrackCount < 1) {
225		fLocker.Unlock();
226		STRACE(("PlayList::GetLastTrack()=-1 (no tracks)\n"));
227		return -1;
228	}
229
230	fTrackIndex = fTrackCount - 1;
231	int16 value = fTrackList[fTrackIndex];
232	STRACE(("PlayList::GetLastTrack()=%d\n",value));
233	fLocker.Unlock();
234	return value;
235}
236
237
238int16
239PlayList::GetFirstTrack()
240{
241	fLocker.Lock();
242
243	if (fTrackCount < 1) {
244		fLocker.Unlock();
245		STRACE(("PlayList::GetFirstTrack()=-1 (no tracks)\n"));
246		return -1;
247	}
248
249	fTrackIndex = 0;
250	int16 value = fTrackList[fTrackIndex];
251	STRACE(("PlayList::GetFirstTrack()=%d\n",value));
252	fLocker.Unlock();
253	return value;
254}
255
256
257void
258PlayList::Randomize()
259{
260	STRACE(("PlayList::Randomize()\n"));
261
262	// Reinitialize the count
263	for (int16 i = fStartingTrack; i <= fTrackCount; i++)
264		fTrackList[i - fStartingTrack] = i;
265
266	// There are probably *much* better ways to do this,
267	// but this is the only one I could think of. :(
268
269	int32 listcount = (fTrackCount - fStartingTrack);
270	int32 swapcount =  listcount * 2;
271
272	int16 temp, first, second;
273	for (int32 i = 0; i < swapcount; i++) {
274		// repeatedly pick two elements at random and swap them
275		// This way we are sure to not have any duplicates and still have
276		// all tracks eventually be played.
277
278		first = (int16)(listcount * ((float)rand() / RAND_MAX));
279		second = (int16)(listcount * ((float)rand() / RAND_MAX));
280
281		temp = fTrackList[first];
282		fTrackList[first] = fTrackList[second];
283		fTrackList[second] = temp;
284	}
285
286	#ifdef DEBUG_PLAYLIST
287		for (int16 i = fStartingTrack; i <= fTrackCount; i++)
288			printf("\tSlot %d: track %d\n", i, fTrackList[i]);
289	#endif
290}
291
292
293void
294PlayList::Unrandomize()
295{
296	STRACE(("PlayList::Unrandomize()\n"));
297	for (int16 i = fStartingTrack; i <= fTrackCount; i++)
298		fTrackList[i - fStartingTrack] = i;
299}
300