~ubuntu-branches/ubuntu/natty/spring/natty

« back to all changes in this revision

Viewing changes to rts/System/Sound/OggStream.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Ritchie
  • Date: 2010-09-23 18:56:03 UTC
  • mfrom: (3.1.9 experimental)
  • Revision ID: james.westby@ubuntu.com-20100923185603-st97s5chplo42y7w
Tags: 0.82.5.1+dfsg1-1ubuntu1
* Latest upstream version for online play
* debian/control: Replace (rather than conflict) spring-engine
  - spring-engine will be a dummy package (LP: #612905)
  - also set maintainer to MOTU

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
 
2
 
1
3
#include "OggStream.h"
2
4
 
3
5
#include <SDL.h>
7
9
#include "ALShared.h"
8
10
#include "VorbisShared.h"
9
11
 
10
 
namespace
11
 
{
12
 
// 512KB buffer
13
 
const int BUFFER_SIZE = (4096 * 128);
14
 
 
15
 
size_t VorbisStreamRead(void* ptr, size_t size, size_t nmemb, void* datasource)
16
 
{
17
 
        CFileHandler* buffer = (CFileHandler*)datasource;
18
 
        return buffer->Read(ptr, size * nmemb);
19
 
}
20
 
 
21
 
int     VorbisStreamClose(void* datasource)
22
 
{
23
 
        CFileHandler* buffer = (CFileHandler*)datasource;
24
 
        delete buffer;
25
 
        return 0;
26
 
}
27
 
 
28
 
int VorbisStreamSeek(void* datasource, ogg_int64_t offset, int whence)
29
 
{
30
 
        CFileHandler* buffer = (CFileHandler*)datasource;
31
 
        if (whence == SEEK_SET)
32
 
        {
33
 
                buffer->Seek(offset, std::ios_base::beg);
34
 
        }
35
 
        else if (whence == SEEK_CUR)
36
 
        {
37
 
                buffer->Seek(offset, std::ios_base::cur);
38
 
        }
39
 
        else if (whence == SEEK_END)
40
 
        {
41
 
                buffer->Seek(offset, std::ios_base::end);
42
 
        }
43
 
 
44
 
        return 0;
45
 
}
46
 
 
47
 
long VorbisStreamTell(void* datasource)
48
 
{
49
 
        CFileHandler* buffer = (CFileHandler*)datasource;
50
 
        return buffer->GetPos();
51
 
}
52
 
 
53
 
}
 
12
namespace VorbisCallbacks {
 
13
        size_t VorbisStreamRead(void* ptr, size_t size, size_t nmemb, void* datasource)
 
14
        {
 
15
                CFileHandler* buffer = (CFileHandler*)datasource;
 
16
                return buffer->Read(ptr, size * nmemb);
 
17
        }
 
18
 
 
19
        int VorbisStreamClose(void* datasource)
 
20
        {
 
21
                CFileHandler* buffer = (CFileHandler*)datasource;
 
22
                delete buffer;
 
23
                return 0;
 
24
        }
 
25
 
 
26
        int VorbisStreamSeek(void* datasource, ogg_int64_t offset, int whence)
 
27
        {
 
28
                CFileHandler* buffer = (CFileHandler*)datasource;
 
29
                if (whence == SEEK_SET)
 
30
                {
 
31
                        buffer->Seek(offset, std::ios_base::beg);
 
32
                }
 
33
                else if (whence == SEEK_CUR)
 
34
                {
 
35
                        buffer->Seek(offset, std::ios_base::cur);
 
36
                }
 
37
                else if (whence == SEEK_END)
 
38
                {
 
39
                        buffer->Seek(offset, std::ios_base::end);
 
40
                }
 
41
 
 
42
                return 0;
 
43
        }
 
44
 
 
45
        long VorbisStreamTell(void* datasource)
 
46
        {
 
47
                CFileHandler* buffer = (CFileHandler*)datasource;
 
48
                return buffer->GetPos();
 
49
        }
 
50
 
 
51
}
 
52
 
 
53
 
54
54
 
55
55
COggStream::COggStream(ALuint _source)
 
56
        : vorbisInfo(NULL)
 
57
        , source(_source)
 
58
        , format(AL_FORMAT_MONO16)
 
59
        , stopped(true)
 
60
        , paused(false)
 
61
        , msecsPlayed(0)
 
62
        , lastTick(0)
56
63
{
57
 
        source = _source;
58
 
        vorbisInfo = NULL;
59
 
 
60
 
        stopped = true;
61
 
        paused = false;
62
 
        
63
 
        msecsPlayed = 0;
64
 
        lastTick = 0;
 
64
        for (unsigned i = 0; i < NUM_BUFFERS; ++i) {
 
65
                buffers[i] = 0;
 
66
        }
65
67
}
66
68
 
67
69
COggStream::~COggStream()
83
85
        int result = 0;
84
86
 
85
87
        ov_callbacks vorbisCallbacks;
86
 
        vorbisCallbacks.read_func  = VorbisStreamRead;
87
 
        vorbisCallbacks.close_func = VorbisStreamClose;
88
 
        vorbisCallbacks.seek_func  = VorbisStreamSeek;
89
 
        vorbisCallbacks.tell_func  = VorbisStreamTell;
 
88
                vorbisCallbacks.read_func  = VorbisCallbacks::VorbisStreamRead;
 
89
                vorbisCallbacks.close_func = VorbisCallbacks::VorbisStreamClose;
 
90
                vorbisCallbacks.seek_func  = VorbisCallbacks::VorbisStreamSeek;
 
91
                vorbisCallbacks.tell_func  = VorbisCallbacks::VorbisStreamTell;
90
92
 
91
93
        CFileHandler* buf = new CFileHandler(path);
92
94
        if ((result = ov_open_callbacks(buf, &oggStream, NULL, 0, vorbisCallbacks)) < 0) {
94
96
                return;
95
97
        }
96
98
 
 
99
 
97
100
        vorbisInfo = ov_info(&oggStream, -1);
98
101
        {
99
102
                vorbis_comment* vorbisComment;
100
103
                vorbisComment = ov_comment(&oggStream, -1);
101
104
                vorbisTags.resize(vorbisComment->comments);
102
 
                for (unsigned i = 0; i < vorbisComment->comments; ++i)
103
 
                {
 
105
 
 
106
                for (unsigned i = 0; i < vorbisComment->comments; ++i) {
104
107
                        vorbisTags[i] = std::string(vorbisComment->user_comments[i], vorbisComment->comment_lengths[i]);
105
108
                }
 
109
 
106
110
                vendor = std::string(vorbisComment->vendor);
107
 
                //DisplayInfo();
 
111
                // DisplayInfo();
108
112
        }
109
113
 
110
114
        if (vorbisInfo->channels == 1) {
121
125
                stopped = false;
122
126
                paused = false;
123
127
        }
 
128
 
124
129
        CheckError("COggStream");
125
130
}
126
131
 
127
 
float COggStream::GetPlayTime()
 
132
float COggStream::GetPlayTime() const
128
133
{
129
 
        float time = float(msecsPlayed)/1000.0f;
130
 
        return time;
 
134
        return (msecsPlayed / 1000.0f);
131
135
}
132
136
 
133
137
float COggStream::GetTotalTime()
134
138
{
135
 
        double time = ov_time_total(&oggStream,-1);
136
 
        return time;
 
139
        return ov_time_total(&oggStream, -1);
137
140
}
138
141
 
139
 
const COggStream::TagVector& COggStream::VorbisTags()
 
142
const COggStream::TagVector& COggStream::VorbisTags() const
140
143
{
141
144
        return vorbisTags;
142
145
}
173
176
 
174
177
        EmptyBuffers();
175
178
 
176
 
        alDeleteBuffers(2, buffers); CheckError("COggStream");
 
179
        alDeleteBuffers(2, buffers);
 
180
        CheckError("COggStream");
177
181
 
178
182
        ov_clear(&oggStream);
179
183
}
186
190
        msecsPlayed = 0;
