taglib-sharp initial import (r553)

This commit is contained in:
chudov
2012-04-13 23:27:50 +00:00
parent fc236e817e
commit 42064890b7
269 changed files with 91425 additions and 0 deletions

2
taglib-sharp/examples/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
extractKey
listData

View File

@@ -0,0 +1,131 @@
using System;
using System.Collections.Generic;
using TagLib;
public class BatchSet
{
private enum Mode {
Tag, Value, File
}
public static void Main(string [] args)
{
if(args.Length < 3) {
Console.Error.WriteLine ("USAGE: BatchSet.exe -tag value [-tag2 value ...] File1 [File2 ...]");
return;
}
Mode mode = Mode.Tag;
List<string> files = new List<string> ();
Dictionary<string,string> tags = new Dictionary<string,string> ();
string tag = null;
foreach (string str in args) {
if (mode == Mode.Tag) {
if (str [0] == '-') {
if (str == "--") {
mode = Mode.File;
} else {
tag = str.Substring (1);
mode = Mode.Value;
}
continue;
}
mode = Mode.File;
}
if (mode == Mode.Value) {
if (!tags.ContainsKey (tag))
tags.Add (tag, str);
mode = Mode.Tag;
continue;
}
if (mode == Mode.File)
files.Add (str);
}
foreach (string filename in files) {
TagLib.File file = TagLib.File.Create (filename);
if (file == null)
continue;
Console.WriteLine ("Updating Tags For: " + filename);
foreach (string key in tags.Keys) {
string value = tags [key];
try {
switch (key) {
case "id3version":
byte number = byte.Parse (value);
if (number == 1) {
file.RemoveTags (TagTypes.Id3v2);
} else {
TagLib.Id3v2.Tag v2 =
file.GetTag (TagTypes.Id3v2, true)
as TagLib.Id3v2.Tag;
if (v2 != null)
v2.Version = number;
}
break;
case "album":
file.Tag.Album = value;
break;
case "artists":
file.Tag.AlbumArtists = value.Split (new char [] {';'});
break;
case "comment":
file.Tag.Comment = value;
break;
case "lyrics":
file.Tag.Lyrics = value;
break;
case "composers":
file.Tag.Composers = value.Split (new char [] {';'});
break;
case "disc":
file.Tag.Disc = uint.Parse (value);
break;
case "disccount":
file.Tag.DiscCount = uint.Parse (value);
break;
case "genres":
file.Tag.Genres = value.Split (new char [] {';'});
break;
case "performers":
file.Tag.Performers = value.Split (new char [] {';'});
break;
case "title":
file.Tag.Title = value;
break;
case "track":
file.Tag.Track = uint.Parse (value);
break;
case "trackcount":
file.Tag.TrackCount = uint.Parse (value);
break;
case "year":
file.Tag.Year = uint.Parse (value);
break;
case "pictures":
List<Picture> pics = new List<Picture> ();
if (!string.IsNullOrEmpty (value))
foreach (string path in value.Split (new char [] {';'})) {
pics.Add (new Picture (path));
}
file.Tag.Pictures = pics.ToArray ();
break;
}
} catch (Exception e) {
Console.WriteLine ("Error setting tag " + key + ":");
Console.WriteLine (e);
}
}
file.Save();
}
}
}

View File

