ov_open_callbacks doesn't set ass_errno obviously. removed it from the
[laserbrain_demo] / src / audio / ovstream.cc
1 #include <stdio.h>
2 #include <assert.h>
3 #include "assman.h"
4 #include "logger.h"
5 #include "ovstream.h"
6
7 OggVorbisStream::OggVorbisStream()
8 {
9         vfopen = false;
10
11         pthread_mutex_init(&vflock, 0);
12 }
13
14 OggVorbisStream::~OggVorbisStream()
15 {
16         close();
17 }
18
19 static int io_fseek(void *fp, ogg_int64_t offs, int whence)
20 {
21         if(ass_fseek(fp, offs, whence) != -1) {
22                 return 0;
23         }
24         return -1;
25 }
26
27 static int io_close(void *fp)
28 {
29         ass_fclose(fp);
30         return 0;
31 }
32
33
34 bool OggVorbisStream::open(const char *fname)
35 {
36         close();
37
38         pthread_mutex_lock(&vflock);
39
40         ass_file *fp;
41         if(!(fp = ass_fopen(fname, "rb"))) {
42                 error_log("failed to open ogg/vorbis stream: %s: %s\n", fname, strerror(ass_errno));
43                 pthread_mutex_unlock(&vflock);
44                 return false;
45         }
46
47         ov_callbacks iofuncs = { ass_fread, io_fseek, io_close, ass_ftell };
48         if(ov_open_callbacks(fp, &vf, 0, 0, iofuncs) != 0) {
49                 error_log("failed to open ogg/vorbis stream: %s\n", fname);
50                 ass_fclose(fp);
51                 pthread_mutex_unlock(&vflock);
52                 return false;
53         }
54
55         vfopen = true;
56         pthread_mutex_unlock(&vflock);
57         return true;
58 }
59
60 void OggVorbisStream::close()
61 {
62         pthread_mutex_lock(&vflock);
63         if(vfopen) {
64                 ov_clear(&vf);
65                 vfopen = false;
66         }
67         pthread_mutex_unlock(&vflock);
68 }
69
70 void OggVorbisStream::rewind()
71 {
72         pthread_mutex_lock(&vflock);
73         if(vfopen) {
74                 ov_raw_seek(&vf, 0);
75         }
76         pthread_mutex_unlock(&vflock);
77 }
78
79 bool OggVorbisStream::more_samples(AudioStreamBuffer *buf)
80 {
81         pthread_mutex_lock(&vflock);
82
83         vorbis_info *vinfo = ov_info(&vf, -1);
84         buf->channels = vinfo->channels;
85         buf->sample_rate = vinfo->rate;
86         assert(buf->channels == 2);
87         assert(buf->sample_rate == 44100);
88
89         long bufsz = AUDIO_BUFFER_BYTES;
90         long total_read = 0;
91         while(total_read < bufsz) {
92                 int bitstream;
93                 long rd = ov_read(&vf, buf->samples + total_read, bufsz - total_read, 0, 2, 1, &bitstream);
94
95                 if(!rd) {
96                         bufsz = total_read;
97                 } else {
98                         total_read += rd;
99                 }
100         }
101
102         if(!total_read) {
103                 buf->num_samples = 0;
104                 pthread_mutex_unlock(&vflock);
105                 return false;
106         }
107
108         buf->num_samples = bufsz / vinfo->channels / 2;
109         pthread_mutex_unlock(&vflock);
110         return true;
111 }