source: roaraudio/libroar/file.c @ 1660:99bfd21f00ef

Last change on this file since 1660:99bfd21f00ef was 1660:99bfd21f00ef, checked in by phi, 15 years ago

changed name of fh in con struct to fh, this should all apps requiring the private member to fail to build, added function to get fh, change code to use them both everythere

File size: 7.4 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
40#ifdef ROAR_HAVE_IO_POSIX
41#define _CAN_OPERATE
42#endif
43
44int roar_file_codecdetect(char * buf, int len) {
45 int codec = -1;
46
47 if ( len > 3 ) {
48  if ( strncmp(buf, "OggS", 4) == 0 ) {
49   codec = ROAR_CODEC_OGG_GENERAL;
50   if ( len > 32 ) { // this is 5 bytes after the end of the header
51    if ( strncmp(buf+28, "\177FLAC", 5) == 0 ) {
52     codec = ROAR_CODEC_OGG_FLAC;
53    } else if ( strncmp(buf+28, "Speex", 5) == 0 ) {
54     codec = ROAR_CODEC_OGG_SPEEX;
55    } else if ( len > 34 ) { // this is 7 bytes after the end of the header
56     if ( strncmp(buf+28, "\001vorbis", 7) == 0 )
57      codec = ROAR_CODEC_OGG_VORBIS;
58    }
59   }
60  } else if ( strncmp(buf, "MThd", 4) == 0 ) {
61   codec = ROAR_CODEC_MIDI_FILE;
62  } else if ( strncmp(buf, "RIFF", 4) == 0 ) {
63   if ( len > 15 ) {
64    if ( strncmp(buf+8, "WAVEfmt ", 8) == 0 )
65     codec = ROAR_CODEC_RIFF_WAVE;
66   }
67  } else if ( strncmp(buf, "Roar", 4) == 0 ) {
68   if ( len > ROAR_SPEEX_MAGIC_LEN ) {
69    if ( strncmp(buf, ROAR_SPEEX_MAGIC, ROAR_SPEEX_MAGIC_LEN) == 0 )
70     codec = ROAR_CODEC_ROAR_SPEEX;
71#if ROAR_SPEEX_MAGIC_LEN < ROAR_CELT_MAGIC_LEN
72   }
73   if ( len > ROAR_CELT_MAGIC_LEN ) {
74#endif
75    if ( strncmp(buf, ROAR_CELT_MAGIC, ROAR_CELT_MAGIC_LEN) == 0 )
76     codec = ROAR_CODEC_ROAR_CELT;
77   }
78  } else if ( strncmp(buf, "fLaC", 4) == 0 ) {
79   codec = ROAR_CODEC_FLAC;
80  } else if ( len > 7 && strncmp(buf, "RAUM-CF0", 8) == 0 ) {
81   codec = ROAR_CODEC_RAUM;
82  }
83 }
84
85 return codec;
86}
87
88ssize_t roar_file_send_raw (int out, int in) {
89#ifdef _CAN_OPERATE
90 ssize_t r = 0;
91#ifdef ROAR_HAVE_LINUX_SENDFILE
92 ssize_t ret;
93#endif
94 int len;
95 char buf[BUFSIZE];
96#if defined(__linux__) && defined(ROAR_HAVE_IPV4)
97 int cork_new = 1, cork_old;
98 socklen_t cork_len = sizeof(int);
99
100 if ( getsockopt(out, IPPROTO_TCP, TCP_CORK, &cork_old, &cork_len) == -1 ) {
101  cork_old = -1;
102 } else {
103  setsockopt(out, IPPROTO_TCP, TCP_CORK, &cork_new, sizeof(int));
104 }
105#endif
106
107#ifdef ROAR_HAVE_LINUX_SENDFILE
108 while ((ret = sendfile(out, in, NULL, BUFMAX)) > 0)
109  r += ret;
110#endif
111
112 // TODO: try mmap here!
113
114 while ((len = read(in, buf, BUFSIZE)) > 0)
115  r += write(out, buf, len);
116
117#if defined(__linux__) && defined(ROAR_HAVE_IPV4)
118 if ( cork_old != -1 )
119  setsockopt(out, IPPROTO_TCP, TCP_CORK, &cork_old, cork_len);
120#endif
121 return r;
122#else
123 return -1;
124#endif
125}
126
127ssize_t     roar_file_map        (char * filename, int flags, mode_t mode, size_t len, void ** mem) {
128#ifdef ROAR_HAVE_MMAP
129 int fh;
130 int mmap_flags = 0;
131 struct stat stat;
132
133 if ( mem == NULL || filename == NULL )
134  return -1;
135
136 *mem = NULL;
137
138 if ( flags & O_RDWR ) {
139  mmap_flags = PROT_READ|PROT_WRITE;
140 } else if ( flags & O_WRONLY ) {
141  mmap_flags = PROT_WRITE;
142 } else {
143  mmap_flags = PROT_READ;
144 }
145
146 if ( (fh = open(filename, flags, mode)) == -1 ) {
147  return -1;
148 }
149
150 if ( fstat(fh, &stat) == -1 ) {
151  close(fh);
152  return -1;
153 }
154
155 if ( stat.st_size < len ) {
156  if ( ftruncate(fh, len) == -1 ) {
157   close(fh);
158   return -1;
159  }
160 }
161
162 if ( (*mem = mmap(NULL, len, mmap_flags, MAP_SHARED, fh, 0)) == NULL ) {
163  close(fh);
164  return -1;
165 }
166
167 close(fh);
168
169 return len;
170#else
171#ifdef ROAR_TARGET_WIN32
172 ROAR_ERR("roar_file_map(*): There is no support to fast access files via mmap() within win32, download a real OS...");
173#endif
174 return -1;
175#endif
176}
177
178int     roar_file_unmap      (size_t len, void * mem) {
179#ifdef ROAR_HAVE_MMAP
180 return munmap(mem, len);
181#else
182#ifdef ROAR_TARGET_WIN32
183 ROAR_ERR("roar_file_map(*): There is no support to fast access files via mmap() within win32, download a real OS...");
184#endif
185 return -1;
186#endif
187}
188
189
190ssize_t roar_file_play (struct roar_connection * con, char * file, int exec) {
191 return roar_file_play_full(con, file, exec, 0, NULL);
192}
193
194ssize_t roar_file_play_full  (struct roar_connection * con, char * file, int exec, int passfh, struct roar_stream * s) {
195#ifdef _CAN_OPERATE
196 int codec = -1;
197 int in, out = -1;
198 ssize_t r = 0;
199 int seek;
200 int len;
201 char buf[BUFSIZE];
202 int rate = ROAR_RATE_DEFAULT, channels = ROAR_CHANNELS_DEFAULT, bits = ROAR_BITS_DEFAULT;
203 struct roar_stream localstream[1];
204
205 // FIXME: check error cases
206
207 if ( !s )
208  s = localstream;
209
210 if ( !con )
211  return -1;
212
213 if ( !file )
214  return -1;
215
216 if ( exec && passfh )
217  return -1;
218
219 if ( (in = open(file, O_RDONLY, 0644)) == -1 ) {
220  return -1;
221 }
222
223 if ((len = read(in, buf, BUFSIZE)) < 1) {
224  close(in);
225  return -1;
226 }
227
228 codec = roar_file_codecdetect(buf, len);
229
230 ROAR_DBG("roar_file_play_full(*): codec=%i(%s)", codec, roar_codec2str(codec));
231
232 seek = lseek(in, 0, SEEK_SET) == (off_t) -1 ? 0 : 1;
233
234 if ( codec == -1 ) {
235  close(in);
236  return -1;
237 }
238
239 if ( passfh && !seek ) {
240  ROAR_WARN("roar_file_play_full(*): passfh on non seekable file: this may produce incorrect playback");
241 }
242
243 if ( exec ) {
244  if ( roar_stream_new(s, rate, channels, bits, codec) == -1 ) {
245   close(in);
246   return -1;
247  }
248
249  if ( roar_stream_connect(con, s, ROAR_DIR_PLAY) == -1 ) {
250   close(in);
251   return -1;
252  }
253
254  if ( roar_stream_exec(con, s) == -1 ) {
255   close(in);
256   return -1;
257  }
258
259  if ( (out = roar_get_connection_fh(con)) == -1 ) {
260   close(in);
261   return -1;
262  }
263
264  ROAR_SHUTDOWN(out, SHUT_RD);
265 } else {
266  if ( !(passfh && seek) ) {
267   if ( (out = roar_simple_new_stream_obj(con, s, rate, channels, bits, codec, ROAR_DIR_PLAY)) == -1 ) {
268    close(in);
269    return -1;
270   }
271  } else {
272   if ( roar_stream_new(s, rate, channels, bits, codec) == -1 ) {
273    close(in);
274    return -1;
275   }
276
277   if ( roar_stream_connect(con, s, ROAR_DIR_PLAY) == -1 ) {
278    close(in);
279    return -1;
280   }
281  }
282 }
283
284 if ( !seek )
285  write(out, buf, len);
286
287 if ( !passfh ) {
288  r = roar_file_send_raw(out, in);
289
290  close(out);
291
292  if ( exec ) {
293   // TODO: FIXME: this ma cause a memory leak in future
294   // OLD: con->fh = -1;
295   roar_connect_fh(con, -2);
296  }
297
298  close(in);
299 } else {
300  if ( roar_stream_passfh(con, s, in) == -1 ) {
301   return -1;
302  }
303  close(out);
304  close(in);
305  return 0;
306 }
307
308 return r;
309#else
310 return -1;
311#endif
312}
313
314char  * roar_cdromdevice     (void) {
315 char * k;
316
317 if ( (k = getenv("CDDA_DEVICE")) != NULL )
318  return k;
319
320#ifdef ROAR_DEFAULT_CDROM
321 return ROAR_DEFAULT_CDROM;
322#endif
323
324 return NULL;
325}
326
327//ll
Note: See TracBrowser for help on using the repository browser.