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
RevLine 
[202]1//file.c:
2
[690]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
[202]35#include "libroar.h"
36
[208]37#define BUFSIZE 8192
38#define BUFMAX  65536
39
[215]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;
[1000]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    }
[215]55   }
[558]56  } else if ( strncmp(buf, "MThd", 4) == 0 ) {
57   codec = ROAR_CODEC_MIDI_FILE;
[563]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   }
[623]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;
[636]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;
[623]73   }
[1196]74  } else if ( strncmp(buf, "fLaC", 4) == 0 ) {
75   codec = ROAR_CODEC_FLAC;
76  } else if ( len > 7 && strncmp(buf, "RAUM-CF0", 8) == 0 ) {
[889]77   codec = ROAR_CODEC_RAUM;
[215]78  }
79 }
80
81 return codec;
82}
83
[208]84ssize_t roar_file_send_raw (int out, int in) {
85 ssize_t r = 0;
[701]86#ifdef ROAR_HAVE_LINUX_SENDFILE
[208]87 ssize_t ret;
[701]88#endif
[208]89 int len;
90 char buf[BUFSIZE];
[1378]91#if defined(__linux__) && defined(ROAR_HAVE_IPV4)
[217]92 int cork_new = 1, cork_old;
93 socklen_t cork_len = sizeof(int);
94
[219]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 }
[217]100#endif
[208]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
[1379]112#if defined(__linux__) && defined(ROAR_HAVE_IPV4)
[219]113 if ( cork_old != -1 )
114  setsockopt(out, IPPROTO_TCP, TCP_CORK, &cork_old, cork_len);
[217]115#endif
[208]116 return r;
117}
118
[649]119ssize_t     roar_file_map        (char * filename, int flags, mode_t mode, size_t len, void ** mem) {
[1442]120#ifdef ROAR_HAVE_MMAP
[649]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;
[1081]162#else
[1442]163#ifdef ROAR_TARGET_WIN32
[1081]164 ROAR_ERR("roar_file_map(*): There is no support to fast access files via mmap() within win32, download a real OS...");
[1442]165#endif
[1081]166 return -1;
167#endif
[649]168}
169
170int     roar_file_unmap      (size_t len, void * mem) {
[1442]171#ifdef ROAR_HAVE_MMAP
[649]172 return munmap(mem, len);
[1081]173#else
[1442]174#ifdef ROAR_TARGET_WIN32
[1081]175 ROAR_ERR("roar_file_map(*): There is no support to fast access files via mmap() within win32, download a real OS...");
[1442]176#endif
[1081]177 return -1;
178#endif
[649]179}
180
181
[215]182ssize_t roar_file_play (struct roar_connection * con, char * file, int exec) {
[764]183 return roar_file_play_full(con, file, exec, 0, NULL);
[762]184}
185
186ssize_t roar_file_play_full  (struct roar_connection * con, char * file, int exec, int passfh, struct roar_stream * s) {
[215]187 int codec = -1;
188 int in, out = -1;
189 ssize_t r = 0;
[776]190 int seek;
[215]191 int len;
192 char buf[BUFSIZE];
193 int rate = ROAR_RATE_DEFAULT, channels = ROAR_CHANNELS_DEFAULT, bits = ROAR_BITS_DEFAULT;
[764]194 struct roar_stream localstream[1];
195
196 if ( !s )
197  s = localstream;
[215]198
199 if ( !con )
200  return -1;
201
202 if ( !file )
203  return -1;
204
[762]205 if ( exec && passfh )
206  return -1;
207
[215]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
[1000]219 ROAR_DBG("roar_file_play_full(*): codec=%i(%s)", codec, roar_codec2str(codec));
220
[776]221 seek = lseek(in, 0, SEEK_SET) == (off_t) -1 ? 0 : 1;
222
[215]223 if ( codec == -1 ) {
224  close(in);
225  return -1;
226 }
227
[776]228 if ( passfh && !seek ) {
229  ROAR_WARN("roar_file_play_full(*): passfh on non seekable file: this may produce incorrect playback");
230 }
231
[215]232 if ( exec ) {
[762]233  if ( roar_stream_new(s, rate, channels, bits, codec) == -1 ) {
[215]234   close(in);
235   return -1;
236  }
237
[762]238  if ( roar_stream_connect(con, s, ROAR_DIR_PLAY) == -1 ) {
[215]239   close(in);
240   return -1;
241  }
242
[762]243  if ( roar_stream_exec(con, s) == -1 ) {
[215]244   close(in);
245   return -1;
246  }
247
248  shutdown(con->fh, SHUT_RD);
249
250  out = con->fh;
251 } else {
[776]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   }
[215]267  }
268 }
269
[776]270 if ( !seek )
271  write(out, buf, len);
[215]272
[762]273 if ( !passfh ) {
274  r = roar_file_send_raw(out, in);
[215]275
[762]276  close(out);
277
278  if ( exec ) {
[1315]279   // TODO: FIXME: this ma cause a memory leak in future
280   // OLD: con->fh = -1;
281   roar_connect_fh(con, -2);
[762]282  }
[215]283
[762]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;
[215]292 }
293
294 return r;
295}
296
[805]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
[202]310//ll
Note: See TracBrowser for help on using the repository browser.