source: roaraudio/libroar/file.c @ 1442:24423ef2ecc3

Last change on this file since 1442:24423ef2ecc3 was 1442:24423ef2ecc3, checked in by phi, 15 years ago

only try to link with mmap() if we have a OS supporting it

File size: 7.1 KB
Line 
1//file.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 *  NOTE for everyone want's to change something and send patches:
24 *  read README and HACKING! There a addition information on
25 *  the license of this document you need to read before you send
26 *  any patches.
27 *
28 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
29 *  or libpulse*:
30 *  The libs libroaresd, libroararts and libroarpulse link this lib
31 *  and are therefore GPL. Because of this it may be illigal to use
32 *  them with any software that uses libesd, libartsc or libpulse*.
33 */
34
35#include "libroar.h"
36
37#define BUFSIZE 8192
38#define BUFMAX  65536
39
40int roar_file_codecdetect(char * buf, int len) {
41 int codec = -1;
42
43 if ( len > 3 ) {
44  if ( strncmp(buf, "OggS", 4) == 0 ) {
45   codec = ROAR_CODEC_OGG_GENERAL;
46   if ( len > 32 ) { // this is 5 bytes after the end of the header
47    if ( strncmp(buf+28, "\177FLAC", 5) == 0 ) {
48     codec = ROAR_CODEC_OGG_FLAC;
49    } else if ( strncmp(buf+28, "Speex", 5) == 0 ) {
50     codec = ROAR_CODEC_OGG_SPEEX;
51    } else if ( len > 34 ) { // this is 7 bytes after the end of the header
52     if ( strncmp(buf+28, "\001vorbis", 7) == 0 )
53      codec = ROAR_CODEC_OGG_VORBIS;
54    }
55   }
56  } else if ( strncmp(buf, "MThd", 4) == 0 ) {
57   codec = ROAR_CODEC_MIDI_FILE;
58  } else if ( strncmp(buf, "RIFF", 4) == 0 ) {
59   if ( len > 15 ) {
60    if ( strncmp(buf+8, "WAVEfmt ", 8) == 0 )
61     codec = ROAR_CODEC_RIFF_WAVE;
62   }
63  } else if ( strncmp(buf, "Roar", 4) == 0 ) {
64   if ( len > ROAR_SPEEX_MAGIC_LEN ) {
65    if ( strncmp(buf, ROAR_SPEEX_MAGIC, ROAR_SPEEX_MAGIC_LEN) == 0 )
66     codec = ROAR_CODEC_ROAR_SPEEX;
67#if ROAR_SPEEX_MAGIC_LEN < ROAR_CELT_MAGIC_LEN
68   }
69   if ( len > ROAR_CELT_MAGIC_LEN ) {
70#endif
71    if ( strncmp(buf, ROAR_CELT_MAGIC, ROAR_CELT_MAGIC_LEN) == 0 )
72     codec = ROAR_CODEC_ROAR_CELT;
73   }
74  } else if ( strncmp(buf, "fLaC", 4) == 0 ) {
75   codec = ROAR_CODEC_FLAC;
76  } else if ( len > 7 && strncmp(buf, "RAUM-CF0", 8) == 0 ) {
77   codec = ROAR_CODEC_RAUM;
78  }
79 }
80
81 return codec;
82}
83
84ssize_t roar_file_send_raw (int out, int in) {
85 ssize_t r = 0;
86#ifdef ROAR_HAVE_LINUX_SENDFILE
87 ssize_t ret;
88#endif
89 int len;
90 char buf[BUFSIZE];
91#if defined(__linux__) && defined(ROAR_HAVE_IPV4)
92 int cork_new = 1, cork_old;
93 socklen_t cork_len = sizeof(int);
94
95 if ( getsockopt(out, IPPROTO_TCP, TCP_CORK, &cork_old, &cork_len) == -1 ) {
96  cork_old = -1;
97 } else {
98  setsockopt(out, IPPROTO_TCP, TCP_CORK, &cork_new, sizeof(int));
99 }
100#endif
101
102#ifdef ROAR_HAVE_LINUX_SENDFILE
103 while ((ret = sendfile(out, in, NULL, BUFMAX)) > 0)
104  r += ret;
105#endif
106
107 // TODO: try mmap here!
108
109 while ((len = read(in, buf, BUFSIZE)) > 0)
110  r += write(out, buf, len);
111
112#if defined(__linux__) && defined(ROAR_HAVE_IPV4)
113 if ( cork_old != -1 )
114  setsockopt(out, IPPROTO_TCP, TCP_CORK, &cork_old, cork_len);
115#endif
116 return r;
117}
118
119ssize_t     roar_file_map        (char * filename, int flags, mode_t mode, size_t len, void ** mem) {
120#ifdef ROAR_HAVE_MMAP
121 int fh;
122 int mmap_flags = 0;
123 struct stat stat;
124
125 if ( mem == NULL || filename == NULL )
126  return -1;
127
128 *mem = NULL;
129
130 if ( flags & O_RDWR ) {
131  mmap_flags = PROT_READ|PROT_WRITE;
132 } else if ( flags & O_WRONLY ) {
133  mmap_flags = PROT_WRITE;
134 } else {
135  mmap_flags = PROT_READ;
136 }
137
138 if ( (fh = open(filename, flags, mode)) == -1 ) {
139  return -1;
140 }
141
142 if ( fstat(fh, &stat) == -1 ) {
143  close(fh);
144  return -1;
145 }
146
147 if ( stat.st_size < len ) {
148  if ( ftruncate(fh, len) == -1 ) {
149   close(fh);
150   return -1;
151  }
152 }
153
154 if ( (*mem = mmap(NULL, len, mmap_flags, MAP_SHARED, fh, 0)) == NULL ) {
155  close(fh);
156  return -1;
157 }
158
159 close(fh);
160
161 return len;
162#else
163#ifdef ROAR_TARGET_WIN32
164 ROAR_ERR("roar_file_map(*): There is no support to fast access files via mmap() within win32, download a real OS...");
165#endif
166 return -1;
167#endif
168}
169
170int     roar_file_unmap      (size_t len, void * mem) {
171#ifdef ROAR_HAVE_MMAP
172 return munmap(mem, len);
173#else
174#ifdef ROAR_TARGET_WIN32
175 ROAR_ERR("roar_file_map(*): There is no support to fast access files via mmap() within win32, download a real OS...");
176#endif
177 return -1;
178#endif
179}
180
181
182ssize_t roar_file_play (struct roar_connection * con, char * file, int exec) {
183 return roar_file_play_full(con, file, exec, 0, NULL);
184}
185
186ssize_t roar_file_play_full  (struct roar_connection * con, char * file, int exec, int passfh, struct roar_stream * s) {
187 int codec = -1;
188 int in, out = -1;
189 ssize_t r = 0;
190 int seek;
191 int len;
192 char buf[BUFSIZE];
193 int rate = ROAR_RATE_DEFAULT, channels = ROAR_CHANNELS_DEFAULT, bits = ROAR_BITS_DEFAULT;
194 struct roar_stream localstream[1];
195
196 if ( !s )
197  s = localstream;
198
199 if ( !con )
200  return -1;
201
202 if ( !file )
203  return -1;
204
205 if ( exec && passfh )
206  return -1;
207
208 if ( (in = open(file, O_RDONLY, 0644)) == -1 ) {
209  return -1;
210 }
211
212 if ((len = read(in, buf, BUFSIZE)) < 1) {
213  close(in);
214  return -1;
215 }
216
217 codec = roar_file_codecdetect(buf, len);
218
219 ROAR_DBG("roar_file_play_full(*): codec=%i(%s)", codec, roar_codec2str(codec));
220
221 seek = lseek(in, 0, SEEK_SET) == (off_t) -1 ? 0 : 1;
222
223 if ( codec == -1 ) {
224  close(in);
225  return -1;
226 }
227
228 if ( passfh && !seek ) {
229  ROAR_WARN("roar_file_play_full(*): passfh on non seekable file: this may produce incorrect playback");
230 }
231
232 if ( exec ) {
233  if ( roar_stream_new(s, rate, channels, bits, codec) == -1 ) {
234   close(in);
235   return -1;
236  }
237
238  if ( roar_stream_connect(con, s, ROAR_DIR_PLAY) == -1 ) {
239   close(in);
240   return -1;
241  }
242
243  if ( roar_stream_exec(con, s) == -1 ) {
244   close(in);
245   return -1;
246  }
247
248  shutdown(con->fh, SHUT_RD);
249
250  out = con->fh;
251 } else {
252  if ( !(passfh && seek) ) {
253   if ( (out = roar_simple_new_stream_obj(con, s, rate, channels, bits, codec, ROAR_DIR_PLAY)) == -1 ) {
254    close(in);
255    return -1;
256   }
257  } else {
258   if ( roar_stream_new(s, rate, channels, bits, codec) == -1 ) {
259    close(in);
260    return -1;
261   }
262
263   if ( roar_stream_connect(con, s, ROAR_DIR_PLAY) == -1 ) {
264    close(in);
265    return -1;
266   }
267  }
268 }
269
270 if ( !seek )
271  write(out, buf, len);
272
273 if ( !passfh ) {
274  r = roar_file_send_raw(out, in);
275
276  close(out);
277
278  if ( exec ) {
279   // TODO: FIXME: this ma cause a memory leak in future
280   // OLD: con->fh = -1;
281   roar_connect_fh(con, -2);
282  }
283
284  close(in);
285 } else {
286  if ( roar_stream_passfh(con, s, in) == -1 ) {
287   return -1;
288  }
289  close(out);
290  close(in);
291  return 0;
292 }
293
294 return r;
295}
296
297char  * roar_cdromdevice     (void) {
298 char * k;
299
300 if ( (k = getenv("CDDA_DEVICE")) != NULL )
301  return k;
302
303#ifdef ROAR_DEFAULT_CDROM
304 return ROAR_DEFAULT_CDROM;
305#endif
306
307 return NULL;
308}
309
310//ll
Note: See TracBrowser for help on using the repository browser.