Blame src/mpg123.c

Packit c32a2d
/*
Packit c32a2d
	mpg123: main code of the program (not of the decoder...)
Packit c32a2d
Packit c32a2d
	copyright 1995-2013 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 Michael Hipp
Packit c32a2d
*/
Packit c32a2d
Packit c32a2d
#define ME "main"
Packit c32a2d
#include "mpg123app.h"
Packit c32a2d
#include "mpg123.h"
Packit c32a2d
#include "out123.h"
Packit c32a2d
#include "local.h"
Packit c32a2d
Packit c32a2d
#ifdef HAVE_SYS_WAIT_H
Packit c32a2d
#include <sys/wait.h>
Packit c32a2d
#endif
Packit c32a2d
#ifdef HAVE_SYS_RESOURCE_H
Packit c32a2d
#include <sys/resource.h>
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#include <errno.h>
Packit c32a2d
#include <string.h>
Packit c32a2d
#include <time.h>
Packit c32a2d
Packit c32a2d
#ifdef HAVE_SCHED_H
Packit c32a2d
#include <sched.h>
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* be paranoid about setpriority support */
Packit c32a2d
#ifndef PRIO_PROCESS
Packit c32a2d
#undef HAVE_SETPRIORITY
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#include "common.h"
Packit c32a2d
#include "sysutil.h"
Packit c32a2d
#include "getlopt.h"
Packit c32a2d
#include "term.h"
Packit c32a2d
#include "playlist.h"
Packit c32a2d
#include "httpget.h"
Packit c32a2d
#include "metaprint.h"
Packit c32a2d
#include "httpget.h"
Packit c32a2d
#include "streamdump.h"
Packit c32a2d
Packit c32a2d
#include "debug.h"
Packit c32a2d
Packit c32a2d
static void usage(int err);
Packit c32a2d
static void want_usage(char* arg);
Packit c32a2d
static void long_usage(int err);
Packit c32a2d
static void want_long_usage(char* arg);
Packit c32a2d
static void print_title(FILE* o);
Packit c32a2d
static void give_version(char* arg);
Packit c32a2d
Packit c32a2d
struct parameter param = { 
Packit c32a2d
  FALSE , /* aggressiv */
Packit c32a2d
  FALSE , /* shuffle */
Packit c32a2d
  FALSE , /* remote */
Packit c32a2d
  FALSE , /* remote to stderr */
Packit c32a2d
  FALSE , /* silent operation */
Packit c32a2d
  FALSE , /* xterm title on/off */
Packit c32a2d
  0 ,     /* second level buffer size */
Packit c32a2d
  0 ,     /* verbose level */
Packit c32a2d
  DEFAULT_OUTPUT_MODULE,	/* output module */
Packit c32a2d
  NULL,   /* output device */
Packit c32a2d
  0,      /* destination (headphones, ...) */
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
  FALSE,  /* term control */
Packit c32a2d
  TRUE,   /* term visuals */
Packit c32a2d
  MPG123_TERM_USR1,
Packit c32a2d
  MPG123_TERM_USR2,
Packit c32a2d
#endif
Packit c32a2d
  FALSE , /* checkrange */
Packit c32a2d
  0 ,	  /* force_reopen, always (re)opens audio device for next song */
Packit c32a2d
  /* test_cpu flag is valid for multi and 3dnow.. even if 3dnow is built alone; ensure it appears only once */
Packit c32a2d
  FALSE , /* normal operation */
Packit c32a2d
  FALSE,  /* try to run process in 'realtime mode' */
Packit c32a2d
#ifdef HAVE_WINDOWS_H 
Packit c32a2d
  0, /* win32 process priority */
Packit c32a2d
#endif
Packit c32a2d
	0, /* default is to play all titles in playlist */
Packit c32a2d
	NULL, /* no playlist per default */
Packit c32a2d
	0 /* condensed id3 per default */
Packit c32a2d
	,0 /* list_cpu */
Packit c32a2d
	,NULL /* cpu */ 
Packit c32a2d
#ifdef FIFO
Packit c32a2d
	,NULL
Packit c32a2d
#endif
Packit c32a2d
	,0 /* timeout */
Packit c32a2d
	,1 /* loop */
Packit c32a2d
	,0 /* delay */
Packit c32a2d
	,0 /* index */
Packit c32a2d
	/* Parameters for mpg123 handle, defaults are queried from library! */
Packit c32a2d
	,0 /* down_sample */
Packit c32a2d
	,0 /* rva */
Packit c32a2d
	,0 /* halfspeed */
Packit c32a2d
	,0 /* doublespeed */
Packit c32a2d
	,0 /* start_frame */
Packit c32a2d
	,-1 /* frame_number */
Packit c32a2d
	,0 /* outscale */
Packit c32a2d
	,0 /* flags */
Packit c32a2d
	,0 /* force_rate */
Packit c32a2d
	,1 /* ICY */
Packit c32a2d
	,1024 /* resync_limit */
Packit c32a2d
	,0 /* smooth */
Packit c32a2d
	,0.0 /* pitch */
Packit c32a2d
	,0 /* appflags */
Packit c32a2d
	,NULL /* proxyurl */
Packit c32a2d
	,0 /* keep_open */
Packit c32a2d
	,0 /* force_utf8 */
Packit c32a2d
	,INDEX_SIZE
Packit c32a2d
	,NULL /* force_encoding */
Packit c32a2d
	,0.2 /* preload */
Packit c32a2d
	,-1 /* preframes */
Packit c32a2d
	,-1 /* gain */
Packit c32a2d
	,NULL /* stream dump file */
Packit c32a2d
	,0 /* ICY interval */
Packit c32a2d
	,"mpg123" /* name */
Packit c32a2d
	,0. /* device buffer */
Packit c32a2d
};
Packit c32a2d
Packit c32a2d
mpg123_handle *mh = NULL;
Packit c32a2d
off_t framenum;
Packit c32a2d
off_t frames_left;
Packit c32a2d
out123_handle *ao = NULL;
Packit c32a2d
static long output_propflags = 0;
Packit c32a2d
char *prgName = NULL;
Packit c32a2d
/* ThOr: pointers are not TRUE or FALSE */
Packit c32a2d
char *equalfile = NULL;
Packit c32a2d
struct httpdata htd;
Packit c32a2d
int fresh = TRUE;
Packit c32a2d
FILE* aux_out = NULL; /* Output for interesting information, normally on stdout to be parseable. */
Packit c32a2d
Packit c32a2d
int intflag = FALSE;
Packit c32a2d
int deathflag = FALSE;
Packit c32a2d
static int skip_tracks = 0;
Packit c32a2d
int OutputDescriptor;
Packit c32a2d
Packit c32a2d
static int filept = -1;
Packit c32a2d
Packit c32a2d
static int network_sockets_used = 0; /* Win32 socket open/close Support */
Packit c32a2d
Packit c32a2d
char *fullprogname = NULL; /* Copy of argv[0]. */
Packit c32a2d
char *binpath; /* Path to myself. */
Packit c32a2d
Packit c32a2d
/* File-global storage of command line arguments.
Packit c32a2d
   They may be needed for cleanup after charset conversion. */
