/usr/local/CPAN/Video-PlaybackMachine/Video/PlaybackMachine/Filler.pm
package Video::PlaybackMachine::Filler;
####
#### Video::PlaybackMachine::Filler
####
#### $Revision: 370 $
####
#### POE session for the Filler.
####
use strict;
use warnings;
use Carp;
use UNIVERSAL 'isa';
use POE;
use POE::Session;
use Time::Duration;
use Log::Log4perl;
use Video::PlaybackMachine::TimeManager;
############################# Class Constants #############################
############################## Class Methods ##############################
##
## new()
##
## Arguments: hash
## segments => arrayref of FillSegment
##
sub new {
my $type = shift;
my (%in) = @_;
isa($in{segments}, 'ARRAY')
or croak($type, "::new() called improperly");
foreach my $segment (@{ $in{segments} }) {
isa($segment, 'Video::PlaybackMachine::FillSegment')
or croak($type, "::new: option 'segments' contains '$segment')");
}
my $self = {
segments => $in{segments},
logger => Log::Log4perl->get_logger('Video::PlaybackMachine::Filler')
};
bless $self, $type;
}
############################# Object Methods ##############################
sub spawn {
my $self = shift;
POE::Session->create(
inline_states => {
_start => sub {
$_[KERNEL]->alias_set('Filler');
}
},
object_states => [ $self => [
qw(start_fill fill_done next_fill short_ready stop)
] ],
);
}
############################# Session Methods #############################
##
## start_fill()
##
## POE state.
##
## Called to start the Filler filling.
##
sub start_fill {
# Initialize a TimeManager with our FillSegments
$_[HEAP]{time_manager} = Video::PlaybackMachine::TimeManager->new( @{ $_[OBJECT]{segments} } );
# Store the current schedule in the heap
$_[HEAP]{view} = $_[ARG0]
or $_[OBJECT]->{'logger'}->logconfess('ARG0 required');
$_[OBJECT]->{'logger'}->debug("Filling, ttn=", duration($_[ARG0]->get_time_to_next()),"\n");
# View the first segment
$_[KERNEL]->yield('next_fill');
}
sub stop {
$_[KERNEL]->alarm_remove_all();
foreach (keys %{$_[HEAP]}) {
delete $_[HEAP]->{$_};
}
}
##
## fill_done()
##
## Called when the Filler has nothing else to play.
## Posts a call over to the Scheduler telling it
## that we're idle.
##
sub fill_done {
$_[KERNEL]->alarm_set('next_fill');
delete $_[HEAP]->{time_manager};
delete $_[HEAP]->{view};
$_[KERNEL]->post('Scheduler', 'wait_for_scheduled');
}
##
## next_fill()
##
## Starts the next fill segment. If there are no more segments to be
## played, we're done.
##
sub next_fill {
$_[HEAP]{view}
or $_[OBJECT]{'logger'}->logconfess("Somehow called next_fill on us without calling start_fill");
my ($segment, $time) = $_[HEAP]{time_manager}->get_segment(
$_[HEAP]{view}->get_time_to_next(time())
)
or do {
$_[KERNEL]->yield('fill_done');
return;
};
$_[OBJECT]{'logger'}->debug("Starting fill segment name: ", $segment->get_name());
$segment->get_producer()->start($time);
}
##
## short_ready()
##
## Is called when one of the producers wants the Filler to display
## moving pictures.
##
sub short_ready {
$_[KERNEL]->post('Player',
'play',
$_[SESSION]->postback('next_fill'),
0,
@_[ARG0 .. $#_]);
}
1;