mirror of
http://mpg123.de/trunk/.git
synced 2025-08-07 21:02:55 +03:00
Add --continue mode, with example script to utilize it.
git-svn-id: svn://scm.orgis.org/mpg123/trunk@3120 35dc7657-300d-0410-a2e5-dc2837fedb53
This commit is contained in:
@@ -95,5 +95,6 @@ EXTRA_DIST = \
|
||||
ports/Xcode/mpg123.h \
|
||||
ports/Xcode/mpg123.xcodeproj/project.pbxproj \
|
||||
scripts/benchmark-cpu.pl \
|
||||
scripts/tag_lyrics.py
|
||||
scripts/tag_lyrics.py \
|
||||
scripts/con_play
|
||||
|
||||
|
2
NEWS
2
NEWS
@@ -1,9 +1,9 @@
|
||||
1.15.0
|
||||
---
|
||||
|
||||
- added --continue (also see scripts/conplay)
|
||||
- Set xterm title always if asked, disregarding the -q switch (if you want fully quiet, don't specify --title).
|
||||
|
||||
|
||||
1.14.0
|
||||
---
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
.TH mpg123 1 "31 Jan 2008"
|
||||
.TH mpg123 1 "22 Apr 2012"
|
||||
.SH NAME
|
||||
mpg123 \- play audio MPEG 1.0/2.0/2.5 stream (layers 1, 2 and 3)
|
||||
.SH SYNOPSIS
|
||||
@@ -101,6 +101,11 @@ Of the playlist, play specified entry only.
|
||||
.I n
|
||||
is the number of entry starting at 1. A value of 0 is the default and means playling the whole list, a negative value means showing of the list of titles with their numbers...
|
||||
.TP
|
||||
\fB\-\^\-continue
|
||||
Enable playlist continuation mode. This changes frame skipping to apply only to the first track and also continues to play following tracks in playlist after the selected one. Also, the option to play a number of frames only applies to the whole playlist. Basically, this tries to treat the playlist more like one big stream (like, an audio book).
|
||||
The current track number in list (1-based) and frame number (0-based) are printed at exit (useful if you interrupted playback and want to continue later).
|
||||
Note that the continuation info is printed to standard output unless the switch for piping audio data to standard out is used. Also, it really makes sense to work with actual playlist files instead of lists of file names as arguments, to keep track positions consistent.
|
||||
.TP
|
||||
\fB\-\-loop \fItimes\fR
|
||||
for looping track(s) a certain number of times, < 0 means infinite loop (not with \-\-random!).
|
||||
.TP
|
||||
|
89
scripts/conplay
Executable file
89
scripts/conplay
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/bin/env perl
|
||||
|
||||
# Hacked by Thomas Orgis, use at your leisure.
|
||||
|
||||
use strict;
|
||||
|
||||
my @mpg123_command = qw(mpg123 --continue -Cv --rva-album);
|
||||
my $listfile = "conplay.m3u";
|
||||
my $glob = '*.mp[123]';
|
||||
|
||||
my $dir = shift;
|
||||
|
||||
unless(defined $dir)
|
||||
{
|
||||
print STDERR "\nThis little wrapper runs $mpg123_command[0] on a given directory (hand in '.' for the current one), playing all $glob files therein in terminal control mode. The extra trick is that a playlist file ($listfile) is read and updated (created) with the position you left playback at (via 'q' key), to return on next invokation.\n\n";
|
||||
print STDERR "The name stands for CONtinued PLAYback. What did you think?;-)\n\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
chdir($dir) or die "Cannot enter $dir ($!)!\n";
|
||||
|
||||
print STDERR "Playing things in: $dir\n";
|
||||
|
||||
my @files;
|
||||
my $entry = 1;
|
||||
my $frame = 0;
|
||||
|
||||
if(-e $listfile)
|
||||
{
|
||||
open(LIST, '<', $listfile) or die "Cannot read playlist ($!)!\n";
|
||||
while(<LIST>)
|
||||
{
|
||||
chomp;
|
||||
unless(/^#/)
|
||||
{
|
||||
push(@files, $_);
|
||||
}
|
||||
elsif(/^#\s*current entry:\s*(\d+)$/)
|
||||
{
|
||||
$entry = $1;
|
||||
}
|
||||
elsif(/^#\s*current frame:\s*(\d+)$/)
|
||||
{
|
||||
$frame = $1;
|
||||
}
|
||||
}
|
||||
close(LIST);
|
||||
}
|
||||
else
|
||||
{
|
||||
@files = glob($glob);
|
||||
write_list();
|
||||
}
|
||||
|
||||
if($entry < 0 or $entry > $#files or $frame < 0)
|
||||
{
|
||||
die "You got bad data in your playlist file. Clean that up.\n";
|
||||
}
|
||||
|
||||
push(@mpg123_command, '-k', $frame, '--listentry', $entry, '-@', $listfile);
|
||||
print STDERR "running player:\n\t@mpg123_command\n\n";
|
||||
|
||||
open(MPG123, '-|', @mpg123_command) or die "Cannot run mpg123!";
|
||||
while(<MPG123>)
|
||||
{
|
||||
print STDOUT $_;
|
||||
if(/^\[CONTINUE\]\s+track\s+(\d+)\s+frame\s+(\d+)/)
|
||||
{
|
||||
$entry = $1;
|
||||
$frame = $2;
|
||||
}
|
||||
}
|
||||
close(MPG123);
|
||||
|
||||
print STDERR "Continue point is in track $entry, frame $frame.\n";
|
||||
write_list();
|
||||
|
||||
sub write_list
|
||||
{
|
||||
open(LIST, '>', $listfile) or die "Cannot write Playlist";
|
||||
print LIST "#M3U\n";
|
||||
print LIST "#current entry: $entry\n";
|
||||
print LIST "#current frame: $frame\n";
|
||||
for my $f (@files)
|
||||
{
|
||||
print LIST "$f\n";
|
||||
}
|
||||
close(LIST);
|
||||
}
|
31
src/mpg123.c
31
src/mpg123.c
@@ -128,6 +128,7 @@ char *equalfile = NULL;
|
||||
struct httpdata htd;
|
||||
int fresh = TRUE;
|
||||
int have_output = FALSE; /* If we are past the output init step. */
|
||||
FILE* aux_out = NULL; /* Output for interesting information, normally on stdout to be parseable. */
|
||||
|
||||
int buffer_fd[2];
|
||||
int buffer_pid;
|
||||
@@ -322,6 +323,7 @@ static void set_out_stdout(char *arg)
|
||||
{
|
||||
param.outmode=DECODE_FILE;
|
||||
param.remote_err=TRUE;
|
||||
aux_out = stderr;
|
||||
OutputDescriptor=STDOUT_FILENO;
|
||||
#ifdef WIN32
|
||||
_setmode(STDOUT_FILENO, _O_BINARY);
|
||||
@@ -332,6 +334,7 @@ static void set_out_stdout1(char *arg)
|
||||
{
|
||||
param.outmode=DECODE_AUDIOFILE;
|
||||
param.remote_err=TRUE;
|
||||
aux_out = stderr;
|
||||
OutputDescriptor=STDOUT_FILENO;
|
||||
#ifdef WIN32
|
||||
_setmode(STDOUT_FILENO, _O_BINARY);
|
||||
@@ -467,6 +470,7 @@ topt opts[] = {
|
||||
{0 , "longhelp" , 0, want_long_usage, 0, 0 },
|
||||
{0 , "version" , 0, give_version, 0, 0 },
|
||||
{'l', "listentry", GLO_ARG | GLO_LONG, 0, ¶m.listentry, 0 },
|
||||
{0, "continue", GLO_INT, set_appflag, &appflag, MPG123APP_CONTINUE },
|
||||
{0, "rva-mix", GLO_INT, 0, ¶m.rva, 1 },
|
||||
{0, "rva-radio", GLO_INT, 0, ¶m.rva, 1 },
|
||||
{0, "rva-album", GLO_INT, 0, ¶m.rva, 2 },
|
||||
@@ -780,6 +784,7 @@ int skip_or_die(struct timeval *start_time)
|
||||
int main(int sys_argc, char ** sys_argv)
|
||||
{
|
||||
int result;
|
||||
char end_of_files = FALSE;
|
||||
long parr;
|
||||
char *fname;
|
||||
int libpar = 0;
|
||||
@@ -787,7 +792,7 @@ int main(int sys_argc, char ** sys_argv)
|
||||
#if !defined(WIN32) && !defined(GENERIC)
|
||||
struct timeval start_time;
|
||||
#endif
|
||||
|
||||
aux_out = stdout; /* Need to initialize here because stdout is not a constant?! */
|
||||
#if defined (WANT_WIN32_UNICODE)
|
||||
if(win32_cmdline_utf8(&argc, &argv) != 0)
|
||||
{
|
||||
@@ -1027,6 +1032,8 @@ int main(int sys_argc, char ** sys_argv)
|
||||
if(param.term_ctrl)
|
||||
term_init();
|
||||
#endif
|
||||
if(APPFLAG(MPG123APP_CONTINUE)) frames_left = param.frame_number;
|
||||
|
||||
while ((fname = get_next_file()))
|
||||
{
|
||||
char *dirname, *filename;
|
||||
@@ -1050,7 +1057,8 @@ int main(int sys_argc, char ** sys_argv)
|
||||
#endif
|
||||
output_unpause(ao);
|
||||
}
|
||||
frames_left = param.frame_number;
|
||||
if(!APPFLAG(MPG123APP_CONTINUE)) frames_left = param.frame_number;
|
||||
|
||||
debug1("Going to play %s", strcmp(fname, "-") ? fname : "standard input");
|
||||
|
||||
if(intflag || !open_track(fname))
|
||||
@@ -1080,6 +1088,8 @@ int main(int sys_argc, char ** sys_argv)
|
||||
if(param.start_frame > 0)
|
||||
framenum = mpg123_seek_frame(mh, param.start_frame, SEEK_SET);
|
||||
|
||||
if(APPFLAG(MPG123APP_CONTINUE)) param.start_frame = 0;
|
||||
|
||||
if(framenum < 0)
|
||||
{
|
||||
error1("Initial seek failed: %s", mpg123_strerror(mh));
|
||||
@@ -1137,7 +1147,12 @@ int main(int sys_argc, char ** sys_argv)
|
||||
if(param.frame_number > -1)
|
||||
{
|
||||
debug1("frames left: %li", (long) frames_left);
|
||||
if(!frames_left) break;
|
||||
if(!frames_left)
|
||||
{
|
||||
if(APPFLAG(MPG123APP_CONTINUE)) end_of_files = TRUE;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!play_frame()) break;
|
||||
if(!param.quiet)
|
||||
@@ -1194,13 +1209,22 @@ int main(int sys_argc, char ** sys_argv)
|
||||
if(!param.smooth && param.usebuffer) buffer_resync();
|
||||
#endif
|
||||
}
|
||||
|
||||
if(end_of_files) break;
|
||||
} /* end of loop over input files */
|
||||
|
||||
/* Ensure we played everything. */
|
||||
if(param.smooth && param.usebuffer)
|
||||
{
|
||||
buffer_drain();
|
||||
buffer_resync();
|
||||
}
|
||||
|
||||
if(APPFLAG(MPG123APP_CONTINUE))
|
||||
{
|
||||
fprintf(aux_out, "\n[CONTINUE] track %"SIZE_P" frame %"OFF_P"\n", (size_p)pl.pos, (off_p)framenum);
|
||||
}
|
||||
|
||||
/* Free up memory used by playlist */
|
||||
if(!param.remote) free_playlist();
|
||||
|
||||
@@ -1286,6 +1310,7 @@ static void long_usage(int err)
|
||||
fprintf(o," --ignore-mime ignore HTTP MIME types (content-type)\n");
|
||||
fprintf(o," -@ <f> --list <f> play songs in playlist <f> (plain list, m3u, pls (shoutcast))\n");
|
||||
fprintf(o," -l <n> --listentry <n> play nth title in playlist; show whole playlist for n < 0\n");
|
||||
fprintf(o," --continue playlist continuation mode (see man page)\n");
|
||||
fprintf(o," --loop <n> loop track(s) <n> times, < 0 means infinite loop (not with --random!)\n");
|
||||
fprintf(o," --keep-open (--remote mode only) keep loaded file open after reaching end\n");
|
||||
fprintf(o," --timeout <n> Timeout in seconds before declaring a stream dead (if <= 0, wait forever)\n");
|
||||
|
@@ -117,6 +117,7 @@ enum mpg123app_flags
|
||||
{
|
||||
MPG123APP_IGNORE_MIME = 0x01
|
||||
,MPG123APP_LYRICS = 0x02
|
||||
,MPG123APP_CONTINUE = 0x04
|
||||
};
|
||||
|
||||
/* shortcut to check application flags */
|
||||
|
@@ -154,6 +154,9 @@ void init_playlist()
|
||||
pl.size = 0;
|
||||
pl.fill = 0;
|
||||
pl.pos = 0;
|
||||
if(APPFLAG(MPG123APP_CONTINUE) && param.listentry > 0)
|
||||
pl.pos = param.listentry - 1;
|
||||
|
||||
pl.list = NULL;
|
||||
pl.alloc_step = 10;
|
||||
mpg123_init_string(&pl.dir);
|
||||
@@ -464,7 +467,7 @@ int add_next_file (int argc, char *argv[])
|
||||
}
|
||||
++pl.entry;
|
||||
if(param.listentry < 0) printf("#entry %lu\n%s\n", (unsigned long)pl.entry,pl.linebuf.p+line_offset);
|
||||
else if((param.listentry == 0) || (param.listentry == pl.entry))
|
||||
else if((param.listentry == 0) || (param.listentry == pl.entry) || APPFLAG(MPG123APP_CONTINUE))
|
||||
{
|
||||
add_copy_to_playlist(pl.linebuf.p+line_offset);
|
||||
return 1;
|
||||
|
Reference in New Issue
Block a user