teetime: Added file format FourCC: TTM1.
This commit is contained in:
parent
3d2355f59d
commit
5ab7ad938f
134
teetime/teetime
134
teetime/teetime
|
@ -44,7 +44,7 @@ Play back I<factor> times faster. 1.0 = actual speed.
|
||||||
|
|
||||||
=item B<-i>
|
=item B<-i>
|
||||||
|
|
||||||
Read I<file> as input.
|
Read I<file> as input. Use - to read from standard input.
|
||||||
|
|
||||||
|
|
||||||
=item B<--maxwait> I<maxwait>
|
=item B<--maxwait> I<maxwait>
|
||||||
|
@ -53,19 +53,39 @@ Read I<file> as input.
|
||||||
|
|
||||||
Wait at most I<maxwait> seconds.
|
Wait at most I<maxwait> seconds.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
|
|
||||||
=head1 EXAMPLES
|
=head1 EXAMPLES
|
||||||
|
|
||||||
(sleep 0.5; echo After 0.5s; sleep 1.5; echo After 2s) | teetime myfile
|
(sleep 0.5; echo After 0.5s; sleep 1.5; echo After 2s) |
|
||||||
(sleep 0.5; echo After 2.5s; sleep 1.5; echo After 4s) | teetime -a myfile
|
teetime myfile.tt
|
||||||
teetime -i myfile
|
(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
|
=head1 AUTHOR
|
||||||
|
|
||||||
Copyright (C) 2020 Ole Tange,
|
Copyright (C) 2020-2023 Ole Tange,
|
||||||
http://ole.tange.dk and Free Software Foundation, Inc.
|
http://ole.tange.dk and Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,16 +119,39 @@ B<tee>
|
||||||
|
|
||||||
=cut
|
=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 strict;
|
||||||
|
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
|
|
||||||
sub now {
|
sub now {
|
||||||
# Returns time since epoch as in seconds with 3 decimals
|
# Returns time since epoch in ms
|
||||||
# Uses:
|
# Uses:
|
||||||
# @Global::use
|
# @Global::use
|
||||||
# Returns:
|
# Returns:
|
||||||
# $time = time now with millisecond accuracy
|
# $time = in milliseconds
|
||||||
if(not $Global::use{"Time::HiRes"}) {
|
if(not $Global::use{"Time::HiRes"}) {
|
||||||
if(eval "use Time::HiRes qw ( time );") {
|
if(eval "use Time::HiRes qw ( time );") {
|
||||||
eval "sub TimeHiRestime { return Time::HiRes::time };";
|
eval "sub TimeHiRestime { return Time::HiRes::time };";
|
||||||
|
@ -122,22 +165,34 @@ sub now {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub readstdin {
|
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 $file = shift;
|
||||||
my $last_time = now();
|
my $last_time = now();
|
||||||
my $rin = '';
|
my $rin = '';
|
||||||
my $in;
|
my $in;
|
||||||
my $twogb = 2**31;
|
|
||||||
my ($read, $time, $delta);
|
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;
|
vec($rin, fileno(STDIN), 1) = 1;
|
||||||
|
# print FourCC file identifier
|
||||||
|
print $fh "TTM1";
|
||||||
while(1) {
|
while(1) {
|
||||||
select($rin,undef,undef,undef);
|
select($rin,undef,undef,undef);
|
||||||
$read = sysread(STDIN,$in,$twogb);
|
$read = sysread(STDIN,$in,1000000);
|
||||||
$time = now();
|
$time = now();
|
||||||
$delta = $time - $last_time;
|
$delta = $time - $last_time;
|
||||||
print $fh pack("L*",$delta,length $in),$in;
|
print $fh pack("L*",$delta,length $in),$in;
|
||||||
print STDOUT $in;
|
if(not $save_to_stdout) { print STDOUT $in; }
|
||||||
$last_time = $time;
|
$last_time = $time;
|
||||||
if(not $read) {
|
if(not $read) {
|
||||||
# Select says there is something to read,
|
# Select says there is something to read,
|
||||||
|
@ -162,17 +217,39 @@ sub min(@) {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub readfile {
|
sub readfile {
|
||||||
|
# Input is in .tt-format
|
||||||
my $file = shift;
|
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) {
|
while(1) {
|
||||||
my $in;
|
if($nread = sysread($fh,$in,8)) {
|
||||||
if(sysread($fh,$in,8)) {
|
if($nread != 8) { die; }
|
||||||
# time in ms, length in bytes
|
# time in ms, length in bytes
|
||||||
my ($delta,$length) = unpack("L*",$in);
|
my ($delta,$length) = unpack("L*",$in);
|
||||||
$delta = min($delta/$opt::factor,$opt::maxwait*1000);
|
$delta = min($delta/$opt::factor,$opt::maxwait*1000);
|
||||||
select(undef,undef,undef,$delta/1000);
|
select(undef,undef,undef,$delta/1000);
|
||||||
sysread($fh,$in,$length);
|
while($nread = sysread($fh,$in,$length)) {
|
||||||
print $in;
|
$length -= $nread;
|
||||||
|
print $in;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
# Blocking sysread says there is something read,
|
# Blocking sysread says there is something read,
|
||||||
# but there is not => eof
|
# but there is not => eof
|
||||||
|
@ -206,7 +283,7 @@ sub help() {
|
||||||
"teetime [-m max] [-f factor] -i file",
|
"teetime [-m max] [-f factor] -i file",
|
||||||
"",
|
"",
|
||||||
"-a append to file",
|
"-a append to file",
|
||||||
"-f playback speed",
|
"-f playback speed factor",
|
||||||
"-i read from file",
|
"-i read from file",
|
||||||
"-m max wait seconds",
|
"-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 {
|
sub debug {
|
||||||
$opt::D or return;
|
$opt::D or return;
|
||||||
@_ = grep { defined $_ ? $_ : "" } @_;
|
@_ = grep { defined $_ ? $_ : "" } @_;
|
||||||
|
@ -252,5 +342,3 @@ if(GetOptions("debug|D=s" => \$opt::D,
|
||||||
help();
|
help();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue