File::Format::RIFF::Container - RIFF Container (Lists and RIFFs)


File-Format-RIFF documentation Contained in the File-Format-RIFF distribution.

Index


Code Index:

NAME

Top

File::Format::RIFF::Container - RIFF Container (Lists and RIFFs)

SYNOPSIS

Top

You should not instantiate a File::Format::RIFF::Container directly; instead, you should instantiate one of its subclasses: either a File::Format::RIFF object, or a File::Format::RIFF::List object.

DESCRIPTION

Top

File::Format::RIFF::Container is a base class for both RIFF objects and RIFF lists. It is, essentially, an array of other RIFF lists and/or RIFF chunks, and you can add, change, delete, and read them.

METHODS

Top

$type = $container->type;

Returns the type of $container.

$container->type( $type );

Sets the type of $container. $type must be a four character code, which represents what data will be found in $container.

$id = $container->id;

Returns the id of $container. $container must be either a RIFF object or a List object, so $id will be 'RIFF' or 'LIST', respectively.

@data = $container->data;

Returns the RIFF chunks and/or RIFF lists contained by $container.

$container->data( $data );

Clears out any existing RIFF chunks contained by $container and replaces them with $data. $data must be an array reference containing some number of RIFF lists and/or RIFF chunks.

$numChunks = $container->numChunks;

Returns the number of RIFF lists and/or RIFF chunks contained by $container.

$size = $container->size;

Returns the size (in bytes) of $container's data, when written to a file.

$total_size = $container->total_size;

Returns the total size (in bytes) that $container will take up when written out to a file. Total size is the size of the data, plus 12 bytes for the header.

@replaced = $self->splice( $offset, $length, @list );
$container->push( @chunks );
$chunk = $container->pop;
$container->unshift( @chunks );
$chunk = $container->shift;

splice, push, pop, unshift, and shift operate analogously to the same-named functions in core perl, acting on $container's array of RIFF lists and/or RIFF chunks. All items added must be RIFF lists or RIFF chunks.

$chunk = $container->at( $i );

Returns the RIFF list or RIFF chunk at the $ith position in $container's array.

$container->at( $i, $chunk );

Sets the $ith position in $container's array to $chunk, replacing the previous item. $chunk must be a RIFF list or a RIFF chunk.

$newChunk = $container->addChunk( $id, $data );

Creates a new RIFF chunk object with the given $id and $data, appending it to $container's array. Returns the just-created RIFF chunk.

$newList = $container->addList( $type, $data );

Creates a new List object with the given $type and $data, appending it to $container's array. Returns the just-created RIFF list.

$container->dump( $max );

Prints a string representation of $container to STDOUT, recursively printing contained items. If a RIFF chunk's data is larger than $max bytes, prints '[...]' instead of the actual data. If $max is not specified or undef, it defaults to 64.

A RIFF chunk is rendered as:

id: <id> size: <size> (<total size>): <data>

A RIFF container is rendered as:

id: <id> (<type>) size: <size> (<total size>)

Items contained in the RIFF list are recursively printed on subsequent lines, and are indented in one additional tab level.

SEE ALSO

Top

File::Format::RIFF
File::Format::RIFF::List

AUTHOR

Top

Paul Sturm <sturm@branewave.com>


File-Format-RIFF documentation Contained in the File-Format-RIFF distribution.

package File::Format::RIFF::Container;
use base File::Format::RIFF::Chunk;


our $VERSION = '0.08';


use Carp;
use File::Format::RIFF::List;


sub new
{
   my ( $proto, $type, $id, $data ) = @_;
   my ( $self ) = $proto->SUPER::new( $id, $data );
   $self->type( defined $type ? $type : '    ' );
   return $self;
}


sub type
{
   my ( $self ) = shift;
   return $self->{type} unless ( @_ );
   my ( $type ) = shift;
   croak "Length of type must be 4" unless ( length( $type ) == 4 );
   $self->{type} = $type;
}


sub id
{
   my ( $self ) = shift;
   croak "Cannot set id of $self->{id} chunk" if ( @_ and exists $self->{id} );
   return $self->SUPER::id( @_ );
}


