teetime: Added file format FourCC: TTM1.
This commit is contained in:
parent
3d2355f59d
commit
5ab7ad938f
132
teetime/teetime
132
teetime/teetime
|
@ -44,7 +44,7 @@ Play back I<factor> times faster. 1.0 = actual speed.
|
|||
|
||||
=item B<-i>
|
||||
|
||||
Read I<file> as input.
|
||||
Read I<file> as input. Use - to read from standard input.
|
||||
|
||||
|
||||
=item B<--maxwait> I<maxwait>
|
||||
|
@ -53,19 +53,39 @@ Read I<file> as input.
|
|||
|
||||
Wait at most I<maxwait> seconds.
|
||||
|
||||
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
(sleep 0.5; echo After 0.5s; sleep 1.5; echo After 2s) | teetime myfile
|
||||
(sleep 0.5; echo After 2.5s; sleep 1.5; echo After 4s) | teetime -a myfile
|
||||
teetime -i myfile
|
||||
(sleep 0.5; echo After 0.5s; sleep 1.5; echo After 2s) |
|
||||
teetime myfile.tt
|
||||
(sleep 0.5; echo After 2.5s; sleep 1.5; echo After 4s) |
|
||||
teetime -a myfile.tt
|
||||
teetime -i myfile.tt
|
||||
|
||||
Play file using stdin:
|
||||
|
||||
cat myfile.tt | teetime -i -
|
||||
|
||||
Play it faster:
|
||||
|
||||
teetime -f 2 -i myfile.tt
|
||||
|
||||
=head1 File format
|
||||
|
||||
The .tt-format is simply:
|
||||
|
||||
Version: "TTM1"
|
||||
Repeat: (
|
||||
Wait ms: Unsigned 32-bit
|
||||
Length of string: Unsigned 32-bit
|
||||
String: string
|
||||
)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Copyright (C) 2020 Ole Tange,
|
||||
Copyright (C) 2020-2023 Ole Tange,
|
||||
http://ole.tange.dk and Free Software Foundation, Inc.
|
||||
|
||||
|
||||
|
@ -99,16 +119,39 @@ B<tee>
|
|||
|
||||
=cut
|
||||
|
||||
sub bashtest1 {
|
||||
q{
|
||||
rand -s 8 | head -c 1G | teetime - |mbuffer -q | teetime -i - | pv | md5sum
|
||||
rand -s 8 | head -c 1G | pv | md5sum
|
||||
};
|
||||
}
|
||||
|
||||
sub bashtest2 {
|
||||
q{
|
||||
doit() {
|
||||
diff <(rand -s $1 |
|
||||
head -c$1 |
|
||||
md5sum) <(rand -s $1 |
|
||||
teetime - |
|
||||
teetime -i - |
|
||||
head -c$1 |
|
||||
md5sum);
|
||||
}
|
||||
export -f doit
|
||||
find-first-fail -v doit
|
||||
};
|
||||
}
|
||||
|
||||
use strict;
|
||||
|
||||
use Getopt::Long;
|
||||
|
||||
sub now {
|
||||
# Returns time since epoch as in seconds with 3 decimals
|
||||
# Returns time since epoch in ms
|
||||
# Uses:
|
||||
# @Global::use
|
||||
# Returns:
|
||||
# $time = time now with millisecond accuracy
|
||||
# $time = in milliseconds
|
||||
if(not $Global::use{"Time::HiRes"}) {
|
||||
if(eval "use Time::HiRes qw ( time );") {
|
||||
eval "sub TimeHiRestime { return Time::HiRes::time };";
|
||||
|
@ -122,22 +165,34 @@ sub now {
|
|||
}
|
||||
|
||||
sub readstdin {
|
||||
# Read stdin and save it in .tt-format
|
||||
# If no file: save to stdout, but do not tee output
|
||||
my $file = shift;
|
||||
my $last_time = now();
|
||||
my $rin = '';
|
||||
my $in;
|
||||
my $twogb = 2**31;
|
||||
my ($read, $time, $delta);
|
||||
open(my $fh, ($opt::append ? ">>" : ">"), $file) || die;
|
||||
|
||||
my $fh;
|
||||
my $save_to_stdout;
|
||||
if(not defined $file or $file eq "-") {
|
||||
$save_to_stdout = 1;
|
||||
}
|
||||
if($save_to_stdout) {
|
||||
$fh = *STDOUT;
|
||||
$| = 1;
|
||||
} else {
|
||||
open($fh, ($opt::append ? ">>" : ">"), $file) || die;
|
||||
}
|
||||
vec($rin, fileno(STDIN), 1) = 1;
|
||||
# print FourCC file identifier
|
||||
print $fh "TTM1";
|
||||
while(1) {
|
||||
select($rin,undef,undef,undef);
|
||||
$read = sysread(STDIN,$in,$twogb);
|
||||
$read = sysread(STDIN,$in,1000000);
|
||||
$time = now();
|
||||
$delta = $time - $last_time;
|
||||
print $fh pack("L*",$delta,length $in),$in;
|
||||
print STDOUT $in;
|
||||
if(not $save_to_stdout) { print STDOUT $in; }
|
||||
$last_time = $time;
|
||||
if(not $read) {
|
||||
# Select says there is something to read,
|
||||
|
@ -162,17 +217,39 @@ sub min(@) {
|
|||
}
|
||||
|
||||
sub readfile {
|
||||
# Input is in .tt-format
|
||||
my $file = shift;
|
||||
open(my $fh, "<", $file) || die;
|
||||
my $fh;
|
||||
if($file eq "-") {
|
||||
$fh = *STDIN;
|
||||
} else {
|
||||
open($fh, "<", $file) || die;
|
||||
}
|
||||
my $fileformat;
|
||||
if(sysread($fh,$fileformat,4)) {
|
||||
if($fileformat eq "TTM1") {
|
||||
read_ttm1($fh);
|
||||
} else {
|
||||
error("Unsupported file format: $fileformat");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub read_ttm1 {
|
||||
my $fh = shift;
|
||||
my $in;
|
||||
my $nread;
|
||||
while(1) {
|
||||
my $in;
|
||||
if(sysread($fh,$in,8)) {
|
||||
if($nread = sysread($fh,$in,8)) {
|
||||
if($nread != 8) { die; }
|
||||
# time in ms, length in bytes
|
||||
my ($delta,$length) = unpack("L*",$in);
|
||||
$delta = min($delta/$opt::factor,$opt::maxwait*1000);
|
||||
select(undef,undef,undef,$delta/1000);
|
||||
sysread($fh,$in,$length);
|
||||
print $in;
|
||||
while($nread = sysread($fh,$in,$length)) {
|
||||
$length -= $nread;
|
||||
print $in;
|
||||
}
|
||||
} else {
|
||||
# Blocking sysread says there is something read,
|
||||
# but there is not => eof
|
||||
|
@ -206,7 +283,7 @@ sub help() {
|
|||
"teetime [-m max] [-f factor] -i file",
|
||||
"",
|
||||
"-a append to file",
|
||||
"-f playback speed",
|
||||
"-f playback speed factor",
|
||||
"-i read from file",
|
||||
"-m max wait seconds",
|
||||
"",
|
||||
|
@ -214,6 +291,19 @@ sub help() {
|
|||
"",);
|
||||
}
|
||||
|
||||
sub error(@) {
|
||||
my @w = @_;
|
||||
my $prog = $Global::progname || "teetime";
|
||||
status(map { ($prog.": Error: ". $_); } @w);
|
||||
}
|
||||
|
||||
sub status(@) {
|
||||
my @w = @_;
|
||||
my $fh = *STDERR;
|
||||
print $fh map { ($_, "\n") } @w;
|
||||
flush $fh;
|
||||
}
|
||||
|
||||
sub debug {
|
||||
$opt::D or return;
|
||||
@_ = grep { defined $_ ? $_ : "" } @_;
|
||||
|
@ -252,5 +342,3 @@ if(GetOptions("debug|D=s" => \$opt::D,
|
|||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue