Branch data Line data Source code
1 : : /***
2 : : This file is part of PulseAudio.
3 : :
4 : : Copyright 2004-2006 Lennart Poettering
5 : :
6 : : PulseAudio is free software; you can redistribute it and/or modify
7 : : it under the terms of the GNU Lesser General Public License as published
8 : : by the Free Software Foundation; either version 2.1 of the License,
9 : : or (at your option) any later version.
10 : :
11 : : PulseAudio 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 : : General Public License for more details.
15 : :
16 : : You should have received a copy of the GNU Lesser General Public License
17 : : along with PulseAudio; if not, write to the Free Software
18 : : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 : : USA.
20 : : ***/
21 : :
22 : : #ifdef HAVE_CONFIG_H
23 : : #include <config.h>
24 : : #endif
25 : :
26 : : #include <unistd.h>
27 : : #include <fcntl.h>
28 : : #include <errno.h>
29 : :
30 : : #include <sndfile.h>
31 : :
32 : : #include <pulse/sample.h>
33 : : #include <pulsecore/log.h>
34 : : #include <pulsecore/macro.h>
35 : : #include <pulsecore/core-error.h>
36 : : #include <pulsecore/core-util.h>
37 : : #include <pulsecore/core-scache.h>
38 : : #include <pulsecore/sndfile-util.h>
39 : :
40 : : #include "sound-file.h"
41 : :
42 : 0 : int pa_sound_file_load(
43 : : pa_mempool *pool,
44 : : const char *fname,
45 : : pa_sample_spec *ss,
46 : : pa_channel_map *map,
47 : : pa_memchunk *chunk,
48 : : pa_proplist *p) {
49 : :
50 : 0 : SNDFILE *sf = NULL;
51 : : SF_INFO sfi;
52 : 0 : int ret = -1;
53 : : size_t l;
54 : 0 : sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames) = NULL;
55 : 0 : void *ptr = NULL;
56 : : int fd;
57 : :
58 [ # # ]: 0 : pa_assert(fname);
59 [ # # ]: 0 : pa_assert(ss);
60 [ # # ]: 0 : pa_assert(chunk);
61 : :
62 : 0 : pa_memchunk_reset(chunk);
63 : :
64 [ # # ]: 0 : if ((fd = pa_open_cloexec(fname, O_RDONLY, 0)) < 0) {
65 : 0 : pa_log("Failed to open file %s: %s", fname, pa_cstrerror(errno));
66 : 0 : goto finish;
67 : : }
68 : :
69 : : #ifdef HAVE_POSIX_FADVISE
70 [ # # ]: 0 : if (posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL) < 0) {
71 : 0 : pa_log_warn("POSIX_FADV_SEQUENTIAL failed: %s", pa_cstrerror(errno));
72 : 0 : goto finish;
73 : : } else
74 : 0 : pa_log_debug("POSIX_FADV_SEQUENTIAL succeeded.");
75 : : #endif
76 : :
77 : : pa_zero(sfi);
78 [ # # ]: 0 : if (!(sf = sf_open_fd(fd, SFM_READ, &sfi, 1))) {
79 : 0 : pa_log("Failed to open file %s", fname);
80 : 0 : goto finish;
81 : : }
82 : :
83 : 0 : fd = -1;
84 : :
85 [ # # ]: 0 : if (pa_sndfile_read_sample_spec(sf, ss) < 0) {
86 : 0 : pa_log("Failed to determine file sample format.");
87 : 0 : goto finish;
88 : : }
89 : :
90 [ # # ][ # # ]: 0 : if ((map && pa_sndfile_read_channel_map(sf, map) < 0)) {
91 [ # # ]: 0 : if (ss->channels > 2)
92 : 0 : pa_log("Failed to determine file channel map, synthesizing one.");
93 : 0 : pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
94 : : }
95 : :
96 [ # # ]: 0 : if (p)
97 : 0 : pa_sndfile_init_proplist(sf, p);
98 : :
99 [ # # ]: 0 : if ((l = pa_frame_size(ss) * (size_t) sfi.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
100 : 0 : pa_log("File too large");
101 : 0 : goto finish;
102 : : }
103 : :
104 : 0 : chunk->memblock = pa_memblock_new(pool, l);
105 : 0 : chunk->index = 0;
106 : 0 : chunk->length = l;
107 : :
108 : 0 : readf_function = pa_sndfile_readf_function(ss);
109 : :
110 : 0 : ptr = pa_memblock_acquire(chunk->memblock);
111 : :
112 [ # # ][ # # ]: 0 : if ((readf_function && readf_function(sf, ptr, sfi.frames) != sfi.frames) ||
[ # # ]
113 [ # # ]: 0 : (!readf_function && sf_read_raw(sf, ptr, (sf_count_t) l) != (sf_count_t) l)) {
114 : 0 : pa_log("Premature file end");
115 : 0 : goto finish;
116 : : }
117 : :
118 : : ret = 0;
119 : :
120 : : finish:
121 : :
122 [ # # ]: 0 : if (sf)
123 : 0 : sf_close(sf);
124 : :
125 [ # # ]: 0 : if (ptr)
126 : 0 : pa_memblock_release(chunk->memblock);
127 : :
128 [ # # ][ # # ]: 0 : if (ret != 0 && chunk->memblock)
129 : 0 : pa_memblock_unref(chunk->memblock);
130 : :
131 [ # # ]: 0 : if (fd >= 0)
132 : 0 : pa_close(fd);
133 : :
134 : 0 : return ret;
135 : : }
136 : :
137 : 0 : int pa_sound_file_too_big_to_cache(const char *fname) {
138 : :
139 : 0 : SNDFILE*sf = NULL;
140 : : SF_INFO sfi;
141 : : pa_sample_spec ss;
142 : :
143 [ # # ]: 0 : pa_assert(fname);
144 : :
145 : : pa_zero(sfi);
146 [ # # ]: 0 : if (!(sf = sf_open(fname, SFM_READ, &sfi))) {
147 : 0 : pa_log("Failed to open file %s", fname);
148 : 0 : return -1;
149 : : }
150 : :
151 [ # # ]: 0 : if (pa_sndfile_read_sample_spec(sf, &ss) < 0) {
152 : 0 : pa_log("Failed to determine file sample format.");
153 : 0 : sf_close(sf);
154 : 0 : return -1;
155 : : }
156 : :
157 : 0 : sf_close(sf);
158 : :
159 [ # # ]: 0 : if ((pa_frame_size(&ss) * (size_t) sfi.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
160 : 0 : pa_log("File too large: %s", fname);
161 : 0 : return 1;
162 : : }
163 : :
164 : : return 0;
165 : : }
|