From 8c8675fa09203b95a98235bbec5a4620d4eb8a13 Mon Sep 17 00:00:00 2001 From: thor Date: Sun, 22 Apr 2012 23:04:16 +0000 Subject: [PATCH] Add --continue mode, with example script to utilize it. git-svn-id: svn://scm.orgis.org/mpg123/trunk@3120 35dc7657-300d-0410-a2e5-dc2837fedb53 --- Makefile.am | 3 +- NEWS | 2 +- man1/mpg123.1 | 7 +++- scripts/conplay | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ src/mpg123.c | 35 ++++++++++++++++--- src/mpg123app.h | 1 + src/playlist.c | 5 ++- 7 files changed, 133 insertions(+), 9 deletions(-) create mode 100755 scripts/conplay diff --git a/Makefile.am b/Makefile.am index a837ffa2..0f41b2d0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/NEWS b/NEWS index 988a526c..2dd5706b 100644 --- a/NEWS +++ b/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 --- diff --git a/man1/mpg123.1 b/man1/mpg123.1 index 725a1190..a3d46144 100644 --- a/man1/mpg123.1 +++ b/man1/mpg123.1 @@ -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 diff --git a/scripts/conplay b/scripts/conplay new file mode 100755 index 00000000..2ee586cf --- /dev/null +++ b/scripts/conplay @@ -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() + { + 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() +{ + 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); +} diff --git a/src/mpg123.c b/src/mpg123.c index d431ae3d..5372b118 100644 --- a/src/mpg123.c +++ b/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) @@ -1193,14 +1208,23 @@ int main(int sys_argc, char ** sys_argv) #ifndef NOXFERMEM if(!param.smooth && param.usebuffer) buffer_resync(); #endif - } - } /* end of loop over input files */ + } + + 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," -@ --list play songs in playlist (plain list, m3u, pls (shoutcast))\n"); fprintf(o," -l --listentry 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 loop track(s) 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 Timeout in seconds before declaring a stream dead (if <= 0, wait forever)\n"); diff --git a/src/mpg123app.h b/src/mpg123app.h index b61bd94e..a03a6098 100644 --- a/src/mpg123app.h +++ b/src/mpg123app.h @@ -117,6 +117,7 @@ enum mpg123app_flags { MPG123APP_IGNORE_MIME = 0x01 ,MPG123APP_LYRICS = 0x02 + ,MPG123APP_CONTINUE = 0x04 }; /* shortcut to check application flags */ diff --git a/src/playlist.c b/src/playlist.c index 3dd63d78..76fcf25f 100644 --- a/src/playlist.c +++ b/src/playlist.c @@ -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;