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__ |