From: Monty Date: Mon, 23 Jul 2007 20:17:41 +0000 (+0000) Subject: Add ov_fopen() (like ov_open, but does the fopen within libvorbisfile) X-Git-Tag: v1.3.3~319 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6a03c6861f4e455600b2a6ad8fbbc67367309a97;p=platform%2Fupstream%2Flibvorbis.git Add ov_fopen() (like ov_open, but does the fopen within libvorbisfile) and extend ov_open_callbacks() mechanism as means of encouraging use over ov_open(). Use of ov_open() now strongly discouraged under Windows; ov_open_callbacks(fd,vf,NULL,0,OV_CALLBACKS_NOCLOSE) as a direct replacement or ov_fopen() as a convenient substitute. svn path=/trunk/vorbis/; revision=13289 --- diff --git a/examples/seeking_example.c b/examples/seeking_example.c index ca465dd..591a408 100644 --- a/examples/seeking_example.c +++ b/examples/seeking_example.c @@ -37,29 +37,29 @@ void _verify(OggVorbis_File *ov, /* verify the raw position, the pcm position and position decode */ if(val!=-1 && ov_raw_tell(ov)pcmval){ - printf("pcm position out of tolerance: requested %ld, got %ld\n", + fprintf(stderr,"pcm position out of tolerance: requested %ld, got %ld\n", (long)pcmval,(long)ov_pcm_tell(ov)); exit(1); } if(timeval!=-1 && ov_time_tell(ov)>timeval){ - printf("time position out of tolerance: requested %f, got %f\n", + fprintf(stderr,"time position out of tolerance: requested %f, got %f\n", timeval,ov_time_tell(ov)); exit(1); } pos=ov_pcm_tell(ov); if(pos<0 || pos>pcmlength){ - printf("pcm position out of bounds: got %ld\n",(long)pos); + fprintf(stderr,"pcm position out of bounds: got %ld\n",(long)pos); exit(1); } bread=ov_read(ov,buffer,4096,1,1,1,&dummy); for(j=0;jchannels!=2){ - printf("Sorry; right now seeking_test can only use Vorbis files\n" + fprintf(stderr,"Sorry; right now seeking_test can only use Vorbis files\n" "that are entirely stereo.\n\n"); exit(1); } @@ -111,7 +110,6 @@ int main(){ /* because we want to do sample-level verification that the seek does what it claimed, decode the entire file into memory */ - fflush(stdout); pcmlength=ov_pcm_total(&ov,-1); timelength=ov_time_total(&ov,-1); bigassbuffer=malloc(pcmlength*2); /* w00t */ @@ -130,16 +128,15 @@ int main(){ { ogg_int64_t length=ov.end; - printf("\rtesting raw seeking to random places in %ld bytes....\n", + fprintf(stderr,"\rtesting raw seeking to random places in %ld bytes....\n", (long)length); for(i=0;i<1000;i++){ ogg_int64_t val=(double)rand()/RAND_MAX*length; - printf("\r\t%d [raw position %ld]... ",i,(long)val); - fflush(stdout); + fprintf(stderr,"\r\t%d [raw position %ld]... ",i,(long)val); ret=ov_raw_seek(&ov,val); if(ret<0){ - printf("seek failed: %d\n",ret); + fprintf(stderr,"seek failed: %d\n",ret); exit(1); } @@ -148,18 +145,17 @@ int main(){ } } - printf("\r"); + fprintf(stderr,"\r"); { - printf("testing pcm page seeking to random places in %ld samples....\n", + fprintf(stderr,"testing pcm page seeking to random places in %ld samples....\n", (long)pcmlength); for(i=0;i<1000;i++){ ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength; - printf("\r\t%d [pcm position %ld]... ",i,(long)val); - fflush(stdout); + fprintf(stderr,"\r\t%d [pcm position %ld]... ",i,(long)val); ret=ov_pcm_seek_page(&ov,val); if(ret<0){ - printf("seek failed: %d\n",ret); + fprintf(stderr,"seek failed: %d\n",ret); exit(1); } @@ -168,22 +164,21 @@ int main(){ } } - printf("\r"); + fprintf(stderr,"\r"); { - printf("testing pcm exact seeking to random places in %ld samples....\n", + fprintf(stderr,"testing pcm exact seeking to random places in %ld samples....\n", (long)pcmlength); for(i=0;i<1000;i++){ ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength; - printf("\r\t%d [pcm position %ld]... ",i,(long)val); - fflush(stdout); + fprintf(stderr,"\r\t%d [pcm position %ld]... ",i,(long)val); ret=ov_pcm_seek(&ov,val); if(ret<0){ - printf("seek failed: %d\n",ret); + fprintf(stderr,"seek failed: %d\n",ret); exit(1); } if(ov_pcm_tell(&ov)!=val){ - printf("Declared position didn't perfectly match request: %ld != %ld\n", + fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n", (long)val,(long)ov_pcm_tell(&ov)); exit(1); } @@ -193,18 +188,17 @@ int main(){ } } - printf("\r"); + fprintf(stderr,"\r"); { - printf("testing time page seeking to random places in %f seconds....\n", + fprintf(stderr,"testing time page seeking to random places in %f seconds....\n", timelength); for(i=0;i<1000;i++){ double val=(double)rand()/RAND_MAX*timelength; - printf("\r\t%d [time position %f]... ",i,val); - fflush(stdout); + fprintf(stderr,"\r\t%d [time position %f]... ",i,val); ret=ov_time_seek_page(&ov,val); if(ret<0){ - printf("seek failed: %d\n",ret); + fprintf(stderr,"seek failed: %d\n",ret); exit(1); } @@ -213,22 +207,21 @@ int main(){ } } - printf("\r"); + fprintf(stderr,"\r"); { - printf("testing time exact seeking to random places in %f seconds....\n", + fprintf(stderr,"testing time exact seeking to random places in %f seconds....\n", timelength); for(i=0;i<1000;i++){ double val=(double)rand()/RAND_MAX*timelength; - printf("\r\t%d [time position %f]... ",i,val); - fflush(stdout); + fprintf(stderr,"\r\t%d [time position %f]... ",i,val); ret=ov_time_seek(&ov,val); if(ret<0){ - printf("seek failed: %d\n",ret); + fprintf(stderr,"seek failed: %d\n",ret); exit(1); } if(ov_time_tell(&ov)val+1){ - printf("Declared position didn't perfectly match request: %f != %f\n", + fprintf(stderr,"Declared position didn't perfectly match request: %f != %f\n", val,ov_time_tell(&ov)); exit(1); } @@ -238,11 +231,11 @@ int main(){ } } - printf("\r \nOK.\n\n"); + fprintf(stderr,"\r \nOK.\n\n"); }else{ - printf("Standard input was not seekable.\n"); + fprintf(stderr,"Standard input was not seekable.\n"); } ov_clear(&ov); diff --git a/examples/vorbisfile_example.c b/examples/vorbisfile_example.c index 36e679e..1a07010 100644 --- a/examples/vorbisfile_example.c +++ b/examples/vorbisfile_example.c @@ -11,7 +11,7 @@ ******************************************************************** function: simple example decoder using vorbisfile - last mod: $Id: vorbisfile_example.c,v 1.10 2002/07/11 06:40:47 xiphmont Exp $ + last mod: $Id$ ********************************************************************/ @@ -44,7 +44,7 @@ int main(){ _setmode( _fileno( stdout ), _O_BINARY ); #endif - if(ov_open(stdin, &vf, NULL, 0) < 0) { + if(ov_open_callbacks(stdin, &vf, NULL, 0, OV_CALLBACKS_NOCLOSE) < 0) { fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n"); exit(1); } diff --git a/include/vorbis/vorbisfile.h b/include/vorbis/vorbisfile.h index 6592cfe..bac5629 100644 --- a/include/vorbis/vorbisfile.h +++ b/include/vorbis/vorbisfile.h @@ -5,7 +5,7 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 * * by the XIPHOPHORUS Company http://www.xiph.org/ * * * ******************************************************************** @@ -43,6 +43,44 @@ typedef struct { long (*tell_func) (void *datasource); } ov_callbacks; +/* a few sets of convenient callbacks, especially for use under + * Windows where ov_open_callbacks() should always be used instead of + * ov_open() to avoid problems with incompatable crt.o version linking + * issues. */ + +static int _ov_header_fseek_wrap(FILE *f,ogg_int64_t off,int whence){ + if(f==NULL)return(-1); + return fseek(f,off,whence); +} + +static ov_callbacks OV_CALLBACKS_DEFAULT = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) _ov_header_fseek_wrap, + (int (*)(void *)) fclose, + (long (*)(void *)) ftell +}; + +static ov_callbacks OV_CALLBACKS_NOCLOSE = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) _ov_header_fseek_wrap, + (int (*)(void *)) NULL, + (long (*)(void *)) ftell +}; + +static ov_callbacks OV_CALLBACKS_STREAMONLY = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) NULL, + (int (*)(void *)) fclose, + (long (*)(void *)) NULL +}; + +static ov_callbacks OV_CALLBACKS_STREAMONLY_NOCLOSE = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) NULL, + (int (*)(void *)) NULL, + (long (*)(void *)) NULL +}; + #define NOTOPEN 0 #define PARTOPEN 1 #define OPENED 2 @@ -88,6 +126,7 @@ typedef struct OggVorbis_File { extern int ov_clear(OggVorbis_File *vf); +extern int ov_fopen(char *path,OggVorbis_File *vf); extern int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes); extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf, char *initial, long ibytes, ov_callbacks callbacks); diff --git a/lib/vorbisfile.c b/lib/vorbisfile.c index f5710e8..e631aae 100644 --- a/lib/vorbisfile.c +++ b/lib/vorbisfile.c @@ -5,7 +5,7 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 * * by the XIPHOPHORUS Company http://www.xiph.org/ * * * ******************************************************************** @@ -62,6 +62,7 @@ static long _get_data(OggVorbis_File *vf){ errno=0; + if(!(vf->callbacks.read_func))return(-1); if(vf->datasource){ char *buffer=ogg_sync_buffer(&vf->oy,CHUNKSIZE); long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource); @@ -75,7 +76,8 @@ static long _get_data(OggVorbis_File *vf){ /* save a tiny smidge of verbosity to make the code more readable */ static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){ if(vf->datasource){ - if((vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1) + if(!(vf->callbacks.seek_func)|| + (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1) return OV_EREAD; vf->offset=offset; ogg_sync_reset(&vf->oy); @@ -551,8 +553,12 @@ static int _open_seekable2(OggVorbis_File *vf){ /* we're partially open and have a first link header state in storage in vf */ /* we can seek, so set out learning all about this file */ - (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END); - vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource); + if(vf->callbacks.seek_func){ + (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END); + vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource); + }else{ + vf->offset=vf->end=-1; + } /* If seek_func is implemented, tell_func must also be implemented */ if(vf->end==-1) return(OV_EINVAL); @@ -796,7 +802,7 @@ static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial, long ibytes, ov_callbacks callbacks){ - int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1); + int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1); int ret; memset(vf,0,sizeof(*vf)); @@ -873,7 +879,8 @@ int ov_clear(OggVorbis_File *vf){ if(vf->serialnos)_ogg_free(vf->serialnos); if(vf->offsets)_ogg_free(vf->offsets); ogg_sync_clear(&vf->oy); - if(vf->datasource)(vf->callbacks.close_func)(vf->datasource); + if(vf->datasource && vf->callbacks.close_func) + (vf->callbacks.close_func)(vf->datasource); memset(vf,0,sizeof(*vf)); } #ifdef DEBUG_LEAKS @@ -907,6 +914,17 @@ int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){ return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks); } + +int ov_fopen(char *path,OggVorbis_File *vf){ + int ret; + FILE *f = fopen(path,"rb"); + if(!f) return -1; + + ret = ov_open(f,vf,NULL,0); + if(ret) fclose(f); + return ret; +} + /* cheap hack for game usage where downsampling is desirable; there's no need for SRC as we can just do it cheaply in libvorbis. */ @@ -1130,7 +1148,7 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){ vorbis_synthesis_restart(&vf->vd); ret=_seek_helper(vf,pos); - if(ret)return(ret); + if(ret)goto seek_error; /* we need to make sure the pcm_offset is set, but we don't want to advance the raw cursor past good packets just to get to the first