4 /* all mmq code to read audio files is here */
6 /* we only open one file at a time */
11 /* current (early 2010) Linux doesn't handle POSIX_FADV_NOREUSE */
12 static int force_noreuse
13 #if defined(__linux__)
19 # define SIZE_T_MAX ((size_t)-1)
23 # if defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
24 # define PAGE_SIZE (4096)
26 # define PAGE_SIZE (sysconf(_SC_PAGESIZE))
29 #define PAGE_MASK (~(PAGE_SIZE - 1))
30 #define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
33 * Linux madvise(2) doesn't map exactly to posix_madvise for DONTNEED,
34 * but the difference does not matter for read-only mappings.
37 # define madv_dontneed(addr,len) madvise(addr,len,MADV_DONTNEED)
39 # define madv_dontneed(addr,len) posix_madvise(addr,len,POSIX_MADV_DONTNEED)
42 static void init_readahead(off_t offset
)
44 /* no error checking here, these are only optimizations */
45 (void)posix_fadvise(fd
, offset
, sb
.st_size
, POSIX_FADV_NOREUSE
);
46 (void)posix_fadvise(fd
, offset
, sb
.st_size
, POSIX_FADV_SEQUENTIAL
);
49 int input_open(const char *path
)
52 int flags
= O_RDONLY
| O_NOATIME
;
57 fd
= open(path
, flags
);
59 if (flags
& O_NOATIME
) {
64 } else if (fstat(fd
, &sb
) < 0) {
72 warn("%s: %s\n", err
, strerror(errno
));
78 * this may only be called once per song
79 * mmq will never be able to seek once playback is started
80 * (frontends that want to can implement this feature trivially)
82 off_t
input_seek(off_t offset
, int whence
)
84 off_t off
= lseek(fd
, offset
, whence
);
87 if (errno
!= ESPIPE
) {
88 warn("lseek: %s\n", strerror(errno
));
98 off_t
input_size(void)
101 g_state
= STATE_NEXT
;
106 * FLAC/Tremor currently require a read()-like interface, we use read()
107 * instead of mmap()+memcpy() since setting up and maintaining memory
108 * mappings are still expensive and generally outweigh the cost of the
109 * copying and extra syscalls.
111 ssize_t
input_read(void *buf
, size_t count
)
114 if (likely(g_state
== STATE_PLAY
)) {
115 r
= read(fd
, buf
, count
);
119 warn("read: %s\n", strerror(errno
));
120 g_state
= STATE_NEXT
;
122 } else if (g_state
== STATE_NEXT
) {
125 assert(0 && "unknown g_state, should never get here");
129 * mmap won't work on MMU-less machines since they can't mmap, but since
130 * only MAD uses this for MP3, and MP3s are reasonably small maybe we
131 * could just slurp the whole thing into memory (and refuse to play MP3s
134 /* TODO: seek awareness */
135 void *input_mmap(size_t *size
)
139 /* already mmap-ed, consider this an EOF */
143 length
= PAGE_ALIGN(sb
.st_size
);
144 if (length
> SIZE_T_MAX
) {
145 warn("file too large for mmap\n");
149 mm
= mmap(NULL
, length
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
150 if (mm
== MAP_FAILED
) {
151 warn("mmap: %s\n", strerror(errno
));
156 (void)posix_madvise(mm
, length
, POSIX_MADV_SEQUENTIAL
);
161 g_state
= STATE_NEXT
;
165 void input_close(void)
168 (void)madv_dontneed(mm
, PAGE_ALIGN(sb
.st_size
));
169 if (munmap(mm
, sb
.st_size
) < 0)
170 warn("munmap: %s\n", strerror(errno
));
174 (void)posix_fadvise(fd
, 0, sb
.st_size
, POSIX_FADV_DONTNEED
);
176 warn("close: %s\n", strerror(errno
));