Skip to content

Latest commit

 

History

History
525 lines (461 loc) · 14.8 KB

music_ogg.c

File metadata and controls

525 lines (461 loc) · 14.8 KB
 
Dec 31, 2011
Dec 31, 2011
2
SDL_mixer: An audio mixer library based on the SDL library
Jan 5, 2019
Jan 5, 2019
3
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Dec 31, 2011
Dec 31, 2011
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
20
21
*/
Oct 17, 2017
Oct 17, 2017
22
#ifdef MUSIC_OGG
23
24
25
/* This file supports Ogg Vorbis music streams */
Oct 17, 2017
Oct 17, 2017
26
#include "SDL_loadso.h"
27
28
29
#include "music_ogg.h"
Oct 28, 2018
Oct 28, 2018
30
#define OV_EXCLUDE_STATIC_CALLBACKS
Oct 17, 2017
Oct 17, 2017
31
32
33
34
35
36
37
38
#if defined(OGG_HEADER)
#include OGG_HEADER
#elif defined(OGG_USE_TREMOR)
#include <tremor/ivorbisfile.h>
#else
#include <vorbis/vorbisfile.h>
#endif
Nov 17, 2019
Nov 17, 2019
39
Oct 17, 2017
Oct 17, 2017
40
41
42
43
44
typedef struct {
int loaded;
void *handle;
int (*ov_clear)(OggVorbis_File *vf);
vorbis_info *(*ov_info)(OggVorbis_File *vf,int link);
Oct 18, 2017
Oct 18, 2017
45
vorbis_comment *(*ov_comment)(OggVorbis_File *vf,int link);
Oct 17, 2017
Oct 17, 2017
46
47
48
49
50
51
52
53
54
55
56
int (*ov_open_callbacks)(void *datasource, OggVorbis_File *vf, const char *initial, long ibytes, ov_callbacks callbacks);
ogg_int64_t (*ov_pcm_total)(OggVorbis_File *vf,int i);
#ifdef OGG_USE_TREMOR
long (*ov_read)(OggVorbis_File *vf,char *buffer,int length, int *bitstream);
#else
long (*ov_read)(OggVorbis_File *vf,char *buffer,int length, int bigendianp,int word,int sgned,int *bitstream);
#endif
#ifdef OGG_USE_TREMOR
int (*ov_time_seek)(OggVorbis_File *vf,ogg_int64_t pos);
#else
int (*ov_time_seek)(OggVorbis_File *vf,double pos);
Dec 17, 2019
Dec 17, 2019
57
58
59
60
61
#endif
#ifdef OGG_USE_TREMOR
ogg_int64_t (*ov_time_total)(OggVorbis_File *vf, int i);
#else
double (*ov_time_total)(OggVorbis_File *vf, int i);
Oct 17, 2017
Oct 17, 2017
62
#endif
Oct 18, 2017
Oct 18, 2017
63
64
int (*ov_pcm_seek)(OggVorbis_File *vf, ogg_int64_t pos);
ogg_int64_t (*ov_pcm_tell)(OggVorbis_File *vf);
Oct 17, 2017
Oct 17, 2017
65
66
67
68
69
70
71
} vorbis_loader;
static vorbis_loader vorbis = {
0, NULL
};
#ifdef OGG_DYNAMIC
Oct 21, 2017
Oct 21, 2017
72
73
74
75
76
77
78
#define FUNCTION_LOADER(FUNC, SIG) \
vorbis.FUNC = (SIG) SDL_LoadFunction(vorbis.handle, #FUNC); \
if (vorbis.FUNC == NULL) { SDL_UnloadObject(vorbis.handle); return -1; }
#else
#define FUNCTION_LOADER(FUNC, SIG) \
vorbis.FUNC = FUNC;
#endif
Oct 17, 2017
Oct 17, 2017
80
static int OGG_Load(void)
Oct 17, 2017
Oct 17, 2017
82
if (vorbis.loaded == 0) {
Oct 21, 2017
Oct 21, 2017
83
#ifdef OGG_DYNAMIC
Oct 17, 2017
Oct 17, 2017
84
85
86
87
vorbis.handle = SDL_LoadObject(OGG_DYNAMIC);
if (vorbis.handle == NULL) {
return -1;
}
Oct 21, 2017
Oct 21, 2017
88
89
90
91
92
93
#elif defined(__MACOSX__)
extern int ov_open_callbacks(void*, OggVorbis_File*, const char*, long, ov_callbacks) __attribute__((weak_import));
if (ov_open_callbacks == NULL)
{
/* Missing weakly linked framework */
Mix_SetError("Missing Vorbis.framework");
Oct 17, 2017
Oct 17, 2017
94
95
return -1;
}
Oct 21, 2017
Oct 21, 2017
96
97
98
99
#endif
FUNCTION_LOADER(ov_clear, int (*)(OggVorbis_File *))
FUNCTION_LOADER(ov_info, vorbis_info *(*)(OggVorbis_File *,int))
FUNCTION_LOADER(ov_comment, vorbis_comment *(*)(OggVorbis_File *,int))
Nov 18, 2019
Nov 18, 2019
100
FUNCTION_LOADER(ov_open_callbacks, int (*)(void *,OggVorbis_File *,const char *,long,ov_callbacks))
Oct 21, 2017
Oct 21, 2017
101
FUNCTION_LOADER(ov_pcm_total, ogg_int64_t (*)(OggVorbis_File *,int))
Oct 17, 2017
Oct 17, 2017
102
#ifdef OGG_USE_TREMOR
Oct 21, 2017
Oct 21, 2017
103
FUNCTION_LOADER(ov_read, long (*)(OggVorbis_File *,char *,int,int *))
Nov 25, 2019
Nov 25, 2019
104
FUNCTION_LOADER(ov_time_seek, int (*)(OggVorbis_File *,ogg_int64_t))
Dec 17, 2019
Dec 17, 2019
105
FUNCTION_LOADER(ov_time_total, ogg_int64_t (*)(OggVorbis_File *, int))
Oct 17, 2017
Oct 17, 2017
106
#else
Oct 21, 2017
Oct 21, 2017
107
108
FUNCTION_LOADER(ov_read, long (*)(OggVorbis_File *,char *,int,int,int,int,int *))
FUNCTION_LOADER(ov_time_seek, int (*)(OggVorbis_File *,double))
Dec 17, 2019
Dec 17, 2019
109
FUNCTION_LOADER(ov_time_total, double (*)(OggVorbis_File *, int))
Oct 17, 2017
Oct 17, 2017
110
#endif
Oct 21, 2017
Oct 21, 2017
111
112
FUNCTION_LOADER(ov_pcm_seek, int (*)(OggVorbis_File *,ogg_int64_t))
FUNCTION_LOADER(ov_pcm_tell, ogg_int64_t (*)(OggVorbis_File *))
Oct 17, 2017
Oct 17, 2017
113
114
115
116
}
++vorbis.loaded;
return 0;
117
118
}
Oct 17, 2017
Oct 17, 2017
119
static void OGG_Unload(void)
Oct 17, 2017
Oct 17, 2017
121
122
123
124
if (vorbis.loaded == 0) {
return;
}
if (vorbis.loaded == 1) {
Oct 21, 2017
Oct 21, 2017
125
#ifdef OGG_DYNAMIC
Oct 17, 2017
Oct 17, 2017
126
SDL_UnloadObject(vorbis.handle);
Oct 21, 2017
Oct 21, 2017
127
#endif
Oct 17, 2017
Oct 17, 2017
128
129
}
--vorbis.loaded;
130
131
}
Oct 17, 2017
Oct 17, 2017
132
133
134
135
typedef struct {
SDL_RWops *src;
int freesrc;
Oct 21, 2017
Oct 21, 2017
136
int play_count;
Oct 17, 2017
Oct 17, 2017
137
138
int volume;
OggVorbis_File vf;
Oct 21, 2017
Oct 21, 2017
139
vorbis_info vi;
Oct 17, 2017
Oct 17, 2017
140
int section;
Oct 21, 2017
Oct 21, 2017
141
142
143
SDL_AudioStream *stream;
char *buffer;
int buffer_size;
Oct 18, 2017
Oct 18, 2017
144
145
146
147
int loop;
ogg_int64_t loop_start;
ogg_int64_t loop_end;
ogg_int64_t loop_len;
Oct 17, 2017
Oct 17, 2017
148
149
} OGG_music;
Oct 21, 2017
Oct 21, 2017
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
static int set_ov_error(const char *function, int error)
{
#define HANDLE_ERROR_CASE(X) case X: Mix_SetError("%s: %s", function, #X); break;
switch (error) {
HANDLE_ERROR_CASE(OV_FALSE);
HANDLE_ERROR_CASE(OV_EOF);
HANDLE_ERROR_CASE(OV_HOLE);
HANDLE_ERROR_CASE(OV_EREAD);
HANDLE_ERROR_CASE(OV_EFAULT);
HANDLE_ERROR_CASE(OV_EIMPL);
HANDLE_ERROR_CASE(OV_EINVAL);
HANDLE_ERROR_CASE(OV_ENOTVORBIS);
HANDLE_ERROR_CASE(OV_EBADHEADER);
HANDLE_ERROR_CASE(OV_EVERSION);
HANDLE_ERROR_CASE(OV_ENOTAUDIO);
HANDLE_ERROR_CASE(OV_EBADPACKET);
HANDLE_ERROR_CASE(OV_EBADLINK);
HANDLE_ERROR_CASE(OV_ENOSEEK);
default:
Mix_SetError("%s: unknown error %d\n", function, error);
break;
}
return -1;
}
Aug 22, 2004
Aug 22, 2004
176
177
178
179
180
static size_t sdl_read_func(void *ptr, size_t size, size_t nmemb, void *datasource)
{
return SDL_RWread((SDL_RWops*)datasource, ptr, size, nmemb);
}
Jul 7, 2014
Jul 7, 2014
181
static int sdl_seek_func(void *datasource, ogg_int64_t offset, int whence)
Aug 22, 2004
Aug 22, 2004
182
{
Jul 7, 2014
Jul 7, 2014
183
return (int)SDL_RWseek((SDL_RWops*)datasource, offset, whence);
Aug 22, 2004
Aug 22, 2004
184
185
}
Jul 7, 2014
Jul 7, 2014
186
static long sdl_tell_func(void *datasource)
Aug 22, 2004
Aug 22, 2004
187
{
Jul 7, 2014
Jul 7, 2014
188
return (long)SDL_RWtell((SDL_RWops*)datasource);
Aug 22, 2004
Aug 22, 2004
189
190
}
Oct 21, 2017
Oct 21, 2017
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
static int OGG_Seek(void *context, double time);
static void OGG_Delete(void *context);
static int OGG_UpdateSection(OGG_music *music)
{
vorbis_info *vi;
vi = vorbis.ov_info(&music->vf, -1);
if (!vi) {
Mix_SetError("ov_info returned NULL");
return -1;
}
if (vi->channels == music->vi.channels && vi->rate == music->vi.rate) {
return 0;
}
SDL_memcpy(&music->vi, vi, sizeof(*vi));
if (music->buffer) {
SDL_free(music->buffer);
music->buffer = NULL;
}
if (music->stream) {
SDL_FreeAudioStream(music->stream);
music->stream = NULL;
}
Nov 17, 2019
Nov 17, 2019
219
music->stream = SDL_NewAudioStream(AUDIO_S16, (Uint8)vi->channels, (int)vi->rate,
Oct 21, 2017
Oct 21, 2017
220
221
222
223
224
music_spec.format, music_spec.channels, music_spec.freq);
if (!music->stream) {
return -1;
}
Nov 17, 2019
Nov 17, 2019
225
226
music->buffer_size = music_spec.samples * (int)sizeof(Sint16) * vi->channels;
music->buffer = (char *)SDL_malloc((size_t)music->buffer_size);
Oct 21, 2017
Oct 21, 2017
227
228
229
230
231
232
if (!music->buffer) {
return -1;
}
return 0;
}
Nov 1, 2019
Nov 1, 2019
233
234
/* Parse time string of the form HH:MM:SS.mmm and return equivalent sample
* position */
Nov 18, 2019
Nov 18, 2019
235
static ogg_int64_t parse_time(char *time, long samplerate_hz)
Nov 1, 2019
Nov 1, 2019
236
237
238
239
240
{
char *num_start, *p;
ogg_int64_t result = 0;
char c;
Nov 10, 2019
Nov 10, 2019
241
242
/* Time is directly expressed as a sample position */
if (SDL_strchr(time, ':') == NULL) {
Nov 17, 2019
Nov 17, 2019
243
return (ogg_int64_t)SDL_strtoull(time, NULL, 10);
Nov 1, 2019
Nov 1, 2019
244
245
246
247
248
}
result = 0;
num_start = time;
Nov 10, 2019
Nov 10, 2019
249
250
for (p = time; *p != '\0'; ++p) {
if (*p == '.' || *p == ':') {
Nov 1, 2019
Nov 1, 2019
251
252
253
254
255
256
c = *p; *p = '\0';
result = result * 60 + SDL_atoi(num_start);
num_start = p + 1;
*p = c;
}
Nov 10, 2019
Nov 10, 2019
257
if (*p == '.') {
Nov 1, 2019
Nov 1, 2019
258
return result * samplerate_hz
Nov 10, 2019
Nov 10, 2019
259
+ (ogg_int64_t) (SDL_atof(p) * samplerate_hz);
Nov 1, 2019
Nov 1, 2019
260
261
262
263
264
265
}
}
return (result * 60 + SDL_atoi(num_start)) * samplerate_hz;
}
Aug 22, 2004
Aug 22, 2004
266
/* Load an OGG stream from an SDL_RWops object */
Oct 17, 2017
Oct 17, 2017
267
static void *OGG_CreateFromRW(SDL_RWops *src, int freesrc)
Aug 22, 2004
Aug 22, 2004
268
{
May 22, 2013
May 22, 2013
269
270
OGG_music *music;
ov_callbacks callbacks;
Oct 21, 2017
Oct 21, 2017
271
vorbis_comment *vc;
Nov 18, 2019
Nov 18, 2019
272
long rate;
Nov 17, 2019
Nov 17, 2019
273
274
ogg_int64_t full_length;
SDL_bool is_loop_length = SDL_FALSE;
Nov 18, 2019
Nov 18, 2019
275
int i;
May 22, 2013
May 22, 2013
276
Oct 21, 2017
Oct 21, 2017
277
278
279
280
281
282
283
284
285
286
287
288
289
290
music = (OGG_music *)SDL_calloc(1, sizeof *music);
if (!music) {
SDL_OutOfMemory();
return NULL;
}
music->src = src;
music->volume = MIX_MAX_VOLUME;
music->section = -1;
music->loop = -1;
music->loop_start = -1;
music->loop_end = 0;
music->loop_len = 0;
SDL_zero(callbacks);
May 22, 2013
May 22, 2013
291
292
293
294
callbacks.read_func = sdl_read_func;
callbacks.seek_func = sdl_seek_func;
callbacks.tell_func = sdl_tell_func;
Oct 21, 2017
Oct 21, 2017
295
296
297
298
299
if (vorbis.ov_open_callbacks(src, &music->vf, NULL, 0, callbacks) < 0) {
SDL_SetError("Not an Ogg Vorbis audio stream");
SDL_free(music);
return NULL;
}
Oct 18, 2017
Oct 18, 2017
300
Oct 21, 2017
Oct 21, 2017
301
302
303
304
if (OGG_UpdateSection(music) < 0) {
OGG_Delete(music);
return NULL;
}
Oct 18, 2017
Oct 18, 2017
305
Oct 21, 2017
Oct 21, 2017
306
vc = vorbis.ov_comment(&music->vf, -1);
Nov 1, 2019
Nov 1, 2019
307
rate = music->vi.rate;
Oct 21, 2017
Oct 21, 2017
308
309
310
311
312
313
314
315
for (i = 0; i < vc->comments; i++) {
char *param = SDL_strdup(vc->user_comments[i]);
char *argument = param;
char *value = SDL_strchr(param, '=');
if (value == NULL) {
value = param + SDL_strlen(param);
} else {
*(value++) = '\0';
Oct 18, 2017
Oct 18, 2017
316
317
}
Nov 1, 2019
Nov 1, 2019
318
319
320
321
322
323
324
/* Want to match LOOP-START, LOOP_START, etc. Remove - or _ from
* string if it is present at position 4. */
if ((argument[4] == '_') || (argument[4] == '-')) {
SDL_memmove(argument + 4, argument + 5, SDL_strlen(argument) - 4);
}
Oct 21, 2017
Oct 21, 2017
325
if (SDL_strcasecmp(argument, "LOOPSTART") == 0)
Nov 1, 2019
Nov 1, 2019
326
music->loop_start = parse_time(value, rate);
Oct 21, 2017
Oct 21, 2017
327
else if (SDL_strcasecmp(argument, "LOOPLENGTH") == 0) {
Nov 17, 2019
Nov 17, 2019
328
music->loop_len = (ogg_int64_t)SDL_strtoull(value, NULL, 10);
Nov 17, 2019
Nov 17, 2019
329
is_loop_length = SDL_TRUE;
Oct 21, 2017
Oct 21, 2017
330
} else if (SDL_strcasecmp(argument, "LOOPEND") == 0) {
Nov 1, 2019
Nov 1, 2019
331
music->loop_end = parse_time(value, rate);
Nov 17, 2019
Nov 17, 2019
332
is_loop_length = SDL_FALSE;
Oct 18, 2017
Oct 18, 2017
333
}
Oct 21, 2017
Oct 21, 2017
334
335
SDL_free(param);
}
Oct 18, 2017
Oct 18, 2017
336
Nov 17, 2019
Nov 17, 2019
337
if (is_loop_length) {
Oct 21, 2017
Oct 21, 2017
338
music->loop_end = music->loop_start + music->loop_len;
May 22, 2013
May 22, 2013
339
} else {
Oct 21, 2017
Oct 21, 2017
340
341
342
music->loop_len = music->loop_end - music->loop_start;
}
Nov 17, 2019
Nov 17, 2019
343
full_length = vorbis.ov_pcm_total(&music->vf, -1);
Oct 21, 2017
Oct 21, 2017
344
345
if (((music->loop_start >= 0) || (music->loop_end > 0)) &&
((music->loop_start < music->loop_end) || (music->loop_end == 0)) &&
Nov 17, 2019
Nov 17, 2019
346
347
(music->loop_start < full_length) &&
(music->loop_end <= full_length)) {
Oct 21, 2017
Oct 21, 2017
348
if (music->loop_start < 0) music->loop_start = 0;
Nov 17, 2019
Nov 17, 2019
349
if (music->loop_end == 0) music->loop_end = full_length;
Oct 21, 2017
Oct 21, 2017
350
music->loop = 1;
May 22, 2013
May 22, 2013
351
}
Oct 21, 2017
Oct 21, 2017
352
353
music->freesrc = freesrc;
Oct 17, 2017
Oct 17, 2017
354
355
356
357
358
359
360
361
return music;
}
/* Set the volume for an OGG stream */
static void OGG_SetVolume(void *context, int volume)
{
OGG_music *music = (OGG_music *)context;
music->volume = volume;
Aug 22, 2004
Aug 22, 2004
362
363
}
364
/* Start playback of a given OGG stream */
Oct 21, 2017
Oct 21, 2017
365
static int OGG_Play(void *context, int play_count)
Oct 17, 2017
Oct 17, 2017
367
OGG_music *music = (OGG_music *)context;
Oct 21, 2017
Oct 21, 2017
368
369
music->play_count = play_count;
return OGG_Seek(music, 0.0);
370
371
}
Oct 21, 2017
Oct 21, 2017
372
373
/* Play some of a stream previously started with OGG_play() */
static int OGG_GetSome(void *context, void *data, int bytes, SDL_bool *done)
Oct 17, 2017
Oct 17, 2017
375
OGG_music *music = (OGG_music *)context;
Oct 21, 2017
Oct 21, 2017
376
377
SDL_bool looped = SDL_FALSE;
int filled, amount, result;
May 22, 2013
May 22, 2013
378
int section;
Oct 18, 2017
Oct 18, 2017
379
ogg_int64_t pcmPos;
Oct 21, 2017
Oct 21, 2017
381
382
383
384
385
386
387
388
389
390
391
392
filled = SDL_AudioStreamGet(music->stream, data, bytes);
if (filled != 0) {
return filled;
}
if (!music->play_count) {
/* All done */
*done = SDL_TRUE;
return 0;
}
section = music->section;
Jul 15, 2007
Jul 15, 2007
393
#ifdef OGG_USE_TREMOR
Oct 21, 2017
Oct 21, 2017
394
amount = vorbis.ov_read(&music->vf, music->buffer, music->buffer_size, &section);
Jul 15, 2007
Jul 15, 2007
395
#else
Oct 21, 2017
Oct 21, 2017
396
amount = (int)vorbis.ov_read(&music->vf, music->buffer, music->buffer_size, 0, 2, 1, &section);
Jul 15, 2007
Jul 15, 2007
397
#endif
Oct 21, 2017
Oct 21, 2017
398
399
400
if (amount < 0) {
set_ov_error("ov_read", amount);
return -1;
Oct 18, 2017
Oct 18, 2017
401
402
}
Oct 21, 2017
Oct 21, 2017
403
404
405
406
if (section != music->section) {
music->section = section;
if (OGG_UpdateSection(music) < 0) {
return -1;
May 22, 2013
May 22, 2013
407
408
409
}
}
Oct 21, 2017
Oct 21, 2017
410
pcmPos = vorbis.ov_pcm_tell(&music->vf);
Nov 26, 2019
Nov 26, 2019
411
if ((music->loop == 1) && (music->play_count != 1) && (pcmPos >= music->loop_end)) {
Nov 18, 2019
Nov 18, 2019
412
amount -= (int)((pcmPos - music->loop_end) * music->vi.channels) * (int)sizeof(Sint16);
Oct 21, 2017
Oct 21, 2017
413
414
415
416
result = vorbis.ov_pcm_seek(&music->vf, music->loop_start);
if (result < 0) {
set_ov_error("ov_pcm_seek", result);
return -1;
Nov 12, 2019
Nov 12, 2019
417
418
419
420
421
422
} else {
int play_count = -1;
if (music->play_count > 0) {
play_count = (music->play_count - 1);
}
music->play_count = play_count;
May 22, 2013
May 22, 2013
423
}
Oct 21, 2017
Oct 21, 2017
424
looped = SDL_TRUE;
May 22, 2013
May 22, 2013
425
}
Oct 21, 2017
Oct 21, 2017
426
427
428
429
430
431
432
433
434
if (amount > 0) {
if (SDL_AudioStreamPut(music->stream, music->buffer, amount) < 0) {
return -1;
}
} else if (!looped) {
if (music->play_count == 1) {
music->play_count = 0;
SDL_AudioStreamFlush(music->stream);
May 22, 2013
May 22, 2013
435
} else {
Oct 21, 2017
Oct 21, 2017
436
437
438
439
440
441
442
int play_count = -1;
if (music->play_count > 0) {
play_count = (music->play_count - 1);
}
if (OGG_Play(music, play_count) < 0) {
return -1;
}
May 22, 2013
May 22, 2013
443
444
}
}
Oct 21, 2017
Oct 21, 2017
445
return 0;
Oct 17, 2017
Oct 17, 2017
447
static int OGG_GetAudio(void *context, void *data, int bytes)
Oct 17, 2017
Oct 17, 2017
449
OGG_music *music = (OGG_music *)context;
Oct 21, 2017
Oct 21, 2017
450
return music_pcm_getaudio(context, data, bytes, music->volume, OGG_GetSome);
451
452
}
Oct 17, 2017
Oct 17, 2017
453
454
455
456
/* Jump (seek) to a given position (time is in seconds) */
static int OGG_Seek(void *context, double time)
{
OGG_music *music = (OGG_music *)context;
Oct 21, 2017
Oct 21, 2017
457
int result;
Oct 17, 2017
Oct 17, 2017
458
#ifdef OGG_USE_TREMOR
Oct 21, 2017
Oct 21, 2017
459
result = vorbis.ov_time_seek(&music->vf, (ogg_int64_t)(time * 1000.0));
Oct 17, 2017
Oct 17, 2017
460
#else
Oct 21, 2017
Oct 21, 2017
461
result = vorbis.ov_time_seek(&music->vf, time);
Oct 17, 2017
Oct 17, 2017
462
#endif
Oct 21, 2017
Oct 21, 2017
463
464
465
if (result < 0) {
return set_ov_error("ov_time_seek", result);
}
Oct 17, 2017
Oct 17, 2017
466
467
468
return 0;
}
Dec 17, 2019
Dec 17, 2019
469
470
471
472
473
474
475
476
477
478
479
/* Return music duration in seconds */
static double OGG_Duration(void *context)
{
OGG_music *music = (OGG_music *)context;
#ifdef OGG_USE_TREMOR
return vorbis.ov_time_total(&music->vf, -1) / 1000.0;
#else
return vorbis.ov_time_total(&music->vf, -1);
#endif
}
480
/* Close the given OGG stream */
Oct 17, 2017
Oct 17, 2017
481
static void OGG_Delete(void *context)
Oct 17, 2017
Oct 17, 2017
483
OGG_music *music = (OGG_music *)context;
Oct 21, 2017
Oct 21, 2017
484
485
486
487
488
489
490
491
492
vorbis.ov_clear(&music->vf);
if (music->stream) {
SDL_FreeAudioStream(music->stream);
}
if (music->buffer) {
SDL_free(music->buffer);
}
if (music->freesrc) {
SDL_RWclose(music->src);
May 22, 2013
May 22, 2013
493
}
Oct 21, 2017
Oct 21, 2017
494
SDL_free(music);
495
496
}
Oct 17, 2017
Oct 17, 2017
497
Mix_MusicInterface Mix_MusicInterface_OGG =
Dec 20, 2001
Dec 20, 2001
498
{
Oct 17, 2017
Oct 17, 2017
499
500
501
502
503
504
505
506
507
508
509
510
"OGG",
MIX_MUSIC_OGG,
MUS_OGG,
SDL_FALSE,
SDL_FALSE,
OGG_Load,
NULL, /* Open */
OGG_CreateFromRW,
NULL, /* CreateFromFile */
OGG_SetVolume,
OGG_Play,
Oct 21, 2017
Oct 21, 2017
511
NULL, /* IsPlaying */
Oct 17, 2017
Oct 17, 2017
512
513
OGG_GetAudio,
OGG_Seek,
Dec 17, 2019
Dec 17, 2019
514
OGG_Duration,
Oct 17, 2017
Oct 17, 2017
515
516
NULL, /* Pause */
NULL, /* Resume */
Oct 21, 2017
Oct 21, 2017
517
NULL, /* Stop */
Oct 17, 2017
Oct 17, 2017
518
519
OGG_Delete,
NULL, /* Close */
Nov 26, 2019
Nov 26, 2019
520
OGG_Unload
Oct 17, 2017
Oct 17, 2017
521
522
523
};
#endif /* MUSIC_OGG */
Dec 20, 2001
Dec 20, 2001
524
Oct 17, 2017
Oct 17, 2017
525
/* vi: set ts=4 sw=4 expandtab: */