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;