Blame doc/examples/mpg123_to_out123.c

Packit c32a2d
/*
Packit c32a2d
	mpg123_to_wav.c
Packit c32a2d
Packit c32a2d
	copyright 2007-2016 by the mpg123 project - free software under the terms of the LGPL 2.1
Packit c32a2d
	see COPYING and AUTHORS files in distribution or http://mpg123.org
Packit c32a2d
	initially written by Nicholas Humfrey
Packit c32a2d
Packit c32a2d
	The most complicated part is about the choices to make about output format,
Packit c32a2d
	and prepare for the unlikely case a bastard mp3 might file change it.
Packit c32a2d
*/
Packit c32a2d
Packit c32a2d
#include <out123.h>
Packit c32a2d
#include <mpg123.h>
Packit c32a2d
#include <stdio.h>
Packit c32a2d
#include <strings.h>
Packit c32a2d
Packit c32a2d
void usage(const char *cmd)
Packit c32a2d
{
Packit c32a2d
	printf("Usage: %s <input> [<driver> [<output> [encoding [buffersize]]]]\n"
Packit c32a2d
	,	cmd);
Packit c32a2d
	printf( "\nPlay MPEG audio from intput file to output file/device using\n"
Packit c32a2d
		"specified out123 driver, sample encoding and buffer size optional.\n\n" );
Packit c32a2d
	exit(99);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void cleanup(mpg123_handle *mh, out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	out123_del(ao);
Packit c32a2d
	/* It's really to late for error checks here;-) */
Packit c32a2d
	mpg123_close(mh);
Packit c32a2d
	mpg123_delete(mh);
Packit c32a2d
	mpg123_exit();
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
int main(int argc, char *argv[])
Packit c32a2d
{
Packit c32a2d
	mpg123_handle *mh = NULL;
Packit c32a2d
	out123_handle *ao = NULL;
Packit c32a2d
	char *infile = NULL;
Packit c32a2d
	char *driver = NULL;
Packit c32a2d
	char *outfile = NULL;
Packit c32a2d
	unsigned char* buffer = NULL;
Packit c32a2d
	const char *encname;
Packit c32a2d
	size_t buffer_size = 0;
Packit c32a2d
	size_t done = 0;
Packit c32a2d
	int channels = 0;
Packit c32a2d
	int encoding = 0;
Packit c32a2d
	int framesize = 1;
Packit c32a2d
	long rate = 0;
Packit c32a2d
	int  err  = MPG123_OK;
Packit c32a2d
	off_t samples = 0;
Packit c32a2d
Packit c32a2d
	if(argc<2)
Packit c32a2d
		usage(argv[0]);
Packit c32a2d
Packit c32a2d
	infile  = argv[1];
Packit c32a2d
	if(argc >= 3)
Packit c32a2d
		driver  = argv[2];
Packit c32a2d
	if(argc >= 4)
Packit c32a2d
		outfile = argv[3];
Packit c32a2d
	printf("Input file:    %s\n", infile);
Packit c32a2d
	printf("Output driver: %s\n", driver ? driver : "<nil> (default)");
Packit c32a2d
	printf("Output file:   %s\n", outfile ? outfile : "<nil> (default)");
Packit c32a2d
Packit c32a2d
	err = mpg123_init();
Packit c32a2d
	if(err != MPG123_OK || (mh = mpg123_new(NULL, &err)) == NULL)
Packit c32a2d
	{
Packit c32a2d
		fprintf(stderr, "Basic setup goes wrong: %s", mpg123_plain_strerror(err));
Packit c32a2d
		cleanup(mh, ao);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	ao = out123_new();
Packit c32a2d
	if(!ao)
Packit c32a2d
	{
Packit c32a2d
		fprintf(stderr, "Cannot create output handle.\n");
Packit c32a2d
		cleanup(mh, ao);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	if(argc >= 5)
Packit c32a2d
	{ /* Make mpg123 support the desired encoding only for all rates. */
Packit c32a2d
		const long *rates;
Packit c32a2d
		size_t rate_count;
Packit c32a2d
		size_t i;
Packit c32a2d
		int enc;
Packit c32a2d
		/* If that is zero, you'll get the error soon enough from mpg123. */
Packit c32a2d
		enc = out123_enc_byname(argv[4]);
Packit c32a2d
		mpg123_format_none(mh);
Packit c32a2d
		mpg123_rates(&rates, &rate_count);
Packit c32a2d
		for(i=0; i
Packit c32a2d
			mpg123_format(mh, rates[i], MPG123_MONO|MPG123_STEREO, enc);
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Let mpg123 work with the file, that excludes MPG123_NEED_MORE messages. */
Packit c32a2d
	if(    mpg123_open(mh, infile) != MPG123_OK
Packit c32a2d
	/* Peek into track and get first output format. */
Packit c32a2d
	    || mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK )
Packit c32a2d
	{
Packit c32a2d
		fprintf( stderr, "Trouble with mpg123: %s\n", mpg123_strerror(mh) );
Packit c32a2d
		cleanup(mh, ao);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
	if(out123_open(ao, driver, outfile) != OUT123_OK)
Packit c32a2d
	{
Packit c32a2d
		fprintf(stderr, "Trouble with out123: %s\n", out123_strerror(ao));
Packit c32a2d
		cleanup(mh, ao);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
	/* It makes no sense for that to give an error now. */
Packit c32a2d
	out123_driver_info(ao, &driver, &outfile);
Packit c32a2d
	printf("Effective output driver: %s\n", driver ? driver : "<nil> (default)");
Packit c32a2d
	printf("Effective output file:   %s\n", outfile ? outfile : "<nil> (default)");
Packit c32a2d
Packit c32a2d
	/* Ensure that this output format will not change
Packit c32a2d
	   (it might, when we allow it). */
Packit c32a2d
	mpg123_format_none(mh);
Packit c32a2d
	mpg123_format(mh, rate, channels, encoding);
Packit c32a2d
Packit c32a2d
	encname = out123_enc_name(encoding);
Packit c32a2d
	printf( "Playing with %i channels and %li Hz, encoding %s.\n"
Packit c32a2d
	,	channels, rate, encname ? encname : "???" );
Packit c32a2d
	if(  out123_start(ao, rate, channels, encoding)
Packit c32a2d
	  || out123_getformat(ao, NULL, NULL, NULL, &framesize) )
Packit c32a2d
	{
Packit c32a2d
		fprintf(stderr, "Cannot start output / get framesize: %s\n"
Packit c32a2d
		,	out123_strerror(ao));
Packit c32a2d
		cleanup(mh, ao);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Buffer could be almost any size here, mpg123_outblock() is just some
Packit c32a2d
	   recommendation. The size should be a multiple of the PCM frame size. */
Packit c32a2d
	buffer_size = argc >= 6 ? atol(argv[5]) : mpg123_outblock(mh);
Packit c32a2d
	buffer = malloc( buffer_size );
Packit c32a2d
Packit c32a2d
	do
Packit c32a2d
	{
Packit c32a2d
		size_t played;
Packit c32a2d
		err = mpg123_read( mh, buffer, buffer_size, &done );
Packit c32a2d
		played = out123_play(ao, buffer, done);
Packit c32a2d
		if(played != done)
Packit c32a2d
		{
Packit c32a2d
			fprintf(stderr
Packit c32a2d
			,	"Warning: written less than gotten from libmpg123: %li != %li\n"
Packit c32a2d
			,	(long)played, (long)done);
Packit c32a2d
		}
Packit c32a2d
		samples += played/framesize;
Packit c32a2d
		/* We are not in feeder mode, so MPG123_OK, MPG123_ERR and
Packit c32a2d
		   MPG123_NEW_FORMAT are the only possibilities.
Packit c32a2d
		   We do not handle a new format, MPG123_DONE is the end... so
Packit c32a2d
		   abort on anything not MPG123_OK. */
Packit c32a2d
	} while (done && err==MPG123_OK);
Packit c32a2d
Packit c32a2d
	free(buffer);
Packit c32a2d
Packit c32a2d
	if(err != MPG123_DONE)
Packit c32a2d
	fprintf( stderr, "Warning: Decoding ended prematurely because: %s\n",
Packit c32a2d
	         err == MPG123_ERR ? mpg123_strerror(mh) : mpg123_plain_strerror(err) );
Packit c32a2d
Packit c32a2d
	printf("%li samples written.\n", (long)samples);
Packit c32a2d
	cleanup(mh, ao);
Packit c32a2d
	return 0;
Packit c32a2d
}