line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# FLAC encoding component for POE |
2
|
|
|
|
|
|
|
# Copyright (c) 2004 Steve James. All rights reserved. |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# This library is free software; you can redistribute it and/or modify |
5
|
|
|
|
|
|
|
# it under the same terms as Perl itself. |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
package POE::Component::Enc::Flac; |
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
30277
|
use 5.008; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
41
|
|
11
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
139
|
|
|
1
|
|
|
|
|
37
|
|
12
|
1
|
|
|
1
|
|
23
|
use warnings; |
|
1
|
|
|
|
|
12
|
|
|
1
|
|
|
|
|
39
|
|
13
|
1
|
|
|
1
|
|
5
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
148
|
|
14
|
1
|
|
|
1
|
|
2567
|
use POE qw(Wheel::Run Filter::Line Driver::SysRW); |
|
1
|
|
|
|
|
65068
|
|
|
1
|
|
|
|
|
6
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our $VERSION = sprintf("%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/); |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# Create a new encoder object |
19
|
|
|
|
|
|
|
sub new { |
20
|
5
|
|
|
5
|
1
|
18359
|
my $class = shift; |
21
|
5
|
|
|
|
|
10
|
my $opts = shift; |
22
|
|
|
|
|
|
|
|
23
|
5
|
|
|
|
|
22
|
my $self = bless({}, $class); |
24
|
|
|
|
|
|
|
|
25
|
5
|
50
|
|
|
|
41
|
my %opts = !defined($opts) ? () : ref($opts) ? %$opts : ($opts, @_); |
|
|
100
|
|
|
|
|
|
26
|
5
|
|
|
|
|
38
|
%$self = (%$self, %opts); |
27
|
|
|
|
|
|
|
|
28
|
5
|
|
100
|
|
|
26
|
$self->{compression} ||= 5; # Default compression level |
29
|
5
|
|
100
|
|
|
17
|
$self->{priority} ||= 0; # No priority delta by default |
30
|
|
|
|
|
|
|
|
31
|
5
|
|
100
|
|
|
20
|
$self->{parent} ||= 'main'; # Default parent |
32
|
5
|
|
100
|
|
|
14
|
$self->{status} ||= 'status'; # Default events |
33
|
5
|
|
100
|
|
|
19
|
$self->{error} ||= 'error'; |
34
|
5
|
|
100
|
|
|
14
|
$self->{done} ||= 'done'; |
35
|
5
|
|
100
|
|
|
16
|
$self->{warning} ||= 'warning'; |
36
|
|
|
|
|
|
|
|
37
|
5
|
|
|
|
|
186
|
return $self; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# Start an encoder. |
42
|
|
|
|
|
|
|
sub enc { |
43
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
44
|
0
|
|
|
|
|
|
my $opts = shift; |
45
|
|
|
|
|
|
|
|
46
|
0
|
0
|
|
|
|
|
my %opts = !defined($opts) ? () : ref($opts) ? %$opts : ($opts, @_); |
|
|
0
|
|
|
|
|
|
47
|
0
|
|
|
|
|
|
%$self = (%$self, %opts); |
48
|
|
|
|
|
|
|
|
49
|
0
|
0
|
|
|
|
|
croak "No input file specified" unless $self->{input}; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# Output filename is derived from input, unless specified |
52
|
0
|
0
|
|
|
|
|
unless ($self->{output}) { |
53
|
0
|
|
|
|
|
|
($self->{output} = $self->{input}) =~ s/(.*)\.(.*)$/$1.flac/; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# For posting events to the parent session. Always passes $self as |
57
|
|
|
|
|
|
|
# the first event argument. |
58
|
|
|
|
|
|
|
sub post_parent { |
59
|
0
|
|
|
0
|
0
|
|
my $kernel = shift; |
60
|
0
|
|
|
|
|
|
my $self = shift; |
61
|
0
|
|
|
|
|
|
my $event = shift; |
62
|
|
|
|
|
|
|
|
63
|
0
|
0
|
|
|
|
|
$kernel->post($self->{parent}, $event, $self, @_) |
64
|
|
|
|
|
|
|
or carp "Failed to post to '$self->{parent}': $!"; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
POE::Session->create( |
68
|
|
|
|
|
|
|
inline_states => { |
69
|
|
|
|
|
|
|
_start => sub { |
70
|
0
|
|
|
0
|
|
|
my ($heap, $kernel, $self) = @_[HEAP, KERNEL, ARG0]; |
71
|
|
|
|
|
|
|
|
72
|
0
|
|
|
|
|
|
$kernel->sig(CHLD => "child"); # We must handle SIGCHLD |
73
|
|
|
|
|
|
|
|
74
|
0
|
|
|
|
|
|
$heap->{self} = $self; |
75
|
|
|
|
|
|
|
|
76
|
0
|
|
|
|
|
|
my @args; # List of arguments for encoder |
77
|
|
|
|
|
|
|
|
78
|
0
|
|
|
|
|
|
push @args, '--output-name="' . $self->{output} .'"'; |
79
|
|
|
|
|
|
|
|
80
|
0
|
0
|
|
|
|
|
push @args, '-' . $self->{compression} |
81
|
|
|
|
|
|
|
if $self->{compression}; |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
# The comment parameter is a list of tag-value pairs. |
84
|
|
|
|
|
|
|
# Each list element must be passed to the encoder as a |
85
|
|
|
|
|
|
|
# separate --tag argument. |
86
|
0
|
0
|
|
|
|
|
if ($self->{comment}) { |
87
|
0
|
|
|
|
|
|
foreach (@{$self->{comment}}) { |
|
0
|
|
|
|
|
|
|
88
|
0
|
|
|
|
|
|
push @args, '--tag="' . $_ .'"' |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
# Finally, the input file |
93
|
0
|
|
|
|
|
|
push @args, $self->{input}; |
94
|
|
|
|
|
|
|
|
95
|
0
|
|
|
|
|
|
$heap->{wheel} = POE::Wheel::Run->new( |
96
|
|
|
|
|
|
|
Program => 'flac', |
97
|
|
|
|
|
|
|
ProgramArgs => \@args, |
98
|
|
|
|
|
|
|
Priority => $self->{priority}, |
99
|
|
|
|
|
|
|
StdioFilter => POE::Filter::Line->new(), |
100
|
|
|
|
|
|
|
Conduit => 'pty', |
101
|
|
|
|
|
|
|
StdoutEvent => 'wheel_stdout', |
102
|
|
|
|
|
|
|
CloseEvent => 'wheel_done', |
103
|
|
|
|
|
|
|
ErrorEvent => 'wheel_error', |
104
|
|
|
|
|
|
|
); |
105
|
|
|
|
|
|
|
}, |
106
|
|
|
|
|
|
|
|
107
|
0
|
|
|
0
|
|
|
_stop => sub { |
108
|
|
|
|
|
|
|
}, |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
close => sub { |
111
|
0
|
|
|
0
|
|
|
delete $_[HEAP]->{wheel}; |
112
|
|
|
|
|
|
|
}, |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# Handle CHLD signal. Stop the wheel if the exited child is ours. |
115
|
|
|
|
|
|
|
child => sub { |
116
|
0
|
|
|
0
|
|
|
my ($kernel, $heap, $signame, $child_pid, $exit_code) |
117
|
|
|
|
|
|
|
= @_[KERNEL, HEAP, ARG0, ARG1, ARG2]; |
118
|
|
|
|
|
|
|
|
119
|
0
|
0
|
0
|
|
|
|
if ($heap->{wheel} && $heap->{wheel}->PID() == $child_pid) { |
120
|
0
|
|
|
|
|
|
delete $heap->{wheel}; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# If we got en exit code, the child died unexpectedly, |
123
|
|
|
|
|
|
|
# so create a wheel-error event. otherwise the child exited |
124
|
|
|
|
|
|
|
# normally, so create a wheel-done event. |
125
|
0
|
0
|
|
|
|
|
if ($exit_code) { |
126
|
0
|
|
|
|
|
|
$kernel->yield('wheel_error', $exit_code); |
127
|
|
|
|
|
|
|
} else { |
128
|
0
|
|
|
|
|
|
$kernel->yield('wheel_done'); |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
}, |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
wheel_stdout => sub { |
134
|
0
|
|
|
0
|
|
|
my ($kernel, $heap) = @_[KERNEL, HEAP]; |
135
|
0
|
|
|
|
|
|
my $self = $heap->{self}; |
136
|
0
|
|
|
|
|
|
$_ = $_[ARG0]; |
137
|
|
|
|
|
|
|
|
138
|
0
|
0
|
|
|
|
|
if (m{^ERROR: (.*)}i) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# An error message has been emitted by the encoder. |
140
|
|
|
|
|
|
|
# Remember the message for later |
141
|
0
|
|
|
|
|
|
$self->{message} = $1; |
142
|
|
|
|
|
|
|
} elsif (m{^WARNING: (.*)}i) { |
143
|
|
|
|
|
|
|
# A warning message has been emitted by the encoder. |
144
|
|
|
|
|
|
|
# Post the warning message to the parent |
145
|
0
|
|
|
|
|
|
post_parent($kernel, $self, $self->{warning}, |
146
|
|
|
|
|
|
|
$self->{input}, |
147
|
|
|
|
|
|
|
$self->{output}, |
148
|
|
|
|
|
|
|
$1 |
149
|
|
|
|
|
|
|
); |
150
|
0
|
|
|
|
|
|
return; |
151
|
|
|
|
|
|
|
} elsif (m{ |
152
|
|
|
|
|
|
|
\S+:\s+ # input file name |
153
|
|
|
|
|
|
|
(\d+)%\s+complete, # Percentage completion |
154
|
|
|
|
|
|
|
\s+ratio=([0-9.]+) # Current compression ratio |
155
|
|
|
|
|
|
|
}x) { |
156
|
|
|
|
|
|
|
# We have a progress message from the compressor |
157
|
|
|
|
|
|
|
# Post the percentage and ratio to the parent. |
158
|
0
|
|
|
|
|
|
my ($percent, $ratio) = ($1, $2); |
159
|
|
|
|
|
|
|
|
160
|
0
|
|
|
|
|
|
post_parent($kernel, $self, $self->{status}, |
161
|
|
|
|
|
|
|
$self->{input}, |
162
|
|
|
|
|
|
|
$self->{output}, |
163
|
|
|
|
|
|
|
$percent, $ratio |
164
|
|
|
|
|
|
|
); |
165
|
|
|
|
|
|
|
} elsif (m{ |
166
|
|
|
|
|
|
|
\S+:\s+ # input file name |
167
|
|
|
|
|
|
|
wrote\s+(\d+)\s+bytes, # Percentage completion |
168
|
|
|
|
|
|
|
\s+ratio=([0-9.]+) # Compression ratio |
169
|
|
|
|
|
|
|
}x) { |
170
|
|
|
|
|
|
|
# We have a completion message from the compressor |
171
|
|
|
|
|
|
|
# Post the percentage and ratio to the parent. |
172
|
0
|
|
|
|
|
|
my ($size, $ratio) = ($1, $2); |
173
|
|
|
|
|
|
|
|
174
|
0
|
|
|
|
|
|
post_parent($kernel, $self, $self->{status}, |
175
|
|
|
|
|
|
|
$self->{input}, |
176
|
|
|
|
|
|
|
$self->{output}, |
177
|
|
|
|
|
|
|
100, $ratio |
178
|
|
|
|
|
|
|
); |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
}, |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
wheel_error => sub { |
183
|
0
|
|
|
0
|
|
|
my ($kernel, $heap) = @_[KERNEL, HEAP]; |
184
|
0
|
|
|
|
|
|
my $self = $heap->{self}; |
185
|
|
|
|
|
|
|
|
186
|
0
|
|
0
|
|
|
|
post_parent($kernel, $self, $self->{error}, |
187
|
|
|
|
|
|
|
$self->{input}, |
188
|
|
|
|
|
|
|
$self->{output}, |
189
|
|
|
|
|
|
|
$_[ARG0], |
190
|
|
|
|
|
|
|
$self->{message} || '' |
191
|
|
|
|
|
|
|
); |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# Remove output file: might be incomplete |
194
|
0
|
0
|
0
|
|
|
|
$_ = $self->{output}; unlink if ($_ && -f); |
|
0
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
}, |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
wheel_done => sub { |
198
|
0
|
|
|
0
|
|
|
my ($kernel, $heap) = @_[KERNEL, HEAP]; |
199
|
0
|
|
|
|
|
|
my $self = $heap->{self}; |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
# Delete the input file if instructed |
202
|
0
|
0
|
|
|
|
|
unlink $self->{input} if $self->{delete}; |
203
|
|
|
|
|
|
|
|
204
|
0
|
|
|
|
|
|
post_parent($kernel, $self, $self->{done}, |
205
|
|
|
|
|
|
|
$self->{input}, |
206
|
|
|
|
|
|
|
$self->{output} |
207
|
|
|
|
|
|
|
); |
208
|
|
|
|
|
|
|
}, |
209
|
|
|
|
|
|
|
}, |
210
|
0
|
|
|
|
|
|
args => [$self] |
211
|
|
|
|
|
|
|
); |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
1; |
215
|
|
|
|
|
|
|
__END__ |