Implement PictureTag and (partially) Head
authorMarius Gavrilescu <marius@ieval.ro>
Sat, 6 Aug 2016 20:41:13 +0000 (16:41 -0400)
committerMarius Gavrilescu <marius@ieval.ro>
Sat, 6 Aug 2016 20:41:54 +0000 (16:41 -0400)
Opusfile.xs
lib/Audio/Opusfile.pm
lib/Audio/Opusfile/PictureTag.pm [new file with mode: 0644]
typemap

index c1f6353e51b25437fc90033f47c3103e5f55ef0b..6a5f55da6f2148f3303cc97fe552abcd71cb5ecd 100644 (file)
@@ -56,3 +56,172 @@ opus_tags_query(tags, tag, count = 0)
        const OpusTags* tags;
        const char* tag;
        int count;
+
+MODULE = Audio::Opusfile               PACKAGE = Audio::Opusfile::PictureTag           PREFIX = opus_picture_tag_
+
+const OpusPictureTag*
+opus_picture_tag_parse(tag)
+       const char *tag;
+PREINIT:
+       OpusPictureTag *pic;
+       int err;
+CODE:
+       Newx(pic, 1, OpusPictureTag);
+       if(err = opus_picture_tag_parse(pic, tag))
+               croak("opus_picture_tag_parse returned error %d\n", err);
+       RETVAL = pic;
+OUTPUT:
+       RETVAL
+
+void
+DESTROY(pic)
+       const OpusPictureTag* pic
+CODE:
+       Safefree(pic);
+
+int
+type(pic)
+       const OpusPictureTag *pic;
+CODE:
+       RETVAL = pic->type;
+OUTPUT:
+       RETVAL
+
+const char*
+mime_type(pic)
+       const OpusPictureTag *pic;
+CODE:
+       RETVAL = pic->mime_type;
+OUTPUT:
+       RETVAL
+
+const char*
+description(pic)
+       const OpusPictureTag *pic;
+CODE:
+       RETVAL = pic->description;
+OUTPUT:
+       RETVAL
+
+int
+width(pic)
+       const OpusPictureTag *pic;
+CODE:
+       RETVAL = pic->width;
+OUTPUT:
+       RETVAL
+
+int
+height(pic)
+       const OpusPictureTag *pic;
+CODE:
+       RETVAL = pic->height;
+OUTPUT:
+       RETVAL
+
+int
+depth(pic)
+       const OpusPictureTag *pic;
+CODE:
+       RETVAL = pic->depth;
+OUTPUT:
+       RETVAL
+
+int
+colors(pic)
+       const OpusPictureTag *pic;
+CODE:
+       RETVAL = pic->colors;
+OUTPUT:
+       RETVAL
+
+int
+data_length(pic)
+       const OpusPictureTag *pic;
+CODE:
+       RETVAL = pic->data_length;
+OUTPUT:
+       RETVAL
+
+SV*
+data(pic)
+       const OpusPictureTag *pic;
+CODE:
+       RETVAL = newSVpvn(pic->data, pic->data_length);
+OUTPUT:
+       RETVAL
+
+int
+format(pic)
+       const OpusPictureTag *pic;
+CODE:
+       RETVAL = pic->format;
+OUTPUT:
+       RETVAL
+
+MODULE = Audio::Opusfile               PACKAGE = Audio::Opusfile::Head
+
+int
+version(head)
+       const OpusHead* head;
+CODE:
+       RETVAL = head->version;
+OUTPUT:
+       RETVAL
+
+int
+channel_count(head)
+       const OpusHead* head;
+CODE:
+       RETVAL = head->channel_count;
+OUTPUT:
+       RETVAL
+
+unsigned
+pre_skip(head)
+       const OpusHead* head;
+CODE:
+       RETVAL = head->pre_skip;
+OUTPUT:
+       RETVAL
+
+unsigned
+input_sample_rate(head)
+       const OpusHead* head;
+CODE:
+       RETVAL = head->input_sample_rate;
+OUTPUT:
+       RETVAL
+
+int
+mapping_family(head)
+       const OpusHead* head;
+CODE:
+       RETVAL = head->mapping_family;
+OUTPUT:
+       RETVAL
+
+int
+stream_count(head)
+       const OpusHead* head;
+CODE:
+       RETVAL = head->stream_count;
+OUTPUT:
+       RETVAL
+
+int
+coupled_count(head)
+       const OpusHead* head;
+CODE:
+       RETVAL = head->coupled_count;
+OUTPUT:
+       RETVAL
+
+int
+mapping(head, k)
+       const OpusHead* head;
+       int k;
+CODE:
+       RETVAL = (int) head->mapping[k];
+OUTPUT:
+       RETVAL
index 430de4fa0e7248a1f4d81c5ada727df18c10002f..0612416f24f17d729b24df26e87acca2b48bee06 100644 (file)
@@ -74,6 +74,7 @@ sub AUTOLOAD {
 require XSLoader;
 XSLoader::load('Audio::Opusfile', $VERSION);
 require Audio::Opusfile::Tags;
+require Audio::Opusfile::PictureTag;
 
 # Preloaded methods go here.
 
@@ -111,8 +112,8 @@ libopusfile is a library for decoding and basic manipulation of Ogg
 Opus files.
 
 Audio::Opusfile is an interface to libopusfile. At the moment its only
-function is reading tags from an Ogg Opus file. Future versions will
-give access to a larger part of the libopusfile API.
+function is reading metadata and tags from an Ogg Opus file. Future
+versions will give access to a larger part of the libopusfile API.
 
 Expect the API to change in future versions.
 
@@ -126,6 +127,10 @@ Creates a new Audio::Opusfile object from an Ogg Opus file.
 
 Dies if the given file does not exist or is not a valid Ogg Opus file.
 
+=item B<$of>->head
+
+Returns an L<Audio::Opusfile::Head> object corresponding to the file.
+
 =item B<$of>->tags
 
 Returns an L<Audio::Opusfile::Tags> object corresponding to the file.
diff --git a/lib/Audio/Opusfile/PictureTag.pm b/lib/Audio/Opusfile/PictureTag.pm
new file mode 100644 (file)
index 0000000..609e614
--- /dev/null
@@ -0,0 +1,149 @@
+package Audio::Opusfile::PictureTag;
+# Don't load this module directly, load Audio::Opusfile instead
+
+use 5.014000;
+use strict;
+use warnings;
+use subs qw/parse/;
+
+sub new { parse $_[1] }
+
+1;
+__END__
+
+=encoding utf-8
+
+=head1 NAME
+
+Audio::Opusfile::PictureTag - A parsed METADATA_BLOCK_PICTURE tag
+
+=head1 SYNOPSIS
+
+  use Audio::Opusfile;
+  my $of = Audio::Opusfile->new_from_file('file.opus');
+  my @pic_tags = $of->tags->query_all('METADATA_BLOCK_PICTURE');
+  my @pictures = map { Audio::Opusfile::PictureTag->parse($_) } @pic_tags;
+  my $pic = $pictures[0];
+  say $pic->type; # Prints "3", which means Cover (front)
+  say $pic->mime_type; # Prints "image/png"
+  say $pic->description;
+  say $pic->width;
+  say $pic->height;
+  say $pic->depth;
+  say $pic->colors;
+  say $pic->data_length; # The image size
+  my $data = $pic->data; # The contents of the image
+  say $pic->format; # One of the OP_PIC_* constants
+
+=head1 DESCRIPTION
+
+This module represents a METADATA_BLOCK_PICTURE tag. It has the
+following methods (descriptions taken from the libopusfile
+documentation):
+
+=over
+
+=item Audio::Opusfile::PictureTag->B<new>(I<$tag>)
+
+Takes the contents of a METADATA_BLOCK_PICTURE tag (optionally
+prefixed by the string C<METADATA_BLOCK_PICTURE=>) and returns a new
+Audio::Opusfile::PictureTag object.
+
+=item $pic->B<type>
+
+The picture type according to the ID3v2 APIC frame
+
+   0.  Other
+   1.  32x32 pixels 'file icon' (PNG only)
+   2.  Other file icon
+   3.  Cover (front)
+   4.  Cover (back)
+   5.  Leaflet page
+   6.  Media (e.g. label side of CD)
+   7.  Lead artist/lead performer/soloist
+   8.  Artist/performer
+   9.  Conductor
+   10. Band/Orchestra
+   11. Composer
+   12. Lyricist/text writer
+   13. Recording Location
+   14. During recording
+   15. During performance
+   16. Movie/video screen capture
+   17. A bright colored fish
+   18. Illustration
+   19. Band/artist logotype
+   20. Publisher/Studio logotype
+
+Others are reserved and should not be used. There may only be one each
+of picture type 1 and 2 in a file.
+
+=item $pic->B<mime_type>
+
+The MIME type of the picture, in printable ASCII characters 0x20-0x7E.
+
+The MIME type may also be "-->" to signify that the data part is a URL
+pointing to the picture instead of the picture data itself. In this
+case, a terminating NUL is appended to the URL string in data, but
+data_length is set to the length of the string excluding that
+terminating NUL.
+
+=item $pic->B<description>
+
+The description of the picture, in UTF-8.
+
+=item $pic->B<width>
+
+The width of the picture in pixels.
+
+=item $pic->B<height>
+
+The height of the picture in pixels.
+
+=item $pic->B<depth>
+
+The color depth of the picture in bits-per-pixel (not
+bits-per-channel).
+
+=item $pic->B<colors>
+
+For indexed-color pictures (e.g., GIF), the number of colors used, or
+0 for non-indexed pictures.
+
+=item $pic->B<data_length>
+
+The length of the picture data in bytes. Equivalent to C<< length ($pic->data) >>.
+
+=item $pic->B<data>
+
+The binary picture data.
+
+=item $pic->B<format>
+
+The format of the picture data, if known. One of:
+OP_PIC_FORMAT_UNKNOWN, OP_PIC_FORMAT_URL, OP_PIC_FORMAT_JPEG,
+OP_PIC_FORMAT_PNG, or OP_PIC_FORMAT_GIF.
+
+ =back
+
+=head1 SEE ALSO
+
+L<Audio::Opusfile>,
+L<http://opus-codec.org/>,
+L<http://opus-codec.org/docs/opusfile_api-0.7/index.html>,
+L<https://www.opus-codec.org/docs/opusfile_api-0.7/structOpusPictureTag.html>
+
+=head1 AUTHOR
+
+Marius Gavrilescu, E<lt>marius@ieval.roE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2016 by Marius Gavrilescu
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.24.0 or,
+at your option, any later version of Perl 5 you may have available.
+
+
+=cut
diff --git a/typemap b/typemap
index 1181bcfe236ab4aba1e6a21630134b25303e5c12..c780241374648cc7c32c81972a485c01a2858840 100644 (file)
--- a/typemap
+++ b/typemap
@@ -1,9 +1,11 @@
-const OggOpusFile* T_OGG_OPUS_FILE
-      OggOpusFile* T_OGG_OPUS_FILE
-const OpusHead*    T_OPUS_HEAD
-      OpusHead*    T_OPUS_HEAD
-const OpusTags*    T_OPUS_TAGS
-      OpusTags*    T_OPUS_TAGS
+const OggOpusFile*    T_OGG_OPUS_FILE
+      OggOpusFile*    T_OGG_OPUS_FILE
+const OpusHead*       T_OPUS_HEAD
+      OpusHead*       T_OPUS_HEAD
+const OpusTags*       T_OPUS_TAGS
+      OpusTags*       T_OPUS_TAGS
+const OpusPictureTag* T_OPUS_PICTURE_TAG
+      OpusPictureTag* T_OPUS_PICTURE_TAG
 
 INPUT
 # All three types are copies of T_PTROBJ, only difference being the class name
@@ -38,6 +40,16 @@ T_OPUS_TAGS
                        ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
                        \"$var\", \"Audio::Opusfile::Tags\")
 
+T_OPUS_PICTURE_TAG
+       if (SvROK($arg) && sv_derived_from($arg, \"Audio::Opusfile::PictureTag\")) {
+               IV tmp = SvIV((SV*)SvRV($arg));
+               $var = INT2PTR($type,tmp);
+       }
+       else
+               Perl_croak_nocontext(\"%s: %s is not of type %s\",
+                       ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+                       \"$var\", \"Audio::Opusfile::Tags\")
+
 OUTPUT
 
 T_OGG_OPUS_FILE
@@ -48,3 +60,6 @@ T_OPUS_HEAD
 
 T_OPUS_TAGS
        sv_setref_pv($arg, \"Audio::Opusfile::Tags\", (void*)$var);
+
+T_OPUS_PICTURE_TAG
+       sv_setref_pv($arg, \"Audio::Opusfile::PictureTag\", (void*)$var);
This page took 0.017773 seconds and 4 git commands to generate.