@@ -0,0 +1,924 @@
//
// This application parses a photo and compares the output to the output of exiv2.
//
// It can be used to make test fixtures. Manual validation is always required.
//
// You need the exiv2 app for this to work.
//
using GLib;
using System;
using System.Text;
using System.Collections.Generic;
using System.Security.Cryptography;
using TagLib;
using TagLib.IFD;
using TagLib.IFD.Tags;
using TagLib.Xmp;
public class GenerateTestFixtureApp
{
private static MD5 md5 = MD5.Create ();
public static void Main (string [] args)
{
if(args.Length != 2) {
Console.Error.WriteLine ("USAGE: mono GenerateTestFixture.exe NAME PATH");
return;
}
string name = args[0];
string path = args[1];
EmitHeader (name, path);
GenerateIFDFixture (name, path);
GenerateXMPFixture (name, path);
EmitFooter ();
}
static Dictionary<string, int> sub_ifds = new Dictionary<string, int> ();
static Dictionary<string, bool> sub_ifds_emitted = new Dictionary<string, bool> ();
static void GenerateIFDFixture (string name, string path)
{
// First run exiv2 on it.
string output, err;
int code;
var result = GLib.Process.SpawnCommandLineSync (String.Format ("./listData e {0}", path), out output, out err, out code);
if (!result) {
Console.Error.WriteLine ("Invoking listData failed, are you running from the examples folder?");
return;
}
Write ("// ---------- Start of IFD tests ----------");
foreach (string line in output.Split ('\n')) {
string[] parts = line.Split (new char[] {'\t'}, 5);
if (parts.Length == 0 || line.Trim ().Equals (String.Empty) || parts.Length != 5)
continue;
string tag_label = parts[0];
ushort tag = ushort.Parse (parts[1].Substring(2), System.Globalization.NumberStyles.HexNumber);
string ifd = parts[2];
string type = parts[3];
uint length = uint.Parse (parts[4]);
if (ifd == "NikonSi02xx" || ifd == "NikonVr" || ifd == "NikonPc" || ifd == "NikonWt" || ifd == "NikonIi" || ifd == "NikonLd3") {
continue; // Exiv2 makes these up.
}
string val = ExtractKey (path, String.Format ("Exif.{0}.{1}", ifd, tag_label));
if (tag_label == "SubIFDs") {
for (int i = 0; i < val.Split (' ').Length; i++) {
var sub_ifd = String.Format ("SubImage{0}", sub_ifds.Count + 1);
sub_ifds.Add (sub_ifd, sub_ifds.Count);
}
continue;
}
EnsureIFD (ifd);
if (tag_label.Equals ("ExifTag"))
type = "SubIFD";
if (tag_label.Equals ("MakerNote")) {
type = "MakerNote";
val = String.Empty; // No need to echo.
}
if (tag_label.Equals ("InteroperabilityTag"))
type = "SubIFD";
if (tag_label.Equals ("GPSTag"))
type = "SubIFD";
if (tag_label.Equals ("JPEGInterchangeFormat"))
type = "ThumbnailDataIFD";
if (tag_label.Equals ("Preview") && ifd.Equals ("Nikon3"))
type = "SubIFD";
if (tag_label.Equals ("UserComment") && ifd.Equals ("Photo"))
type = "UserComment";
if (tag_label.Equals ("StripOffsets"))
type = "StripOffsets";
if (tag_label.Equals ("IPTCNAA"))
type = "IPTCNAA";
if (tag_label.Equals ("XMLPacket"))
type = "XMLPacket";
if (ifd.Equals ("MakerNote"))
continue; // Exiv2 makes these up.
Write ("// {1}.0x{0:X4} ({2}/{3}/{4}) \"{5}\"", tag, ifd, tag_label, type, length, length > 512 ? "(Value ommitted)" : val);
if (ifd.Equals ("Image")) {
EmitTestIFDEntryOpen ("structure", 0, tag, ifd);
} else if (ifd.Equals ("Thumbnail")) {
EmitTestIFDEntryOpen ("structure", 1, tag, ifd);
} else if (ifd.Equals ("Image2")) {
EmitTestIFDEntryOpen ("structure", 2, tag, ifd);
} else if (ifd.Equals ("Image3")) {
EmitTestIFDEntryOpen ("structure", 3, tag, ifd);
} else if (ifd.Equals ("Photo")) {
EmitTestIFDEntryOpen ("exif_structure", 0, tag, ifd);
} else if (IsPartOfMakernote (ifd)) {
EmitTestIFDEntryOpen ("makernote_structure", 0, tag, ifd);
} else if (ifd.Equals ("NikonPreview")) {
EmitTestIFDEntryOpen ("nikonpreview_structure", 0, tag, ifd);
} else if (ifd.Equals ("Iop")) {
EmitTestIFDEntryOpen ("iop_structure", 0, tag, ifd);
} else if (ifd.Equals ("GPSInfo")) {
EmitTestIFDEntryOpen ("gps_structure", 0, tag, ifd);
} else if (ifd.Equals ("CanonCs")) {
EmitTestIFDEntryOpen ("makernote_structure", 0, (ushort) CanonMakerNoteEntryTag.CameraSettings, ifd);
} else if (ifd.Equals ("CanonSi")) {
EmitTestIFDEntryOpen ("makernote_structure", 0, (ushort) CanonMakerNoteEntryTag.ShotInfo, ifd);
} else if (ifd.Equals ("CanonCf")) {
EmitTestIFDEntryOpen ("makernote_structure", 0, (ushort) CanonMakerNoteEntryTag.CustomFunctions, ifd);
} else if (ifd.Equals ("CanonPi")) {
EmitTestIFDEntryOpen ("makernote_structure", 0, (ushort) CanonMakerNoteEntryTag.PictureInfo, ifd);
} else if (ifd.Equals ("CanonFi")) {
EmitTestIFDEntryOpen ("makernote_structure", 0, (ushort) 0x93, ifd);
} else if (ifd.Equals ("PanasonicRaw")) {
EmitTestIFDEntryOpen ("pana_structure", 0, tag, ifd);
} else if (sub_ifds.ContainsKey (ifd)) {
EmitTestIFDEntryOpen (String.Format ("{0}_structure", ifd), 0, tag, ifd);
} else {
throw new Exception (String.Format ("Unknown IFD: {0}", ifd));
}
if (ifd.Equals ("CanonCs") || ifd.Equals ("CanonSi") || ifd.Equals ("CanonCf") || ifd.Equals ("CanonPi")) {
// This are a made-up directory by exiv2
EmitTestIFDIndexedShortEntry (tag, val);
} else if (ifd.Equals ("CanonFi")) {
// This are a made-up directory by exiv2
// And the fist both entries are combined to a long by exiv2.
if (tag == 0x0001) {
string val1 = ((ushort) UInt32.Parse (val)).ToString ();
string val2 = ((ushort) (UInt32.Parse (val) >> 16)).ToString ();
EmitTestIFDIndexedShortEntry (tag, val1);
EmitTestIFDIndexedShortEntry (tag + 1, val2);
} else {
EmitTestIFDIndexedShortEntry (tag, val);
}
} else if (type.Equals ("Ascii")) {
EmitTestIFDStringEntry (val);
} else if (type.Equals ("Short") && length == 1) {
EmitTestIFDShortEntry (val);
} else if (type.Equals ("Short") && length > 1) {
EmitTestIFDShortArrayEntry (val);
} else if (type.Equals ("SShort") && length == 1) {
EmitTestIFDSShortEntry (val);
} else if (type.Equals ("SShort") && length > 1) {
EmitTestIFDSShortArrayEntry (val);
} else if (type.Equals ("Rational") && length == 1) {
EmitTestIFDRationalEntry (val);
} else if (type.Equals ("Rational") && length > 1) {
EmitTestIFDRationalArrayEntry (val);
} else if (type.Equals ("SRational") && length == 1) {
EmitTestIFDSRationalEntry (val);
} else if (type.Equals ("SRational") && length > 1) {
EmitTestIFDSRationalArrayEntry (val);
} else if (type.Equals ("Long") && length == 1) {
EmitTestIFDLongEntry (val);
} else if (type.Equals ("Long") && length > 1) {
EmitTestIFDLongArrayEntry (val);
} else if (type.Equals ("SLong") && length == 1) {
EmitTestIFDSLongEntry (val);
} else if (type.Equals ("Byte") && length == 1) {
EmitTestIFDByteEntry (val);
} else if (type.Equals ("Byte") && length > 1) {
EmitTestIFDByteArrayEntry (val);
} else if (type.Equals ("SByte") && length == 1) {
EmitTestIFDSByteEntry (val);
} else if (type.Equals ("SubIFD")) {
EmitTestIFDSubIFDEntry (val);
} else if (type.Equals ("ThumbnailDataIFD")) {
EmitTestIFDThumbnailDataIFDEntry (val);
} else if (type.Equals ("MakerNote")) {
EmitTestIFDMakerNoteIFDEntry (val);
} else if (type.Equals ("UserComment")) {
EmitTestIFDUserCommentIFDEntry (val);
} else if (type.Equals ("Undefined")) {
EmitTestIFDUndefinedEntry (val);
} else if (type.Equals ("StripOffsets")) {
EmitTestIFDStripOffsetsEntry (val);
} else if (type.Equals ("IPTCNAA")) {
EmitTestIFDIPTCNAAEntry (val);
} else if (type.Equals ("XMLPacket")) {
EmitTestIFDXMLPacketEntry (val);
} else {
throw new Exception ("Unknown type: " + type);
}
EmitTestIFDEntryClose ();
}
Write ();
Write ("// ---------- End of IFD tests ----------");
Write ();
}
static Dictionary<string, string> xmp_prefixes = new Dictionary<string, string> ();
static void GenerateXMPFixture (string name, string path)
{
// First run exiv2 on it.
string output, err;
int code;
var result = GLib.Process.SpawnCommandLineSync (String.Format ("./listData x {0}", path), out output, out err, out code);
if (!result) {
Console.Error.WriteLine ("Invoking exiv2 failed, do you have it installed?");
return;
}
if (output.Trim ().Equals (""))
return;
Write ();
Write ("// ---------- Start of XMP tests ----------");
Write ();
Write ("XmpTag xmp = file.GetTag (TagTypes.XMP) as XmpTag;");
// Build prefix lookup dictionary.
Type t = typeof(XmpTag);
foreach (var member in t.GetMembers()) {
if (!member.Name.EndsWith ("_NS"))
continue;
string val = (member as System.Reflection.FieldInfo).GetValue (null) as string;
string prefix = XmpTag.NamespacePrefixes [val];
xmp_prefixes [prefix] = member.Name;
}
foreach (string line in output.Split ('\n')) {
string[] parts = line.Split (new char[] {'\t'}, 3);
if (parts.Length == 0 || line.Trim ().Equals (String.Empty))
continue;
string label = parts[0];
string type = parts[1];
uint length = uint.Parse (parts[2]);
string val = ExtractKey (path, label).Trim ();
EmitXmpTest (label, type, length, val);
}
Write ();
Write ("// ---------- End of XMP tests ----------");
Write ();
}
static void EmitXmpTest (string label, string type, uint length, string val)
{
if (label.Equals ("Xmp.xmpMM.InstanceID"))
return; // Continue this, exiv2 makes it up from the about attr
if (label.Equals ("Xmp.tiff.Orientation"))
return; // exiv2 destroys this value
var node_path = label.Split ('/');
Write ("// {0} ({1}/{2}) \"{3}\"", label, type, length, val);
Write ("{");
Write ("var node = xmp.NodeTree;");
// Navigate to the correct node.
foreach (var node in node_path) {
var parts = node.Split ('.');
var partscolon = node.Split (':');
if (parts.Length == 3) {
// Plain node
int index = 0;
string name = parts[2];
if (parts[2].EndsWith("]")) {
int index_start = parts[2].LastIndexOf ("[");
string index_str = parts[2].Substring (index_start+1, parts[2].Length-index_start-2);
index = int.Parse (index_str);
name = parts[2].Substring (0, index_start);
}
string ns = GetXmpNs (parts[1]);
Write ("node = node.GetChild ({0}, \"{1}\");", ns, name);
Write ("Assert.IsNotNull (node);");
if (index > 0) {
Write ("node = node.Children [{0}];", index - 1);
Write ("Assert.IsNotNull (node);");
}
} else if (partscolon.Length == 2) {
string ns = GetXmpNs (partscolon[0]);
string name = partscolon[1];
Write ("node = node.GetChild ({0}, \"{1}\");", ns, name);
Write ("Assert.IsNotNull (node);");
} else {
throw new Exception ("Can't navigate to "+node);
}
}
if (length > 0 && type.Equals ("XmpText")) {
Write ("Assert.AreEqual (\"{0}\", node.Value);", val);
Write ("Assert.AreEqual (XmpNodeType.Simple, node.Type);");
Write ("Assert.AreEqual (0, node.Children.Count);");
} else if (type.Equals ("XmpBag") && length == 1) {
Write ("Assert.AreEqual (XmpNodeType.Bag, node.Type);");
Write ("Assert.AreEqual (\"\", node.Value);");
Write ("Assert.AreEqual ({0}, node.Children.Count);", length);
Write ("Assert.AreEqual (\"{0}\", node.Children [0].Value);", val);
} else if (type.Equals ("LangAlt") && length == 1) {
var langparts = val.Split (new char [] {' '}, 2);
string lang = langparts[0].Substring (langparts[0].IndexOf ('"')+1, langparts [0].Length - langparts[0].IndexOf ('"')-2);
Write ("Assert.AreEqual (\"{0}\", node.Children [0].GetQualifier (XmpTag.XML_NS, \"lang\").Value);", lang);
Write ("Assert.AreEqual (\"{0}\", node.Children [0].Value);", langparts[1]);
} else if (type.Equals ("XmpSeq") && length == 1) {
Write ("Assert.AreEqual (XmpNodeType.Seq, node.Type);");
Write ("Assert.AreEqual (\"\", node.Value);");
Write ("Assert.AreEqual ({0}, node.Children.Count);", length);
Write ("Assert.AreEqual (\"{0}\", node.Children [0].Value);", val);
} else if (type.Equals ("XmpSeq") && length > 1) {
string [] vals = val.Split (',');
Write ("Assert.AreEqual (XmpNodeType.Seq, node.Type);");
Write ("Assert.AreEqual (\"\", node.Value);");
Write ("Assert.AreEqual ({0}, node.Children.Count);", length);
var per_iter = vals.Length / length;
for (int i = 0; i < length; i++) {
var builder = new List<string> ();
for (int j = 0; j < per_iter; j++) {
builder.Add (vals[per_iter*i + j].Trim ());
}
Write ("Assert.AreEqual (\"{0}\", node.Children [{1}].Value);", String.Join (", ", builder.ToArray ()), i);
}
} else if (type.Equals ("XmpBag") && length > 1) {
string [] vals = val.Split (',');
Write ("Assert.AreEqual (XmpNodeType.Bag, node.Type);");
Write ("Assert.AreEqual (\"\", node.Value);");
Write ("Assert.AreEqual ({0}, node.Children.Count);", length);
Write ("var children_array = new System.Collections.Generic.List<string> ();");
Write ("foreach (var child in node.Children)");
Write ("{");
Write ("children_array.Add (child.Value);");
Write ("}");
var per_iter = vals.Length / length;
for (int i = 0; i < length; i++) {
var builder = new List<string> ();
for (int j = 0; j < per_iter; j++) {
builder.Add (vals[per_iter*i + j].Trim ());
}
Write ("Assert.IsTrue (children_array.Contains (\"{0}\"));", String.Join (", ", builder.ToArray ()));
}
} else if (type.Equals ("XmpText") && length == 0 && val.StartsWith ("type=")) {
if (val.Equals ("type=\"Bag\"")) {
Write ("Assert.AreEqual (XmpNodeType.Bag, node.Type);");
} else if (val.Equals ("type=\"Struct\"")) {
// We disagree with exiv2 on the meaning of Struct. In Taglib#,
// struct is meant to denote parseType=Resource types only, not
// the shorthand equivalent. Also see XmpNode.RenderInto()
//Write ("Assert.AreEqual (XmpNodeType.Struct, node.Type);");
} else {
throw new Exception ("Unknown type");
}
} else {
throw new Exception (String.Format ("Can't test this (type: {0}, length: {1})", type, length));
}
Write ("}");
}
static string ExtractKey (string file, string key)
{
string output, err;
int code;
var result = GLib.Process.SpawnCommandLineSync (String.Format ("./extractKey {0} {1}", file, key), out output, out err, out code);
if (!result) {
Console.Error.WriteLine ("Invoking extractKey failed, are you running from the examples folder?");
return String.Empty;
}
return output;
}
static string GetXmpNs (string prefix)
{
string result;
if (prefix.Equals ("xmpBJ"))
prefix = "xapBJ";
if (prefix.Equals ("xmpMM"))
prefix = "xapMM";
if (prefix.Equals ("xmpRights"))
prefix = "xapRights";
if (prefix.Equals ("MicrosoftPhoto_1_")) // We correct this invalid namespace internally
prefix = "MicrosoftPhoto";
if (xmp_prefixes.TryGetValue (prefix, out result))
return String.Format ("XmpTag.{0}", result);
throw new Exception ("Unknown namespace prefix: "+prefix);
}
static bool IsPartOfMakernote (string ifd) {
return ifd.Equals ("MakerNote") ||
ifd.Equals ("Canon") ||
ifd.Equals ("Sony") ||
ifd.Equals ("Nikon1") ||
ifd.Equals ("Nikon2") ||
ifd.Equals ("Nikon3") ||
ifd.Equals ("Panasonic") ||
ifd.Equals ("Olympus") ||
ifd.Equals ("Pentax");
}
static void EmitHeader (string name, string path)
{
int start = path.LastIndexOf ('/');
string filename = path.Substring (start+1);
Write ("// TODO: This file is automatically generated");
Write ("// TODO: Further manual verification is needed");
Write ();
Write ("using System;");
Write ("using NUnit.Framework;");
Write ("using TagLib.IFD;");
Write ("using TagLib.IFD.Entries;");
Write ("using TagLib.IFD.Tags;");
Write ("using TagLib.Xmp;");
Write ("using TagLib.Tests.Images.Validators;");
Write ();
Write ("namespace TagLib.Tests.Images");
Write ("{");
Write ("[TestFixture]");
Write ("public class {0}", name);
Write ("{");
Write ("[Test]");
Write ("public void Test ()");
Write ("{");
Write ("ImageTest.Run (\"{0}\",", filename);
level++;
Write ("new {0}InvariantValidator (),", name);
Write ("NoModificationValidator.Instance");
level--;
Write (");");
Write ("}");
Write ("}");
Write ();
Write ("public class {0}InvariantValidator : IMetadataInvariantValidator", name);
Write ("{");
Write ("public void ValidateMetadataInvariants (Image.File file)");
Write ("{");
Write ("Assert.IsNotNull (file);");
}
static void EmitFooter ()
{
Write ("}"); // Method
Write ("}"); // Class
Write ("}"); // Namespace
}
static bool is_panasonic_raw = false;
static bool structure_emitted = false;
static bool exif_emitted = false;
static bool makernote_emitted = false;
static bool makernote_is_canon = false;
static bool makernote_is_nikon1 = false;
static bool makernote_is_nikon2 = false;
static bool makernote_is_nikon3 = false;
static bool makernote_is_panasonic = false;
static bool nikonpreview_emitted = false;
static bool iop_emitted = false;
static bool gps_emitted = false;
static void EnsureIFD (string ifd) {
if (ifd.Equals ("PanasonicRaw")) {
if (is_panasonic_raw)
return;
Write ();
Write ("var tag = file.GetTag (TagTypes.TiffIFD) as IFDTag;");
Write ("Assert.IsNotNull (tag, \"IFD tag not found\");");
Write ();
Write ("var pana_structure = tag.Structure;");
Write ();
Write ("var jpg_file = (file as TagLib.Tiff.Rw2.File).JpgFromRaw;");
Write ("Assert.IsNotNull (tag, \"JpgFromRaw not found!\");");
Write ("var jpg_tag = jpg_file.GetTag (TagTypes.TiffIFD) as IFDTag;");
Write ("Assert.IsNotNull (tag, \"Jpg has no Exif tag!\");");
Write ("var structure = jpg_tag.Structure;");
is_panasonic_raw = true;
}
if (ifd.Equals ("Image") && !is_panasonic_raw) {
if (structure_emitted)
return;
Write ();
Write ("var tag = file.GetTag (TagTypes.TiffIFD) as IFDTag;");
Write ("Assert.IsNotNull (tag, \"IFD tag not found\");");
Write ();
Write ("var structure = tag.Structure;");
Write ();
structure_emitted = true;
}
if (ifd.Equals ("Photo")) {
if (exif_emitted)
return;
EnsureIFD ("Image");
Write ();
Write ("var exif = structure.GetEntry (0, (ushort) IFDEntryTag.ExifIFD) as SubIFDEntry;");
Write ("Assert.IsNotNull (exif, \"Exif tag not found\");");
Write ("var exif_structure = exif.Structure;");
Write ();
exif_emitted = true;
}
if (ifd.Equals ("MakerNote")) {
if (makernote_emitted)
return;
EnsureIFD ("Photo");
Write ();
Write ("var makernote = exif_structure.GetEntry (0, (ushort) ExifEntryTag.MakerNote) as MakernoteIFDEntry;");
Write ("Assert.IsNotNull (makernote, \"MakerNote tag not found\");");
Write ("var makernote_structure = makernote.Structure;");
Write ();
makernote_emitted = true;
}
if (ifd.Equals ("Canon") || ifd.Equals ("CanonCs") || ifd.Equals ("CanonSi")) {
if (makernote_is_canon)
return;
EnsureIFD ("MakerNote");
Write ();
Write ("Assert.AreEqual (MakernoteType.Canon, makernote.MakernoteType);");
Write ();
makernote_is_canon = true;
}
if (ifd.Equals ("Nikon1")) {
if (makernote_is_nikon1)
return;
EnsureIFD ("MakerNote");
Write ();
Write ("Assert.AreEqual (MakernoteType.Nikon1, makernote.MakernoteType);");
Write ();
makernote_is_nikon1 = true;
}
if (ifd.Equals ("Nikon2")) {
if (makernote_is_nikon2)
return;
EnsureIFD ("MakerNote");
Write ();
Write ("Assert.AreEqual (MakernoteType.Nikon2, makernote.MakernoteType);");
Write ();
makernote_is_nikon2 = true;
}
if (ifd.Equals ("Nikon3")) {
if (makernote_is_nikon3)
return;
EnsureIFD ("MakerNote");
Write ();
Write ("Assert.AreEqual (MakernoteType.Nikon3, makernote.MakernoteType);");
Write ();
makernote_is_nikon3 = true;
}
if (ifd.Equals ("NikonPreview")) {
if (nikonpreview_emitted)
return;
EnsureIFD ("Nikon3");
Write ();
Write ("var nikonpreview = makernote_structure.GetEntry (0, (ushort) Nikon3MakerNoteEntryTag.Preview) as SubIFDEntry;");
Write ("Assert.IsNotNull (nikonpreview, \"Nikon preview tag not found\");");
Write ("var nikonpreview_structure = nikonpreview.Structure;");
Write ();
nikonpreview_emitted = true;
}
if (ifd.Equals ("Panasonic")) {
if (makernote_is_panasonic)
return;
EnsureIFD ("MakerNote");
Write ();
Write ("Assert.AreEqual (MakernoteType.Panasonic, makernote.MakernoteType);");
Write ();
makernote_is_panasonic = true;
}
if (ifd.Equals ("Iop")) {
if (iop_emitted)
return;
EnsureIFD ("Photo");
Write ();
Write ("var iop = exif_structure.GetEntry (0, (ushort) IFDEntryTag.InteroperabilityIFD) as SubIFDEntry;");
Write ("Assert.IsNotNull (iop, \"Iop tag not found\");");
Write ("var iop_structure = iop.Structure;");
Write ();
iop_emitted = true;
}
if (ifd.Equals ("GPSInfo")) {
if (gps_emitted)
return;
EnsureIFD ("Image");
Write ();
Write ("var gps = structure.GetEntry (0, (ushort) IFDEntryTag.GPSIFD) as SubIFDEntry;");
Write ("Assert.IsNotNull (gps, \"GPS tag not found\");");
Write ("var gps_structure = gps.Structure;");
Write ();
gps_emitted = true;
}
if (sub_ifds.ContainsKey (ifd) && !sub_ifds_emitted.ContainsKey (ifd)) {
Write ();
Write ("var {0}_structure = (structure.GetEntry (0, (ushort) IFDEntryTag.SubIFDs) as SubIFDArrayEntry).Entries [{1}];", ifd, sub_ifds[ifd]);
Write ("Assert.IsNotNull ({0}_structure, \"{0} structure not found\");", ifd);
Write ();
sub_ifds_emitted.Add (ifd, true);
}
}
static void EmitTestIFDEntryOpen (string src, int ifd, ushort tag, string ifd_label)
{
Write ("{");
Write (String.Format ("var entry = {0}.GetEntry ({1}, (ushort) {2});", src, ifd, StringifyEntryTag (ifd_label, tag)));
Write (String.Format ("Assert.IsNotNull (entry, \"Entry 0x{0:X4} missing in IFD {1}\");", tag, ifd));
}
static void EmitTestIFDEntryClose ()
{
Write ("}");
}
static void EmitTestIFDStringEntry (string val)
{
Write ("Assert.IsNotNull (entry as StringIFDEntry, \"Entry is not a string!\");");
Write ("Assert.AreEqual (\"{0}\", (entry as StringIFDEntry).Value{1});", val, val == String.Empty ? ".Trim ()" : "");
}
static void EmitTestIFDShortEntry (string val)
{
Write ("Assert.IsNotNull (entry as ShortIFDEntry, \"Entry is not a short!\");");
Write ("Assert.AreEqual ({0}, (entry as ShortIFDEntry).Value);", val);
}
static void EmitTestIFDSShortEntry (string val)
{
Write ("Assert.IsNotNull (entry as SShortIFDEntry, \"Entry is not a signed short!\");");
Write ("Assert.AreEqual ({0}, (entry as SShortIFDEntry).Value);", val);
}
static void EmitTestIFDShortArrayEntry (string val)
{
val = String.Format ("new ushort [] {{ {0} }}", String.Join (", ", val.Split(' ')));
Write ("Assert.IsNotNull (entry as ShortArrayIFDEntry, \"Entry is not a short array!\");");
Write ("Assert.AreEqual ({0}, (entry as ShortArrayIFDEntry).Values);", val);
}
static void EmitTestIFDSShortArrayEntry (string val)
{
val = String.Format ("new short [] {{ {0} }}", String.Join (", ", val.Split(' ')));
Write ("Assert.IsNotNull (entry as SShortArrayIFDEntry, \"Entry is not a signed short array!\");");
Write ("Assert.AreEqual ({0}, (entry as SShortArrayIFDEntry).Values);", val);
}
static void EmitTestIFDRationalEntry (string val)
{
Write ("Assert.IsNotNull (entry as RationalIFDEntry, \"Entry is not a rational!\");");
string[] parts = val.Split('/');
Write ("Assert.AreEqual ({0}, (entry as RationalIFDEntry).Value.Numerator);", parts [0]);
Write ("Assert.AreEqual ({0}, (entry as RationalIFDEntry).Value.Denominator);", parts [1]);
}
static void EmitTestIFDRationalArrayEntry (string val)
{
var parts = val.Split(' ');
Write ("Assert.IsNotNull (entry as RationalArrayIFDEntry, \"Entry is not a rational array!\");");
Write ("var parts = (entry as RationalArrayIFDEntry).Values;");
Write ("Assert.AreEqual ({0}, parts.Length);", parts.Length);
for (int i = 0; i < parts.Length; i++) {
var pieces = parts[i].Split('/');
Write ("Assert.AreEqual ({0}, parts[{1}].Numerator);", pieces[0], i);
Write ("Assert.AreEqual ({0}, parts[{1}].Denominator);", pieces[1], i);
}
}
static void EmitTestIFDSRationalEntry (string val)
{
Write ("Assert.IsNotNull (entry as SRationalIFDEntry, \"Entry is not a srational!\");");
string[] parts = val.Split('/');
Write ("Assert.AreEqual ({0}, (entry as SRationalIFDEntry).Value.Numerator);", parts [0]);
Write ("Assert.AreEqual ({0}, (entry as SRationalIFDEntry).Value.Denominator);", parts [1]);
}
static void EmitTestIFDSRationalArrayEntry (string val)
{
var parts = val.Split(' ');
Write ("Assert.IsNotNull (entry as SRationalArrayIFDEntry, \"Entry is not a srational array!\");");
Write ("var parts = (entry as SRationalArrayIFDEntry).Values;");
Write ("Assert.AreEqual ({0}, parts.Length);", parts.Length);
for (int i = 0; i < parts.Length; i++) {
var pieces = parts[i].Split('/');
Write ("Assert.AreEqual ({0}, parts[{1}].Numerator);", pieces[0], i);
Write ("Assert.AreEqual ({0}, parts[{1}].Denominator);", pieces[1], i);
}
}
static void EmitTestIFDLongEntry (string val)
{
Write ("Assert.IsNotNull (entry as LongIFDEntry, \"Entry is not a long!\");");
Write ("Assert.AreEqual ({0}, (entry as LongIFDEntry).Value);", val);
}
static void EmitTestIFDLongArrayEntry (string val)
{
val = String.Format ("new long [] {{ {0} }}", String.Join (", ", val.Split(' ')));
Write ("Assert.IsNotNull (entry as LongArrayIFDEntry, \"Entry is not a long array!\");");
Write ("Assert.AreEqual ({0}, (entry as LongArrayIFDEntry).Values);", val);
}
static void EmitTestIFDSLongEntry (string val)
{
Write ("Assert.IsNotNull (entry as SLongIFDEntry, \"Entry is not a signed long!\");");
Write ("Assert.AreEqual ({0}, (entry as SLongIFDEntry).Value);", val);
}
static void EmitTestIFDByteEntry (string val)
{
Write ("Assert.IsNotNull (entry as ByteIFDEntry, \"Entry is not a byte!\");");
Write ("Assert.AreEqual ({0}, (entry as ByteIFDEntry).Value);", val);
}
static void EmitTestIFDByteArrayEntry (string val)
{
EmitByteArrayComparison (val, "ByteVectorIFDEntry", "a byte array");
}
static void EmitTestIFDSByteEntry (string val)
{
Write ("Assert.IsNotNull (entry as SByteIFDEntry, \"Entry is not a signed byte!\");");
Write ("Assert.AreEqual ({0}, (entry as SByteIFDEntry).Value);", val);
}
static void EmitTestIFDIPTCNAAEntry (string val)
{
Write ("Assert.IsNotNull (entry as ByteVectorIFDEntry, \"Entry is not a byte array!\");");
}
static void EmitTestIFDXMLPacketEntry (string val)
{
Write ("Assert.IsNotNull (entry as ByteVectorIFDEntry, \"Entry is not a byte array!\");");
}
static void EmitTestIFDUndefinedEntry (string val)
{
EmitByteArrayComparison (val, "UndefinedIFDEntry", "an undefined IFD entry");
}
static void EmitByteArrayComparison (string val, string type, string type_desc)
{
Write ("Assert.IsNotNull (entry as {0}, \"Entry is not {1}!\");", type, type_desc);
Write ("var parsed_bytes = (entry as {0}).Data.Data;", type);
var parts = val.Trim ().Split(' ');
if (parts.Length < 512) {
Write ("var bytes = new byte [] {{ {0} }};", String.Join (", ", parts));
Write ("Assert.AreEqual (bytes, parsed_bytes);");
} else {
// Starting with 512 byte items, we compare based on an MD5 hash, should be faster and reduces
// the size of the test fixtures.
byte [] data = new byte [parts.Length];
for (int i = 0; i < parts.Length; i++) {
data [i] = Byte.Parse (parts [i]);
}
var hash = md5.ComputeHash (data);
StringBuilder shash = new StringBuilder ();
for (int i = 0; i < hash.Length; i++) {
shash.Append (hash[i].ToString ("x2"));
}
Write ("var parsed_hash = Utils.Md5Encode (parsed_bytes);");
Write ("Assert.AreEqual (\"{0}\", parsed_hash);", shash.ToString ());
Write ("Assert.AreEqual ({0}, parsed_bytes.Length);", parts.Length);
}
}
static void EmitTestIFDSubIFDEntry (string val)
{
Write ("Assert.IsNotNull (entry as SubIFDEntry, \"Entry is not a sub IFD!\");");
}
static void EmitTestIFDThumbnailDataIFDEntry (string val)
{
Write ("Assert.IsNotNull (entry as ThumbnailDataIFDEntry, \"Entry is not a thumbnail IFD!\");");
}
static void EmitTestIFDMakerNoteIFDEntry (string val)
{
Write ("Assert.IsNotNull (entry as MakernoteIFDEntry, \"Entry is not a makernote IFD!\");");
}
static void EmitTestIFDUserCommentIFDEntry (string val)
{
Write ("Assert.IsNotNull (entry as UserCommentIFDEntry, \"Entry is not a user comment!\");");
if (val.StartsWith ("charset=\"Ascii\""))
val = val.Substring (15).Trim ();
Write ("Assert.AreEqual (\"{0}\", (entry as UserCommentIFDEntry).Value.Trim ());", val);
}
static void EmitTestIFDStripOffsetsEntry (string val)
{
// The offsets may change after writing. Therfore we cannot compare them directly.
string offset_count = String.Format ("{0}", val.Split(' ').Length);
//val = String.Format ("new long [] {{ {0} }}", String.Join (", ", val.Split(' ')));
Write ("Assert.IsNotNull (entry as StripOffsetsIFDEntry, \"Entry is not a strip offsets entry!\");");
//Write ("Assert.AreEqual ({0}, (entry as StripOffsetsIFDEntry).Values);", val);
Write ("Assert.AreEqual ({0}, (entry as StripOffsetsIFDEntry).Values.Length);", offset_count);
}
static void EmitTestIFDIndexedShortEntry (int index, string val)
{
Write ("Assert.IsNotNull (entry as ShortArrayIFDEntry, \"Entry is not a short array!\");");
var parts = val.Trim ().Split (' ');
Write ("Assert.IsTrue ({0} <= (entry as ShortArrayIFDEntry).Values.Length);", index + parts.Length);
for (int i = 0; i < parts.Length; i++)
Write ("Assert.AreEqual ({0}, (entry as ShortArrayIFDEntry).Values [{1}]);", parts [i], index + i);
}
#region IFD tag names lookup
static Dictionary<string, Dictionary<ushort, string>> tag_names = null;
static string StringifyEntryTag (string src, ushort tag)
{
if (tag_names == null)
BuildTagNamesTable ();
Dictionary<ushort, string> table;
string result;
if (tag_names.TryGetValue (src, out table)) {
if (table.TryGetValue (tag, out result))
return result;
}
Write ("// TODO: Unknown IFD tag: {1} / 0x{0:X4}", tag, src);
return String.Format ("0x{0:X4}", tag);
}
static void BuildTagNamesTable ()
{
tag_names = new Dictionary<string, Dictionary<ushort, string>> ();
IndexTagType ("Image", typeof (IFDEntryTag), "IFDEntryTag");
IndexTagType ("Image2", typeof (IFDEntryTag), "IFDEntryTag");
IndexTagType ("Image3", typeof (IFDEntryTag), "IFDEntryTag");
IndexTagType ("SubImage1", typeof (IFDEntryTag), "IFDEntryTag");
IndexTagType ("SubImage2", typeof (IFDEntryTag), "IFDEntryTag");
IndexTagType ("Thumbnail", typeof (IFDEntryTag), "IFDEntryTag"); // IFD1, for thumbnails
IndexTagType ("Photo", typeof (IFDEntryTag), "IFDEntryTag");
IndexTagType ("Photo", typeof (ExifEntryTag), "ExifEntryTag");
IndexTagType ("Image", typeof (ExifEntryTag), "ExifEntryTag"); // Also put exif into Image, for DNG
IndexTagType ("GPSInfo", typeof (GPSEntryTag), "GPSEntryTag");
IndexTagType ("Iop", typeof (IOPEntryTag), "IOPEntryTag");
IndexTagType ("Canon", typeof (CanonMakerNoteEntryTag), "CanonMakerNoteEntryTag");
IndexTagType ("CanonCs", typeof (CanonMakerNoteEntryTag), "CanonMakerNoteEntryTag");
IndexTagType ("CanonSi", typeof (CanonMakerNoteEntryTag), "CanonMakerNoteEntryTag");
IndexTagType ("CanonCf", typeof (CanonMakerNoteEntryTag), "CanonMakerNoteEntryTag");
IndexTagType ("CanonFi", typeof (CanonFileInfoEntryTag), "CanonFileInfoEntryTag");
IndexTagType ("CanonFi", typeof (CanonMakerNoteEntryTag), "CanonMakerNoteEntryTag");
IndexTagType ("CanonPi", typeof (CanonPictureInfoEntryTag), "CanonPictureInfoEntryTag");
IndexTagType ("CanonPi", typeof (CanonMakerNoteEntryTag), "CanonMakerNoteEntryTag");
IndexTagType ("Sony", typeof (SonyMakerNoteEntryTag), "SonyMakerNoteEntryTag");
IndexTagType ("Olympus", typeof (OlympusMakerNoteEntryTag), "OlympusMakerNoteEntryTag");
IndexTagType ("Pentax", typeof (PentaxMakerNoteEntryTag), "PentaxMakerNoteEntryTag");
IndexTagType ("Nikon3", typeof (Nikon3MakerNoteEntryTag), "Nikon3MakerNoteEntryTag");
IndexTagType ("NikonPreview", typeof (NikonPreviewMakerNoteEntryTag), "NikonPreviewMakerNoteEntryTag");
IndexTagType ("Panasonic", typeof (PanasonicMakerNoteEntryTag), "PanasonicMakerNoteEntryTag");
IndexTagType ("PanasonicRaw", typeof (IFDEntryTag), "IFDEntryTag");
}
static void IndexTagType (string ifd, Type t, string typename)
{
if (!tag_names.ContainsKey (ifd))
tag_names[ifd] = new Dictionary<ushort, string> ();
foreach (string name in Enum.GetNames (t)) {
ushort tag = (ushort) Enum.Parse (t, name);
tag_names[ifd][tag] = String.Format ("{1}.{0}", name, typename);
}
}
#endregion
#region Code emission
static int level = 0;
static void Write (string str, params object[] p)
{
Console.Write (new String ('\t', level));
Console.WriteLine (str, p);
}
static void Write ()
{
Console.WriteLine ();
}
static void Write (string str)
{
if (str.Equals ("}"))
level--;
Console.Write (new String ('\t', level));
Console.WriteLine (str);
if (str.Equals ("{"))
level++;
}
#endregion
}

