Fix crash in seeking_example.
[opusfile.git] / examples / opusfile_example.c
1 /*For fileno()*/
2 #if !defined(_POSIX_SOURCE)
3 # define _POSIX_SOURCE 1
4 #endif
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <errno.h>
8 #include <string.h>
9 #if defined(_WIN32)
10 /*We need the following two to set stdin/stdout to binary.*/
11 # include <io.h>
12 # include <fcntl.h>
13 #endif
14 #include <opusfile.h>
15
16 int main(int _argc,const char **_argv){
17   OggOpusFile *of;
18   ogg_int64_t  pcm_offset;
19   ogg_int64_t  nsamples;
20   int          ret;
21   int          prev_li;
22 #if defined(_WIN32)
23 # undef fileno
24 # define fileno _fileno
25   /*We need to set stdin/stdout to binary mode. Damn windows.*/
26   /*Beware the evil ifdef. We avoid these where we can, but this one we
27      cannot.
28     Don't add any more.
29     You'll probably go to hell if you do.*/
30   _setmode(fileno(stdin),_O_BINARY);
31   _setmode(fileno(stdout),_O_BINARY);
32 #endif
33   if(_argc!=2){
34     fprintf(stderr,"Usage: %s <file.opus>\n",_argv[0]);
35     return EXIT_FAILURE;
36   }
37   if(strcmp(_argv[1],"-")==0){
38     OpusFileCallbacks cb={NULL,NULL,NULL,NULL};
39     of=op_open_callbacks(op_fdopen(&cb,fileno(stdin),"rb"),&cb,NULL,0,&ret);
40   }
41 #if 0
42   /*For debugging: force a file to not be seekable.*/
43   else{
44     OpusFileCallbacks  cb={NULL,NULL,NULL,NULL};
45     void              *fp;
46     fp=op_fopen(&cb,_argv[1],"rb");
47     cb.seek=NULL;
48     cb.tell=NULL;
49     of=op_open_callbacks(fp,&cb,NULL,0,NULL);
50   }
51 #else
52   else of=op_open_file(_argv[1],&ret);
53 #endif
54   if(of==NULL){
55     fprintf(stderr,"Failed to open file '%s': %i\n",_argv[1],ret);
56     return EXIT_FAILURE;
57   }
58   if(op_seekable(of)){
59     ogg_int64_t duration;
60     fprintf(stderr,"Total number of links: %i\n",op_link_count(of));
61     duration=op_pcm_total(of,-1);
62     fprintf(stderr,"Total duration: %f seconds (%li samples @ 48 kHz).\n",
63      duration/48000.0,(long)duration);
64   }
65   prev_li=-1;
66   nsamples=0;
67   pcm_offset=op_pcm_tell(of);
68   if(pcm_offset!=0){
69     fprintf(stderr,"Non-zero starting PCM offset: %li\n",(long)pcm_offset);
70   }
71   for(;;){
72     ogg_int64_t next_pcm_offset;
73     float       pcm[120*48*2];
74     int         li;
75     ret=op_read_float_stereo(of,pcm,sizeof(pcm)/sizeof(*pcm));
76     if(ret<0){
77       fprintf(stderr,"Error decoding '%s': %i\n",_argv[1],ret);
78       ret=EXIT_FAILURE;
79       break;
80     }
81     li=op_current_link(of);
82     if(li!=prev_li){
83       const OpusHead *head;
84       const OpusTags *tags;
85       int             ci;
86       /*We found a new link.
87         Print out some information.*/
88       fprintf(stderr,"Decoding link %i:\n",li);
89       head=op_head(of,li);
90       fprintf(stderr,"  Channels: %i\n",head->channel_count);
91       if(op_seekable(of)){
92         ogg_int64_t duration;
93         duration=op_pcm_total(of,li);
94         fprintf(stderr,"  Duration: %f seconds (%li samples @ 48 kHz).\n",
95          duration/48000.0,(long)duration);
96       }
97       if(head->input_sample_rate){
98         fprintf(stderr,"  Original sampling rate: %lu Hz\n",
99          (unsigned long)head->input_sample_rate);
100       }
101       tags=op_tags(of,li);
102       fprintf(stderr,"  Encoded by: %s\n",tags->vendor);
103       for(ci=0;ci<tags->comments;ci++){
104         fprintf(stderr,"  %s\n",tags->user_comments[ci]);
105       }
106       fprintf(stderr,"\n");
107       if(!op_seekable(of)){
108         pcm_offset=op_pcm_tell(of)-ret;
109         if(pcm_offset!=0){
110           fprintf(stderr,"Non-zero starting PCM offset in link %i: %li\n",
111            li,(long)pcm_offset);
112         }
113       }
114     }
115     next_pcm_offset=op_pcm_tell(of);
116     if(pcm_offset+ret!=next_pcm_offset){
117       fprintf(stderr,"PCM offset gap! %li+%i!=%li\n",
118        (long)pcm_offset,ret,(long)next_pcm_offset);
119     }
120     pcm_offset=next_pcm_offset;
121     if(ret<=0){
122       ret=EXIT_SUCCESS;
123       break;
124     }
125     if(!fwrite(pcm,sizeof(*pcm)*2,ret,stdout)){
126       fprintf(stderr,"Error writing decoded audio data: %s\n",strerror(errno));
127       ret=EXIT_FAILURE;
128       break;
129     }
130     nsamples+=ret;
131     prev_li=li;
132   }
133   op_free(of);
134   if(ret==EXIT_SUCCESS){
135     fprintf(stderr,"Done (played %li samples).\n",(long)nsamples);
136   }
137   return ret;
138 }