1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "backends/audiocd/default/default-audiocd.h"
24 #include "audio/audiostream.h"
25 #include "common/config-manager.h"
26 #include "common/system.h"
27
DefaultAudioCDManager()28 DefaultAudioCDManager::DefaultAudioCDManager() {
29 _cd.playing = false;
30 _cd.track = 0;
31 _cd.start = 0;
32 _cd.duration = 0;
33 _cd.numLoops = 0;
34 _cd.volume = Audio::Mixer::kMaxChannelVolume;
35 _cd.balance = 0;
36 _mixer = g_system->getMixer();
37 _emulating = false;
38 assert(_mixer);
39 }
40
~DefaultAudioCDManager()41 DefaultAudioCDManager::~DefaultAudioCDManager() {
42 // Subclasses should call close as well
43 close();
44 }
45
open()46 bool DefaultAudioCDManager::open() {
47 // For emulation, opening is always valid
48 close();
49 return true;
50 }
51
close()52 void DefaultAudioCDManager::close() {
53 // Only need to stop for emulation
54 stop();
55 }
56
play(int track,int numLoops,int startFrame,int duration,bool onlyEmulate,Audio::Mixer::SoundType soundType)57 bool DefaultAudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate,
58 Audio::Mixer::SoundType soundType) {
59 stop();
60
61 if (numLoops != 0 || startFrame != 0) {
62 _cd.track = track;
63 _cd.numLoops = numLoops;
64 _cd.start = startFrame;
65 _cd.duration = duration;
66
67 // Try to load the track from a compressed data file, and if found, use
68 // that. If not found, attempt to start regular Audio CD playback of
69 // the requested track.
70 char trackName[2][16];
71 sprintf(trackName[0], "track%d", track);
72 sprintf(trackName[1], "track%02d", track);
73 Audio::SeekableAudioStream *stream = 0;
74
75 for (int i = 0; !stream && i < 2; ++i)
76 stream = Audio::SeekableAudioStream::openStreamFile(trackName[i]);
77
78 if (stream != 0) {
79 Audio::Timestamp start = Audio::Timestamp(0, startFrame, 75);
80 Audio::Timestamp end = duration ? Audio::Timestamp(0, startFrame + duration, 75) : stream->getLength();
81
82 /*
83 FIXME: Seems numLoops == 0 and numLoops == 1 both indicate a single repetition,
84 while all other positive numbers indicate precisely the number of desired
85 repetitions. Finally, -1 means infinitely many
86 */
87 _emulating = true;
88 _mixer->playStream(soundType, &_handle,
89 Audio::makeLoopingAudioStream(stream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops), -1, _cd.volume, _cd.balance);
90 return true;
91 }
92 }
93
94 return false;
95 }
96
stop()97 void DefaultAudioCDManager::stop() {
98 if (_emulating) {
99 // Audio CD emulation
100 _mixer->stopHandle(_handle);
101 _emulating = false;
102 }
103 }
104
isPlaying() const105 bool DefaultAudioCDManager::isPlaying() const {
106 // Audio CD emulation
107 if (_emulating)
108 return _mixer->isSoundHandleActive(_handle);
109
110 // The default class only handles emulation
111 return false;
112 }
113
setVolume(byte volume)114 void DefaultAudioCDManager::setVolume(byte volume) {
115 _cd.volume = volume;
116
117 // Audio CD emulation
118 if (_emulating && isPlaying())
119 _mixer->setChannelVolume(_handle, _cd.volume);
120 }
121
setBalance(int8 balance)122 void DefaultAudioCDManager::setBalance(int8 balance) {
123 _cd.balance = balance;
124
125 // Audio CD emulation
126 if (_emulating && isPlaying())
127 _mixer->setChannelBalance(_handle, _cd.balance);
128 }
129
update()130 void DefaultAudioCDManager::update() {
131 if (_emulating) {
132 // Check whether the audio track stopped playback
133 if (!_mixer->isSoundHandleActive(_handle)) {
134 // FIXME: We do not update the numLoops parameter here (and in fact,
135 // currently can't do that). Luckily, only one engine ever checks
136 // this part of the AudioCD status, namely the SCUMM engine; and it
137 // only checks whether the track is currently set to infinite looping
138 // or not.
139 _emulating = false;
140 }
141 }
142 }
143
getStatus() const144 DefaultAudioCDManager::Status DefaultAudioCDManager::getStatus() const {
145 Status info = _cd;
146 info.playing = isPlaying();
147 return info;
148 }
149
openRealCD()150 bool DefaultAudioCDManager::openRealCD() {
151 Common::String cdrom = ConfMan.get("cdrom");
152
153 // Try to parse it as an int
154 char *endPos;
155 int drive = strtol(cdrom.c_str(), &endPos, 0);
156
157 // If not an integer, treat as a drive path
158 if (endPos == cdrom.c_str())
159 return openCD(cdrom);
160
161 if (drive < 0)
162 return false;
163
164 return openCD(drive);
165 }
166
167