Net-DAAP-DMAP

 view release on metacpan or  search on metacpan

lib/Net/DAAP/DMAP.pm  view on Meta::CPAN

            my ($n1, $n2) = unpack("N2", $data);
            $data = new Math::BigInt(new Math::BigInt($n1)->blsft(32));
            $data += $n2;
            $data = "$data";
        } else {
            $data = unpack($Type_To_Unpack{$type}, $data);
        }
        # type 9 is really utf-8 encoded, so if we can, show that it is
        if ($type == 9 && eval { require Encode; 1 }) {
            $data = Encode::decode('utf-8', $data);
        }
        push @tags, [ $Types->{$tag}{NAME}, $data ];
    }

    return \@tags;
}

sub dmap_to_xml {
    my $buf = shift;
    my $xml = '';

    while (length $buf) {
        my ($tag, $len) = unpack("a4N", $buf);
        my $data = substr($buf, 8, $len);
        my $type = $Types->{$tag}{TYPE};

        if ($type == 12) {
            $data = dmap_to_xml($data);
        } else {
            $data = unpack($Type_To_Unpack{$type}, $data);
        }
        $xml .= sprintf("<%s>\n  %s\n</%s>\n", $tag, $data, $tag);
        substr($buf, 0, 8+$len) = '';
      }
    return $xml;
}

sub dmap_to_array_ref {
    my $buf = shift;
    my @tags;

    while (length $buf) {
        my ($tag, $len) = unpack("a4N", $buf);
        if (!defined($len) or length $buf < 8+$len) {
            return;
          }
        my $data = substr($buf, 8, $len);
        # try to unpack, assume it was a container if it succeeded
        my $data2 = dmap_to_array_ref($data);
        push @tags, [ $tag,  $data2 ? $data2 : $data ];
        substr($buf, 0, 8+$len) = '';
      }
    return \@tags;
}

sub dmap_seek {
    my($struct, $to_find) = @_;

    CHUNK: while (defined($to_find) && length($to_find)) {
        my $top;
        ($top, $to_find) = split m{/}, $to_find, 2;

      ELEMENT: foreach my $elt (@$struct) {

          if ($elt->[0] eq $top) {
                $struct = $elt->[1];
                next CHUNK;
            }
        }
        return;  # NOT FOUND
    }
    return $struct;
}

sub update_content_codes {
  my $array = shift;
  my $short;

  my $mccr = dmap_seek($array, "dmap.contentcodesresponse");
  die "Couldn't find mccr" unless defined $mccr;

  foreach my $mdcl_rec (@$mccr) {
    next unless $mdcl_rec->[0] eq 'dmap.dictionary';
    my @fields = @{$mdcl_rec->[1]};
    my ($name, $id, $type);
    foreach my $f (@fields) {
      if ($f->[0] eq 'dmap.contentcodesnumber') { $id = $f->[1] }
      if ($f->[0] eq 'dmap.contentcodesname') { $name = $f->[1] }
      if ($f->[0] eq 'dmap.contentcodestype') { $type = $f->[1] }
    }
    if ($id eq 'mcnm') { $type = 9  } # string names please
    if ($id eq 'pfdt') { $type = 42 } # and straight binary pictures
    my $record = { NAME => $name, ID => $id, TYPE => $type };
    $short->{$id} = $record;
  }

  $Types = $short;
}

sub dmap_pack {
    my $struct = shift;
    my $out = '';

    my %by_name = map { %{$_} ? ( $_->{NAME} => $_ ) : () } values %$Types;
    for my $pair (@$struct) {
        my ($name, $value) = @$pair;
        # dmap_unpack doesn't populate the name when its decoded
        # something it doesn't know the content-code of, like aeSV
        # which is new to 4.5
        unless ($name) {
            carp "element without a name - skipping" if $NOISY;
            next;
        }
        # or, it may be we don't know what kind of thing this is
        unless ($by_name{ $name }) {
            carp "$name has unknown type - skipping" if $NOISY;
            next;
        }

        my $tag  = $by_name{ $name }{ID};
        my $type = $by_name{ $name }{TYPE};



( run in 4.274 seconds using v1.01-cache-2.11-cpan-71847e10f99 )