| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# Ogg Vorbis 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::Ogg; |
|
9
|
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
41141
|
use 5.008; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
33
|
|
|
11
|
1
|
|
|
1
|
|
5
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
39
|
|
|
12
|
1
|
|
|
1
|
|
10
|
use warnings; |
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
194
|
|
|
13
|
1
|
|
|
1
|
|
5
|
use Carp; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
88
|
|
|
14
|
1
|
|
|
1
|
|
846
|
use POE qw(Wheel::Run Filter::Line Driver::SysRW); |
|
|
1
|
|
|
|
|
65560
|
|
|
|
1
|
|
|
|
|
7
|
|
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our $VERSION = sprintf("%d.%02d", q$Revision: 1.5 $ =~ /(\d+)\.(\d+)/); |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# Create a new encoder object |
|
19
|
|
|
|
|
|
|
sub new { |
|
20
|
6
|
|
|
6
|
1
|
34745
|
my $class = shift; |
|
21
|
6
|
|
|
|
|
15
|
my $opts = shift; |
|
22
|
|
|
|
|
|
|
|
|
23
|
6
|
|
|
|
|
119
|
my $self = bless({}, $class); |
|
24
|
|
|
|
|
|
|
|
|
25
|
6
|
50
|
|
|
|
67
|
my %opts = !defined($opts) ? () : ref($opts) ? %$opts : ($opts, @_); |
|
|
|
100
|
|
|
|
|
|
|
26
|
6
|
|
|
|
|
68
|
%$self = (%$self, %opts); |
|
27
|
|
|
|
|
|
|
|
|
28
|
6
|
|
100
|
|
|
142
|
$self->{quality} ||= 3; # Default quality level of 3 |
|
29
|
6
|
|
100
|
|
|
21
|
$self->{priority} ||= 0; # No priority delta by default |
|
30
|
|
|
|
|
|
|
|
|
31
|
6
|
|
100
|
|
|
27
|
$self->{parent} ||= 'main'; # Default parent |
|
32
|
6
|
|
100
|
|
|
21
|
$self->{status} ||= 'status'; # Default events |
|
33
|
6
|
|
100
|
|
|
19
|
$self->{error} ||= 'error'; |
|
34
|
6
|
|
100
|
|
|
28
|
$self->{done} ||= 'done'; |
|
35
|
6
|
|
100
|
|
|
20
|
$self->{warning} ||= 'warning'; |
|
36
|
|
|
|
|
|
|
|
|
37
|
6
|
|
|
|
|
25
|
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
|
0
|
0
|
|
|
|
|
croak "Input file does not exist: '$self->{input}'" |
|
52
|
|
|
|
|
|
|
unless (-f $self->{input}); |
|
53
|
|
|
|
|
|
|
|
|
54
|
0
|
|
|
|
|
|
$self->{input} =~ /(.*)\.(.*)$/; |
|
55
|
0
|
|
|
|
|
|
my ($path, $ext) = ($1, $2); |
|
56
|
|
|
|
|
|
|
|
|
57
|
0
|
0
|
0
|
|
|
|
croak "Input file extension must be 'wav' or 'flac': I have '$ext'" |
|
58
|
|
|
|
|
|
|
unless ($ext eq 'wav' || $ext eq 'flac'); |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# Output filename is derived from input, unless specified |
|
61
|
0
|
0
|
|
|
|
|
unless ($self->{output}) { |
|
62
|
0
|
|
|
|
|
|
$self->{output} = "$path.ogg"; |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# For posting events to the parent session. Always passes $self as |
|
66
|
|
|
|
|
|
|
# the first event argument. |
|
67
|
|
|
|
|
|
|
sub post_parent { |
|
68
|
0
|
|
|
0
|
0
|
|
my $kernel = shift; |
|
69
|
0
|
|
|
|
|
|
my $self = shift; |
|
70
|
0
|
|
|
|
|
|
my $event = shift; |
|
71
|
|
|
|
|
|
|
|
|
72
|
0
|
0
|
|
|
|
|
$kernel->post($self->{parent}, $event, $self, @_) |
|
73
|
|
|
|
|
|
|
or carp "Failed to post to '$self->{parent}': $!"; |
|
74
|
|
|
|
|
|
|
} |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
POE::Session->create( |
|
77
|
|
|
|
|
|
|
inline_states => { |
|
78
|
|
|
|
|
|
|
_start => sub { |
|
79
|
0
|
|
|
0
|
|
|
my ($heap, $kernel, $self) = @_[HEAP, KERNEL, ARG0]; |
|
80
|
|
|
|
|
|
|
|
|
81
|
0
|
|
|
|
|
|
$kernel->sig(CHLD => "child"); # We must handle SIGCHLD |
|
82
|
|
|
|
|
|
|
|
|
83
|
0
|
|
|
|
|
|
$heap->{self} = $self; |
|
84
|
|
|
|
|
|
|
|
|
85
|
0
|
|
|
|
|
|
my @args; # List of arguments for encoder |
|
86
|
|
|
|
|
|
|
|
|
87
|
0
|
0
|
|
|
|
|
push @args, '--album="' . $self->{album} .'"' |
|
88
|
|
|
|
|
|
|
if $self->{album}; |
|
89
|
|
|
|
|
|
|
|
|
90
|
0
|
0
|
|
|
|
|
push @args, '--genre="' . $self->{genre} .'"' |
|
91
|
|
|
|
|
|
|
if $self->{genre}; |
|
92
|
|
|
|
|
|
|
|
|
93
|
0
|
0
|
|
|
|
|
push @args, '--title="' . $self->{title} .'"' |
|
94
|
|
|
|
|
|
|
if $self->{title}; |
|
95
|
|
|
|
|
|
|
|
|
96
|
0
|
0
|
|
|
|
|
push @args, '--date="' . $self->{date} .'"' |
|
97
|
|
|
|
|
|
|
if $self->{date}; |
|
98
|
|
|
|
|
|
|
|
|
99
|
0
|
0
|
|
|
|
|
push @args, '--artist="' . $self->{artist} .'"' |
|
100
|
|
|
|
|
|
|
if $self->{artist}; |
|
101
|
|
|
|
|
|
|
|
|
102
|
0
|
|
|
|
|
|
push @args, '--output="' . $self->{output} .'"'; |
|
103
|
|
|
|
|
|
|
|
|
104
|
0
|
0
|
|
|
|
|
push @args, '--quality="' . $self->{quality} .'"' |
|
105
|
|
|
|
|
|
|
if $self->{quality}; |
|
106
|
|
|
|
|
|
|
|
|
107
|
0
|
0
|
|
|
|
|
push @args, '--tracknum="'. $self->{tracknumber}.'"' |
|
108
|
|
|
|
|
|
|
if $self->{tracknumber}; |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# The comment parameter is a list of tag-value pairs. |
|
111
|
|
|
|
|
|
|
# Each list element must be passed to the encoder as a |
|
112
|
|
|
|
|
|
|
# separate --comment argument. |
|
113
|
0
|
0
|
|
|
|
|
if ($self->{comment}) { |
|
114
|
0
|
|
|
|
|
|
foreach (@{$self->{comment}}) { |
|
|
0
|
|
|
|
|
|
|
|
115
|
0
|
|
|
|
|
|
push @args, '--comment="' . $_ .'"' |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
} |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# Name of the encoder program we will use |
|
120
|
0
|
|
|
|
|
|
my $encoder = 'oggenc'; |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# We might need to use a decoder front-end pipe |
|
123
|
0
|
|
|
|
|
|
my $decoder = ''; |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# If the input is in flac format, use a flac decoder |
|
126
|
|
|
|
|
|
|
# front-end, and pipe it to the encoder. |
|
127
|
|
|
|
|
|
|
# Otherwise pass the input file name direct to the encoder |
|
128
|
0
|
0
|
|
|
|
|
if ($ext eq 'flac') { |
|
129
|
0
|
|
|
|
|
|
$decoder = "flac --decode --silent --stdout $self->{input} |"; |
|
130
|
0
|
|
|
|
|
|
push @args, '-'; |
|
131
|
|
|
|
|
|
|
} else { |
|
132
|
0
|
|
|
|
|
|
push @args, $self->{input}; |
|
133
|
|
|
|
|
|
|
} |
|
134
|
|
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
|
$heap->{wheel} = POE::Wheel::Run->new( |
|
136
|
|
|
|
|
|
|
Program => $decoder.$encoder, |
|
137
|
|
|
|
|
|
|
ProgramArgs => \@args, |
|
138
|
|
|
|
|
|
|
Priority => $self->{priority}, |
|
139
|
|
|
|
|
|
|
StdioFilter => POE::Filter::Line->new(), |
|
140
|
|
|
|
|
|
|
Conduit => 'pty', |
|
141
|
|
|
|
|
|
|
StdoutEvent => 'wheel_stdout', |
|
142
|
|
|
|
|
|
|
CloseEvent => 'wheel_done', |
|
143
|
|
|
|
|
|
|
ErrorEvent => 'wheel_error', |
|
144
|
|
|
|
|
|
|
); |
|
145
|
|
|
|
|
|
|
}, |
|
146
|
|
|
|
|
|
|
|
|
147
|
0
|
|
|
0
|
|
|
_stop => sub { |
|
148
|
|
|
|
|
|
|
}, |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
close => sub { |
|
151
|
0
|
|
|
0
|
|
|
delete $_[HEAP]->{wheel}; |
|
152
|
|
|
|
|
|
|
}, |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
# Handle CHLD signal. Stop the wheel if the exited child is ours. |
|
155
|
|
|
|
|
|
|
child => sub { |
|
156
|
0
|
|
|
0
|
|
|
my ($kernel, $heap, $signame, $child_pid, $exit_code) |
|
157
|
|
|
|
|
|
|
= @_[KERNEL, HEAP, ARG0, ARG1, ARG2]; |
|
158
|
|
|
|
|
|
|
|
|
159
|
0
|
0
|
0
|
|
|
|
if ($heap->{wheel} && $heap->{wheel}->PID() == $child_pid) { |
|
160
|
0
|
|
|
|
|
|
delete $heap->{wheel}; |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# If we got en exit code, the child died unexpectedly, |
|
163
|
|
|
|
|
|
|
# so create a wheel-error event. otherwise the child exited |
|
164
|
|
|
|
|
|
|
# normally, so create a wheel-done event. |
|
165
|
0
|
0
|
|
|
|
|
if ($exit_code) { |
|
166
|
0
|
|
|
|
|
|
$kernel->yield('wheel_error', $exit_code); |
|
167
|
|
|
|
|
|
|
} else { |
|
168
|
0
|
|
|
|
|
|
$kernel->yield('wheel_done'); |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
}, |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
wheel_stdout => sub { |
|
174
|
0
|
|
|
0
|
|
|
my ($kernel, $heap) = @_[KERNEL, HEAP]; |
|
175
|
0
|
|
|
|
|
|
my $self = $heap->{self}; |
|
176
|
0
|
|
|
|
|
|
$_ = $_[ARG0]; |
|
177
|
|
|
|
|
|
|
|
|
178
|
0
|
0
|
|
|
|
|
if (m{^ERROR: (.*)}i) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
# An error message has been emitted by the encoder. |
|
180
|
|
|
|
|
|
|
# Remember the message for later |
|
181
|
0
|
|
|
|
|
|
$self->{message} = $1; |
|
182
|
|
|
|
|
|
|
} elsif (m{^WARNING: (.*)}i) { |
|
183
|
|
|
|
|
|
|
# A warning message has been emitted by the encoder. |
|
184
|
|
|
|
|
|
|
# Post the warning message to the parent |
|
185
|
0
|
|
|
|
|
|
post_parent($kernel, $self, $self->{warning}, |
|
186
|
|
|
|
|
|
|
$self->{input}, |
|
187
|
|
|
|
|
|
|
$self->{output}, |
|
188
|
|
|
|
|
|
|
$1 |
|
189
|
|
|
|
|
|
|
); |
|
190
|
0
|
|
|
|
|
|
return; |
|
191
|
|
|
|
|
|
|
} elsif (m{^ |
|
192
|
|
|
|
|
|
|
\s+ \[ \s+ ([0-9.]+) % \s* \] |
|
193
|
|
|
|
|
|
|
\s+ \[ \s+ (\d+) m (\d+) s \s+ remaining \s* \] |
|
194
|
|
|
|
|
|
|
}x) { |
|
195
|
|
|
|
|
|
|
# We have a progress message from the encoder |
|
196
|
|
|
|
|
|
|
# Post the percentage and number of remaining seconds |
|
197
|
|
|
|
|
|
|
# to the parent. |
|
198
|
0
|
|
|
|
|
|
my ($percent, $seconds) = ($1, $2 * 60 + $3); |
|
199
|
|
|
|
|
|
|
|
|
200
|
0
|
|
|
|
|
|
post_parent($kernel, $self, $self->{status}, |
|
201
|
|
|
|
|
|
|
$self->{input}, |
|
202
|
|
|
|
|
|
|
$self->{output}, |
|
203
|
|
|
|
|
|
|
$percent, $seconds |
|
204
|
|
|
|
|
|
|
); |
|
205
|
|
|
|
|
|
|
} |
|
206
|
|
|
|
|
|
|
}, |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
wheel_error => sub { |
|
209
|
0
|
|
|
0
|
|
|
my ($kernel, $heap) = @_[KERNEL, HEAP]; |
|
210
|
0
|
|
|
|
|
|
my $self = $heap->{self}; |
|
211
|
|
|
|
|
|
|
|
|
212
|
0
|
|
0
|
|
|
|
post_parent($kernel, $self, $self->{error}, |
|
213
|
|
|
|
|
|
|
$self->{input}, |
|
214
|
|
|
|
|
|
|
$self->{output}, |
|
215
|
|
|
|
|
|
|
$_[ARG0], |
|
216
|
|
|
|
|
|
|
$self->{message} || '' |
|
217
|
|
|
|
|
|
|
); |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# Remove output file: might be incomplete |
|
220
|
0
|
0
|
0
|
|
|
|
$_ = $self->{output}; unlink if ($_ && -f); |
|
|
0
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
}, |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
wheel_done => sub { |
|
224
|
0
|
|
|
0
|
|
|
my ($kernel, $heap) = @_[KERNEL, HEAP]; |
|
225
|
0
|
|
|
|
|
|
my $self = $heap->{self}; |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
# Delete the input file if instructed |
|
228
|
0
|
0
|
|
|
|
|
unlink $self->{input} if $self->{delete}; |
|
229
|
|
|
|
|
|
|
|
|
230
|
0
|
|
|
|
|
|
post_parent($kernel, $self, $self->{done}, |
|
231
|
|
|
|
|
|
|
$self->{input}, |
|
232
|
|
|
|
|
|
|
$self->{output} |
|
233
|
|
|
|
|
|
|
); |
|
234
|
|
|
|
|
|
|
}, |
|
235
|
|
|
|
|
|
|
}, |
|
236
|
0
|
|
|
|
|
|
args => [$self] |
|
237
|
|
|
|
|
|
|
); |
|
238
|
|
|
|
|
|
|
} |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
1; |
|
241
|
|
|
|
|
|
|
__END__ |