View File

@@ -0,0 +1,13 @@
using System;
using TagLib;
public class ListSupportedMimeTypes
{
public static void Main()
{
foreach(string type in SupportedMimeType.AllMimeTypes) {
Console.WriteLine(type);
}
}
}

View File

@@ -0,0 +1,61 @@
READ_FROM_URI = ReadFromUri
SET_PICTURES = SetPictures
LIST_TYPES = ListSupportedMimeTypes
BATCH_SET = BatchSet
PARSE_PHOTO = ParsePhoto
STRIP_IMAGE = StripImageData
GENERATE_TEST_FIXTURE = GenerateTestFixture
REFERENCES = -r:taglib-sharp.dll
EXAMPLES_BUILD = taglib-sharp.dll $(SET_PICTURES).exe $(LIST_TYPES).exe $(BATCH_SET).exe $(PARSE_PHOTO).exe $(STRIP_IMAGE).exe
if HAVE_GNOME_SHARP
EXAMPLES_BUILD += $(READ_FROM_URI).exe
if HAVE_EXIV2
EXAMPLES_BUILD += $(GENERATE_TEST_FIXTURE).exe
endif
endif
all: $(EXAMPLES_BUILD)
taglib-sharp.dll:
if [ ! -e $@ ]; then ln -s $(top_builddir)/src/taglib-sharp.dll $@; fi
if HAVE_GNOME_SHARP
$(READ_FROM_URI).exe: $(READ_FROM_URI).cs
$(MCS) -out:$@ -debug $(REFERENCES) $(GNOME_SHARP_LIBS) $<
if HAVE_EXIV2
$(GENERATE_TEST_FIXTURE).exe: $(GENERATE_TEST_FIXTURE).cs listData extractKey
$(MCS) -out:$@ -debug $(REFERENCES) $(GNOME_SHARP_LIBS) $<
listData: listData.cpp
g++ -o $@ $(EXIV2_LIBS) $<
extractKey: extractKey.cpp
g++ -o $@ $(EXIV2_LIBS) $<
endif
endif
$(SET_PICTURES).exe: $(SET_PICTURES).cs
$(MCS) -out:$@ -debug $(REFERENCES) $<
$(LIST_TYPES).exe: $(LIST_TYPES).cs
$(MCS) -out:$@ -debug $(REFERENCES) $<
$(BATCH_SET).exe: $(BATCH_SET).cs
$(MCS) -out:$@ -debug $(REFERENCES) $<
$(PARSE_PHOTO).exe: $(PARSE_PHOTO).cs
$(MCS) -out:$@ -debug $(REFERENCES) $<
$(STRIP_IMAGE).exe: $(STRIP_IMAGE).cs
$(MCS) -out:$@ -debug $(REFERENCES) $<
EXTRA_DIST = $(READ_FROM_URI).cs $(SET_PICTURES).cs $(LIST_TYPES).cs $(BATCH_SET).cs $(PARSE_PHOTO).cs $(STRIP_IMAGE).cs $(GENERATE_TEST_FIXTURE).cs \
$(srcdir)/covers/sample*
DISTCLEANFILES = *.pidb
CLEANFILES = *.dll *.exe *.mdb
MAINTAINERCLEANFILES = Makefile.in

