/usr/local/CPAN/Video-PlaybackMachine/Video/PlaybackMachine/FillProducer/SlideShow.pm
package Video::PlaybackMachine::FillProducer::SlideShow;
####
#### Video::PlaybackMachine::FillProducer::SlideShow
####
#### $Revision: 384 $
####
#### Plays a bunch of random photos. Since we need to do things
#### at particular delay times, launches its own POE session.
####
use strict;
use warnings;
use Carp;
use POE;
use Log::Log4perl;
use base 'Video::PlaybackMachine::FillProducer';
use Video::PlaybackMachine::TimeLayout::GranularTimeLayout;
use Video::PlaybackMachine::Player qw(PLAYBACK_OK PLAYBACK_STOPPED);
use Video::PlaybackMachine::FillProducer::Chooser;
############################# Class Constants #############################
# Maximum number of slides to play in a row
our $Max_Slides = 5;
############################## Class Methods ##############################
##
## new()
##
## Arguments: (hash)
## TIME: int -- Time in seconds that we want to display a still
## DIRECTORY: string -- Directory containing stills we want to display
##
sub new
{
my $type = shift;
my %in = @_;
defined $in{time} or croak( $type, "::new() called incorrectly" );
my $self = {
time_layout =>
Video::PlaybackMachine::TimeLayout::GranularTimeLayout->new(
$in{time}, $Max_Slides
),
frame_chooser => Video::PlaybackMachine::FillProducer::Chooser->new(
DIRECTORY => $in{'directory'},
),
music_chooser => Video::PlaybackMachine::FillProducer::Chooser->new(
DIRECTORY => $in{'music_directory'},
FILTER => qr/\.(mp3|wav|ogg)$/
),
time => $in{time},
logger => Log::Log4perl->get_logger(
'Video::PlaybackMachine::Filler::Slideshow'),
};
bless $self, $type;
}
############################# Object Methods ##############################
##
## get_time_layout()
##
## Returns the FixedTimeLayout for the appropriate time.
##
sub get_time_layout
{
$_[0]->{time_layout};
}
##
## has_audio()
##
## The slide show provides an audio track.
##
sub has_audio { return 1; }
##
## Slideshow is available if the directory exists
## and there are images in it.
##
sub is_available
{
my $self = shift;
return $self->{'frame_chooser'}->is_available();
}
##
## show_slide()
##
## Displays a set of random still frames.
##
sub show_slide
{
my ( $self, $kernel, $heap ) = @_[ OBJECT, KERNEL, HEAP ];
# If we have enough time to play another slide, call the player
# to play it.
my $time_played = ( time() - $heap->{'slide_start_time'} );
if ( $heap->{planned_time} > $time_played )
{
my $frame = $self->{'frame_chooser'}->choose();
$kernel->post( 'Player', 'play_still', $frame );
$kernel->delay( 'show_slide', $self->{'time'} );
}
# Otherwise, cancel all slides and shut things down.
# (The alarm cancel should be redundant.)
else
{
$self->{'logger'}->debug(
"Shutting down slideshow (time left=$time_played, $heap->{planned_time})"
);
$kernel->alarm_remove('show_slide');
$kernel->state('show_slide');
$kernel->state('next_song');
$kernel->alarm_remove('next_song');
$kernel->state('song_done');
$kernel->alarm_remove('song_done');
delete $heap->{'slide_start_time'};
delete $heap->{'planned_time'};
$kernel->yield('next_fill');
}
}
##
## start()
##
## Starts the display of random still frames. Adds event handlers to
## the current session to show slides. Assumes that we're being called
## in a POE Filler session.
##
sub start
{
my $self = shift;
my ($planned_time) = @_;
$self->{'logger'}->debug("Starting slideshow");
my $heap = $poe_kernel->get_active_session->get_heap();
$heap->{'slide_start_time'} = time();
$heap->{'planned_time'} = $planned_time;
$poe_kernel->state( 'show_slide', $self );
$poe_kernel->state( 'next_song', $self );
$poe_kernel->state( 'song_done', $self );
$poe_kernel->yield('show_slide');
$poe_kernel->yield('next_song');
}
sub next_song
{
$_[OBJECT]{'logger'}->debug("Running next song");
$_[KERNEL]->post(
'Player', 'play_music',
$_[SESSION]->postback('song_done'),
$_[OBJECT]->{'music_chooser'}->choose()
);
}
sub song_done
{
$_[OBJECT]{'logger'}->debug("Song done");
my ( $stream, $status ) = @{ $_[ARG1] };
if ( $status == PLAYBACK_OK() )
{
$_[OBJECT]{'logger'}->debug("Returned OK, playing next song");
$_[KERNEL]->yield('next_song');
}
else
{
$_[OBJECT]{'logger'}->debug("'$status' Not OK, stopping");
$_[KERNEL]->alarm('next_song');
}
}
1;