Packit c32a2d
static char **argv = NULL;
Packit c32a2d
static int    argc = 0;
Packit c32a2d
Packit c32a2d
/* Cleanup marker to know that we intiialized libmpg123 already. */
Packit c32a2d
static int cleanup_mpg123 = FALSE;
Packit c32a2d
Packit c32a2d
static long new_header = FALSE;
Packit c32a2d
static char *prebuffer = NULL;
Packit c32a2d
static size_t prebuffer_size = 0;
Packit c32a2d
static size_t prebuffer_fill = 0;
Packit c32a2d
static size_t minbytes = 0;
Packit c32a2d
Packit c32a2d
void set_intflag()
Packit c32a2d
{
Packit c32a2d
	debug("set_intflag TRUE");
Packit c32a2d
	intflag = TRUE;
Packit c32a2d
	skip_tracks = 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
#if !defined(WIN32) && !defined(GENERIC)
Packit c32a2d
static void catch_interrupt(void)
Packit c32a2d
{
Packit c32a2d
	intflag = TRUE;
Packit c32a2d
}
Packit c32a2d
static void handle_fatal_msg(const char *msg, size_t n)
Packit c32a2d
{
Packit c32a2d
	if(msg && !param.quiet)
Packit c32a2d
		write(STDERR_FILENO, msg, n);
Packit c32a2d
	intflag = TRUE;
Packit c32a2d
	deathflag = TRUE;
Packit c32a2d
}
Packit c32a2d
static void catch_fatal_term(void)
Packit c32a2d
{
Packit c32a2d
	const char msg[] = "\nmpg123: death by SIGTERM\n";
Packit c32a2d
	handle_fatal_msg(msg, sizeof(msg));
Packit c32a2d
}
Packit c32a2d
static void catch_fatal_pipe(void)
Packit c32a2d
{
Packit c32a2d
	/* If the SIGPIPE is because of piped stderr, trying to write
Packit c32a2d
	   in the signal handler hangs the program. */
Packit c32a2d
	handle_fatal_msg(NULL, 0);
Packit c32a2d
}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
static void skip_track(void)
Packit c32a2d
{
Packit c32a2d
	intflag = TRUE;
Packit c32a2d
	++skip_tracks;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void next_track(void)
Packit c32a2d
{
Packit c32a2d
	playlist_jump(+1);
Packit c32a2d
	skip_track();
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void prev_track(void)
Packit c32a2d
{
Packit c32a2d
	playlist_jump(-1);
Packit c32a2d
	skip_track();
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void next_dir(void)
Packit c32a2d
{
Packit c32a2d
	playlist_next_dir();
Packit c32a2d
	skip_track();
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void prev_dir(void)
Packit c32a2d
{
Packit c32a2d
	playlist_prev_dir();
Packit c32a2d
	skip_track();
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void safe_exit(int code);
Packit c32a2d
Packit c32a2d
static void play_prebuffer(void)
Packit c32a2d
{
Packit c32a2d
	/* Ensure that the prebuffer bit has been posted. */
Packit c32a2d
	if(prebuffer_fill)
Packit c32a2d
	{
Packit c32a2d
		if(out123_play(ao, prebuffer, prebuffer_fill) < prebuffer_fill)
Packit c32a2d
		{
Packit c32a2d
			error("Deep trouble! Cannot flush to my output anymore!");
Packit c32a2d
			safe_exit(133);
Packit c32a2d
		}
Packit c32a2d
		prebuffer_fill = 0;
Packit c32a2d
	}
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
/* Drain output device/buffer, but still give the option to interrupt things. */
Packit c32a2d
static void controlled_drain(void)
Packit c32a2d
{
Packit c32a2d
	int framesize;
Packit c32a2d
	size_t drain_block;
Packit c32a2d
Packit c32a2d
	play_prebuffer();
Packit c32a2d
Packit c32a2d
	if(intflag || !out123_buffered(ao))
Packit c32a2d
		return;
Packit c32a2d
	if(out123_getformat(ao, NULL, NULL, NULL, &framesize))
Packit c32a2d
		return;
Packit c32a2d
	drain_block = 1152*framesize;
Packit c32a2d
	if(param.verbose)
Packit c32a2d
		fprintf(stderr, "\n");
Packit c32a2d
	do
Packit c32a2d
	{
Packit c32a2d
		out123_ndrain(ao, drain_block);
Packit c32a2d
		if(param.verbose)
Packit c32a2d
			print_buf("Draining buffer: ", ao);
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
		if(param.term_ctrl)
Packit c32a2d
			term_control(mh, ao);
Packit c32a2d
#endif
Packit c32a2d
	}
Packit c32a2d
	while(!intflag && out123_buffered(ao));
Packit c32a2d
	if(param.verbose)
Packit c32a2d
		fprintf(stderr, "\n");
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void safe_exit(int code)
Packit c32a2d
{
Packit c32a2d
	char *dummy, *dammy;
Packit c32a2d
Packit c32a2d
	if(prebuffer)
Packit c32a2d
		free(prebuffer);
Packit c32a2d
Packit c32a2d
	dump_close();
Packit c32a2d
	if(!code)
Packit c32a2d
		controlled_drain();
Packit c32a2d
	if(intflag)
Packit c32a2d
		out123_drop(ao);
Packit c32a2d
	out123_del(ao);
Packit c32a2d
Packit c32a2d
	if(mh != NULL) mpg123_delete(mh);
Packit c32a2d
Packit c32a2d
	if(cleanup_mpg123) mpg123_exit();
Packit c32a2d
Packit c32a2d
	httpdata_free(&htd);
Packit c32a2d
Packit c32a2d
#ifdef WANT_WIN32_UNICODE
Packit c32a2d
	win32_cmdline_free(argc, argv); /* This handles the premature argv == NULL, too. */
Packit c32a2d
#endif
Packit c32a2d
#if defined (WANT_WIN32_SOCKETS)
Packit c32a2d
	win32_net_deinit();
Packit c32a2d
#endif
Packit c32a2d
	/* It's ugly... but let's just fix this still-reachable memory chunk of static char*. */
Packit c32a2d
	split_dir_file("", &dummy, &dammy);
Packit c32a2d
	if(fullprogname) free(fullprogname);
Packit c32a2d
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
	term_exit();
Packit c32a2d
#endif
Packit c32a2d
	exit(code);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void check_fatal_output(int code)
Packit c32a2d
{
Packit c32a2d
	if(code)
Packit c32a2d
	{
Packit c32a2d
		if(!param.quiet)
Packit c32a2d
			error2( "out123 error %i: %s"
Packit c32a2d
			,	out123_errcode(ao), out123_strerror(ao) );
Packit c32a2d
		safe_exit(code);
Packit c32a2d
	}
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void set_output_module( char *arg )
Packit c32a2d
{
Packit c32a2d
	unsigned int i;
Packit c32a2d
		
Packit c32a2d
	/* Search for a colon and set the device if found */
Packit c32a2d
	for(i=0; i< strlen( arg ); i++) {
Packit c32a2d
		if (arg[i] == ':') {
Packit c32a2d
			arg[i] = 0;
Packit c32a2d
			param.output_device = &arg[i+1];
Packit c32a2d
			debug1("Setting output device: %s", param.output_device);
Packit c32a2d
			break;
Packit c32a2d
		}	
Packit c32a2d
	}
Packit c32a2d
	/* Set the output module */
Packit c32a2d
	param.output_module = arg;
Packit c32a2d
	debug1("Setting output module: %s", param.output_module );
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void set_output_flag(int flag)
Packit c32a2d
{
Packit c32a2d
  if(param.output_flags <= 0) param.output_flags = flag;
Packit c32a2d
  else param.output_flags |= flag;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void set_output_h(char *a)
Packit c32a2d
{
Packit c32a2d
	set_output_flag(OUT123_HEADPHONES);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void set_output_s(char *a)
Packit c32a2d
{
Packit c32a2d
	set_output_flag(OUT123_INTERNAL_SPEAKER);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void set_output_l(char *a)
Packit c32a2d
{
Packit c32a2d
	set_output_flag(OUT123_LINE_OUT);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void set_output(char *arg)
Packit c32a2d
{
Packit c32a2d
	/* If single letter, it's the legacy output switch for AIX/HP/Sun.
Packit c32a2d
	   If longer, it's module[:device] . If zero length, it's rubbish. */
Packit c32a2d
	if(strlen(arg) <= 1) switch(arg[0])
Packit c32a2d
	{
Packit c32a2d
		case 'h': set_output_h(arg); break;
Packit c32a2d
		case 's': set_output_s(arg); break;
Packit c32a2d
		case 'l': set_output_l(arg); break;
Packit c32a2d
		default:
Packit c32a2d
			error1("\"%s\" is no valid output", arg);
Packit c32a2d
			safe_exit(1);
Packit c32a2d
	}
Packit c32a2d
	else set_output_module(arg);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void set_verbose (char *arg)
Packit c32a2d
{
Packit c32a2d
    param.verbose++;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void set_quiet (char *arg)
Packit c32a2d
{
Packit c32a2d
	param.verbose=0;
Packit c32a2d
	param.quiet=TRUE;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void set_out_wav(char *arg)
Packit c32a2d
{
Packit c32a2d
	param.output_module = "wav";
Packit c32a2d
	param.output_device = arg;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void set_out_cdr(char *arg)
Packit c32a2d
{
Packit c32a2d
	param.output_module = "cdr";
Packit c32a2d
	param.output_device = arg;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void set_out_au(char *arg)
Packit c32a2d
{
Packit c32a2d
	param.output_module = "au";
Packit c32a2d
	param.output_device = arg;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void set_out_test(char *arg)
Packit c32a2d
{
Packit c32a2d
	param.output_module = "test";
Packit c32a2d
	param.output_device = NULL;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void set_out_file(char *arg)
Packit c32a2d
{
Packit c32a2d
	param.output_module = "raw";
Packit c32a2d
	param.output_device = arg;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void set_out_stdout(char *arg)
Packit c32a2d
{
Packit c32a2d
	param.output_module = "raw";
Packit c32a2d
	param.output_device = NULL;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void set_out_stdout1(char *arg)
Packit c32a2d
{
Packit c32a2d
	param.output_module = "raw";
Packit c32a2d
	param.output_device = NULL;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
#if !defined (HAVE_SCHED_SETSCHEDULER) && !defined (HAVE_WINDOWS_H)
Packit c32a2d
static void realtime_not_compiled(char *arg)
Packit c32a2d
{
Packit c32a2d
	fprintf(stderr,"Option '-T / --realtime' not compiled into this binary.\n");
Packit c32a2d
}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
static int frameflag; /* ugly, but that's the way without hacking getlopt */
Packit c32a2d
static void set_frameflag(char *arg)
Packit c32a2d
{
Packit c32a2d
	/* Only one mono flag at a time! */
Packit c32a2d
	if(frameflag & MPG123_FORCE_MONO) param.flags &= ~MPG123_FORCE_MONO;
Packit c32a2d
	param.flags |= frameflag;
Packit c32a2d
}
Packit c32a2d
static void unset_frameflag(char *arg)
Packit c32a2d
{
Packit c32a2d
	param.flags &= ~frameflag;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static int appflag; /* still ugly, but works */
Packit c32a2d
static void set_appflag(char *arg)
Packit c32a2d
{
Packit c32a2d
	param.appflags |= appflag;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void list_output_modules(char *arg)
Packit c32a2d
{
Packit c32a2d
	char **names = NULL;
Packit c32a2d
	char **descr = NULL;
Packit c32a2d
	int count = -1;
Packit c32a2d
	out123_handle *lao;
Packit c32a2d
Packit c32a2d
	if((lao=out123_new()))
Packit c32a2d
	{
Packit c32a2d
		printf("\n");
Packit c32a2d
		printf("Available modules\n");
Packit c32a2d
		printf("-----------------\n");
Packit c32a2d
		out123_param_string(lao, OUT123_BINDIR, binpath);
Packit c32a2d
		out123_param_int(lao, OUT123_VERBOSE, param.verbose);
Packit c32a2d
		if(param.quiet)
Packit c32a2d
			out123_param_int(lao, OUT123_FLAGS, OUT123_QUIET);
Packit c32a2d
		if((count=out123_drivers(lao, &names, &descr)) >= 0)
Packit c32a2d
		{
Packit c32a2d
			int i;
Packit c32a2d
			for(i=0; i
Packit c32a2d
			{
Packit c32a2d
				printf( "%-15s%s  %s\n"
Packit c32a2d
				,	names[i], "output", descr[i] );
Packit c32a2d
				free(names[i]);
Packit c32a2d
				free(descr[i]);
Packit c32a2d
			}
Packit c32a2d
			free(names);
Packit c32a2d
			free(descr);
Packit c32a2d
		}
Packit c32a2d
		out123_del(lao);
Packit c32a2d
	}
Packit c32a2d
	else if(!param.quiet)
Packit c32a2d
		error("Failed to create an out123 handle.");
Packit c32a2d
	exit(count >= 0 ? 0 : 1);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
Packit c32a2d
/* static void unset_appflag(char *arg)
Packit c32a2d
{
Packit c32a2d
	param.appflags &= ~appflag;
Packit c32a2d
} */
Packit c32a2d
Packit c32a2d
/* Please note: GLO_NUM expects point to LONG! */
Packit c32a2d
/* ThOr:
Packit c32a2d
 *  Yeah, and despite that numerous addresses to int variables were 
Packit c32a2d
passed.
Packit c32a2d
 *  That's not good on my Alpha machine with int=32bit and long=64bit!
Packit c32a2d
 *  Introduced GLO_INT and GLO_LONG as different bits to make that clear.
Packit c32a2d
 *  GLO_NUM no longer exists.
Packit c32a2d
 */
Packit c32a2d
#ifdef OPT_3DNOW
Packit c32a2d
static int dnow = 0; /* helper for mapping the old 3dnow options */
Packit c32a2d
#endif
Packit c32a2d
topt opts[] = {
Packit c32a2d
	{'k', "skip",        GLO_ARG | GLO_LONG, 0, &param.start_frame, 0},
Packit c32a2d
	{'2', "2to1",        GLO_INT,  0, &param.down_sample, 1},
Packit c32a2d
	{'4', "4to1",        GLO_INT,  0, &param.down_sample, 2},
Packit c32a2d
	{'t', "test",        GLO_INT,  set_out_test, NULL, 0},
Packit c32a2d
	{'s', "stdout",      GLO_INT,  set_out_stdout,  NULL, 0},
Packit c32a2d
	{'S', "STDOUT",      GLO_INT,  set_out_stdout1, NULL, 0},
Packit c32a2d
	{'O', "outfile",     GLO_ARG | GLO_CHAR, set_out_file, NULL, 0},
Packit c32a2d
	{'c', "check",       GLO_INT,  0, &param.checkrange, TRUE},
Packit c32a2d
	{'v', "verbose",     0,        set_verbose, 0,           0},
Packit c32a2d
	{'q', "quiet",       0,        set_quiet,   0,           0},
Packit c32a2d
	{'y', "no-resync",      GLO_INT,  set_frameflag, &frameflag, MPG123_NO_RESYNC},
Packit c32a2d
	/* compatibility, no-resync is to be used nowadays */
Packit c32a2d
	{0, "resync",      GLO_INT,  set_frameflag, &frameflag, MPG123_NO_RESYNC},
Packit c32a2d
	{'0', "single0",     GLO_INT,  set_frameflag, &frameflag, MPG123_MONO_LEFT},
Packit c32a2d
	{0,   "left",        GLO_INT,  set_frameflag, &frameflag, MPG123_MONO_LEFT},
Packit c32a2d
	{'1', "single1",     GLO_INT,  set_frameflag, &frameflag, MPG123_MONO_RIGHT},
Packit c32a2d
	{0,   "right",       GLO_INT,  set_frameflag, &frameflag, MPG123_MONO_RIGHT},
Packit c32a2d
	{'m', "singlemix",   GLO_INT,  set_frameflag, &frameflag, MPG123_MONO_MIX},
Packit c32a2d
	{0,   "mix",         GLO_INT,  set_frameflag, &frameflag, MPG123_MONO_MIX},
Packit c32a2d
	{0,   "mono",        GLO_INT,  set_frameflag, &frameflag, MPG123_MONO_MIX},
Packit c32a2d
	{0,   "stereo",      GLO_INT,  set_frameflag, &frameflag, MPG123_FORCE_STEREO},
Packit c32a2d
	{0,   "reopen",      GLO_INT,  0, &param.force_reopen, 1},
Packit c32a2d
	{'g', "gain",        GLO_ARG | GLO_LONG, 0, &param.gain,    0},
Packit c32a2d
	{'r', "rate",        GLO_ARG | GLO_LONG, 0, &param.force_rate,  0},
Packit c32a2d
	{0,   "8bit",        GLO_INT,  set_frameflag, &frameflag, MPG123_FORCE_8BIT},
Packit c32a2d
	{0,   "float",       GLO_INT,  set_frameflag, &frameflag, MPG123_FORCE_FLOAT},
Packit c32a2d
	{0,   "headphones",  0,                  set_output_h, 0,0},
Packit c32a2d
	{0,   "speaker",     0,                  set_output_s, 0,0},
Packit c32a2d
	{0,   "lineout",     0,                  set_output_l, 0,0},
Packit c32a2d
	{'o', "output",      GLO_ARG | GLO_CHAR, set_output, 0,  0},
Packit c32a2d
	{0,   "list-modules",0,       list_output_modules, NULL, 0},
Packit c32a2d
	{'a', "audiodevice", GLO_ARG | GLO_CHAR, 0, &param.output_device,  0},
Packit c32a2d
	{'f', "scale",       GLO_ARG | GLO_LONG, 0, &param.outscale,   0},
Packit c32a2d
	{'n', "frames",      GLO_ARG | GLO_LONG, 0, &param.frame_number,  0},
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
	{'C', "control",     GLO_INT,  0, &param.term_ctrl, TRUE},
Packit c32a2d
	{0, "no-control",    GLO_INT,  0, &param.term_ctrl, FALSE},
Packit c32a2d
	{0,   "ctrlusr1",    GLO_ARG | GLO_CHAR, 0, &param.term_usr1, 0},
Packit c32a2d
	{0,   "ctrlusr2",    GLO_ARG | GLO_CHAR, 0, &param.term_usr2, 0},
Packit c32a2d
#endif
Packit c32a2d
#ifndef NOXFERMEM
Packit c32a2d
	{'b', "buffer",      GLO_ARG | GLO_LONG, 0, &param.usebuffer,  0},
Packit c32a2d
	{0,  "smooth",      GLO_INT,  0, &param.smooth, 1},
Packit c32a2d
	{0, "preload", GLO_ARG|GLO_DOUBLE, 0, &param.preload, 0},
Packit c32a2d
#endif
Packit c32a2d
	{'R', "remote",      GLO_INT,  0, &param.remote, TRUE},
Packit c32a2d
	{0,   "remote-err",  GLO_INT,  0, &param.remote_err, TRUE},
Packit c32a2d
	{'d', "doublespeed", GLO_ARG | GLO_LONG, 0, &param.doublespeed, 0},
Packit c32a2d
	{'h', "halfspeed",   GLO_ARG | GLO_LONG, 0, &param.halfspeed, 0},
Packit c32a2d
#ifdef NETWORK
Packit c32a2d
	{'p', "proxy",       GLO_ARG | GLO_CHAR, 0, &param.proxyurl,   0},
Packit c32a2d
#endif
Packit c32a2d
	{'@', "list",        GLO_ARG | GLO_CHAR, 0, &param.listname,   0},
Packit c32a2d
	/* 'z' comes from the the german word 'zufall' (eng: random) */
Packit c32a2d
	{'z', "shuffle",     GLO_INT,  0, &param.shuffle, 1},
Packit c32a2d
	{'Z', "random",      GLO_INT,  0, &param.shuffle, 2},
Packit c32a2d
	{'E', "equalizer",	 GLO_ARG | GLO_CHAR, 0, &equalfile,1},
Packit c32a2d
	#ifdef HAVE_SETPRIORITY
Packit c32a2d
	{0,   "aggressive",	 GLO_INT,  0, &param.aggressive, 2},
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_3DNOW
Packit c32a2d
#define SET_3DNOW 1
Packit c32a2d
#define SET_I586  2
Packit c32a2d
	{0,   "force-3dnow", GLO_CHAR,  0, &dnow, SET_3DNOW},
Packit c32a2d
	{0,   "no-3dnow",    GLO_CHAR,  0, &dnow, SET_I586},
Packit c32a2d
	{0,   "test-3dnow",  GLO_INT,  0, &param.test_cpu, TRUE},
Packit c32a2d
	#endif
Packit c32a2d
	{0, "cpu", GLO_ARG | GLO_CHAR, 0, &param.cpu,  0},
Packit c32a2d
	{0, "test-cpu",  GLO_INT,  0, &param.test_cpu, TRUE},
Packit c32a2d
	{0, "list-cpu", GLO_INT,  0, &param.list_cpu , 1},
Packit c32a2d
#ifdef NETWORK
Packit c32a2d
	{'u', "auth",        GLO_ARG | GLO_CHAR, 0, &httpauth,   0},
Packit c32a2d
#endif
Packit c32a2d
	#if defined (HAVE_SCHED_SETSCHEDULER) || defined (HAVE_WINDOWS_H)
Packit c32a2d
	/* check why this should be a long variable instead of int! */
Packit c32a2d
	{'T', "realtime",    GLO_LONG,  0, &param.realtime, TRUE },
Packit c32a2d
	#else
Packit c32a2d
	{'T', "realtime",    0,  realtime_not_compiled, 0,           0 },    
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef HAVE_WINDOWS_H
Packit c32a2d
	{0, "priority", GLO_ARG | GLO_INT, 0, &param.w32_priority, 0},
Packit c32a2d
	#endif
Packit c32a2d
	{0, "title",         GLO_INT,  0, &param.xterm_title, TRUE },
Packit c32a2d
	{'w', "wav",         GLO_ARG | GLO_CHAR, set_out_wav, 0, 0 },
Packit c32a2d
	{0, "cdr",           GLO_ARG | GLO_CHAR, set_out_cdr, 0, 0 },
Packit c32a2d
	{0, "au",            GLO_ARG | GLO_CHAR, set_out_au, 0, 0 },
Packit c32a2d
	{0,   "gapless",	 GLO_INT,  set_frameflag, &frameflag, MPG123_GAPLESS},
Packit c32a2d
	{0,   "no-gapless", GLO_INT, unset_frameflag, &frameflag, MPG123_GAPLESS},
Packit c32a2d
	{0, "no-infoframe", GLO_INT, set_frameflag, &frameflag, MPG123_IGNORE_INFOFRAME},
Packit c32a2d
	{'?', "help",            0,  want_usage, 0,           0 },
Packit c32a2d
	{0 , "longhelp" ,        0,  want_long_usage, 0,      0 },
Packit c32a2d
	{0 , "version" ,         0,  give_version, 0,         0 },
Packit c32a2d
	{'l', "listentry",       GLO_ARG | GLO_LONG, 0, &param.listentry, 0 },
Packit c32a2d
	{0, "continue", GLO_INT, set_appflag, &appflag, MPG123APP_CONTINUE },
Packit c32a2d
	{0, "rva-mix",         GLO_INT,  0, &param.rva, 1 },
Packit c32a2d
	{0, "rva-radio",         GLO_INT,  0, &param.rva, 1 },
Packit c32a2d
	{0, "rva-album",         GLO_INT,  0, &param.rva, 2 },
Packit c32a2d
	{0, "rva-audiophile",         GLO_INT,  0, &param.rva, 2 },
Packit c32a2d
	{0, "no-icy-meta",      GLO_INT,  0, &param.talk_icy, 0 },
Packit c32a2d
	{0, "long-tag",         GLO_INT,  0, &param.long_id3, 1 },
Packit c32a2d
#ifdef FIFO
Packit c32a2d
	{0, "fifo", GLO_ARG | GLO_CHAR, 0, &param.fifo,  0},
Packit c32a2d
#endif
Packit c32a2d
	{0, "timeout", GLO_ARG | GLO_LONG, 0, &param.timeout, 0},
Packit c32a2d
	{0, "loop", GLO_ARG | GLO_LONG, 0, &param.loop, 0},
Packit c32a2d
	{'i', "index", GLO_INT, 0, &param.index, 1},
Packit c32a2d
	{'D', "delay", GLO_ARG | GLO_INT, 0, &param.delay, 0},
Packit c32a2d
	{0, "resync-limit", GLO_ARG | GLO_LONG, 0, &param.resync_limit, 0},
Packit c32a2d
	{0, "pitch", GLO_ARG|GLO_DOUBLE, 0, &param.pitch, 0},
Packit c32a2d
#ifdef NETWORK
Packit c32a2d
	{0, "ignore-mime", GLO_INT, set_appflag, &appflag, MPG123APP_IGNORE_MIME },
Packit c32a2d
#endif
Packit c32a2d
	{0, "lyrics", GLO_INT, set_appflag, &appflag, MPG123APP_LYRICS},
Packit c32a2d
	{0, "keep-open", GLO_INT, 0, &param.keep_open, 1},
Packit c32a2d
	{0, "utf8", GLO_INT, 0, &param.force_utf8, 1},
Packit c32a2d
	{0, "fuzzy", GLO_INT,  set_frameflag, &frameflag, MPG123_FUZZY},
Packit c32a2d
	{0, "index-size", GLO_ARG|GLO_LONG, 0, &param.index_size, 0},
Packit c32a2d
	{0, "no-seekbuffer", GLO_INT, unset_frameflag, &frameflag, MPG123_SEEKBUFFER},
Packit c32a2d
	{'e', "encoding", GLO_ARG|GLO_CHAR, 0, &param.force_encoding, 0},
Packit c32a2d
	{0, "preframes", GLO_ARG|GLO_LONG, 0, &param.preframes, 0},
Packit c32a2d
	{0, "skip-id3v2", GLO_INT, set_frameflag, &frameflag, MPG123_SKIP_ID3V2},
Packit c32a2d
	{0, "streamdump", GLO_ARG|GLO_CHAR, 0, &param.streamdump, 0},
Packit c32a2d
	{0, "icy-interval", GLO_ARG|GLO_LONG, 0, &param.icy_interval, 0},
Packit c32a2d
	{0, "ignore-streamlength", GLO_INT, set_frameflag, &frameflag, MPG123_IGNORE_STREAMLENGTH},
Packit c32a2d
	{0, "name", GLO_ARG|GLO_CHAR, 0, &param.name, 0},
Packit c32a2d
	{0, "devbuffer", GLO_ARG|GLO_DOUBLE, 0, &param.device_buffer, 0},
Packit c32a2d
	{0, 0, 0, 0, 0, 0}
Packit c32a2d
};
Packit c32a2d
Packit c32a2d
static int open_track_fd (void)
Packit c32a2d
{
Packit c32a2d
	/* Let reader handle invalid filept */
Packit c32a2d
	if(mpg123_open_fd(mh, filept) != MPG123_OK)
Packit c32a2d
	{
Packit c32a2d
		error2("Cannot open fd %i: %s", filept, mpg123_strerror(mh));
Packit c32a2d
		return 0;
Packit c32a2d
	}
Packit c32a2d
	debug("Track successfully opened.");
Packit c32a2d
	fresh = TRUE;
Packit c32a2d
	return 1;
Packit c32a2d
	/*1 for success, 0 for failure */
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
/* 1 on success, 0 on failure */
Packit c32a2d
int open_track(char *fname)
Packit c32a2d
{
Packit c32a2d
	filept=-1;
Packit c32a2d
	httpdata_reset(&htd);
Packit c32a2d
	if(MPG123_OK != mpg123_param(mh, MPG123_ICY_INTERVAL, 0, 0))
Packit c32a2d
	error1("Cannot (re)set ICY interval: %s", mpg123_strerror(mh));
Packit c32a2d
	if(!strcmp(fname, "-"))
Packit c32a2d
	{
Packit c32a2d
		filept = STDIN_FILENO;
Packit c32a2d
#ifdef WIN32
Packit c32a2d
		_setmode(STDIN_FILENO, _O_BINARY);
Packit c32a2d
#endif
Packit c32a2d
	}
Packit c32a2d
	else if (!strncmp(fname, "http://", 7)) /* http stream */
Packit c32a2d
	{
Packit c32a2d
#if defined (WANT_WIN32_SOCKETS)
Packit c32a2d
	if(param.streamdump != NULL)
Packit c32a2d
	{
Packit c32a2d
		fprintf(stderr, "\nWarning: win32 networking conflicts with stream dumping. Aborting the dump.\n");
Packit c32a2d
		dump_close();
Packit c32a2d
	}
Packit c32a2d
	/*Use recv instead of stdio functions */
Packit c32a2d
	win32_net_replace(mh);
Packit c32a2d
	filept = win32_net_http_open(fname, &htd);
Packit c32a2d
#else
Packit c32a2d
	filept = http_open(fname, &htd);
Packit c32a2d
#endif
Packit c32a2d
	network_sockets_used = 1;
Packit c32a2d
/* utf-8 encoded URLs might not work under Win32 */
Packit c32a2d
		
Packit c32a2d
		/* now check if we got sth. and if we got sth. good */
Packit c32a2d
		if(    (filept >= 0) && (htd.content_type.p != NULL)
Packit c32a2d
			  && !APPFLAG(MPG123APP_IGNORE_MIME) && !(debunk_mime(htd.content_type.p) & IS_FILE) )
Packit c32a2d
		{
Packit c32a2d
			error1("Unknown mpeg MIME type %s - is it perhaps a playlist (use -@)?", htd.content_type.p == NULL ? "<nil>" : htd.content_type.p);
Packit c32a2d
			error("If you know the stream is mpeg1/2 audio, then please report this as "PACKAGE_NAME" bug");
Packit c32a2d
			return 0;
Packit c32a2d
		}
Packit c32a2d
		if(filept < 0)
Packit c32a2d
		{
Packit c32a2d
			error1("Access to http resource %s failed.", fname);
Packit c32a2d
			return 0;
Packit c32a2d
		}
Packit c32a2d
		if(MPG123_OK != mpg123_param(mh, MPG123_ICY_INTERVAL, htd.icy_interval, 0))
Packit c32a2d
		error1("Cannot set ICY interval: %s", mpg123_strerror(mh));
Packit c32a2d
		if(param.verbose > 1) fprintf(stderr, "Info: ICY interval %li\n", (long)htd.icy_interval);
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	if(param.icy_interval > 0)
Packit c32a2d
	{
Packit c32a2d
		if(MPG123_OK != mpg123_param(mh, MPG123_ICY_INTERVAL, param.icy_interval, 0))
Packit c32a2d
		error1("Cannot set ICY interval: %s", mpg123_strerror(mh));
Packit c32a2d
		if(param.verbose > 1) fprintf(stderr, "Info: Forced ICY interval %li\n", param.icy_interval);
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	debug("OK... going to finally open.");
Packit c32a2d
	/* Now hook up the decoder on the opened stream or the file. */
Packit c32a2d
	if(filept > -1)
Packit c32a2d
	{
Packit c32a2d
		return open_track_fd();
Packit c32a2d
	}
Packit c32a2d
	else if(mpg123_open(mh, fname) != MPG123_OK)
Packit c32a2d
	{
Packit c32a2d
		error2("Cannot open %s: %s", fname, mpg123_strerror(mh));
Packit c32a2d
		return 0;
Packit c32a2d
	}
Packit c32a2d
	debug("Track successfully opened.");
Packit c32a2d
Packit c32a2d
	fresh = TRUE;
Packit c32a2d
	return 1;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
/* for symmetry */
Packit c32a2d
void close_track(void)
Packit c32a2d
{
Packit c32a2d
	mpg123_close(mh);
Packit c32a2d
#if defined (WANT_WIN32_SOCKETS)
Packit c32a2d
	if (network_sockets_used)
Packit c32a2d
	win32_net_close(filept);
Packit c32a2d
	filept = -1;
Packit c32a2d
	return;
Packit c32a2d
#endif
Packit c32a2d
	network_sockets_used = 0;
Packit c32a2d
	if(filept > -1) close(filept);
Packit c32a2d
	filept = -1;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
/* return 1 on success, 0 on failure */
Packit c32a2d
int play_frame(void)
Packit c32a2d
{
Packit c32a2d
	unsigned char *audio;
Packit c32a2d
	int mc;
Packit c32a2d
	size_t bytes = 0;
Packit c32a2d
	debug("play_frame");
Packit c32a2d
	mc = mpg123_decode_frame(mh, &framenum, &audio, &bytes);
Packit c32a2d
	mpg123_getstate(mh, MPG123_FRESH_DECODER, &new_header, NULL);
Packit c32a2d
Packit c32a2d
	/* Play what is there to play (starting with second decode_frame call!) */
Packit c32a2d
	if(bytes)
Packit c32a2d
	{
Packit c32a2d
		if(param.frame_number > -1) --frames_left;
Packit c32a2d
		if(fresh && framenum >= param.start_frame)
Packit c32a2d
		{
Packit c32a2d
			fresh = FALSE;
Packit c32a2d
		}
Packit c32a2d
		if(bytes < minbytes && !prebuffer_fill)
Packit c32a2d
		{
Packit c32a2d
			/* Postpone playback of little buffers until large buffers can
Packit c32a2d
				follow them right away, preventing underruns. */
Packit c32a2d
			if(prebuffer_size < minbytes)
Packit c32a2d
			{
Packit c32a2d
				if(prebuffer)
Packit c32a2d
					free(prebuffer);
Packit c32a2d
				if(!(prebuffer = malloc(minbytes)))
Packit c32a2d
					safe_exit(11);
Packit c32a2d
				prebuffer_size = minbytes;
Packit c32a2d
			}
Packit c32a2d
			memcpy(prebuffer, audio, bytes);
Packit c32a2d
			prebuffer_fill = bytes;
Packit c32a2d
			bytes = 0;
Packit c32a2d
			debug1("prebuffered %"SIZE_P" bytes", prebuffer_fill);
Packit c32a2d
		}
Packit c32a2d
		if(param.checkrange)
Packit c32a2d
		{
Packit c32a2d
			long clip = mpg123_clip(mh);
Packit c32a2d
			if(clip > 0) fprintf(stderr,"\n%ld samples clipped\n", clip);
Packit c32a2d
		}
Packit c32a2d
	}
Packit c32a2d
	/* The bytes could have been postponed to later. */
Packit c32a2d
	if(bytes)
Packit c32a2d
	{
Packit c32a2d
		unsigned char *playbuf = audio;
Packit c32a2d
		if(prebuffer_fill)
Packit c32a2d
		{
Packit c32a2d
			size_t missing;
Packit c32a2d
			/* This is tricky: The small piece needs to be filled up. Playing 10
Packit c32a2d
			   pcm frames will always trigger underruns with ALSA, dammit!
Packit c32a2d
			   This grabs some data from current frame, unless it itself would
Packit c32a2d
			   end up smaller than the prebuffer. Ending up empty is fine. */
Packit c32a2d
			if(  prebuffer_fill < prebuffer_size
Packit c32a2d
			  && (  bytes <= (missing=prebuffer_size-prebuffer_fill)
Packit c32a2d
			     || bytes >= missing+prebuffer_size ) )
Packit c32a2d
			{
Packit c32a2d
				if(bytes < missing)
Packit c32a2d
					missing=bytes;
Packit c32a2d
				memcpy(prebuffer+prebuffer_fill, playbuf, missing);
Packit c32a2d
				playbuf += missing;
Packit c32a2d
				bytes -= missing;
Packit c32a2d
				prebuffer_fill += missing;
Packit c32a2d
			}
Packit c32a2d
			if(   out123_play(ao, prebuffer, prebuffer_fill) < prebuffer_fill
Packit c32a2d
			   && !intflag )
Packit c32a2d
			{
Packit c32a2d
				error("Deep trouble! Cannot flush to my output anymore!");
Packit c32a2d
				safe_exit(133);
Packit c32a2d
			}
Packit c32a2d
			prebuffer_fill = 0;
Packit c32a2d
		}
Packit c32a2d
		/* Interrupt here doesn't necessarily interrupt out123_play().
Packit c32a2d
		   I wonder if that makes us miss errors. Actual issues should
Packit c32a2d
		   just be postponed. */
Packit c32a2d
		if(bytes && !intflag) /* Previous piece could already be interrupted. */
Packit c32a2d
		if(out123_play(ao, playbuf, bytes) < bytes && !intflag)
Packit c32a2d
		{
Packit c32a2d
			error("Deep trouble! Cannot flush to my output anymore!");
Packit c32a2d
			safe_exit(133);
Packit c32a2d
		}
Packit c32a2d
	}
Packit c32a2d
	/* Special actions and errors. */
Packit c32a2d
	if(mc != MPG123_OK)
Packit c32a2d
	{
Packit c32a2d
		if(mc == MPG123_ERR || mc == MPG123_DONE)
Packit c32a2d
		{
Packit c32a2d
			if(mc == MPG123_ERR) error1("...in decoding next frame: %s", mpg123_strerror(mh));
Packit c32a2d
			return 0;
Packit c32a2d
		}
Packit c32a2d
		if(mc == MPG123_NO_SPACE)
Packit c32a2d
		{
Packit c32a2d
			error("I have not enough output space? I didn't plan for this.");
Packit c32a2d
			return 0;
Packit c32a2d
		}
Packit c32a2d
		if(mc == MPG123_NEW_FORMAT)
Packit c32a2d
		{
Packit c32a2d
			long rate;
Packit c32a2d
			int channels;
Packit c32a2d
			int encoding;
Packit c32a2d
			play_prebuffer(); /* Make sure we got rid of old data. */
Packit c32a2d
			mpg123_getformat(mh, &rate, &channels, &encoding);
Packit c32a2d
			/* A layer I frame duration at minimum for live outputs. */
Packit c32a2d
			if(output_propflags & OUT123_PROP_LIVE)
Packit c32a2d
				minbytes = out123_encsize(encoding)*channels*384;
Packit c32a2d
			else
Packit c32a2d
				minbytes = 0;
Packit c32a2d
			if(param.verbose > 2)
Packit c32a2d
			{
Packit c32a2d
				const char* encname = out123_enc_name(encoding);
Packit c32a2d
				fprintf( stderr
Packit c32a2d
				,	"\nNote: New output format with %li Hz, %i channels, encoding %s.\n"
Packit c32a2d
				,	rate, channels, encname ? encname : "???" );
Packit c32a2d
			}
Packit c32a2d
			new_header = TRUE;
Packit c32a2d
			check_fatal_output(out123_start(ao, rate, channels, encoding));
Packit c32a2d
			/* We may take some time feeding proper data, so pause by default. */
Packit c32a2d
			out123_pause(ao);
Packit c32a2d
		}
Packit c32a2d
	}
Packit c32a2d
	if(new_header && !param.quiet)
Packit c32a2d
	{
Packit c32a2d
		new_header = FALSE;
Packit c32a2d
		fprintf(stderr, "\n");
Packit c32a2d
		if(param.verbose > 1)
Packit c32a2d
			print_header(mh);
Packit c32a2d
		else
Packit c32a2d
			print_header_compact(mh);
Packit c32a2d
	}
Packit c32a2d
	return 1;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
/* Return TRUE if we should continue (second interrupt happens quickly), skipping tracks, or FALSE if we should die. */
Packit c32a2d
#if !defined(WIN32) && !defined(GENERIC)
Packit c32a2d
int skip_or_die(struct timeval *start_time)
Packit c32a2d
{
Packit c32a2d
	/* Death is fatal right away. */
Packit c32a2d
	if(deathflag)
Packit c32a2d
	{
Packit c32a2d
		debug("The world wants me to die.");
Packit c32a2d
		return FALSE;
Packit c32a2d
	}
Packit c32a2d
/* 
Packit c32a2d
 * When HAVE_TERMIOS is defined, there is 'q' to terminate a list of songs, so
Packit c32a2d
 * no pressing need to keep up this first second SIGINT hack that was too
Packit c32a2d
 * often mistaken as a bug. [dk]
Packit c32a2d
 * ThOr: Yep, I deactivated the Ctrl+C hack for active control modes.
Packit c32a2d
 *       Though, some sort of hack remains, still using intflag for track skip.
Packit c32a2d
 */
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
	if(!param.term_ctrl)
Packit c32a2d
#endif
Packit c32a2d
	{
Packit c32a2d
		struct timeval now;
Packit c32a2d
		unsigned long secdiff;
Packit c32a2d
		gettimeofday (&now, NULL);
Packit c32a2d
		secdiff = (now.tv_sec - start_time->tv_sec) * 1000;
Packit c32a2d
		if(now.tv_usec >= start_time->tv_usec)
Packit c32a2d
		secdiff += (now.tv_usec - start_time->tv_usec) / 1000;
Packit c32a2d
		else
Packit c32a2d
		secdiff -= (start_time->tv_usec - now.tv_usec) / 1000;
Packit c32a2d
		if (secdiff < 1000)
Packit c32a2d
		{
Packit c32a2d
			debug("got the second interrupt: out of here!");
Packit c32a2d
			return FALSE;
Packit c32a2d
		}
Packit c32a2d
		else
Packit c32a2d
		{
Packit c32a2d
			debug("It's a track advancement message.");
Packit c32a2d
			++skip_tracks;
Packit c32a2d
		}
Packit c32a2d
	}
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
	else if(skip_tracks == 0)
Packit c32a2d
	{
Packit c32a2d
		debug("breaking up");
Packit c32a2d
		return FALSE;
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
	return TRUE; /* Track advancement... no instant kill on generic/windows... */
Packit c32a2d
}
Packit c32a2d
#else
Packit c32a2d
/* On generic systems and win32, there is no decision here... just TRUE. */
Packit c32a2d
#define skip_or_die(a) TRUE
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
int main(int sys_argc, char ** sys_argv)
Packit c32a2d
{
Packit c32a2d
	int result;
Packit c32a2d
	char end_of_files = FALSE;
Packit c32a2d
	long parr;
Packit c32a2d
	char *fname;
Packit c32a2d
	int libpar = 0;
Packit c32a2d
	mpg123_pars *mp;
Packit c32a2d
#if !defined(WIN32) && !defined(GENERIC)
Packit c32a2d
	struct timeval start_time;
Packit c32a2d
#endif
Packit c32a2d
	aux_out = stdout; /* Need to initialize here because stdout is not a constant?! */
Packit c32a2d
#if defined (WANT_WIN32_UNICODE)
Packit c32a2d
	if(win32_cmdline_utf8(&argc, &argv) != 0)
Packit c32a2d
	{
Packit c32a2d
		error("Cannot convert command line to UTF8!");
Packit c32a2d
		safe_exit(76);
Packit c32a2d
	}
Packit c32a2d
#else
Packit c32a2d
	argv = sys_argv;
Packit c32a2d
	argc = sys_argc;
Packit c32a2d
#endif
Packit c32a2d
#if defined (WANT_WIN32_SOCKETS)
Packit c32a2d
	win32_net_init();
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#ifdef WIN32
Packit c32a2d
	/* Despite in Unicode form, the path munging backend is still in ANSI/ASCII
Packit c32a2d
	 * so using _wpgmptr with unicode paths after UTF8 conversion is broken on Windows
Packit c32a2d
	 */
Packit c32a2d
	
Packit c32a2d
	fullprogname = compat_strdup(_pgmptr);
Packit c32a2d
#else
Packit c32a2d
	fullprogname = compat_strdup(argv[0]);
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
	if(!fullprogname)
Packit c32a2d
	{
Packit c32a2d
		error("OOM"); /* Out Of Memory. Don't waste bytes on that error. */
Packit c32a2d
		safe_exit(1);
Packit c32a2d
	}
Packit c32a2d
	/* Extract binary and path, take stuff before/after last / or \ . */
Packit c32a2d
	if(  (prgName = strrchr(fullprogname, '/')) 
Packit c32a2d
	  || (prgName = strrchr(fullprogname, '\\')))
Packit c32a2d
	{
Packit c32a2d
		/* There is some explicit path. */
Packit c32a2d
		prgName[0] = 0; /* End byte for path. */
Packit c32a2d
		prgName++;
Packit c32a2d
		binpath = fullprogname;
Packit c32a2d
	}
Packit c32a2d
	else
Packit c32a2d
	{
Packit c32a2d
		prgName = fullprogname; /* No path separators there. */
Packit c32a2d
		binpath = NULL; /* No path at all. */
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Need to initialize mpg123 lib here for default parameter values. */
Packit c32a2d
Packit c32a2d
	result = mpg123_init();
Packit c32a2d
	if(result != MPG123_OK)
Packit c32a2d
	{
Packit c32a2d
		error1("Cannot initialize mpg123 library: %s", mpg123_plain_strerror(result));
Packit c32a2d
		safe_exit(77);
Packit c32a2d
	}
Packit c32a2d
	cleanup_mpg123 = TRUE;
Packit c32a2d
Packit c32a2d
	mp = mpg123_new_pars(&result); /* This may get leaked on premature exit(), which is mainly a cosmetic issue... */
Packit c32a2d
	if(mp == NULL)
Packit c32a2d
	{
Packit c32a2d
		error1("Crap! Cannot get mpg123 parameters: %s", mpg123_plain_strerror(result));
Packit c32a2d
		safe_exit(78);
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* get default values */
Packit c32a2d
	mpg123_getpar(mp, MPG123_DOWN_SAMPLE, &parr, NULL);
Packit c32a2d
	param.down_sample = (int) parr;
Packit c32a2d
	mpg123_getpar(mp, MPG123_RVA, &param.rva, NULL);
Packit c32a2d
	mpg123_getpar(mp, MPG123_DOWNSPEED, &param.halfspeed, NULL);
Packit c32a2d
	mpg123_getpar(mp, MPG123_UPSPEED, &param.doublespeed, NULL);
Packit c32a2d
	mpg123_getpar(mp, MPG123_OUTSCALE, &param.outscale, NULL);
Packit c32a2d
	mpg123_getpar(mp, MPG123_FLAGS, &parr, NULL);
Packit c32a2d
	mpg123_getpar(mp, MPG123_INDEX_SIZE, &param.index_size, NULL);
Packit c32a2d
	param.flags = (int) parr;
Packit c32a2d
	param.flags |= MPG123_SEEKBUFFER; /* Default on, for HTTP streams. */
Packit c32a2d
	mpg123_getpar(mp, MPG123_RESYNC_LIMIT, &param.resync_limit, NULL);
Packit c32a2d
	mpg123_getpar(mp, MPG123_PREFRAMES, &param.preframes, NULL);
Packit c32a2d
	/* Also need proper default flags from libout123. */
Packit c32a2d
	{
Packit c32a2d
		out123_handle *paro = out123_new();
Packit c32a2d
		out123_getparam_int(paro, OUT123_FLAGS, &param.output_flags);
Packit c32a2d
		out123_del(paro);
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
#ifdef OS2
Packit c32a2d
        _wildcard(&argc,&argv);
Packit c32a2d
#endif
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
	/* Detect terminal on input side, enable control by default. */
Packit c32a2d
	param.term_ctrl = !(term_width(STDIN_FILENO) < 0);
Packit c32a2d
#endif
Packit c32a2d
	while ((result = getlopt(argc, argv, opts)))
Packit c32a2d
	switch (result) {
Packit c32a2d
		case GLO_UNKNOWN:
Packit c32a2d
			fprintf (stderr, "%s: Unknown option \"%s\".\n", 
Packit c32a2d
				prgName, loptarg);
Packit c32a2d
			usage(1);
Packit c32a2d
		case GLO_NOARG:
Packit c32a2d
			fprintf (stderr, "%s: Missing argument for option \"%s\".\n",
Packit c32a2d
				prgName, loptarg);
Packit c32a2d
			usage(1);
Packit c32a2d
	}
Packit c32a2d
	/* Do this _after_ parameter parsing. */
Packit c32a2d
	check_locale(); /* Check/set locale; store if it uses UTF-8. */
Packit c32a2d
Packit c32a2d
	if(param.list_cpu)
Packit c32a2d
	{
Packit c32a2d
		const char **all_dec = mpg123_decoders();
Packit c32a2d
		printf("Builtin decoders:");
Packit c32a2d
		while(*all_dec != NULL){ printf(" %s", *all_dec); ++all_dec; }
Packit c32a2d
		printf("\n");
Packit c32a2d
		mpg123_delete_pars(mp);
Packit c32a2d
		return 0;
Packit c32a2d
	}
Packit c32a2d
	if(param.test_cpu)
Packit c32a2d
	{
Packit c32a2d
		const char **all_dec = mpg123_supported_decoders();
Packit c32a2d
		printf("Supported decoders:");
Packit c32a2d
		while(*all_dec != NULL){ printf(" %s", *all_dec); ++all_dec; }
Packit c32a2d
		printf("\n");
Packit c32a2d
		mpg123_delete_pars(mp);
Packit c32a2d
		return 0;
Packit c32a2d
	}
Packit c32a2d
	if(param.gain != -1)
Packit c32a2d
	{
Packit c32a2d
	    warning("The parameter -g is deprecated and may be removed in the future.");
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	if (loptind >= argc && !param.listname && !param.remote) usage(1);
Packit c32a2d
	/* Init audio as early as possible.
Packit c32a2d
	   If there is the buffer process to be spawned, it shouldn't carry the mpg123_handle with it. */
Packit c32a2d
Packit c32a2d
	/* ========================================================================================================= */
Packit c32a2d
	/* Enterning the leaking zone... we start messing with stuff here that should be taken care of when leaving. */
Packit c32a2d
	/* Don't just exit() or return out...                                                                        */
Packit c32a2d
	/* ========================================================================================================= */
Packit c32a2d
Packit c32a2d
	httpdata_init(&htd);
Packit c32a2d
Packit c32a2d
#if !defined(WIN32) && !defined(GENERIC)
Packit c32a2d
	if(param.remote && !param.verbose)
Packit c32a2d
		param.quiet = 1;
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
	/* Set the frame parameters from command line options */
Packit c32a2d
	if(param.quiet)
Packit c32a2d
	{
Packit c32a2d
		param.flags |= MPG123_QUIET;
Packit c32a2d
		param.output_flags |= OUT123_QUIET;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
#ifdef OPT_3DNOW
Packit c32a2d
	if(dnow != 0) param.cpu = (dnow == SET_3DNOW) ? "3dnow" : "i586";
Packit c32a2d
#endif
Packit c32a2d
	if(param.cpu != NULL && (!strcmp(param.cpu, "auto") || !strcmp(param.cpu, ""))) param.cpu = NULL;
Packit c32a2d
	if(!(  MPG123_OK == (result = mpg123_par(mp, MPG123_VERBOSE, param.verbose, 0))
Packit c32a2d
	    && ++libpar
Packit c32a2d
	    && MPG123_OK == (result = mpg123_par(mp, MPG123_FLAGS, param.flags, 0))
Packit c32a2d
	    && ++libpar
Packit c32a2d
	    && MPG123_OK == (result = mpg123_par(mp, MPG123_DOWN_SAMPLE, param.down_sample, 0))
Packit c32a2d
	    && ++libpar
Packit c32a2d
	    && MPG123_OK == (result = mpg123_par(mp, MPG123_RVA, param.rva, 0))
Packit c32a2d
	    && ++libpar
Packit c32a2d
	    && MPG123_OK == (result = mpg123_par(mp, MPG123_FORCE_RATE, param.force_rate, 0))
Packit c32a2d
	    && ++libpar
Packit c32a2d
	    && MPG123_OK == (result = mpg123_par(mp, MPG123_DOWNSPEED, param.halfspeed, 0))
Packit c32a2d
	    && ++libpar
Packit c32a2d
	    && MPG123_OK == (result = mpg123_par(mp, MPG123_UPSPEED, param.doublespeed, 0))
Packit c32a2d
	    && ++libpar
Packit c32a2d
	    && MPG123_OK == (result = mpg123_par(mp, MPG123_ICY_INTERVAL, 0, 0))
Packit c32a2d
	    && ++libpar
Packit c32a2d
	    && MPG123_OK == (result = mpg123_par(mp, MPG123_RESYNC_LIMIT, param.resync_limit, 0))
Packit c32a2d
	    && ++libpar
Packit c32a2d
	    && MPG123_OK == (result = mpg123_par(mp, MPG123_TIMEOUT, param.timeout, 0))
Packit c32a2d
	    && ++libpar
Packit c32a2d
	    && MPG123_OK == (result = mpg123_par(mp, MPG123_OUTSCALE, param.outscale, 0))
Packit c32a2d
	    && ++libpar
Packit c32a2d
	    && MPG123_OK == (result = mpg123_par(mp, MPG123_PREFRAMES, param.preframes, 0))
Packit c32a2d
			))
Packit c32a2d
	{
Packit c32a2d
		error2("Cannot set library parameter %i: %s", libpar, mpg123_plain_strerror(result));
Packit c32a2d
		safe_exit(45);
Packit c32a2d
	}
Packit c32a2d
	if (!(param.listentry < 0) && !param.quiet) print_title(stderr); /* do not pollute stdout! */
Packit c32a2d
Packit c32a2d
	{
Packit c32a2d
		long default_index;
Packit c32a2d
		mpg123_getpar(mp, MPG123_INDEX_SIZE, &default_index, NULL);
Packit c32a2d
		if( param.index_size != default_index && (result = mpg123_par(mp, MPG123_INDEX_SIZE, param.index_size, 0.)) != MPG123_OK )
Packit c32a2d
		error1("Setting of frame index size failed: %s", mpg123_plain_strerror(result));
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	if(param.force_rate && param.down_sample)
Packit c32a2d
	{
Packit c32a2d
		error("Down sampling and fixed rate options not allowed together!");
Packit c32a2d
		safe_exit(1);
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Now actually get an mpg123_handle. */
Packit c32a2d
	mh = mpg123_parnew(mp, param.cpu, &result);
Packit c32a2d
	if(mh == NULL)
Packit c32a2d
	{
Packit c32a2d
		error1("Crap! Cannot get a mpg123 handle: %s", mpg123_plain_strerror(result));
Packit c32a2d
		safe_exit(77);
Packit c32a2d
	}
Packit c32a2d
	mpg123_delete_pars(mp); /* Don't need the parameters anymore ,they're in the handle now. */
Packit c32a2d
Packit c32a2d
	/* Prepare stream dumping, possibly replacing mpg123 reader. */
Packit c32a2d
	if(dump_open(mh) != 0) safe_exit(78);
Packit c32a2d
Packit c32a2d
	load_equalizer(mh);
Packit c32a2d
Packit c32a2d
#ifdef HAVE_SETPRIORITY
Packit c32a2d
	if(param.aggressive) { /* tst */
Packit c32a2d
		int mypid = getpid();
Packit c32a2d
		if(!param.quiet) fprintf(stderr,"Aggressively trying to increase priority.\n");
Packit c32a2d
		if(setpriority(PRIO_PROCESS,mypid,-20))
Packit c32a2d
			error("Failed to aggressively increase priority.\n");
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#if defined (HAVE_SCHED_SETSCHEDULER) && !defined (__CYGWIN__) && !defined (HAVE_WINDOWS_H)
Packit c32a2d
/* Cygwin --realtime seems to fail when accessing network, using win32 set priority instead */
Packit c32a2d
/* MinGW may have pthread installed, we prefer win32API */
Packit c32a2d
	if (param.realtime) {  /* Get real-time priority */
Packit c32a2d
	  struct sched_param sp;
Packit c32a2d
	  fprintf(stderr,"Getting real-time priority\n");
Packit c32a2d
	  memset(&sp, 0, sizeof(struct sched_param));
Packit c32a2d
	  sp.sched_priority = sched_get_priority_min(SCHED_FIFO);
Packit c32a2d
	  if (sched_setscheduler(0, SCHED_RR, &sp) == -1)
Packit c32a2d
	    error("Can't get realtime priority\n");
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* make sure not Cygwin, it doesn't need it */
Packit c32a2d
#if defined(WIN32) && defined(HAVE_WINDOWS_H)
Packit c32a2d
	/* argument "3" is equivalent to realtime priority class */
Packit c32a2d
	win32_set_priority( param.realtime ? 3 : param.w32_priority);
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
	/* TODO: There's some memory leaking on fatal safe_exits().
Packit c32a2d
	   This is a cosmetic issue, though. */
Packit c32a2d
Packit c32a2d
Packit c32a2d
	/* Initializing output after the priority stuff, might influence
Packit c32a2d
	   buffer process. */
Packit c32a2d
	ao = out123_new();
Packit c32a2d
	if(!ao)
Packit c32a2d
	{
Packit c32a2d
		if(!param.quiet)
Packit c32a2d
			error("Failed to allocate output.");
Packit c32a2d
		safe_exit(97);
Packit c32a2d
	}
Packit c32a2d
	if
Packit c32a2d
	( 0
Packit c32a2d
	||	out123_param_int(ao, OUT123_FLAGS, param.output_flags)
Packit c32a2d
	|| out123_param_float(ao, OUT123_PRELOAD, param.preload)
Packit c32a2d
	|| out123_param_int(ao, OUT123_GAIN, param.gain)
Packit c32a2d
	|| out123_param_int(ao, OUT123_VERBOSE, param.verbose)
Packit c32a2d
	|| out123_param_string(ao, OUT123_NAME, param.name)
Packit c32a2d
	|| out123_param_string(ao, OUT123_BINDIR, binpath)
Packit c32a2d
	|| out123_param_float(ao, OUT123_DEVICEBUFFER, param.device_buffer)
Packit c32a2d
	)
Packit c32a2d
	{
Packit c32a2d
		if(!param.quiet)
Packit c32a2d
			error("Error setting output parameters. Do you need a usage reminder?");
Packit c32a2d
		safe_exit(98);
Packit c32a2d
	}
Packit c32a2d
	check_fatal_output(out123_set_buffer(ao, param.usebuffer*1024));
Packit c32a2d
	check_fatal_output(out123_open( ao
Packit c32a2d
	,	param.output_module, param.output_device ));
Packit c32a2d
	out123_getparam_int(ao, OUT123_PROPFLAGS, &output_propflags);
Packit c32a2d
Packit c32a2d
	if(!param.remote) prepare_playlist(argc, argv);
Packit c32a2d
Packit c32a2d
#if !defined(WIN32) && !defined(GENERIC)
Packit c32a2d
	/* Remote mode is special... but normal console and terminal-controlled operation needs to catch the SIGINT.
Packit c32a2d
	   For one it serves for track skip when not in terminal control mode.
Packit c32a2d
	   The more important use being a graceful exit, including telling the buffer process what's going on. */
Packit c32a2d
	if(!param.remote)
Packit c32a2d
		catchsignal(SIGINT, catch_interrupt);
Packit c32a2d
	/* Need to catch things to exit cleanly, not messing up the terminal. */
Packit c32a2d
	catchsignal(SIGTERM, catch_fatal_term);
Packit c32a2d
	catchsignal(SIGPIPE, catch_fatal_pipe);
Packit c32a2d
#endif
Packit c32a2d
	/* Now either check caps myself or query buffer for that. */
Packit c32a2d
	audio_capabilities(ao, mh);
Packit c32a2d
Packit c32a2d
	if(param.remote) {
Packit c32a2d
		int ret;
Packit c32a2d
		ret = control_generic(mh);
Packit c32a2d
		safe_exit(ret);
Packit c32a2d
	}
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
			term_init();
Packit c32a2d
#endif
Packit c32a2d
	if(APPFLAG(MPG123APP_CONTINUE)) frames_left = param.frame_number;
Packit c32a2d
Packit c32a2d
	while ((fname = get_next_file()))
Packit c32a2d
	{
Packit c32a2d
		char *dirname, *filename;
Packit c32a2d
		int newdir;
Packit c32a2d
		/* skip_tracks includes the previous one. */
Packit c32a2d
		if(skip_tracks) --skip_tracks;
Packit c32a2d
		if(skip_tracks)
Packit c32a2d
		{
Packit c32a2d
			debug("Skipping this track.");
Packit c32a2d
			continue;
Packit c32a2d
		}
Packit c32a2d
		if(param.delay > 0)
Packit c32a2d
		{
Packit c32a2d
			controlled_drain();
Packit c32a2d
			/* One should enable terminal control during that sleeping phase! */
Packit c32a2d
			if(param.verbose > 2) fprintf(stderr, "Note: pausing %i seconds before next track.\n", param.delay);
Packit c32a2d
#ifdef WIN32
Packit c32a2d
			Sleep(param.delay*1000);
Packit c32a2d
#else
Packit c32a2d
			sleep(param.delay);
Packit c32a2d
#endif
Packit c32a2d
		}
Packit c32a2d
		if(!APPFLAG(MPG123APP_CONTINUE)) frames_left = param.frame_number;
Packit c32a2d
Packit c32a2d
		debug1("Going to play %s", strcmp(fname, "-") ? fname : "standard input");
Packit c32a2d
Packit c32a2d
		if(intflag || !open_track(fname))
Packit c32a2d
		{
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
			/* We need the opportunity to cancel in case of --loop -1 . */
Packit c32a2d
			if(param.term_ctrl) term_control(mh, ao);
Packit c32a2d
			else
Packit c32a2d
#endif
Packit c32a2d
			/* No wait for a second interrupt before we started playing. */
Packit c32a2d
			if(intflag) break;
Packit c32a2d
Packit c32a2d
			/* We already interrupted this cycle, start fresh with the next one. */
Packit c32a2d
			intflag = FALSE;
Packit c32a2d
			continue;
Packit c32a2d
		}
Packit c32a2d
Packit c32a2d
		if(!param.quiet) fprintf(stderr, "\n");
Packit c32a2d
		if(param.index)
Packit c32a2d
		{
Packit c32a2d
			if(param.verbose) fprintf(stderr, "indexing...\r");
Packit c32a2d
			mpg123_scan(mh);
Packit c32a2d
		}
Packit c32a2d
		/*
Packit c32a2d
			Only trigger a seek if we do not want to start with the first frame.
Packit c32a2d
			Rationale: Because of libmpg123 sample accuracy, this could cause an unnecessary backwards seek, that even may fail on non-seekable streams.
Packit c32a2d
			For start frame of 0, we are already at the correct position!
Packit c32a2d
		*/
Packit c32a2d
		framenum = 0;
Packit c32a2d
		if(param.start_frame > 0)
Packit c32a2d
		framenum = mpg123_seek_frame(mh, param.start_frame, SEEK_SET);
Packit c32a2d
Packit c32a2d
		if(APPFLAG(MPG123APP_CONTINUE)) param.start_frame = 0;
Packit c32a2d
Packit c32a2d
		if(framenum < 0)
Packit c32a2d
		{
Packit c32a2d
			error1("Initial seek failed: %s", mpg123_strerror(mh));
Packit c32a2d
			if(mpg123_errcode(mh) == MPG123_BAD_OUTFORMAT)
Packit c32a2d
			{
Packit c32a2d
				fprintf(stderr, "%s", "So, you have trouble getting an output format... this is the matrix of currently possible formats:\n");
Packit c32a2d
				print_capabilities(ao, mh);
Packit c32a2d
				fprintf(stderr, "%s", "Somehow the input data and your choices don't allow one of these.\n");
Packit c32a2d
			}
Packit c32a2d
			mpg123_close(mh);
Packit c32a2d
			continue;
Packit c32a2d
		}
Packit c32a2d
Packit c32a2d
		/* Prinout and xterm title need this, possibly independently. */
Packit c32a2d
		newdir = split_dir_file(fname ? fname : "standard input", &dirname, &filename);
Packit c32a2d
Packit c32a2d
		if (!param.quiet)
Packit c32a2d
		{
Packit c32a2d
			size_t plpos;
Packit c32a2d
			size_t plfill;
Packit c32a2d
			long plloop;
Packit c32a2d
			plpos = playlist_pos(&plfill, &plloop);
Packit c32a2d
			if(newdir) fprintf(stderr, "Directory: %s\n", dirname);
Packit c32a2d
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
		/* Reminder about terminal usage. */
Packit c32a2d
		if(param.term_ctrl) term_hint();
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
			if(param.verbose)
Packit c32a2d
			{
Packit c32a2d
				if(plloop < 0)
Packit c32a2d
					fprintf(stderr, "Repeating endlessly.\n");
Packit c32a2d
				else if(plloop > 1)
Packit c32a2d
					fprintf( stderr, "Repeating %ld %s.\n"
Packit c32a2d
					,	plloop-1, plloop > 2 ? "times" : "time" );
Packit c32a2d
			}
Packit c32a2d
			fprintf( stderr, "Playing MPEG stream %"SIZE_P" of %"SIZE_P": %s ...\n"
Packit c32a2d
			,	(size_p)plpos, (size_p)plfill, filename );
Packit c32a2d
			if(htd.icy_name.fill) fprintf(stderr, "ICY-NAME: %s\n", htd.icy_name.p);
Packit c32a2d
			if(htd.icy_url.fill)  fprintf(stderr, "ICY-URL: %s\n",  htd.icy_url.p);
Packit c32a2d
		}
Packit c32a2d
#if !defined(GENERIC)
Packit c32a2d
{
Packit c32a2d
	const char *term_type;
Packit c32a2d
	term_type = getenv("TERM");
Packit c32a2d
	if(term_type && param.xterm_title)
Packit c32a2d
	{
Packit c32a2d
		if(!strncmp(term_type,"xterm",5) || !strncmp(term_type,"rxvt",4))
Packit c32a2d
		fprintf(stderr, "\033]0;%s\007", filename);
Packit c32a2d
		else if(!strncmp(term_type,"screen",6))
Packit c32a2d
		fprintf(stderr, "\033k%s\033\\", filename);
Packit c32a2d
		else if(!strncmp(term_type,"iris-ansi",9))
Packit c32a2d
		fprintf(stderr, "\033P1.y %s\033\\\033P3.y%s\033\\", filename, filename);
Packit c32a2d
Packit c32a2d
		fflush(stderr); /* Paranoia: will the buffer buffer the escapes? */
Packit c32a2d
	}
Packit c32a2d
}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* Rethink that SIGINT logic... */
Packit c32a2d
#if !defined(WIN32) && !defined(GENERIC)
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
		if(!param.term_ctrl)
Packit c32a2d
#endif
Packit c32a2d
			gettimeofday (&start_time, NULL);
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
		while(!intflag)
Packit c32a2d
		{
Packit c32a2d
			int meta;
Packit c32a2d
			if(param.frame_number > -1)
Packit c32a2d
			{
Packit c32a2d
				debug1("frames left: %li", (long) frames_left);
Packit c32a2d
				if(!frames_left)
Packit c32a2d
				{
Packit c32a2d
					if(APPFLAG(MPG123APP_CONTINUE)) end_of_files = TRUE;
Packit c32a2d
Packit c32a2d
					break;
Packit c32a2d
				}
Packit c32a2d
			}
Packit c32a2d
			if(!play_frame()) break;
Packit c32a2d
			if(!param.quiet)
Packit c32a2d
			{
Packit c32a2d
				meta = mpg123_meta_check(mh);
Packit c32a2d
				if(meta & (MPG123_NEW_ID3|MPG123_NEW_ICY))
Packit c32a2d
				{
Packit c32a2d
					if(meta & MPG123_NEW_ID3) print_id3_tag(mh, param.long_id3, stderr);
Packit c32a2d
					if(meta & MPG123_NEW_ICY) print_icy(mh, stderr);
Packit c32a2d
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
					if(!param.term_ctrl) /* Terminal user can query meta data again. */
Packit c32a2d
#endif
Packit c32a2d
					mpg123_meta_free(mh); /* Do not waste memory after delivering. */
Packit c32a2d
				}
Packit c32a2d
			}
Packit c32a2d
			if(!fresh && param.verbose)
Packit c32a2d
			{
Packit c32a2d
				if(param.verbose > 1 || !(framenum & 0x7)) print_stat(mh,0,ao,1);
Packit c32a2d
			}
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
			if(!param.term_ctrl) continue;
Packit c32a2d
			else term_control(mh, ao);
Packit c32a2d
#endif
Packit c32a2d
		}
Packit c32a2d
Packit c32a2d
	if(!param.smooth && !intflag)
Packit c32a2d
		controlled_drain();
Packit c32a2d
	if(param.verbose) print_stat(mh,0,ao,0);
Packit c32a2d
Packit c32a2d
	if(!param.quiet)
Packit c32a2d
	{
Packit c32a2d
		double secs;
Packit c32a2d
		long frank;
Packit c32a2d
		fprintf(stderr, "\n");
Packit c32a2d
		if(mpg123_getstate(mh, MPG123_FRANKENSTEIN, &frank, NULL) == MPG123_OK && frank)
Packit c32a2d
		fprintf(stderr, "This was a Frankenstein track.\n");
Packit c32a2d
Packit c32a2d
		mpg123_position(mh, 0, 0, NULL, NULL, &secs, NULL);
Packit c32a2d
		fprintf(stderr,"[%d:%02d] Decoding of %s finished.\n", (int)(secs / 60), ((int)secs) % 60, filename);
Packit c32a2d
	}
Packit c32a2d
	else if(param.verbose) fprintf(stderr, "\n");
Packit c32a2d
Packit c32a2d
	close_track();
Packit c32a2d
Packit c32a2d
	if (intflag)
Packit c32a2d
	{
Packit c32a2d
		if(!skip_or_die(&start_time)) break;
Packit c32a2d
Packit c32a2d
        intflag = FALSE;
Packit c32a2d
Packit c32a2d
		if(!param.smooth)
Packit c32a2d
			out123_drop(ao);
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
		if(end_of_files) break;
Packit c32a2d
	} /* end of loop over input files */
Packit c32a2d
Packit c32a2d
	if(APPFLAG(MPG123APP_CONTINUE))
Packit c32a2d
	{
Packit c32a2d
		continue_msg("CONTINUE");
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Free up memory used by playlist */    
Packit c32a2d
	if(!param.remote) free_playlist();
Packit c32a2d
Packit c32a2d
	safe_exit(0); /* That closes output and restores terminal, too. */
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void print_title(FILE *o)
Packit c32a2d
{
Packit c32a2d
	fprintf(o, "High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3\n");
Packit c32a2d
	fprintf(o, "\tversion %s; written and copyright by Michael Hipp and others\n", PACKAGE_VERSION);
Packit c32a2d
	fprintf(o, "\tfree software (LGPL) without any warranty but with best wishes\n");
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void usage(int err)  /* print syntax & exit */
Packit c32a2d
{
Packit c32a2d
	FILE* o = stdout;
Packit c32a2d
	if(err)
Packit c32a2d
	{
Packit c32a2d
		o = stderr; 
Packit c32a2d
		fprintf(o, "You made some mistake in program usage... let me briefly remind you:\n\n");
Packit c32a2d
	}
Packit c32a2d
	print_title(o);
Packit c32a2d
	fprintf(o,"\nusage: %s [option(s)] [file(s) | URL(s) | -]\n", prgName);
Packit c32a2d
	fprintf(o,"supported options [defaults in brackets]:\n");
Packit c32a2d
	fprintf(o,"   -v    increase verbosity level       -q    quiet (don't print title)\n");
Packit c32a2d
	fprintf(o,"   -t    testmode (no output)           -s    write to stdout\n");
Packit c32a2d
	fprintf(o,"   -w f  write output as WAV file\n");
Packit c32a2d
	fprintf(o,"   -k n  skip first n frames [0]        -n n  decode only n frames [all]\n");
Packit c32a2d
	fprintf(o,"   -c    check range violations         -y    DISABLE resync on errors\n");
Packit c32a2d
	fprintf(o,"   -b n  output buffer: n Kbytes [0]    -f n  change scalefactor [%li]\n", param.outscale);
Packit c32a2d
	fprintf(o,"   -r n  set/force samplerate [auto]\n");
Packit c32a2d
	fprintf(o,"   -o m  select output module           -a d  set audio device\n");
Packit c32a2d
	fprintf(o,"   -2    downsample 1:2 (22 kHz)        -4    downsample 1:4 (11 kHz)\n");
Packit c32a2d
	fprintf(o,"   -d n  play every n'th frame only     -h n  play every frame n times\n");
Packit c32a2d
	fprintf(o,"   -0    decode channel 0 (left) only   -1    decode channel 1 (right) only\n");
Packit c32a2d
#ifdef NETWORK
Packit c32a2d
	fprintf(o,"   -m    mix both channels (mono)       -p p  use HTTP proxy p [$HTTP_PROXY]\n");
Packit c32a2d
#else
Packit c32a2d
	fprintf(o,"   -m    mix both channels (mono)\n");
Packit c32a2d
#endif
Packit c32a2d
	#ifdef HAVE_SCHED_SETSCHEDULER
Packit c32a2d
	fprintf(o,"   -@ f  read filenames/URLs from f     -T get realtime priority\n");
Packit c32a2d
	#else
Packit c32a2d
	fprintf(o,"   -@ f  read filenames/URLs from f\n");
Packit c32a2d
	#endif
Packit c32a2d
	fprintf(o,"   -z    shuffle play (with wildcards)  -Z    random play\n");
Packit c32a2d
	fprintf(o,"   -u a  HTTP authentication string     -E f  Equalizer, data from file\n");
Packit c32a2d
#ifdef HAVE_TERMIOS
Packit c32a2d
	fprintf(o,"   -C    enable control keys            --no-gapless  not skip junk/padding in mp3s\n");
Packit c32a2d
#else
Packit c32a2d
	fprintf(o,"                                        --no-gapless  not skip junk/padding in mp3s\n");
Packit c32a2d
#endif
Packit c32a2d
	fprintf(o,"   -?    this help                      --version  print name + version\n");
Packit c32a2d
	fprintf(o,"See the manpage "PACKAGE_NAME"(1) or call %s with --longhelp for more parameters and information.\n", prgName);
Packit c32a2d
	safe_exit(err);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void want_usage(char* arg)
Packit c32a2d
{
Packit c32a2d
	usage(0);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void long_usage(int err)
Packit c32a2d
{
Packit c32a2d
	mpg123_string *enclist;
Packit c32a2d
	FILE* o = stdout;
Packit c32a2d
	if(err)
Packit c32a2d
	{
Packit c32a2d
  	o = stderr; 
Packit c32a2d
  	fprintf(o, "You made some mistake in program usage... let me remind you:\n\n");
Packit c32a2d
	}
Packit c32a2d
	enclist = audio_enclist();
Packit c32a2d
	print_title(o);
Packit c32a2d
	fprintf(o,"\nusage: %s [option(s)] [file(s) | URL(s) | -]\n", prgName);
Packit c32a2d
Packit c32a2d
	fprintf(o,"\ninput options\n\n");
Packit c32a2d
	fprintf(o," -k <n> --skip <n>         skip n frames at beginning\n");
Packit c32a2d
	fprintf(o,"        --skip-id3v2       skip ID3v2 tags without parsing\n");
Packit c32a2d
	fprintf(o," -n     --frames <n>       play only <n> frames of every stream\n");
Packit c32a2d
	fprintf(o,"        --fuzzy            Enable fuzzy seeks (guessing byte offsets or using approximate seek points from Xing TOC)\n");
Packit c32a2d
	fprintf(o," -y     --no-resync        DISABLES resync on error (--resync is deprecated)\n");
Packit c32a2d
#ifdef NETWORK
Packit c32a2d
	fprintf(o," -p <f> --proxy <f>        set WWW proxy\n");
Packit c32a2d
	fprintf(o," -u     --auth             set auth values for HTTP access\n");
Packit c32a2d
	fprintf(o,"        --ignore-mime      ignore HTTP MIME types (content-type)\n");
Packit c32a2d
#endif
Packit c32a2d
	fprintf(o,"        --no-seekbuffer    disable seek buffer\n");
Packit c32a2d
	fprintf(o," -@ <f> --list <f>         play songs in playlist <f> (plain list, m3u, pls (shoutcast))\n");
Packit c32a2d
	fprintf(o," -l <n> --listentry <n>    play nth title in playlist; show whole playlist for n < 0\n");
Packit c32a2d
	fprintf(o,"        --continue         playlist continuation mode (see man page)\n");
Packit c32a2d
	fprintf(o,"        --loop <n>         loop track(s) <n> times, < 0 means infinite loop (not with --random!)\n");
Packit c32a2d
	fprintf(o,"        --keep-open        (--remote mode only) keep loaded file open after reaching end\n");
Packit c32a2d
	fprintf(o,"        --timeout <n>      Timeout in seconds before declaring a stream dead (if <= 0, wait forever)\n");
Packit c32a2d
	fprintf(o," -z     --shuffle          shuffle song-list before playing\n");
Packit c32a2d
	fprintf(o," -Z     --random           full random play\n");
Packit c32a2d
	fprintf(o,"        --no-icy-meta      Do not accept ICY meta data\n");
Packit c32a2d
	fprintf(o," -i     --index            index / scan through the track before playback\n");
Packit c32a2d
	fprintf(o,"        --index-size <n>   change size of frame index\n");
Packit c32a2d
	fprintf(o,"        --preframes  <n>   number of frames to decode in advance after seeking (to keep layer 3 bit reservoir happy)\n");
Packit c32a2d
	fprintf(o,"        --resync-limit <n> Set number of bytes to search for valid MPEG data; <0 means search whole stream.\n");
Packit c32a2d
	fprintf(o,"        --streamdump <f>   Dump a copy of input data (as read by libmpg123) to given file.\n");
Packit c32a2d
	fprintf(o,"        --icy-interval <n> Enforce ICY interval in bytes (for playing a stream dump.\n");
Packit c32a2d
	fprintf(o,"        --ignore-streamlength Ignore header info about length of MPEG streams.");
Packit c32a2d
	fprintf(o,"\noutput/processing options\n\n");
Packit c32a2d
	fprintf(o," -o <o> --output <o>       select audio output module\n");
Packit c32a2d
	fprintf(o,"        --list-modules     list the available modules\n");
Packit c32a2d
	fprintf(o," -a <d> --audiodevice <d>  select audio device (depending on chosen module)\n");
Packit c32a2d
	fprintf(o," -s     --stdout           write raw audio to stdout (host native format)\n");
Packit c32a2d
	fprintf(o," -S     --STDOUT           play AND output stream (not implemented yet)\n");
Packit c32a2d
	fprintf(o," -w <f> --wav <f>          write samples as WAV file in <f> (- is stdout)\n");
Packit c32a2d
	fprintf(o,"        --au <f>           write samples as Sun AU file in <f> (- is stdout)\n");
Packit c32a2d
	fprintf(o,"        --cdr <f>          write samples as raw CD audio file in <f> (- is stdout)\n");
Packit c32a2d
	fprintf(o,"        --reopen           force close/open on audiodevice\n");
Packit c32a2d
	#ifdef OPT_MULTI
Packit c32a2d
	fprintf(o,"        --cpu <string>     set cpu optimization\n");
Packit c32a2d
	fprintf(o,"        --test-cpu         list optimizations possible with cpu and exit\n");
Packit c32a2d
	fprintf(o,"        --list-cpu         list builtin optimizations and exit\n");
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_3DNOW
Packit c32a2d
	fprintf(o,"        --test-3dnow       display result of 3DNow! autodetect and exit (obsoleted by --cpu)\n");
Packit c32a2d
	fprintf(o,"        --force-3dnow      force use of 3DNow! optimized routine (obsoleted by --test-cpu)\n");
Packit c32a2d
	fprintf(o,"        --no-3dnow         force use of floating-pointer routine (obsoleted by --cpu)\n");
Packit c32a2d
	#endif
Packit c32a2d
	fprintf(o," -g     --gain             [DEPRECATED] set audio hardware output gain\n");
Packit c32a2d
	fprintf(o," -f <n> --scale <n>        scale output samples (soft gain - based on 32768), default=%li)\n", param.outscale);
Packit c32a2d
	fprintf(o,"        --rva-mix,\n");
Packit c32a2d
	fprintf(o,"        --rva-radio        use RVA2/ReplayGain values for mix/radio mode\n");
Packit c32a2d
	fprintf(o,"        --rva-album,\n");
Packit c32a2d
	fprintf(o,"        --rva-audiophile   use RVA2/ReplayGain values for album/audiophile mode\n");
Packit c32a2d
	fprintf(o," -0     --left --single0   play only left channel\n");
Packit c32a2d
	fprintf(o," -1     --right --single1  play only right channel\n");
Packit c32a2d
	fprintf(o," -m     --mono --mix       mix stereo to mono\n");
Packit c32a2d
	fprintf(o,"        --stereo           duplicate mono channel\n");
Packit c32a2d
	fprintf(o," -r     --rate             force a specific audio output rate\n");
Packit c32a2d
	fprintf(o," -2     --2to1             2:1 downsampling\n");
Packit c32a2d
	fprintf(o," -4     --4to1             4:1 downsampling\n");
Packit c32a2d
  fprintf(o,"        --pitch <value>    set hardware pitch (speedup/down, 0 is neutral; 0.05 is 5%%)\n");
Packit c32a2d
	fprintf(o,"        --8bit             force 8 bit output\n");
Packit c32a2d
	fprintf(o,"        --float            force floating point output (internal precision)\n");
Packit c32a2d
	fprintf(o," -e <c> --encoding <c>     force a specific encoding (%s)\n"
Packit c32a2d
	,	enclist != NULL ? enclist->p : "OOM!");
Packit c32a2d
	fprintf(o," -d n   --doublespeed n    play only every nth frame\n");
Packit c32a2d
	fprintf(o," -h n   --halfspeed   n    play every frame n times\n");
Packit c32a2d
	fprintf(o,"        --equalizer        exp.: scales freq. bands acrd. to 'equalizer.dat'\n");
Packit c32a2d
	fprintf(o,"        --gapless          remove padding/junk on mp3s (best with Lame tag)\n");
Packit c32a2d
	fprintf(o,"                           This is on by default when libmpg123 supports it.\n");
Packit c32a2d
	fprintf(o,"        --no-gapless       disable gapless mode, not remove padding/junk\n");
Packit c32a2d
	fprintf(o,"        --no-infoframe     disable parsing of Xing/Lame/VBR/Info frame\n");
Packit c32a2d
	fprintf(o," -D n   --delay n          insert a delay of n seconds before each track\n");
Packit c32a2d
	fprintf(o," -o h   --headphones       (aix/hp/sun) output on headphones\n");
Packit c32a2d
	fprintf(o," -o s   --speaker          (aix/hp/sun) output on speaker\n");
Packit c32a2d
	fprintf(o," -o l   --lineout          (aix/hp/sun) output to lineout\n");
Packit c32a2d
#ifndef NOXFERMEM
Packit c32a2d
	fprintf(o," -b <n> --buffer <n>       set play buffer (\"output cache\")\n");
Packit c32a2d
	fprintf(o,"        --preload <value>  fraction of buffer to fill before playback\n");
Packit c32a2d
	fprintf(o,"        --smooth           keep buffer over track boundaries\n");
Packit c32a2d
#endif
Packit c32a2d
	fprintf(o,"        --devbuffer <s>    set device buffer in seconds; <= 0 means default\n");
Packit c32a2d
Packit c32a2d
	fprintf(o,"\nmisc options\n\n");
Packit c32a2d
	fprintf(o," -t     --test             only decode, no output (benchmark)\n");
Packit c32a2d
	fprintf(o," -c     --check            count and display clipped samples\n");
Packit c32a2d
	fprintf(o," -v[*]  --verbose          increase verboselevel\n");
Packit c32a2d
	fprintf(o," -q     --quiet            quiet mode\n");
Packit c32a2d
	#ifdef HAVE_TERMIOS
Packit c32a2d
	fprintf(o," -C     --control          enable terminal control keys (else auto detect)\n");
Packit c32a2d
	fprintf(o,"        --no-control       disable terminal control keys (disable auto detect)\n");
Packit c32a2d
	fprintf(o,"        --ctrlusr1 <c>     control key (characer) to map to SIGUSR1\n");
Packit c32a2d
	fprintf(o,"                           (default is for stop/start)\n");
Packit c32a2d
	fprintf(o,"        --ctrlusr2 <c>     control key (characer) to map to SIGUSR2\n");
Packit c32a2d
	fprintf(o,"                           (default is for next track)\n");
Packit c32a2d
	#endif
Packit c32a2d
	#ifndef GENERIC
Packit c32a2d
	fprintf(o,"        --title            set terminal title to filename\n");
Packit c32a2d
	#endif
Packit c32a2d
	fprintf(o,"        --name <n>         set instance name (used in various places)\n");
Packit c32a2d
	fprintf(o,"        --long-tag         spacy id3 display with every item on a separate line\n");
Packit c32a2d
	fprintf(o,"        --lyrics           show lyrics (from ID3v2 USLT frame)\n");
Packit c32a2d
	fprintf(o,"        --utf8             Regardless of environment, print metadata in UTF-8.\n");
Packit c32a2d
	fprintf(o," -R     --remote           generic remote interface\n");
Packit c32a2d
	fprintf(o,"        --remote-err       force use of stderr for generic remote interface\n");
Packit c32a2d
#ifdef FIFO
Packit c32a2d
	fprintf(o,"        --fifo <path>      open a FIFO at <path> for commands instead of stdin\n");
Packit c32a2d
#endif
Packit c32a2d
	#ifdef HAVE_SETPRIORITY
Packit c32a2d
	fprintf(o,"        --aggressive       tries to get higher priority (nice)\n");
Packit c32a2d
	#endif
Packit c32a2d
	#if defined (HAVE_SCHED_SETSCHEDULER) || defined (HAVE_WINDOWS_H)
Packit c32a2d
	fprintf(o," -T     --realtime         tries to get realtime priority\n");
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef HAVE_WINDOWS_H
Packit c32a2d
	fprintf(o,"        --priority <n>     use specified process priority\n");
Packit c32a2d
	fprintf(o,"                           accepts -2 to 3 as integer arguments\n");
Packit c32a2d
	fprintf(o,"                           -2 as idle, 0 as normal and 3 as realtime.\n");
Packit c32a2d
	#endif
Packit c32a2d
	fprintf(o," -?     --help             give compact help\n");
Packit c32a2d
	fprintf(o,"        --longhelp         give this long help listing\n");
Packit c32a2d
	fprintf(o,"        --version          give name / version string\n");
Packit c32a2d
Packit c32a2d
	fprintf(o,"\nSee the manpage "PACKAGE_NAME"(1) for more information.\n");
Packit c32a2d
	mpg123_free_string(enclist);
Packit c32a2d
	free(enclist);
Packit c32a2d
	safe_exit(err);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void want_long_usage(char* arg)
Packit c32a2d
{
Packit c32a2d
	long_usage(0);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void give_version(char* arg)
Packit c32a2d
{
Packit c32a2d
	fprintf(stdout, PACKAGE_NAME" "PACKAGE_VERSION"\n");
Packit c32a2d
	safe_exit(0);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void continue_msg(const char *name)
Packit c32a2d
{
Packit c32a2d
	fprintf( aux_out, "\n[%s] track %"SIZE_P" frame %"OFF_P"\n", name
Packit c32a2d
	,	(size_p)playlist_pos(NULL, NULL), (off_p)framenum );
Packit c32a2d
}