View File

@@ -0,0 +1,82 @@
using System;
public class ParsePhotoApp
{
public static void Main (string [] args)
{
if(args.Length == 0) {
Console.Error.WriteLine("USAGE: mono ParsePhoto.exe PATH [...]");
return;
}
foreach (string path in args)
ParsePhoto (path);
}
static void ParsePhoto (string path)
{
TagLib.File file = null;
try {
file = TagLib.File.Create(path);
} catch (TagLib.UnsupportedFormatException) {
Console.WriteLine ("UNSUPPORTED FILE: " + path);
Console.WriteLine (String.Empty);
Console.WriteLine ("---------------------------------------");
Console.WriteLine (String.Empty);
return;
}
var image = file as TagLib.Image.File;
if (file == null) {
Console.WriteLine ("NOT AN IMAGE FILE: " + path);
Console.WriteLine (String.Empty);
Console.WriteLine ("---------------------------------------");
Console.WriteLine (String.Empty);
return;
}
Console.WriteLine (String.Empty);
Console.WriteLine (path);
Console.WriteLine (String.Empty);
Console.WriteLine("Tags in object : " + image.TagTypes);
Console.WriteLine (String.Empty);
Console.WriteLine("Comment : " + image.ImageTag.Comment);
Console.Write("Keywords : ");
foreach (var keyword in image.ImageTag.Keywords) {
Console.Write (keyword + " ");
}
Console.WriteLine ();
Console.WriteLine("Rating : " + image.ImageTag.Rating);
Console.WriteLine("DateTime : " + image.ImageTag.DateTime);
Console.WriteLine("Orientation : " + image.ImageTag.Orientation);
Console.WriteLine("Software : " + image.ImageTag.Software);
Console.WriteLine("ExposureTime : " + image.ImageTag.ExposureTime);
Console.WriteLine("FNumber : " + image.ImageTag.FNumber);
Console.WriteLine("ISOSpeedRatings : " + image.ImageTag.ISOSpeedRatings);
Console.WriteLine("FocalLength : " + image.ImageTag.FocalLength);
Console.WriteLine("FocalLength35mm : " + image.ImageTag.FocalLengthIn35mmFilm);
Console.WriteLine("Make : " + image.ImageTag.Make);
Console.WriteLine("Model : " + image.ImageTag.Model);
if (image.Properties != null) {
Console.WriteLine("Width : " + image.Properties.PhotoWidth);
Console.WriteLine("Height : " + image.Properties.PhotoHeight);
Console.WriteLine("Type : " + image.Properties.Description);
}
Console.WriteLine ();
Console.WriteLine("Writable? : " + image.Writeable.ToString ());
Console.WriteLine("Corrupt? : " + image.PossiblyCorrupt.ToString ());
if (image.PossiblyCorrupt) {
foreach (string reason in image.CorruptionReasons) {
Console.WriteLine (" * " + reason);
}
}
Console.WriteLine ("---------------------------------------");
}
}