sub read
{
   my ( $proto ) = shift;
   delete $proto->{id} if ( ref( $proto ) );
   return $proto->SUPER::read( @_ );
}


sub total_size
{
   my ( $self ) = @_;
   return $self->SUPER::total_size + 4;
}


sub data
{
   my ( $self ) = shift;
   return @{ $self->{data} } unless ( @_ );
   my ( $data ) = @_;
   $data = [ ] unless ( defined $data and ref( $data ) eq 'ARRAY' );
   $self->{data} = [ ];
   $self->push( @$data );
}


sub numChunks
{
   my ( $self ) = @_;
   return scalar( @{ $self->{data} } );
}


sub size
{
   my ( $self ) = @_;
   my ( $sz ) = 0;
   map { $sz += $_->total_size } @{ $self->{data} };
   return $sz;
}


sub splice
{
   my ( $self, $offset, $length, @elts ) = @_;
   map { croak "Can only add Chunk or List elements"
      unless ( ref( $_ ) and $_->isa( 'File::Format::RIFF::Chunk' ) ) } @elts;
   return ( @_ > 3 )
      ? splice( @{ $self->{data} }, $offset, $length, @elts )
      : ( @_ == 3 )
         ? splice( @{ $self->{data} }, $offset, $length )
         : ( @_ == 2 )
            ? splice( @{ $self->{data} }, $offset )
            : splice( @{ $self->{data} } );
}


sub push
{
   my ( $self, @elts ) = @_;
   return $self->splice( scalar( @{ $self->{data} } ), 0, @elts );
}


sub pop
{
   my ( $self ) = @_;
   return $self->splice( -1 );
}


sub unshift
{
   my ( $self, @elts ) = @_;
   return $self->splice( 0, 0, @elts );
}


sub at
{
   my ( $self ) = shift;
   my ( $i ) = shift;
   return $self->splice( $i, 1, shift ) if ( @_ );
   return $self->{data}->[ $i ];
}


sub addChunk
{
   my ( $self ) = shift;
   my ( $chk ) = new File::Format::RIFF::Chunk( @_ );
   $self->push( $chk );
   return $chk;
}


sub addList
{
   my ( $self ) = shift;
   my ( $ctr ) = new File::Format::RIFF::List( @_ );
   $self->push( $ctr );
   return $ctr;
}


sub _read_header
{
   my ( $self, $fh ) = @_;
   $self->SUPER::_read_header( $fh );
   $self->{size} -= 4;
   $self->{type} = $self->_read_fourcc( $fh );
}


sub _write_header
{
   my ( $self, $fh ) = @_;
   $self->_write_fourcc( $fh, $self->{id} );
   $self->_write_size( $fh, $self->size + 4 );
   $self->_write_fourcc( $fh, $self->{type} );
}


sub _read_data
{
   my ( $self, $fh ) = @_;
   my ( $to_read ) = $self->{size};
   $self->{data} = [ ];
   while ( $to_read )
   {
      my ( $id ) = $self->_read_fourcc( $fh );
      croak "Embedded RIFF chunks not allowed" if ( $id eq 'RIFF' );
      my ( $subchunk ) = ( $id eq 'LIST' )
         ? File::Format::RIFF::List->read( $fh )
         : File::Format::RIFF::Chunk->read( $id, $fh );
      $to_read -= $subchunk->total_size;
      $self->push( $subchunk );
   }
}


sub _write_data
{
   my ( $self, $fh ) = @_;
   map { $_->write( $fh ) } @{ $self->{data} };
}


sub dump
{
   my ( $self, $max, $indent ) = @_;
   $max = 64 unless ( defined $max );
   $indent = 0 unless ( defined $indent and $indent > 0 );
   print join( '', "\t" x $indent ), 'id: ', $self->id, ' (',
      $self->type, ') size: ', $self->size, ' (', $self->total_size, ")\n";

   ++ $indent;
   map { $_->dump( $max, $indent ) } @{ $self->{data} };
}


sub shift
{
   my ( $self ) = @_;
   return $self->splice( 0, 1 );
}


1;