Starshatter_Open
Open source Starshatter engine
Main Page
Classes
Files
File List
File Members
All
Classes
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
MusicDirector.cpp
Go to the documentation of this file.
1
/* Project Starshatter 4.5
2
Destroyer Studios LLC
3
Copyright © 1997-2004. All Rights Reserved.
4
5
SUBSYSTEM: Stars.exe
6
FILE: MusicDirector.cpp
7
AUTHOR: John DiCamillo
8
9
10
OVERVIEW
11
========
12
Music Director class to manage selection, setup, and playback
13
of background music tracks for both menu and game modes
14
*/
15
16
17
#include "
MemDebug.h
"
18
#include "
MusicDirector.h
"
19
#include "
MusicTrack.h
"
20
21
#include "
Random.h
"
22
#include "
DataLoader.h
"
23
#include "
FormatUtil.h
"
24
#include "
Sound.h
"
25
26
static
MusicDirector
* music_director = 0;
27
28
// +-------------------------------------------------------------------+
29
30
MusicDirector::MusicDirector
()
31
: mode(0), transition(0), track(0), next_track(0), no_music(true),
32
hproc(0)
33
{
34
music_director =
this
;
35
36
ScanTracks
();
37
38
if
(!
no_music
)
39
StartThread
();
40
}
41
42
MusicDirector::~MusicDirector
()
43
{
44
StopThread
();
45
46
delete
track
;
47
delete
next_track
;
48
49
menu_tracks
.
destroy
();
50
intro_tracks
.
destroy
();
51
brief_tracks
.
destroy
();
52
debrief_tracks
.
destroy
();
53
promote_tracks
.
destroy
();
54
flight_tracks
.
destroy
();
55
combat_tracks
.
destroy
();
56
launch_tracks
.
destroy
();
57
recovery_tracks
.
destroy
();
58
victory_tracks
.
destroy
();
59
defeat_tracks
.
destroy
();
60
credit_tracks
.
destroy
();
61
62
if
(
this
== music_director)
63
music_director = 0;
64
}
65
66
// +--------------------------------------------------------------------+
67
68
void
69
MusicDirector::Initialize
()
70
{
71
if
(music_director)
delete
music_director;
72
music_director =
new
(__FILE__,__LINE__)
MusicDirector
();
73
}
74
75
void
76
MusicDirector::Close
()
77
{
78
delete
music_director;
79
music_director = 0;
80
}
81
82
MusicDirector
*
83
MusicDirector::GetInstance
()
84
{
85
return
music_director;
86
}
87
88
// +-------------------------------------------------------------------+
89
90
void
91
MusicDirector::ExecFrame
()
92
{
93
if
(
no_music
)
return
;
94
95
AutoThreadSync
a(
sync
);
96
97
if
(
next_track
&& !
track
) {
98
track
=
next_track
;
99
next_track
= 0;
100
}
101
102
if
(
track
) {
103
if
(
track
->
IsDone
()) {
104
if
(
mode
!=
NONE
&&
mode
!=
SHUTDOWN
&&
next_track
== 0) {
105
GetNextTrack
(
track
->
GetIndex
()+1);
106
}
107
108
delete
track
;
109
track
=
next_track
;
110
next_track
= 0;
111
}
112
113
else
if
(
track
->
IsLooped
()) {
114
if
(
mode
!=
NONE
&&
mode
!=
SHUTDOWN
&&
next_track
== 0) {
115
GetNextTrack
(
track
->
GetIndex
()+1);
116
}
117
118
track
->
FadeOut
();
119
track
->
ExecFrame
();
120
}
121
122
else
{
123
track
->
ExecFrame
();
124
}
125
}
126
127
if
(
next_track
) {
128
if
(
next_track
->
IsDone
()) {
129
delete
next_track
;
130
next_track
= 0;
131
}
132
133
else
if
(
next_track
->
IsLooped
()) {
134
next_track
->
FadeOut
();
135
next_track
->
ExecFrame
();
136
}
137
138
else
{
139
next_track
->
ExecFrame
();
140
}
141
}
142
}
143
144
// +-------------------------------------------------------------------+
145
146
void
147
MusicDirector::ScanTracks
()
148
{
149
DataLoader
* loader =
DataLoader::GetLoader
();
150
151
bool
old_file_system = loader->
IsFileSystemEnabled
();
152
loader->
UseFileSystem
(
true
);
153
loader->
SetDataPath
(
"Music/"
);
154
155
List<Text>
files;
156
loader->
ListFiles
(
"*.ogg"
, files,
true
);
157
158
if
(files.
size
() == 0) {
159
loader->
UseFileSystem
(old_file_system);
160
no_music
=
true
;
161
return
;
162
}
163
164
no_music
=
false
;
165
166
ListIter<Text>
iter = files;
167
while
(++iter) {
168
Text
* name = iter.
value
();
169
Text
* file =
new
(__FILE__,__LINE__)
Text
(
"Music/"
);
170
171
name->
setSensitive
(
false
);
172
file->
append
(*name);
173
174
if
(name->
indexOf
(
"Menu"
) == 0) {
175
menu_tracks
.
append
(file);
176
}
177
178
else
if
(name->
indexOf
(
"Intro"
) == 0) {
179
intro_tracks
.
append
(file);
180
}
181
182
else
if
(name->
indexOf
(
"Brief"
) == 0) {
183
brief_tracks
.
append
(file);
184
}
185
186
else
if
(name->
indexOf
(
"Debrief"
) == 0) {
187
debrief_tracks
.
append
(file);
188
}
189
190
else
if
(name->
indexOf
(
"Promot"
) == 0) {
191
promote_tracks
.
append
(file);
192
}
193
194
else
if
(name->
indexOf
(
"Flight"
) == 0) {
195
flight_tracks
.
append
(file);
196
}
197
198
else
if
(name->
indexOf
(
"Combat"
) == 0) {
199
combat_tracks
.
append
(file);
200
}
201
202
else
if
(name->
indexOf
(
"Launch"
) == 0) {
203
launch_tracks
.
append
(file);
204
}
205
206
else
if
(name->
indexOf
(
"Recovery"
) == 0) {
207
recovery_tracks
.
append
(file);
208
}
209
210
else
if
(name->
indexOf
(
"Victory"
) == 0) {
211
victory_tracks
.
append
(file);
212
}
213
214
else
if
(name->
indexOf
(
"Defeat"
) == 0) {
215
defeat_tracks
.
append
(file);
216
}
217
218
else
if
(name->
indexOf
(
"Credit"
) == 0) {
219
credit_tracks
.
append
(file);
220
}
221
222
else
{
223
menu_tracks
.
append
(file);
224
}
225
226
delete
iter.
removeItem
();
227
}
228
229
loader->
UseFileSystem
(old_file_system);
230
231
menu_tracks
.
sort
();
232
intro_tracks
.
sort
();
233
brief_tracks
.
sort
();
234
debrief_tracks
.
sort
();
235
promote_tracks
.
sort
();
236
flight_tracks
.
sort
();
237
combat_tracks
.
sort
();
238
launch_tracks
.
sort
();
239
recovery_tracks
.
sort
();
240
victory_tracks
.
sort
();
241
defeat_tracks
.
sort
();
242
credit_tracks
.
sort
();
243
}
244
245
// +-------------------------------------------------------------------+
246
247
const
char
*
248
MusicDirector::GetModeName
(
int
mode)
249
{
250
switch
(mode) {
251
case
NONE
:
return
"NONE"
;
252
case
MENU
:
return
"MENU"
;
253
case
INTRO
:
return
"INTRO"
;
254
case
BRIEFING
:
return
"BRIEFING"
;
255
case
DEBRIEFING
:
return
"DEBRIEFING"
;
256
case
PROMOTION
:
return
"PROMOTION"
;
257
case
FLIGHT
:
return
"FLIGHT"
;
258
case
COMBAT
:
return
"COMBAT"
;
259
case
LAUNCH
:
return
"LAUNCH"
;
260
case
RECOVERY
:
return
"RECOVERY"
;
261
case
VICTORY
:
return
"VICTORY"
;
262
case
DEFEAT
:
return
"DEFEAT"
;
263
case
CREDITS
:
return
"CREDITS"
;
264
case
SHUTDOWN
:
return
"SHUTDOWN"
;
265
}
266
267
return
"UNKNOWN?"
;
268
}
269
270
// +-------------------------------------------------------------------+
271
272
void
273
MusicDirector::SetMode
(
int
mode)
274
{
275
if
(!music_director || music_director->
no_music
)
return
;
276
277
AutoThreadSync
a(music_director->
sync
);
278
279
// stay in intro mode until it is complete:
280
if
(mode ==
MENU
&& (music_director->
GetMode
() ==
NONE
||
281
music_director->
GetMode
() ==
INTRO
))
282
mode =
INTRO
;
283
284
mode = music_director->
CheckMode
(mode);
285
286
if
(mode != music_director->
mode
) {
287
::Print
(
"MusicDirector::SetMode() old: %s new: %s\n"
,
288
GetModeName
(music_director->
mode
),
289
GetModeName
(mode));
290
291
music_director->
mode
=
mode
;
292
293
MusicTrack
* t = music_director->
track
;
294
if
(t && t->
GetState
() && !t->
IsDone
()) {
295
if
(mode ==
NONE
|| mode ==
SHUTDOWN
)
296
t->
SetFadeTime
(0.5);
297
298
t->
FadeOut
();
299
}
300
301
t = music_director->
next_track
;
302
if
(t && t->
GetState
() && !t->
IsDone
()) {
303
if
(mode ==
NONE
|| mode ==
SHUTDOWN
)
304
t->
SetFadeTime
(0.5);
305
t->
FadeOut
();
306
307
delete
music_director->
track
;
308
music_director->
track
= t;
309
music_director->
next_track
= 0;
310
}
311
312
music_director->
ShuffleTracks
();
313
music_director->
GetNextTrack
(0);
314
315
if
(music_director->
next_track
)
316
music_director->
next_track
->
FadeIn
();
317
}
318
}
319
320
int
321
MusicDirector::CheckMode
(
int
req_mode)
322
{
323
if
(req_mode ==
RECOVERY
&&
recovery_tracks
.
size
() == 0)
324
req_mode =
LAUNCH
;
325
326
if
(req_mode ==
LAUNCH
&&
launch_tracks
.
size
() == 0)
327
req_mode =
FLIGHT
;
328
329
if
(req_mode ==
COMBAT
&&
combat_tracks
.
size
() == 0)
330
req_mode =
FLIGHT
;
331
332
if
(req_mode ==
FLIGHT
&&
flight_tracks
.
size
() == 0)
333
req_mode =
NONE
;
334
335
if
(req_mode ==
PROMOTION
&&
promote_tracks
.
size
() == 0)
336
req_mode =
VICTORY
;
337
338
if
(req_mode ==
DEBRIEFING
&&
debrief_tracks
.
size
() == 0)
339
req_mode =
BRIEFING
;
340
341
if
(req_mode ==
BRIEFING
&&
brief_tracks
.
size
() == 0)
342
req_mode =
MENU
;
343
344
if
(req_mode ==
INTRO
&&
intro_tracks
.
size
() == 0)
345
req_mode =
MENU
;
346
347
if
(req_mode ==
VICTORY
&&
victory_tracks
.
size
() == 0)
348
req_mode =
MENU
;
349
350
if
(req_mode ==
DEFEAT
&&
defeat_tracks
.
size
() == 0)
351
req_mode =
MENU
;
352
353
if
(req_mode ==
CREDITS
&&
credit_tracks
.
size
() == 0)
354
req_mode =
MENU
;
355
356
if
(req_mode ==
MENU
&&
menu_tracks
.
size
() == 0)
357
req_mode =
NONE
;
358
359
return
req_mode;
360
}
361
362
// +-------------------------------------------------------------------+
363
364
bool
365
MusicDirector::IsNoMusic
()
366
{
367
if
(music_director)
368
return
music_director->
no_music
;
369
370
return
true
;
371
}
372
373
// +-------------------------------------------------------------------+
374
375
void
376
MusicDirector::GetNextTrack
(
int
index)
377
{
378
List<Text>
* tracks = 0;
379
380
switch
(
mode
) {
381
case
MENU
: tracks = &
menu_tracks
;
break
;
382
case
INTRO
: tracks = &
intro_tracks
;
break
;
383
case
BRIEFING
: tracks = &
brief_tracks
;
break
;
384
case
DEBRIEFING
: tracks = &
debrief_tracks
;
break
;
385
case
PROMOTION
: tracks = &
promote_tracks
;
break
;
386
case
FLIGHT
: tracks = &
flight_tracks
;
break
;
387
case
COMBAT
: tracks = &
combat_tracks
;
break
;
388
case
LAUNCH
: tracks = &
launch_tracks
;
break
;
389
case
RECOVERY
: tracks = &
recovery_tracks
;
break
;
390
case
VICTORY
: tracks = &
victory_tracks
;
break
;
391
case
DEFEAT
: tracks = &
defeat_tracks
;
break
;
392
case
CREDITS
: tracks = &
credit_tracks
;
break
;
393
default
: tracks = 0;
break
;
394
}
395
396
if
(tracks && tracks->
size
()) {
397
if
(
next_track
)
398
delete
next_track
;
399
400
if
(index < 0 || index >= tracks->
size
()) {
401
index = 0;
402
403
if
(
mode
==
INTRO
) {
404
mode
=
MENU
;
405
ShuffleTracks
();
406
tracks = &
menu_tracks
;
407
408
::Print
(
"MusicDirector: INTRO mode complete, switching to MENU\n"
);
409
410
if
(!tracks || !tracks->
size
())
411
return
;
412
}
413
}
414
415
next_track
=
new
(__FILE__,__LINE__)
MusicTrack
(*tracks->
at
(index),
mode
, index);
416
next_track
->
FadeIn
();
417
}
418
419
else
if
(
next_track
) {
420
next_track
->
FadeOut
();
421
}
422
}
423
424
// +-------------------------------------------------------------------+
425
426
void
427
MusicDirector::ShuffleTracks
()
428
{
429
List<Text>
* tracks = 0;
430
431
switch
(
mode
) {
432
case
MENU
: tracks = &
menu_tracks
;
break
;
433
case
INTRO
: tracks = &
intro_tracks
;
break
;
434
case
BRIEFING
: tracks = &
brief_tracks
;
break
;
435
case
DEBRIEFING
: tracks = &
debrief_tracks
;
break
;
436
case
PROMOTION
: tracks = &
promote_tracks
;
break
;
437
case
FLIGHT
: tracks = &
flight_tracks
;
break
;
438
case
COMBAT
: tracks = &
combat_tracks
;
break
;
439
case
LAUNCH
: tracks = &
launch_tracks
;
break
;
440
case
RECOVERY
: tracks = &
recovery_tracks
;
break
;
441
case
VICTORY
: tracks = &
victory_tracks
;
break
;
442
case
DEFEAT
: tracks = &
defeat_tracks
;
break
;
443
case
CREDITS
: tracks = &
credit_tracks
;
break
;
444
default
: tracks = 0;
break
;
445
}
446
447
if
(tracks && tracks->
size
() > 1) {
448
tracks->
sort
();
449
450
Text
* t = tracks->
at
(0);
451
452
if
(!isdigit(*t[0]))
453
tracks->
shuffle
();
454
}
455
}
456
457
// +--------------------------------------------------------------------+
458
459
DWORD WINAPI
MusicDirectorThreadProc
(LPVOID link);
460
461
void
462
MusicDirector::StartThread
()
463
{
464
if
(
hproc
!= 0) {
465
DWORD result = 0;
466
GetExitCodeThread(
hproc
, &result);
467
468
if
(result != STILL_ACTIVE) {
469
CloseHandle(
hproc
);
470
hproc
= 0;
471
}
472
else
{
473
return
;
474
}
475
}
476
477
if
(
hproc
== 0) {
478
DWORD thread_id = 0;
479
hproc
= CreateThread(0, 4096,
MusicDirectorThreadProc
, (LPVOID)
this
, 0, &thread_id);
480
481
if
(
hproc
== 0) {
482
static
int
report = 10;
483
if
(report > 0) {
484
::Print
(
"WARNING: MusicDirector failed to create thread (err=%08x)\n"
, GetLastError());
485
report--;
486
487
if
(report == 0)
488
::Print
(
" Further warnings of this type will be supressed.\n"
);
489
}
490
}
491
}
492
}
493
494
void
495
MusicDirector::StopThread
()
496
{
497
if
(
hproc
!= 0) {
498
SetMode
(
SHUTDOWN
);
499
WaitForSingleObject(
hproc
, 1500);
500
CloseHandle(
hproc
);
501
hproc
= 0;
502
}
503
}
504
505
DWORD WINAPI
MusicDirectorThreadProc
(LPVOID link)
506
{
507
MusicDirector
* dir = (
MusicDirector
*) link;
508
509
if
(dir) {
510
while
(dir->
GetMode
() !=
MusicDirector::SHUTDOWN
) {
511
dir->
ExecFrame
();
512
Sleep(100);
513
}
514
515
return
0;
516
}
517
518
return
(DWORD) E_POINTER;
519
}
520
Stars45
MusicDirector.cpp
Generated on Tue Jun 5 2012 20:47:00 for Starshatter_Open by
1.8.1