View File

@@ -0,0 +1,136 @@
import TagLib from "taglib-sharp.dll"
import Gnome.Vfs from "gnome-vfs-sharp"
import System
import System.IO
def ReadFromUri(argv as (string)):
if len(argv) < 1:
print "Usage: booi ReadFromUri.boo PATH [...]"
return
Vfs.Initialize()
TagLib.File.SetFileAbstractionCreator(TagLib.File.FileAbstractionCreator(CreateFile))
start = DateTime.Now
songs_read = 0
try:
for path as string in argv:
print path
file_info as System.IO.FileInfo = System.IO.FileInfo(path)
uri as string = Gnome.Vfs.Uri.GetUriFromLocalPath (file_info.FullName)
file as TagLib.File = null
try:
file = TagLib.File.Create(uri)
except UnsupportedFormatException:
print "UNSUPPORTED FILE: ${path}"
print string.Empty
print "---------------------------------------"
print string.Empty
continue
print "Title: ${file.Tag.Title}"
if file.Tag.AlbumArtists is null:
print "Artists:"
else:
print "Artists: ${string.Join ('\n ', file.Tag.AlbumArtists)}"
if file.Tag.Performers is null:
print 'Performers:'
else:
print "Performers: ${string.Join ('\n ', file.Tag.Performers)}"
if file.Tag.Composers is null:
print 'Composers:'
else:
print "Composers: ${string.Join ('\n ', file.Tag.Composers)}"
print "Album: ${file.Tag.Album}"
print "Comment: ${file.Tag.Comment}"
if file.Tag.Genres is null:
print 'Genres:'
else:
print "Genres: ${string.Join ('\n ', file.Tag.Genres)}"
print "Year: ${file.Tag.Year}"
print "Track: ${file.Tag.Track}"
print "TrackCount: ${file.Tag.TrackCount}"
print "Disc: ${file.Tag.Disc}"
print "DiscCount: ${file.Tag.DiscCount}"
print "Lyrics:\n${file.Tag.Lyrics}"
print string.Empty
print "Media Types: ${file.Properties.MediaTypes}"
print string.Empty
for codec as ICodec in file.Properties.Codecs:
if codec.MediaTypes & MediaTypes.Audio:
print "Audio Properties : ${(codec as IAudioCodec).Description}"
print "Bitrate: ${(codec as IAudioCodec).AudioBitrate}"
print "SampleRate: ${(codec as IAudioCodec).AudioSampleRate}"
print "Channels: ${(codec as IAudioCodec).AudioChannels}"
print string.Empty
if codec.MediaTypes & MediaTypes.Video:
print "Video Properties : ${(codec as IVideoCodec).Description}"
print "Width: ${(codec as IVideoCodec).VideoWidth}"
print "Height: ${(codec as IVideoCodec).VideoHeight}"
print string.Empty
if file.Properties.MediaTypes:
print "Length: ${file.Properties.Duration}"
print string.Empty
print "Embedded Pictures: ${file.Tag.Pictures.Length}"
for picture in file.Tag.Pictures:
print picture.Description
print " MimeType: ${picture.MimeType}"
print " Size: ${picture.Data.Count}"
print " Type: ${picture.Type}"
print ""
print "---------------------------------------"
print ""
songs_read = songs_read + 1
ensure:
Vfs.Shutdown()
end as DateTime = DateTime.Now;
print "Total running time: ${end - start}"
print "Total files read: ${songs_read}"
print "Average time per file: ${TimeSpan ((end - start).Ticks / songs_read)}"
class VfsFileAbstraction(TagLib.File.IFileAbstraction):
_name as string
def constructor(file as string):
_name = file
Name:
get:
return _name
ReadStream:
get:
return VfsStream(_name, FileMode.Open)
WriteStream:
get:
return VfsStream(_name, FileMode.Open)
def CreateFile(path):
return VfsFileAbstraction(path)
ReadFromUri(argv)

