From 22d8fb72d59389301748844be7a93a8b18f0228a Mon Sep 17 00:00:00 2001 From: thor Date: Tue, 19 Sep 2023 14:16:52 +0000 Subject: [PATCH] doc/examples: fix some warnings, add mpg123_to_wav_reader64.c git-svn-id: svn://scm.orgis.org/mpg123/trunk@5331 35dc7657-300d-0410-a2e5-dc2837fedb53 --- doc/Makemodule.am | 1 + doc/examples/Makefile | 4 + doc/examples/extract_frames.c | 15 +- doc/examples/mpg123_to_wav_reader64.c | 203 +++++++++++++++++++++++ doc/examples/mpg123_to_wav_replaced_io.c | 3 +- 5 files changed, 221 insertions(+), 5 deletions(-) create mode 100644 doc/examples/mpg123_to_wav_reader64.c diff --git a/doc/Makemodule.am b/doc/Makemodule.am index 0edcbd15..abdd4981 100644 --- a/doc/Makemodule.am +++ b/doc/Makemodule.am @@ -23,6 +23,7 @@ EXTRA_DIST += \ doc/windows-notes.html \ doc/examples/mpg123_to_out123.c \ doc/examples/mpg123_to_wav_replaced_io.c \ + doc/examples/mpg123_to_wav_reader64.c \ doc/examples/scan.c \ doc/examples/mpglib.c \ doc/examples/id3dump.c \ diff --git a/doc/examples/Makefile b/doc/examples/Makefile index f185c513..44bda594 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -2,6 +2,7 @@ targets = \ feedseek \ mpg123_to_out123 \ mpg123_to_wav_replaced_io \ + mpg123_to_wav_reader64 \ scan \ id3dump \ mpglib \ @@ -40,6 +41,9 @@ mpg123_to_out123: mpg123_to_out123.c mpg123_to_wav_replaced_io: mpg123_to_wav_replaced_io.c $(compile) -o $@ $< $(OUT123_CFLAGS) $(OUT123_LDFLAGS) $(linkflags) +mpg123_to_wav_reader64: mpg123_to_wav_reader64.c + $(compile) -o $@ $< $(OUT123_CFLAGS) $(OUT123_LDFLAGS) $(linkflags) + feedseek: feedseek.c $(compile) -o feedseek feedseek.c $(OUT123_CFLAGS) $(OUT123_LDFLAGS) $(linkflags) diff --git a/doc/examples/extract_frames.c b/doc/examples/extract_frames.c index 6fd523f8..7ec490dd 100644 --- a/doc/examples/extract_frames.c +++ b/doc/examples/extract_frames.c @@ -69,7 +69,8 @@ int do_work(mpg123_handle *m) ret = mpg123_open_fd(m, STDIN_FILENO); if(ret != MPG123_OK) return ret; - while( (ret = mpg123_framebyframe_next(m)) == MPG123_OK || ret == MPG123_NEW_FORMAT ) + ssize_t wret = 0; + while( !wret && (ret = mpg123_framebyframe_next(m)) == MPG123_OK || ret == MPG123_NEW_FORMAT ) { unsigned long header; unsigned char *bodydata; @@ -82,14 +83,20 @@ int do_work(mpg123_handle *m) for(i=0; i<4; ++i) hbuf[i] = (unsigned char) ((header >> ((3-i)*8)) & 0xff); /* Now write out both header and data, fire and forget. */ - write(STDOUT_FILENO, hbuf, 4); - write(STDOUT_FILENO, bodydata, bodybytes); + wret = write(STDOUT_FILENO, hbuf, 4); + if(!wret) + wret = write(STDOUT_FILENO, bodydata, bodybytes); fprintf(stderr, "%zu: header 0x%08lx, %zu body bytes\n", ++count, header, bodybytes); } } if(ret != MPG123_DONE) - fprintf(stderr, "Some error occured (non-fatal?): %s\n", mpg123_strerror(m)); + fprintf(stderr, "Some error occured (non-fatal?): %s\n", mpg123_strerror(m)); + if(wret) + { + fprintf(stderr, "Write error.\n"); + ret = MPG123_ERR; + } fprintf(stderr, "Done with %zu MPEG frames.\n", count); diff --git a/doc/examples/mpg123_to_wav_reader64.c b/doc/examples/mpg123_to_wav_reader64.c new file mode 100644 index 00000000..a8d9d0f4 --- /dev/null +++ b/doc/examples/mpg123_to_wav_reader64.c @@ -0,0 +1,203 @@ +/* + mpg123_to_wav_replaced_io.c + + This is example code only sensible to be considered in the public domain. + Initially written by Nicholas Humfrey (moved to 64 bit handle I/O by Thomas Orgis). + + This example program demonstrates how to use libmpg123 to decode a file to WAV (writing via libsndfile), while doing the I/O (read and seek) with custom callback functions. + This should cater for any situation where you have some special means to get to the data (like, mmapped files / plain buffers in memory, funky network streams). + + Disregarding format negotiations, the basic synopsis is: + + mpg123_init() + mpg123_new() + mpg123_replace_reader_handle() + + mpg123_open_handle() + mpg123_read() + mpg123_close() + + mpg123_delete() + mpg123_exit() +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#else +#include +#endif +#include + +#if MPG123_API_VERSION < 48 +#error "Need minimum mpg123 API version 48." +#endif + + +void usage(const char *cmd) +{ + printf("Usage: %s \n", cmd); + exit(99); +} + +void cleanup(mpg123_handle *mh, out123_handle *ao) +{ + out123_del(ao); + /* It's really to late for error checks here;-) */ + mpg123_close(mh); + mpg123_delete(mh); + mpg123_exit(); +} + +/* Simple handle for you private I/O data. */ +struct ioh { int fd; }; + +/* The callback functions; simple wrappers over standard I/O. + They could be anything you like... */ + +static int read_cb(void *handle, void *buf, size_t sz, size_t *got) +{ + if(!handle) + return -1; + struct ioh *h = handle; + errno = 0; + // Ideally, you check for singnals in here where they should not interrupt + // operations (handle EINTR, for example). + ssize_t gots = read(h->fd, buf, sz); + if(gots < 0) + { + fprintf(stderr, "read error: %s\n", strerror(errno)); + return -1; + } + if(got) + *got = (size_t)gots; + return 0; +} + +// You should be more careful if off_t < int64_t. Ideally, you know +// you have 64 bit I/O. +static int64_t lseek_cb(void *handle, int64_t offset, int whence) +{ + if(!handle) + return -1; + int64_t ret; + struct ioh *h = handle; + ret = (int64_t)lseek(h->fd, (off_t)offset, whence); + if(ret < 0) fprintf(stderr, "seek error: %s\n", strerror(errno)); + + return ret; +} + +/* The cleanup handler is called on mpg123_close(), it can cleanup your part of the mess... */ +void cleanup_cb(void *handle) +{ + if(!handle) + return; + struct ioh *h = handle; + close(h->fd); + h->fd = -1; +} + + +int main(int argc, char *argv[]) +{ + mpg123_handle *mh = NULL; + out123_handle *ao = NULL; + unsigned char* buffer = NULL; + size_t buffer_size = 0; + size_t done = 0; + int channels = 0, encoding = 0; + long rate = 0; + int err = MPG123_OK; + off_t samples = 0; + struct ioh *iohandle; + + if (argc!=3) usage(argv[0]); + printf( "Input file: %s\n", argv[1]); + printf( "Output file: %s\n", argv[2]); + +#if MPG123_API_VERSION < 46 + // Newer versions of the library don't need that anymore, but it is safe + // to have the no-op call present for compatibility with old versions. + err = mpg123_init(); +#endif + + errno = 0; + iohandle = malloc(sizeof(struct ioh)); + iohandle->fd = open(argv[1], O_RDONLY); + if(iohandle->fd < 0) + { + fprintf(stderr, "Cannot open input file (%s).\n", strerror(errno)); + return -1; + } + + if( err != MPG123_OK || (mh = mpg123_new(NULL, &err)) == NULL + /* Let mpg123 work with the file, that excludes MPG123_NEED_MORE messages. */ + || mpg123_reader64(mh, read_cb, lseek_cb, cleanup_cb) != MPG123_OK + || mpg123_open_handle(mh, iohandle) != MPG123_OK + /* Peek into track and get first output format. */ + || mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK ) + { + fprintf( stderr, "Trouble with mpg123: %s\n", + mh==NULL ? mpg123_plain_strerror(err) : mpg123_strerror(mh) ); + cleanup(mh, ao); + return -1; + } + + if(encoding != MPG123_ENC_SIGNED_16) + { /* Signed 16 is the default output format anyways; it would actually by only different if we forced it. + So this check is here just for this explanation. */ + cleanup(mh, ao); + fprintf(stderr, "Bad encoding: 0x%x!\n", encoding); + return -2; + } + /* Ensure that this output format will not change (it could, when we allow it). */ + mpg123_format_none(mh); + mpg123_format(mh, rate, channels, encoding); + + printf("Creating 16bit WAV with %i channels and %liHz.\n", channels, rate); + if( + !(ao = out123_new()) + || out123_open(ao, "wav", argv[2]) + || out123_start(ao, rate, channels, encoding) + ) + { + fprintf(stderr, "Cannot create / start output: %s\n" + , out123_strerror(ao)); + cleanup(mh, ao); + return -1; + } + + /* Buffer could be almost any size here, mpg123_outblock() is just some recommendation. + Important, especially for sndfile writing, is that the size is a multiple of sample size. */ + buffer_size = mpg123_outblock( mh ); + buffer = malloc( buffer_size ); + + do + { + err = mpg123_read( mh, buffer, buffer_size, &done ); + out123_play(ao, buffer, done); + samples += done/sizeof(short); + /* We are not in feeder mode, so MPG123_OK, MPG123_ERR and MPG123_NEW_FORMAT are the only possibilities. + We do not handle a new format, MPG123_DONE is the end... so abort on anything not MPG123_OK. */ + } while (done && err==MPG123_OK); + + free(buffer); + + if(err != MPG123_DONE) + fprintf( stderr, "Warning: Decoding ended prematurely because: %s\n", + err == MPG123_ERR ? mpg123_strerror(mh) : mpg123_plain_strerror(err) ); + + samples /= channels; + printf("%li samples written.\n", (long)samples); + cleanup(mh, ao); + free(iohandle); + return 0; +} diff --git a/doc/examples/mpg123_to_wav_replaced_io.c b/doc/examples/mpg123_to_wav_replaced_io.c index cf5a90c3..75c43b93 100644 --- a/doc/examples/mpg123_to_wav_replaced_io.c +++ b/doc/examples/mpg123_to_wav_replaced_io.c @@ -4,7 +4,7 @@ This is example code only sensible to be considered in the public domain. Initially written by Nicholas Humfrey (moved to handle I/O by Thomas Orgis). - This example program demonstrates how to use libmpg123 to decode a file to WAV (writing via libsndfile), while doing the I/O (read and seek) with custom callback functions. + This example program demonstrates how to use libmpg123 to decode a file to WAV (writing via libout123), while doing the I/O (read and seek) with custom callback functions. This should cater for any situation where you have some special means to get to the data (like, mmapped files / plain buffers in memory, funky network streams). Disregarding format negotiations, the basic synopsis is: @@ -22,6 +22,7 @@ */ #include +#include #include #include #include