187
191
        lastTick = SDL_GetTicks();
188
192
 
189
 
        if (!DecodeStream(buffers[0]))
190
 
                return false;
191
 
 
192
 
        if (!DecodeStream(buffers[1]))
193
 
                return false;
 
193
        if (!DecodeStream(buffers[0])) { return false; }
 
194
        if (!DecodeStream(buffers[1])) { return false; }
194
195
 
195
196
        alSourceQueueBuffers(source, 2, buffers); CheckError("COggStream");
196
197
        alSourcePlay(source); CheckError("COggStream");
211
212
// stops the currently playing stream
212
213
void COggStream::Stop()
213
214
{
214
 
        if (!stopped) {
215
 
                ReleaseBuffers();
216
 
                msecsPlayed = 0;
217
 
                vorbisInfo = NULL;
218
 
                lastTick = SDL_GetTicks();
 
215
        if (stopped) {
 
216
                return;
219
217
        }
 
218
 
 
219
        ReleaseBuffers();
 
220
        msecsPlayed = 0;
 
221
        vorbisInfo = NULL;
 
222
        lastTick = SDL_GetTicks();
220
223
}
221
224
 
222
225
bool COggStream::TogglePause()
224
227
        if (!stopped) {
225
228
                paused = !paused;
226
229
        }
 
230
 
227
231
        return paused;
228
232
}
229
233
 