View File

@@ -0,0 +1,171 @@
using System;
using TagLib;
using Gnome.Vfs;
public class ReadFromUri
{
public static void Write (string name, object value)
{
Console.WriteLine ("{0,20}: {1}",
name, value == null ? "" : value
);
}
public static void Write (string name, string [] values)
{
Console.WriteLine ("{0,20}: {1}",
name,
values == null ? "" : String.Join ("\n ", values)
);
}
public static void Main(string [] args)
{
if(args.Length == 0) {
Console.Error.WriteLine("USAGE: mono ReadFromUri.exe PATH [...]");
return;
}
Gnome.Vfs.Vfs.Initialize();
DateTime start = DateTime.Now;
int songs_read = 0;
try {
foreach (string path in args)
{
string uri = path;
Console.WriteLine (uri);
TagLib.File file = null;
try {
System.IO.FileInfo file_info = new System.IO.FileInfo(uri);
uri = Gnome.Vfs.Uri.GetUriFromLocalPath (file_info.FullName);
} catch {
}
try
{
file = TagLib.File.Create(new VfsFileAbstraction (uri));
}
catch (TagLib.UnsupportedFormatException)
{
Console.WriteLine ("UNSUPPORTED FILE: " + uri);
Console.WriteLine (String.Empty);
Console.WriteLine ("---------------------------------------");
Console.WriteLine (String.Empty);
continue;
}
Console.WriteLine("Tags on disk: " + file.TagTypesOnDisk);
Console.WriteLine("Tags in object: " + file.TagTypes);
Console.WriteLine (String.Empty);
Write ("Grouping", file.Tag.Grouping);
Write ("Title", file.Tag.Title);
Write ("TitleSort", file.Tag.TitleSort);
Write ("Album Artists", file.Tag.AlbumArtists);
Write ("Album Artists Sort", file.Tag.AlbumArtistsSort);
Write ("Performers", file.Tag.Performers);
Write ("Performers Sort", file.Tag.PerformersSort);
Write ("Composers", file.Tag.Composers);
Write ("Composers Sort", file.Tag.ComposersSort);
Write ("Conductor", file.Tag.Conductor);
Write ("Album", file.Tag.Album);
Write ("Album Sort", file.Tag.AlbumSort);
Write ("Comment", file.Tag.Comment);
Write ("Copyright", file.Tag.Copyright);
Write ("Genres", file.Tag.Genres);
Write ("BPM", file.Tag.BeatsPerMinute);
Write ("Year", file.Tag.Year);
Write ("Track", file.Tag.Track);
Write ("TrackCount", file.Tag.TrackCount);
Write ("Disc", file.Tag.Disc);
Write ("DiscCount", file.Tag.DiscCount);
Console.WriteLine("Lyrics:\n" + file.Tag.Lyrics + "\n");
Console.WriteLine("Media Types: " + file.Properties.MediaTypes + "\n");
foreach (TagLib.ICodec codec in file.Properties.Codecs)
{
TagLib.IAudioCodec acodec = codec as TagLib.IAudioCodec;
TagLib.IVideoCodec vcodec = codec as TagLib.IVideoCodec;
if (acodec != null && (acodec.MediaTypes & TagLib.MediaTypes.Audio) != TagLib.MediaTypes.None)
{
Console.WriteLine("Audio Properties : " + acodec.Description);
Console.WriteLine("Bitrate: " + acodec.AudioBitrate);
Console.WriteLine("SampleRate: " + acodec.AudioSampleRate);
Console.WriteLine("Channels: " + acodec.AudioChannels + "\n");
}
if (vcodec != null && (vcodec.MediaTypes & TagLib.MediaTypes.Video) != TagLib.MediaTypes.None)
{
Console.WriteLine("Video Properties : " + vcodec.Description);
Console.WriteLine("Width: " + vcodec.VideoWidth);
Console.WriteLine("Height: " + vcodec.VideoHeight + "\n");
}
}
if (file.Properties.MediaTypes != TagLib.MediaTypes.None)
Console.WriteLine("Length: " + file.Properties.Duration + "\n");
IPicture [] pictures = file.Tag.Pictures;
Console.WriteLine("Embedded Pictures: " + pictures.Length);
foreach(IPicture picture in pictures) {
Console.WriteLine(picture.Description);
Console.WriteLine(" MimeType: " + picture.MimeType);
Console.WriteLine(" Size: " + picture.Data.Count);
Console.WriteLine(" Type: " + picture.Type);
}
Console.WriteLine (String.Empty);
Console.WriteLine ("---------------------------------------");
Console.WriteLine (String.Empty);
songs_read ++;
}
} finally {
Gnome.Vfs.Vfs.Shutdown();
}
DateTime end = DateTime.Now;
Console.WriteLine ("Total running time: " + (end - start));
Console.WriteLine ("Total files read: " + songs_read);
if (songs_read > 0)
{
Console.WriteLine ("Average time per file: " + new TimeSpan ((end - start).Ticks / songs_read));
}
}
}
public class VfsFileAbstraction : TagLib.File.IFileAbstraction
{
private string name;
public VfsFileAbstraction(string file)
{
name = file;
}
public string Name {
get { return name; }
}
public System.IO.Stream ReadStream {
get { return new VfsStream(Name, System.IO.FileMode.Open); }
}
public System.IO.Stream WriteStream {
get { return new VfsStream(Name, System.IO.FileMode.Open); }
}
public void CloseStream (System.IO.Stream stream)
{
stream.Close ();
}
}

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{AB35577D-31CB-4848-AC41-13F00A5171A6}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>ReadFromUri</RootNamespace>
<AssemblyName>ReadFromUri</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>.</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Commandlineparameters>../tests/samples/sample.ogg</Commandlineparameters>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<Execution>
<Execution clr-version="Net_2_0" />
</Execution>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>.</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Commandlineparameters>../tests/samples/sample_v2_only.mp3</Commandlineparameters>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<Execution>
<Execution clr-version="Net_2_0" />
</Execution>
</PropertyGroup>
<ItemGroup>
<Compile Include="ReadFromUri.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\taglib-sharp.csproj">
<Project>{6B143A39-C7B2-4743-9917-92262C60E9A6}</Project>
<Name>taglib-sharp</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="gnome-vfs-sharp, Version=2.8.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,28 @@
using System;
using TagLib;
public class SetPictures
{
public static void Main(string [] args)
{
if(args.Length < 2) {
Console.Error.WriteLine("USAGE: mono SetPictures.exe AUDIO_PATH IMAGE_PATH_1[...IMAGE_PATH_N]");
return;
}
TagLib.File file = TagLib.File.Create(args[0]);
Console.WriteLine("Current picture count: " + file.Tag.Pictures.Length);
Picture [] pictures = new Picture[args.Length - 1];
for(int i = 1; i < args.Length; i++) {
Picture picture = new Picture(args[i]);
pictures[i - 1] = picture;
}
file.Tag.Pictures = pictures;
file.Save();
Console.WriteLine("New picture count: " + file.Tag.Pictures.Length);
}
}

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0C4645BE-7413-43FC-8856-1ECF1A790FF8}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>SetPictures</RootNamespace>
<AssemblyName>SetPictures</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>.</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Commandlineparameters>../tests/samples/sample_v2_only.mp3 covers/sample_a.png covers/sample_b.jpg</Commandlineparameters>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<Execution>
<Execution clr-version="Net_2_0" />
</Execution>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>.</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Commandlineparameters>../tests/samples/sample_v2_only.mp3 covers/sample_a.png covers/sample_b.jpg</Commandlineparameters>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<Execution>
<Execution clr-version="Net_2_0" />
</Execution>
</PropertyGroup>
<ItemGroup>
<Compile Include="SetPictures.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\taglib-sharp.csproj">
<Project>{6B143A39-C7B2-4743-9917-92262C60E9A6}</Project>
<Name>taglib-sharp</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,117 @@
using System;
using TagLib;
public class StripImageData
{
private static byte[] image_data = new byte[] {
0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00,
0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00,
0x8C, 0x80, 0x07, 0xFF, 0xD9
};
public static void Main (string [] args)
{
if (args.Length != 1) {
Console.Out.WriteLine ("usage: mono StripImageData.exe [jpegfile]");
return;
}
ImageFile file = new ImageFile (args [0]);
file.Mode = File.AccessMode.Write;
long greatest_segment_position = 0;
long greatest_segment_length = 0;
// collect data segments
while (true) {
long sos = file.Find (new byte [] {0xFF, 0xDA}, file.Tell);
if (sos == -1)
break;
file.Seek (sos);
long segment_length = SkipDataSegment (file);
if (segment_length > greatest_segment_length) {
greatest_segment_length = segment_length;
greatest_segment_position = sos;
}
}
if (greatest_segment_length == 0)
{
Console.Out.WriteLine ("doesn't look like an jpeg file");
return;
}
System.Console.WriteLine ("Stripping data segment at {0}", greatest_segment_position);
file.RemoveBlock (greatest_segment_position, greatest_segment_length);
file.Seek (greatest_segment_position);
file.WriteBlock (image_data);
file.Mode = File.AccessMode.Closed;
}
private static long SkipDataSegment (ImageFile file)
{
long position = file.Tell;
// skip sos maker
if (file.ReadBlock (2).ToUInt () != 0xFFDA)
throw new Exception (String.Format ("Not a data segment at position: {0}", position));
while (true) {
if (0xFF == (byte) file.ReadBlock (1)[0]) {
byte maker = (byte) file.ReadBlock (1)[0];
if (maker != 0x00 && (maker <= 0xD0 || maker >= 0xD7))
break;
}
}
long length = file.Tell - position - 2;
System.Console.WriteLine ("Data segment of length {0} found at {1}", length, position);
return length;
}
private class ImageFile : File {
// Hacky implementation to make use of some methods defined in TagLib.File
public ImageFile (string path)
: base (new File.LocalFileAbstraction (path)) {}
public override Tag GetTag (TagLib.TagTypes type, bool create)
{
throw new System.NotImplementedException ();
}
public override Properties Properties {
get {
throw new System.NotImplementedException ();
}
}
public override void RemoveTags (TagLib.TagTypes types)
{
throw new System.NotImplementedException ();
}
public override void Save ()
{
throw new System.NotImplementedException ();
}
public override Tag Tag {
get {
throw new System.NotImplementedException ();
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,41 @@
#include <exiv2/image.hpp>
#include <exiv2/exif.hpp>
#include <iostream>
#include <iomanip>
#include <cassert>
int main(int argc, char* const argv[])
try {
if (argc != 3) {
std::cout << "Usage: " << argv[0] << " file key\n";
return 1;
}
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]);
assert(image.get() != 0);
image->readMetadata();
try {
Exiv2::ExifData &exifData = image->exifData();
const Exiv2::Value &value = exifData[argv[2]].value();
std::cout << value;
} catch (Exiv2::AnyError &e) {}
try {
Exiv2::IptcData &iptcData = image->iptcData();
const Exiv2::Value &value = iptcData[argv[2]].value();
std::cout << value;
} catch (Exiv2::AnyError &e) {}
try {
Exiv2::XmpData &xmpData = image->xmpData();
const Exiv2::Value &value = xmpData[argv[2]].value();
std::cout << value;
} catch (Exiv2::AnyError &e) {}
return 0;
} catch (Exiv2::AnyError& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@@ -0,0 +1,62 @@
#include <exiv2/image.hpp>
#include <exiv2/exif.hpp>
#include <iostream>
#include <iomanip>
#include <cassert>
int main(int argc, char* const argv[])
try {
if (argc != 3) {
std::cout << "Usage: " << argv[0] << " mode file\n";
return 1;
}
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[2]);
assert(image.get() != 0);
image->readMetadata();
if (argv[1][0] == 'e') {
Exiv2::ExifData &exifData = image->exifData();
if (!exifData.empty()) {
Exiv2::ExifData::const_iterator exifEnd = exifData.end();
for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != exifEnd; ++i) {
std::cout << i->tagName() << "\t"
<< "0x" << std::setw(4) << std::setfill('0') << std::right
<< std::hex << i->tag() << std::dec << "\t"
<< i->groupName() << "\t"
<< i->typeName() << "\t"
<< i->count() << "\t"
<< "\n";
}
}
}
if (argv[1][0] == 'i') {
Exiv2::IptcData &iptcData = image->iptcData();
if (!iptcData.empty()) {
Exiv2::IptcData::const_iterator iptcEnd = iptcData.end();
for (Exiv2::IptcData::const_iterator i = iptcData.begin(); i != iptcEnd; ++i) {
std::cout << i->key() << "\n";
}
}
}
if (argv[1][0] == 'x') {
Exiv2::XmpData &xmpData = image->xmpData();
if (!xmpData.empty()) {
Exiv2::XmpData::const_iterator xmpEnd = xmpData.end();
for (Exiv2::XmpData::const_iterator i = xmpData.begin(); i != xmpEnd; ++i) {
std::cout << i->key() << "\t"
<< i->typeName() << "\t"
<< i->count() << "\t"
<< "\n";
}
}
}
return 0;
} catch (Exiv2::AnyError& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}