xorriso  1.5.4.pl02
About: GNU xorriso creates, loads, manipulates and writes ISO 9660 filesystem images with Rock Ridge extensions. It is suitable for incremental data backup and for production of bootable ISO 9660 images. GNU xorriso is a statical compilation of the libraries libburn, libisofs, libisoburn, and libjte.
  Fossies Dox: xorriso-1.5.4.pl02.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

libdax_audioxtr.c
Go to the documentation of this file.
1 
2 /* libdax_audioxtr
3  Audio track data extraction facility of libdax and libburn.
4  Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
5 */
6 
7 #ifdef HAVE_CONFIG_H
8 #include "../config.h"
9 #endif
10 
11 #include <stdio.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <errno.h>
19 
20 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
21 #ifndef O_BINARY
22 #define O_BINARY 0
23 #endif
24 
25 #include "libdax_msgs.h"
26 extern struct libdax_msgs *libdax_messenger;
27 
28 
29 /* Only this single source module is entitled to do this */
30 #define LIBDAX_AUDIOXTR_H_INTERNAL 1
31 
32 /* All clients of the extraction facility must do this or include libburn.h */
33 #define LIBDAX_AUDIOXTR_H_PUBLIC 1
34 #include "libdax_audioxtr.h"
35 
36 
37 int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag)
38 {
39  int ret= -1;
40  struct libdax_audioxtr *o;
41 
42  o= *xtr= (struct libdax_audioxtr *) calloc(1, sizeof(struct libdax_audioxtr));
43  if(o==NULL)
44  return(-1);
45  strncpy(o->path,path,LIBDAX_AUDIOXTR_STRLEN-1);
46  o->path[LIBDAX_AUDIOXTR_STRLEN-1]= 0;
47  o->fd= -1;
48  strcpy(o->fmt,"unidentified");
49  o->fmt_info[0]= 0;
50  o->data_size= 0;
51  o->extract_count= 0;
52 
53  o->num_channels= 0;
54  o->sample_rate= 0;
55  o->bits_per_sample= 0;
56  o->msb_first= 0;
57 
58  o->wav_data_location= 44;
59  o->wav_subchunk2_size= 0;
60 
61  o->au_data_location= 0;
62  o->au_data_size= 0xffffffff;
63 
64  ret= libdax_audioxtr_open(o,0);
65  if(ret<=0)
66  {ret= -2*(ret<0); goto failure;}
67 
68  return(1);
69 failure:
71  return(ret);
72 }
73 
74 
75 int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag)
76 {
77  struct libdax_audioxtr *o;
78 
79  o= *xtr;
80  if(o==NULL)
81  return(0);
82  if(o->fd>=0 && strcmp(o->path,"-")!=0)
83  close(o->fd);
84  free((char *) o);
85  *xtr= NULL;
86  return(1);
87 }
88 
89 
90 static int libdax_audioxtr_open(struct libdax_audioxtr *o, int flag)
91 {
92  int ret;
93  char msg[LIBDAX_AUDIOXTR_STRLEN+80];
94 
95  if(strcmp(o->path,"-")==0)
96  o->fd= 0;
97  else
98  o->fd= open(o->path, O_RDONLY | O_BINARY);
99  if(o->fd<0) {
100  sprintf(msg,"Cannot open audio source file : %s",o->path);
101  libdax_msgs_submit(libdax_messenger,-1,0x00020200,
103  msg, errno, 0);
104  return(-1);
105  }
106  ret= libdax_audioxtr_identify(o,0);
107  if(ret<=0) {
108  sprintf(msg,"Audio source file has unsuitable format : %s",o->path);
109  libdax_msgs_submit(libdax_messenger,-1,0x00020201,
111  msg, 0, 0);
112  return(0);
113  }
115  if(ret<=0) {
116  sprintf(msg,"Failed to prepare reading of audio data : %s",o->path);
117  libdax_msgs_submit(libdax_messenger,-1,0x00020202,
119  msg, 0, 0);
120  return(0);
121  }
122  return(1);
123 }
124 
125 /* @param flag: bit0= sequential file, skip by reading data
126 */
127 static int libdax_audioxtr_skip(struct libdax_audioxtr *o,
128  off_t *old_pos,
129  off_t pos, int flag)
130 {
131  int ret;
132  size_t to_read;
133  static char buf[256]; /* Thread safe because the content does not matter */
134 
135  if((flag & 1) || o->fd == 0) { /* stdin */
136  while(pos - *old_pos > 0) {
137  to_read= pos - *old_pos;
138  if(to_read > sizeof(buf))
139  to_read= sizeof(buf);
140  ret= read(o->fd, buf, to_read);
141  if(ret < (int) to_read)
142  return(0);
143  *old_pos+= to_read;
144  }
145  } else {
146  ret= lseek(o->fd, pos, SEEK_SET);
147  if(ret == -1)
148  return(0);
149  *old_pos= pos;
150  }
151  return(1);
152 }
153 
154 static int libdax_audioxtr_identify_wav(struct libdax_audioxtr *o, int flag)
155 {
156  int ret, fmt_seen= 0, data_seen= 0;
157  off_t pos= 0, old_pos= 0, riff_end= 0;
158  char buf[16];
159  unsigned char *ubuf;
160 
161  /* check whether this is a MS WAVE file .wav */
162  /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
163  https://en.wikipedia.org/wiki/WAV
164  see summary in: doc/waveformat.txt
165  */
166  ubuf= (unsigned char *) buf;
167 
168  /* Look for ChunkID "RIFF" , tolerate other known chunks */
169  while(1) {
170  ret= libdax_audioxtr_skip(o, &old_pos, pos, 0);
171  if(ret <= 0)
172  return(0);
173  ret= read(o->fd, buf, 8);
174  if(ret < 8)
175  return(0);
176  old_pos+= 8;
177  pos= old_pos + libdax_audioxtr_to_int(o, ubuf + 4, 4, 0);
178  if(pos > 0xffffffff || pos - old_pos < 4) /* Too large or no Format word */
179  return(0);
180  if(strncmp(buf, "RIFF", 4) == 0)
181  break;
182  /* Wikipedia mentions these known ChunkId values */
183  if(strncmp(buf, "INFO", 4) == 0 ||
184  strncmp(buf, "CSET", 4) == 0 ||
185  strncmp(buf, "JUNK", 4) == 0 ||
186  strncmp(buf, "PAD ", 4) == 0)
187  continue;
188  return(0);
189  }
190 
191  /* Read RIFF Format header */
192  ret= read(o->fd, buf, 4);
193  if(ret < 4)
194  return(0);
195  old_pos+= 4;
196  if(strncmp(buf, "WAVE", 4) != 0) /* Format */
197  return(0);
198  riff_end= pos;
199 
200  /* Look for SubchunkID "fmt " and "data" */
201  pos= old_pos;
202  while(old_pos < riff_end) {
203  ret= libdax_audioxtr_skip(o, &old_pos, pos, 0);
204  if(ret <= 0)
205  return(0);
206  ret= read(o->fd, buf, 8);
207  if(ret < 8)
208  return(0);
209  old_pos= pos + 8;
210  pos= old_pos + libdax_audioxtr_to_int(o, ubuf + 4, 4, 0); /* SubchunkSize */
211 
212  if(strncmp(buf,"fmt ", 4) == 0) {
213  if(pos - old_pos < 16)
214  return(0);
215  ret= read(o->fd, buf, 16);
216  if(ret < 16)
217  return(0);
218  old_pos+= 16;
219  if(buf[0]!=1 || buf[1]!=0) /* AudioFormat (1 = Linear quantization) */
220  return(0);
221  o->msb_first= 0;
222  o->num_channels= libdax_audioxtr_to_int(o, ubuf + 2 , 2, 0);
223  o->sample_rate= libdax_audioxtr_to_int(o, ubuf + 4, 4, 0);
224  o->bits_per_sample= libdax_audioxtr_to_int(o, ubuf + 14, 2, 0);
225  sprintf(o->fmt_info,
226  ".wav , num_channels=%d , sample_rate=%d , bits_per_sample=%d",
227  o->num_channels, o->sample_rate, o->bits_per_sample);
228  fmt_seen= 1;
229 
230  } else if(strncmp(buf,"data", 4) == 0) {
231  o->wav_data_location= old_pos;
232  o->wav_subchunk2_size= pos - old_pos;
233  o->data_size= o->wav_subchunk2_size;
234  data_seen= 1;
235  }
236  if(fmt_seen && data_seen) {
237  strcpy(o->fmt,".wav");
238  return(1);
239  }
240  }
241  return(0);
242 }
243 
244 
245 static int libdax_audioxtr_identify_au(struct libdax_audioxtr *o, int flag)
246 {
247  int ret,encoding;
248  char buf[24];
249 
250  /* Check whether this is a Sun Audio, .au file */
251  /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */
252 
253  if(o->fd!=0) {
254  ret= lseek(o->fd,0,SEEK_SET);
255  if(ret==-1)
256  return(0);
257  }
258  ret= read(o->fd, buf, 24);
259  if(ret<24)
260  return(0);
261 
262  if(strncmp(buf,".snd",4)!=0)
263  return(0);
264  strcpy(o->fmt,".au");
265  o->msb_first= 1;
266  o->au_data_location= libdax_audioxtr_to_int(o,(unsigned char *)buf+4,4,1);
267  o->au_data_size= libdax_audioxtr_to_int(o,(unsigned char *)buf+8,4,1);
268  encoding= libdax_audioxtr_to_int(o,(unsigned char *)buf+12,4,1);
269  if(encoding==2)
270  o->bits_per_sample= 8;
271  else if(encoding==3)
272  o->bits_per_sample= 16;
273  else if(encoding==4)
274  o->bits_per_sample= 24;
275  else if(encoding==5)
276  o->bits_per_sample= 32;
277  else
278  o->bits_per_sample= -encoding;
279  o->sample_rate= libdax_audioxtr_to_int(o,(unsigned char *)buf+16,4,1);
280  o->num_channels= libdax_audioxtr_to_int(o,(unsigned char *)buf+20,4,1);
281  if(o->au_data_size!=0xffffffff)
282  o->data_size= o->au_data_size;
283  else
284  o->data_size= 0;
285  sprintf(o->fmt_info,
286  ".au , num_channels=%d , sample_rate=%d , bits_per_sample=%d",
287  o->num_channels,o->sample_rate,o->bits_per_sample);
288  return(o->bits_per_sample>0); /* Audio format must be linear PCM */
289 }
290 
291 
292 static int libdax_audioxtr_identify(struct libdax_audioxtr *o, int flag)
293 {
294  int ret;
295 
296  ret= libdax_audioxtr_identify_wav(o, 0);
297  if(ret!=0)
298  return(ret);
299  if(o->fd==0) /* cannot rewind stdin */
300  return(0);
301  ret= libdax_audioxtr_identify_au(o, 0);
302  if(ret!=0)
303  return(ret);
304  return(0);
305 }
306 
307 
308 /* @param flag bit0=msb_first */
309 static unsigned libdax_audioxtr_to_int(struct libdax_audioxtr *o,
310  unsigned char *bytes, int len, int flag)
311 {
312  unsigned int ret= 0;
313  int i;
314 
315  if(flag&1)
316  for(i= 0; i<len; i++)
317  ret= ret*256+bytes[i];
318  else
319  for(i= len-1; i>=0; i--)
320  ret= ret*256+bytes[i];
321  return(ret);
322 }
323 
324 
325 static int libdax_audioxtr_init_reading(struct libdax_audioxtr *o, int flag)
326 {
327  int ret;
328 
329 
330  /* currently this only works for MS WAVE files .wav and Sun .au*/;
331  if(o->fd==0) /* stdin: hope no read came after libdax_audioxtr_identify() */
332  return(1);
333 
334  o->extract_count= 0;
335  if(strcmp(o->fmt,".wav")==0)
336  ret= lseek(o->fd, o->wav_data_location, SEEK_SET);
337  else if(strcmp(o->fmt,".au")==0)
338  ret= lseek(o->fd,o->au_data_location,SEEK_SET);
339  else
340  ret= -1;
341  if(ret==-1)
342  return(0);
343 
344  return(1);
345 }
346 
347 
348 int libdax_audioxtr_get_id(struct libdax_audioxtr *o,
349  char **fmt, char **fmt_info,
350  int *num_channels, int *sample_rate, int *bits_per_sample,
351  int *msb_first, int flag)
352 {
353  *fmt= o->fmt;
354  *fmt_info= o->fmt_info;
355  *num_channels= o->num_channels;
356  *sample_rate= o->sample_rate;
357  *bits_per_sample= o->bits_per_sample;
358  *msb_first= o->msb_first;
359  return(1);
360 }
361 
362 
363 int libdax_audioxtr_get_size(struct libdax_audioxtr *o, off_t *size, int flag)
364 {
365  *size= o->data_size;
366  return(1);
367 }
368 
369 
370 int libdax_audioxtr_read(struct libdax_audioxtr *o,
371  char buffer[], int buffer_size, int flag)
372 {
373  int ret;
374 
375  if(buffer_size<=0 || o->fd<0)
376  return(-2);
377  if(o->data_size>0 && !(flag&1))
378  if(buffer_size > o->data_size - o->extract_count)
379  buffer_size= o->data_size - o->extract_count;
380  if(buffer_size<=0)
381  return(0);
382  ret= read(o->fd,buffer,buffer_size);
383  if(ret>0)
384  o->extract_count+= ret;
385  return(ret);
386 }
387 
388 
389 int libdax_audioxtr_detach_fd(struct libdax_audioxtr *o, int *fd, int flag)
390 {
391  if(o->fd<0)
392  return(-1);
393  if(strcmp(o->fmt,".wav")!=0 && strcmp(o->fmt,".au")!=0)
394  return(0);
395  if(flag&1) {
396  *fd= o->fd;
397  } else {
398  *fd= dup(o->fd);
399  if(*fd>=0 && strcmp(o->path,"-")!=0)
400  close(o->fd);
401  }
402  if(*fd>=0) {
403  o->fd= -1;
404  return(1);
405  }
406  return(-1);
407 }
408 
#define LIBDAX_AUDIOXTR_STRLEN
Definition: libburn.h:4350
static unsigned libdax_audioxtr_to_int(struct libdax_audioxtr *o, unsigned char *bytes, int len, int flag)
static int libdax_audioxtr_skip(struct libdax_audioxtr *o, off_t *old_pos, off_t pos, int flag)
static int libdax_audioxtr_identify_au(struct libdax_audioxtr *o, int flag)
int libdax_audioxtr_get_size(struct libdax_audioxtr *o, off_t *size, int flag)
#define O_BINARY
static int libdax_audioxtr_identify_wav(struct libdax_audioxtr *o, int flag)
int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag)
int libdax_audioxtr_read(struct libdax_audioxtr *o, char buffer[], int buffer_size, int flag)
struct libdax_msgs * libdax_messenger
Definition: init.c:42
int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag)
static int libdax_audioxtr_open(struct libdax_audioxtr *o, int flag)
static int libdax_audioxtr_identify(struct libdax_audioxtr *o, int flag)
int libdax_audioxtr_get_id(struct libdax_audioxtr *o, char **fmt, char **fmt_info, int *num_channels, int *sample_rate, int *bits_per_sample, int *msb_first, int flag)
int libdax_audioxtr_detach_fd(struct libdax_audioxtr *o, int *fd, int flag)
static int libdax_audioxtr_init_reading(struct libdax_audioxtr *o, int flag)
int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code, int severity, int priority, char *msg_text, int os_errno, int flag)
Definition: libdax_msgs.c:334
#define LIBDAX_MSGS_PRIO_HIGH
Definition: libdax_msgs.h:237
#define LIBDAX_MSGS_SEV_SORRY
Definition: libdax_msgs.h:176