232
236
// refill them, and push them back in line
233
237
bool COggStream::UpdateBuffers()
234
238
{
235
 
        int processed = 0;
 
239
        int buffersProcessed = 0;
236
240
        bool active = true;
237
241
 
238
 
        alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
 
242
        alGetSourcei(source, AL_BUFFERS_PROCESSED, &buffersProcessed);
239
243
 
240
 
        while (processed-- > 0) {
 
244
        while (buffersProcessed-- > 0) {
241
245
                ALuint buffer;
242
246
                alSourceUnqueueBuffers(source, 1, &buffer); CheckError("COggStream");
243
247
 
253
257
 
254
258
void COggStream::Update()
255
259
{
256
 
        if (!stopped)
257
 
        {
258
 
                unsigned tick = SDL_GetTicks();
259
 
                if (!paused)
260
 
                {
261
 
                        if (UpdateBuffers()) {
262
 
                                if (!IsPlaying()) {
263
 
                                        // source state changed
264
 
                                        if (!StartPlaying()) {
265
 
                                                // stream stopped
266
 
                                                ReleaseBuffers();
267
 
                                        } else {
268
 
                                                // stream interrupted
269
 
                                                ReleaseBuffers();
270
 
                                        }
 
260
        if (stopped) {
 
261
                return;
 
262
        }
 
263
 
 
264
        unsigned tick = SDL_GetTicks();
 
265
 
 
266
        if (!paused) {
 
267
                if (UpdateBuffers()) {
 
268
                        if (!IsPlaying()) {
 
269
                                // source state changed
 
270
                                if (!StartPlaying()) {
 
271
                                        // stream stopped
 
272
                                        ReleaseBuffers();
 
273
                                } else {
 
274
                                        // stream interrupted
 
275
                                        ReleaseBuffers();
271
276
                                }
272
 
                        } else if (!IsPlaying()) {
273
 
                                // EOS and all chunks processed by OpenALs
274
 
                                ReleaseBuffers();
275
277
                        }
276
 
                        msecsPlayed += (tick - lastTick);
 
278
                } else if (!IsPlaying()) {
 
279
                        // EOS and all chunks processed by OpenALs
 
280
                        ReleaseBuffers();
277
281
                }
278
 
                lastTick = tick;
 
282
 
 
283
                msecsPlayed += (tick - lastTick);
279
284
        }
 
285
 
 
286
        lastTick = tick;
280
287
}
281
288
 
282
289
 
316
323
// dequeue any buffers pending on source
317
324
void COggStream::EmptyBuffers()
318
325
{
319
 
        int queued = 0;
320
 
        alGetSourcei(source, AL_BUFFERS_QUEUED, &queued); CheckError("COggStream");
 
326
        int queuedBuffers = 0;
 
327
        alGetSourcei(source, AL_BUFFERS_QUEUED, &queuedBuffers); CheckError("COggStream");
321
328
 
322
 
        while (queued-- > 0) {
 
329
        while (queuedBuffers-- > 0) {
323
330
                ALuint buffer;
324
331
                alSourceUnqueueBuffers(source, 1, &buffer); CheckError("COggStream");
325
332
        }