source: roaraudio/libroar/file.c @ 649:0ee35e06288f

Last change on this file since 649:0ee35e06288f was 649:0ee35e06288f, checked in by phi, 16 years ago

added roar_file_map() and roar_file_unmap()

File size: 3.7 KB
Line 
1//file.c:
2
3#include "libroar.h"
4
5#define BUFSIZE 8192
6#define BUFMAX  65536
7
8int roar_file_codecdetect(char * buf, int len) {
9 int codec = -1;
10
11 if ( len > 3 ) {
12  if ( strncmp(buf, "OggS", 4) == 0 ) {
13   codec = ROAR_CODEC_OGG_GENERAL;
14   if ( len > 34 ) { // this is 7 bytes after the end of the header
15    if ( strncmp(buf+28, "\001vorbis", 7) == 0 )
16     codec = ROAR_CODEC_OGG_VORBIS;
17   }
18  } else if ( strncmp(buf, "MThd", 4) == 0 ) {
19   codec = ROAR_CODEC_MIDI_FILE;
20  } else if ( strncmp(buf, "RIFF", 4) == 0 ) {
21   if ( len > 15 ) {
22    if ( strncmp(buf+8, "WAVEfmt ", 8) == 0 )
23     codec = ROAR_CODEC_RIFF_WAVE;
24   }
25  } else if ( strncmp(buf, "Roar", 4) == 0 ) {
26   if ( len > ROAR_SPEEX_MAGIC_LEN ) {
27    if ( strncmp(buf, ROAR_SPEEX_MAGIC, ROAR_SPEEX_MAGIC_LEN) == 0 )
28     codec = ROAR_CODEC_ROAR_SPEEX;
29#if ROAR_SPEEX_MAGIC_LEN < ROAR_CELT_MAGIC_LEN
30   }
31   if ( len > ROAR_CELT_MAGIC_LEN ) {
32#endif
33    if ( strncmp(buf, ROAR_CELT_MAGIC, ROAR_CELT_MAGIC_LEN) == 0 )
34     codec = ROAR_CODEC_ROAR_CELT;
35   }
36  }
37 }
38
39 return codec;
40}
41
42ssize_t roar_file_send_raw (int out, int in) {
43 ssize_t r = 0;
44 ssize_t ret;
45 int len;
46 char buf[BUFSIZE];
47#ifdef __linux__
48 int cork_new = 1, cork_old;
49 socklen_t cork_len = sizeof(int);
50
51 if ( getsockopt(out, IPPROTO_TCP, TCP_CORK, &cork_old, &cork_len) == -1 ) {
52  cork_old = -1;
53 } else {
54  setsockopt(out, IPPROTO_TCP, TCP_CORK, &cork_new, sizeof(int));
55 }
56#endif
57
58#ifdef ROAR_HAVE_LINUX_SENDFILE
59 while ((ret = sendfile(out, in, NULL, BUFMAX)) > 0)
60  r += ret;
61#endif
62
63 // TODO: try mmap here!
64
65 while ((len = read(in, buf, BUFSIZE)) > 0)
66  r += write(out, buf, len);
67
68#ifdef __linux__
69 if ( cork_old != -1 )
70  setsockopt(out, IPPROTO_TCP, TCP_CORK, &cork_old, cork_len);
71#endif
72 return r;
73}
74
75ssize_t     roar_file_map        (char * filename, int flags, mode_t mode, size_t len, void ** mem) {
76 int fh;
77 int mmap_flags = 0;
78 struct stat stat;
79
80 if ( mem == NULL || filename == NULL )
81  return -1;
82
83 *mem = NULL;
84
85 if ( flags & O_RDWR ) {
86  mmap_flags = PROT_READ|PROT_WRITE;
87 } else if ( flags & O_WRONLY ) {
88  mmap_flags = PROT_WRITE;
89 } else {
90  mmap_flags = PROT_READ;
91 }
92
93 if ( (fh = open(filename, flags, mode)) == -1 ) {
94  return -1;
95 }
96
97 if ( fstat(fh, &stat) == -1 ) {
98  close(fh);
99  return -1;
100 }
101
102 if ( stat.st_size < len ) {
103  if ( ftruncate(fh, len) == -1 ) {
104   close(fh);
105   return -1;
106  }
107 }
108
109 if ( (*mem = mmap(NULL, len, mmap_flags, MAP_SHARED, fh, 0)) == NULL ) {
110  close(fh);
111  return -1;
112 }
113
114 close(fh);
115
116 return len;
117}
118
119int     roar_file_unmap      (size_t len, void * mem) {
120 return munmap(mem, len);
121}
122
123
124ssize_t roar_file_play (struct roar_connection * con, char * file, int exec) {
125 int codec = -1;
126 int in, out = -1;
127 struct roar_stream s;
128 ssize_t r = 0;
129 int len;
130 char buf[BUFSIZE];
131 int rate = ROAR_RATE_DEFAULT, channels = ROAR_CHANNELS_DEFAULT, bits = ROAR_BITS_DEFAULT;
132
133 if ( !con )
134  return -1;
135
136 if ( !file )
137  return -1;
138
139 if ( (in = open(file, O_RDONLY, 0644)) == -1 ) {
140  return -1;
141 }
142
143 if ((len = read(in, buf, BUFSIZE)) < 1) {
144  close(in);
145  return -1;
146 }
147
148 codec = roar_file_codecdetect(buf, len);
149
150 if ( codec == -1 ) {
151  close(in);
152  return -1;
153 }
154
155 if ( exec ) {
156  if ( roar_stream_new(&s, rate, channels, bits, codec) == -1 ) {
157   close(in);
158   return -1;
159  }
160
161  if ( roar_stream_connect(con, &s, ROAR_DIR_PLAY) == -1 ) {
162   close(in);
163   return -1;
164  }
165
166  if ( roar_stream_exec(con, &s) == -1 ) {
167   close(in);
168   return -1;
169  }
170
171  shutdown(con->fh, SHUT_RD);
172
173  out = con->fh;
174 } else {
175  if ( (out = roar_simple_new_stream(con, rate, channels, bits, codec, ROAR_DIR_PLAY)) == -1 ) {
176   close(in);
177   return -1;
178  }
179 }
180
181 write(out, buf, len);
182
183 r = roar_file_send_raw(out, in);
184
185 close(out);
186
187 if ( exec ) {
188  con->fh = -1;
189 }
190
191 close(in);
192
193 return r;
194}
195
196//ll
Note: See TracBrowser for help on using the repository browser.