~ubuntu-branches/ubuntu/raring/libcanberra/raring-proposed

« back to all changes in this revision

Viewing changes to src/read-vorbis.c

  • Committer: Bazaar Package Importer
  • Author(s): Marc-Andre Lureau
  • Date: 2008-06-15 21:33:00 UTC
  • Revision ID: james.westby@ubuntu.com-20080615213300-r1lkzghf3t36idpc
Tags: upstream-0.3
ImportĀ upstreamĀ versionĀ 0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***
 
2
  This file is part of libcanberra.
 
3
 
 
4
  Copyright 2008 Lennart Poettering
 
5
 
 
6
  libcanberra is free software; you can redistribute it and/or modify
 
7
  it under the terms of the GNU Lesser General Public License as
 
8
  published by the Free Software Foundation, either version 2.1 of the
 
9
  License, or (at your option) any later version.
 
10
 
 
11
  libcanberra is distributed in the hope that it will be useful, but
 
12
  WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
14
  Lesser General Public License for more details.
 
15
 
 
16
  You should have received a copy of the GNU Lesser General Public
 
17
  License along with libcanberra. If not, If not, see
 
18
  <http://www.gnu.org/licenses/>.
 
19
***/
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#include <config.h>
 
23
#endif
 
24
 
 
25
#include <vorbis/vorbisfile.h>
 
26
#include <vorbis/codec.h>
 
27
 
 
28
#include "canberra.h"
 
29
#include "read-vorbis.h"
 
30
#include "macro.h"
 
31
#include "malloc.h"
 
32
 
 
33
#define FILE_SIZE_MAX (64U*1024U*1024U)
 
34
 
 
35
struct ca_vorbis {
 
36
    OggVorbis_File ovf;
 
37
    size_t size;
 
38
};
 
39
 
 
40
static int convert_error(int or) {
 
41
    switch (or) {
 
42
        case OV_ENOSEEK:
 
43
        case OV_EBADPACKET:
 
44
        case OV_EBADLINK:
 
45
        case OV_EFAULT:
 
46
        case OV_EREAD:
 
47
        case OV_HOLE:
 
48
            return CA_ERROR_IO;
 
49
 
 
50
        case OV_EIMPL:
 
51
        case OV_EVERSION:
 
52
        case OV_ENOTAUDIO:
 
53
            return CA_ERROR_NOTSUPPORTED;
 
54
 
 
55
        case OV_ENOTVORBIS:
 
56
        case OV_EBADHEADER:
 
57
        case OV_EOF:
 
58
            return CA_ERROR_CORRUPT;
 
59
 
 
60
        case OV_EINVAL:
 
61
            return CA_ERROR_INVALID;
 
62
 
 
63
        default:
 
64
            return CA_ERROR_IO;
 
65
    }
 
66
}
 
67
 
 
68
int ca_vorbis_open(ca_vorbis **_v, FILE *f)  {
 
69
    int ret, or;
 
70
    ca_vorbis *v;
 
71
    int64_t n;
 
72
 
 
73
    ca_return_val_if_fail(_v, CA_ERROR_INVALID);
 
74
    ca_return_val_if_fail(f, CA_ERROR_INVALID);
 
75
 
 
76
    if (!(v = ca_new0(ca_vorbis, 1)))
 
77
        return CA_ERROR_OOM;
 
78
 
 
79
    if ((or = ov_open(f, &v->ovf, NULL, 0)) < 0) {
 
80
        ret = convert_error(or);
 
81
        goto fail;
 
82
    }
 
83
 
 
84
    if ((n = ov_pcm_total(&v->ovf, -1)) < 0) {
 
85
        ret = convert_error(or);
 
86
        ov_clear(&v->ovf);
 
87
        goto fail;
 
88
    }
 
89
 
 
90
    if (n * sizeof(int16_t) > FILE_SIZE_MAX) {
 
91
        ret = CA_ERROR_TOOBIG;
 
92
        ov_clear(&v->ovf);
 
93
        goto fail;
 
94
    }
 
95
 
 
96
    v->size = n * sizeof(int16_t) * ca_vorbis_get_nchannels(v);
 
97
 
 
98
    *_v = v;
 
99
 
 
100
    return CA_SUCCESS;
 
101
 
 
102
fail:
 
103
 
 
104
    ca_free(v);
 
105
    return ret;
 
106
}
 
107
 
 
108
void ca_vorbis_close(ca_vorbis *v) {
 
109
    ca_assert(v);
 
110
 
 
111
    ov_clear(&v->ovf);
 
112
    ca_free(v);
 
113
}
 
114
 
 
115
unsigned ca_vorbis_get_nchannels(ca_vorbis *v) {
 
116
    const vorbis_info *vi;
 
117
    ca_assert(v);
 
118
 
 
119
    ca_assert_se(vi = ov_info(&v->ovf, -1));
 
120
 
 
121
    return vi->channels;
 
122
}
 
123
 
 
124
unsigned ca_vorbis_get_rate(ca_vorbis *v) {
 
125
    const vorbis_info *vi;
 
126
    ca_assert(v);
 
127
 
 
128
    ca_assert_se(vi = ov_info(&v->ovf, -1));
 
129
 
 
130
    return (unsigned) vi->rate;
 
131
}
 
132
 
 
133
int ca_vorbis_read_s16ne(ca_vorbis *v, int16_t *d, unsigned *n){
 
134
    long r;
 
135
    int section;
 
136
    int length;
 
137
    size_t n_read = 0;
 
138
 
 
139
    ca_return_val_if_fail(v, CA_ERROR_INVALID);
 
140
    ca_return_val_if_fail(d, CA_ERROR_INVALID);
 
141
    ca_return_val_if_fail(n, CA_ERROR_INVALID);
 
142
    ca_return_val_if_fail(*n > 0, CA_ERROR_INVALID);
 
143
 
 
144
    length = *n * sizeof(int16_t);
 
145
 
 
146
    do {
 
147
 
 
148
        r = ov_read(&v->ovf, (char*) d, length,
 
149
#ifdef WORDS_BIGENDIAN
 
150
                    1,
 
151
#else
 
152
                    0,
 
153
#endif
 
154
                    2, 1, &section);
 
155
 
 
156
        if (r < 0)
 
157
            return convert_error(r);
 
158
 
 
159
        if (r == 0)
 
160
            break;
 
161
 
 
162
        /* We only read the first section */
 
163
        if (section != 0)
 
164
            break;
 
165
 
 
166
        length -= r;
 
167
        d += r/sizeof(int16_t);
 
168
        n_read += r;
 
169
 
 
170
    } while (length >= 4096);
 
171
 
 
172
    ca_assert(v->size >= n_read);
 
173
    v->size -= n_read;
 
174
 
 
175
    *n = (unsigned) n_read/sizeof(int16_t);
 
176
 
 
177
    return CA_SUCCESS;
 
178
}
 
179
 
 
180
size_t ca_vorbis_get_size(ca_vorbis *v) {
 
181
    ca_return_val_if_fail(v, CA_ERROR_INVALID);
 
182
 
 
183
    return v->size;
 
184
}