Logo Search packages:      
Sourcecode: f-spot version File versions  Download package

Tag.cs

//
// Tag.cs: Provides a representation of an APEv2 tag which can be read from and
// written to disk.
//
// Author:
//   Brian Nickel (brian.nickel@gmail.com)
//
// Original Source:
//   apetag.cpp from TagLib
//
// Copyright (C) 2005-2007 Brian Nickel
// Copyright (C) 2004 Allan Sandfeld Jensen (Original Implementation)
// 
// This library is free software; you can redistribute it and/or modify
// it  under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
// USA
//

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;

namespace TagLib.Ape {
      /// <summary>
      ///    This class extends <see cref="TagLib.Tag" /> and implements <see
      ///    cref="T:System.Collections.Generic.IEnumerable`1" /> to provide a representation of an APEv2
      ///    tag which can be read from and written to disk.
      /// </summary>
00040       public class Tag : TagLib.Tag, IEnumerable<string>
      {
            
#region Private Static Fields
            
            /// <summary>
            ///    Contains names of picture fields, indexed to correspond
            ///    to their picture item names.
            /// </summary>
00049             private static string [] picture_item_names = new string [] {
                  "Cover Art (other)",
                  "Cover Art (icon)",
                  "Cover Art (other icon)",
                  "Cover Art (front)",
                  "Cover Art (back)",
                  "Cover Art (leaflet)",
                  "Cover Art (media)",
                  "Cover Art (lead)",
                  "Cover Art (artist)",
                  "Cover Art (conductor)",
                  "Cover Art (band)",
                  "Cover Art (composer)",
                  "Cover Art (lyricist)",
                  "Cover Art (studio)",
                  "Cover Art (recording)",
                  "Cover Art (performance)",
                  "Cover Art (movie scene)",
                  "Cover Art (colored fish)",
                  "Cover Art (illustration)",
                  "Cover Art (band logo)",
                  "Cover Art (publisher logo)"
            };
            
#endregion
            
            
            
#region Private Fields
            
            /// <summary>
            ///    Contains the tag footer.
            /// </summary>
00082             private Footer footer = new Footer ();
            
            /// <summary>
            ///    Contains the items in the tag.
            /// </summary>
00087             private List<Item> items = new List<Item> ();
            
            #endregion
            
            
            
            #region Public Static Properties
            
            /// <summary>
            ///    Specifies the identifier used find an APEv2 tag in a
            ///    file.
            /// </summary>
            /// <value>
            ///    "<c>APETAGEX</c>"
            /// </value>
            [Obsolete("Use Footer.FileIdentifer")]
00103             public static readonly ReadOnlyByteVector FileIdentifier =
                  Footer.FileIdentifier;
            
            #endregion
            
            
            
            #region Constructors
            
            /// <summary>
            ///    Constructs and initializes a new instance of <see
            ///    cref="Tag" /> with no contents.
            /// </summary>
00116             public Tag ()
            {
            }
            
            /// <summary>
            ///    Constructs and initializes a new instance of <see
            ///    cref="Tag" /> by reading the contents from a specified
            ///    position in a specified file.
            /// </summary>
            /// <param name="file">
            ///    A <see cref="TagLib.File" /> object containing the file
            ///    from which the contents of the new instance is to be
            ///    read.
            /// </param>
            /// <param name="position">
            ///    A <see cref="long" /> value specify at what position to
            ///    read the tag.
            /// </param>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="file" /> is <see langword="null" />.
            /// </exception>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="position" /> is less than zero or greater
            ///    than the size of the file.
            /// </exception>
00141             public Tag (TagLib.File file, long position)
            {
                  if (file == null)
                        throw new ArgumentNullException ("file");
                  
                  if (position < 0 ||
                        position > file.Length - Footer.Size)
                        throw new ArgumentOutOfRangeException (
                              "position");
                  
                  Read (file, position);
            }
            
            /// <summary>
            ///    Constructs and initializes a new instance of <see
            ///    cref="Tag" /> by reading the contents of a raw tag in a
            ///    specified <see cref="ByteVector"/> object.
            /// </summary>
            /// <param name="data">
            ///    A <see cref="ByteVector" /> object containing the raw
            ///    tag.
            /// </param>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="data" /> is <see langword="null"/>.
            /// </exception>
            /// <exception cref="CorruptFileException">
            ///    <paramref name="data" /> is too small to contain a tag,
            ///    has a header where the footer should be, or is smaller
            ///    than the tag it is supposed to contain.
            /// </exception>
00171             public Tag (ByteVector data)
            {
                  if (data == null)
                        throw new ArgumentNullException ("data");
                  
                  if (data.Count < Footer.Size)
                        throw new CorruptFileException (
                              "Does not contain enough footer data.");
                  
                  footer = new Footer (
                        data.Mid ((int) (data.Count - Footer.Size)));
                  
                  if (footer.TagSize == 0)
                        throw new CorruptFileException (
                              "Tag size out of bounds.");
                  
                  // If we've read a header at the end of the block, the
                  // block is invalid.
                  if ((footer.Flags & FooterFlags.IsHeader) != 0)
                        throw new CorruptFileException (
                              "Footer was actually header.");
                  
                  if (data.Count < footer.TagSize)
                        throw new CorruptFileException (
                              "Does not contain enough tag data.");
                  
                  Parse (data.Mid ((int) (data.Count - footer.TagSize),
                        (int) (footer.TagSize - Footer.Size)));
            }
            
            #endregion
            
            
            
            #region Public Properties
            
            /// <summary>
            ///    Gets and sets whether or not the current instance has a
            ///    header when rendered.
            /// </summary>
            /// <value>
            ///    A <see cref="bool" /> value indicating whether or not the
            ///    current instance has a header when rendered.
            /// </value>
00215             public bool HeaderPresent {
                  get {
                        return (footer.Flags &
                              FooterFlags.HeaderPresent) != 0;
                  }
                  set {
                        if (value)
                              footer.Flags |= FooterFlags.HeaderPresent;
                        else
                              footer.Flags &= ~FooterFlags.HeaderPresent;
                  }
            }
            
            #endregion
            
            
            
            #region Public Methods
            
            /// <summary>
            ///    Adds a number to the value stored in a specified item.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key of the
            ///    item to store the value in.
            /// </param>
            /// <param name="number">
            ///    A <see cref="uint" /> value containing the number to
            ///    store.
            /// </param>
            /// <param name="count">
            ///    A <see cref="uint" /> value representing a total which
            ///    <paramref name="number" /> is a part of, or zero if
            ///    <paramref name="number" /> is not part of a set.
            /// </param>
            /// <remarks>
            ///    If both <paramref name="number" /> and <paramref
            ///    name="count" /> are equal to zero, the value will not be
            ///    added. If <paramref name="count" /> is zero, <paramref
            ///    name="number" /> by itself will be stored. Otherwise, the
            ///    values will be stored as "<paramref name="number"
            ///    />/<paramref name="count" />".
            /// </remarks>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="key" /> is <see langword="null" />.
            /// </exception>
00261             public void AddValue (string key, uint number, uint count)
            {
                  if (key == null)
                        throw new ArgumentNullException ("key");
                  
                  if (number == 0 && count == 0)
                        return;
                  else if (count != 0)
                        AddValue (key, string.Format (
                              CultureInfo.InvariantCulture, "{0}/{1}",
                              number, count));
                  else
                        AddValue (key, number.ToString (
                              CultureInfo.InvariantCulture));
            }
            
            /// <summary>
            ///    Stores a number in a specified item.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key of the
            ///    item to store the value in.
            /// </param>
            /// <param name="number">
            ///    A <see cref="uint" /> value containing the number to
            ///    store.
            /// </param>
            /// <param name="count">
            ///    A <see cref="uint" /> value representing a total which
            ///    <paramref name="number" /> is a part of, or zero if
            ///    <paramref name="number" /> is not part of a set.
            /// </param>
            /// <remarks>
            ///    If both <paramref name="number" /> and <paramref
            ///    name="count" /> are equal to zero, the value will be
            ///    cleared. If <paramref name="count" /> is zero, <paramref
            ///    name="number" /> by itself will be stored. Otherwise, the
            ///    values will be stored as "<paramref name="number"
            ///    />/<paramref name="count" />".
            /// </remarks>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="ident" /> is <see langword="null" />.
            /// </exception>
00304             public void SetValue (string key, uint number, uint count)
            {
                  if (key == null)
                        throw new ArgumentNullException ("key");
                  
                  if (number == 0 && count == 0)
                        RemoveItem (key);
                  else if (count != 0)
                        SetValue (key, string.Format (
                              CultureInfo.InvariantCulture, "{0}/{1}",
                              number, count));
                  else
                        SetValue (key, number.ToString (
                              CultureInfo.InvariantCulture));
            }
            
            /// <summary>
            ///    Adds the contents of a <see cref="string" /> to the value
            ///    stored in a specified item.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key of the
            ///    item to store the value in.
            /// </param>
            /// <param name="value">
            ///    A <see cref="string" /> object containing the text to
            ///    add.
            /// </param>
            /// <remarks>
            ///    If <paramref name="value" /> is <see langword="null" />
            ///    or empty, the value will not be added.
            /// </remarks>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="key" /> is <see langword="null" />.
            /// </exception>
00339             public void AddValue (string key, string value)
            {
                  if (key == null)
                        throw new ArgumentNullException ("key");
                  
                  if (string.IsNullOrEmpty (value))
                        return;
                  
                  AddValue (key, new string [] {value});
            }
            
            /// <summary>
            ///    Stores the contents of a <see cref="string" /> in a
            ///    specified item.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key of the
            ///    item to store the value in.
            /// </param>
            /// <param name="value">
            ///    A <see cref="string" /> object containing the text to
            ///    store.
            /// </param>
            /// <remarks>
            ///    If <paramref name="value" /> is <see langword="null" />
            ///    or empty, the value will be cleared.
            /// </remarks>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="key" /> is <see langword="null" />.
            /// </exception>
00369             public void SetValue (string key, string value)
            {
                  if (key == null)
                        throw new ArgumentNullException ("key");
                  
                  if (string.IsNullOrEmpty (value))
                        RemoveItem (key);
                  else
                        SetValue (key, new string [] {value});
            }
            
            /// <summary>
            ///    Adds the contents of a <see cref="string[]" /> to the
            ///    value stored in a specified item.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key of the
            ///    item to store the value in.
            /// </param>
            /// <param name="value">
            ///    A <see cref="string[]" /> containing the text to add.
            /// </param>
            /// <remarks>
            ///    If <paramref name="value" /> is <see langword="null" />
            ///    or empty, the value will not be added.
            /// </remarks>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="key" /> is <see langword="null" />.
            /// </exception>
00398             public void AddValue (string key, string [] value)
            {
                  if (key == null)
                        throw new ArgumentNullException ("key");
                  
                  if (value == null || value.Length == 0)
                        return;
                  
                  int index = GetItemIndex (key);
                  
                  List<string> values = new List<string> ();
                  
                  if (index >= 0)
                        values.AddRange (items [index].ToStringArray ());
                  
                  values.AddRange (value);
                  
                  Item item = new Item (key, values.ToArray ());
                  
                  if (index >= 0)
                        items [index] = item;
                  else
                        items.Add (item);
            }
            
            /// <summary>
            ///    Stores the contents of a <see cref="string[]" /> in a
            ///    specified item.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key of the
            ///    item to store the value in.
            /// </param>
            /// <param name="value">
            ///    A <see cref="string[]" /> containing the text to store.
            /// </param>
            /// <remarks>
            ///    If <paramref name="value" /> is <see langword="null" />
            ///    or empty, the value will be cleared.
            /// </remarks>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="key" /> is <see langword="null" />.
            /// </exception>
00441             public void SetValue (string key, string [] value)
            {
                  if (key == null)
                        throw new ArgumentNullException ("key");
                  
                  if (value == null || value.Length == 0) {
                        RemoveItem (key);
                        return;
                  }
                  
                  Item item = new Item (key, value);
                  
                  int index = GetItemIndex (key);
                  if (index >= 0)
                        items [index] = item;
                  else
                        items.Add (item);
                  
            }
            
            /// <summary>
            ///    Gets a specified item from the current instance.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key of the
            ///    item to get from the current instance.
            /// </param>
            /// <returns>
            ///    The item with the matching name contained in the current
            ///    instance, or <see langword="null" /> if a matching object
            ///    was not found.
            /// </returns>
00473             public Item GetItem (string key)
            {
                  if (key == null)
                        throw new ArgumentNullException ("key");
                  
                  StringComparison comparison =
                        StringComparison.InvariantCultureIgnoreCase;
                  
                  foreach (Item item in items)
                        if (key.Equals (item.Key, comparison))
                              return item;
                  
                  return null;
            }
            
            /// <summary>
            ///    Adds an item to the current instance, replacing the
            ///    existing one of the same name.
            /// </summary>
            /// <param name="item">
            ///    A <see cref="Item" /> object to add to the current
            ///    instance.
            /// </param>
00496             public void SetItem (Item item)
            {
                  if (item == null)
                        throw new ArgumentNullException ("item");
                  
                  int index = GetItemIndex (item.Key);
                  if (index >= 0)
                        items [index] = item;
                  else
                        items.Add (item);
            }
            
            /// <summary>
            ///    Removes the item with a specified key from the current
            ///    instance.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key of the
            ///    item to remove from the current instance.
            /// </param>
00516             public void RemoveItem (string key)
            {
                  if (key == null)
                        throw new ArgumentNullException ("key");
                  
                  StringComparison comparison =
                        StringComparison.InvariantCultureIgnoreCase;
                  
                  for (int i = items.Count - 1; i >= 0; i --)
                        if (key.Equals (items [i].Key, comparison))
                              items.RemoveAt (i);
            }
            
            /// <summary>
            /// Checks if an item exists.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key of the
            ///    item to check.
            /// </param>
            /// <returns>
            ///    Returns <see langword="true"/> if the <paramref name="key"/>
            ///    exists - else <see langword="false"/> is returned.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="key" /> is <see langword="null" />.
            /// </exception>
00543             public bool HasItem(string key)
            {
                  if (key == null)
                        throw new ArgumentNullException("key");
                  
                  return GetItemIndex(key) >= 0;
            }
            
            /// <summary>
            ///    Renders the current instance as a raw APEv2 tag.
            /// </summary>
            /// <returns>
            ///    A <see cref="ByteVector" /> object containing the
            ///    rendered tag.
            /// </returns>
00558             public ByteVector Render ()
            {
                  ByteVector data = new ByteVector ();
                  uint item_count = 0;
                  
                  foreach (Item item in items) {
                        data.Add (item.Render ());
                        item_count ++;
                  }
                  
                  footer.ItemCount = item_count;
                  footer.TagSize = (uint) (data.Count + Footer.Size);
                  HeaderPresent = true;
                  
                  data.Insert (0, footer.RenderHeader ());
                  data.Add (footer.RenderFooter ());
                  return data;
            }
            
            #endregion
            
            
            
            #region Protected Methods
            
            /// <summary>
            ///    Populates the current instance be reading in a tag from
            ///    a specified position in a specified file.
            /// </summary>
            /// <param name="file">
            ///    A <see cref="TagLib.File" /> object to read the tag from.
            /// </param>
            /// <param name="position">
            ///    A <see cref="long" /> value specifying the seek position
            ///    at which to read the tag.
            /// </param>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="file" /> is <see langword="null" />.
            /// </exception>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="position" /> is less than 0 or greater
            ///    than the size of the file.
            /// </exception>
00601             protected void Read (TagLib.File file, long position)
            {
                  if (file == null)
                        throw new ArgumentNullException ("file");
                  
                  file.Mode = File.AccessMode.Read;
                  
                  if (position < 0 || position > file.Length - Footer.Size)
                        throw new ArgumentOutOfRangeException (
                              "position");
                  
                  file.Seek (position);
                  footer = new Footer (file.ReadBlock ((int)Footer.Size));
                  
                  if (footer.TagSize == 0)
                        throw new CorruptFileException (
                              "Tag size out of bounds.");
                  
                  // If we've read a header, we don't have to seek to read
                  // the content. If we've read a footer, we need to move
                  // back to the start of the tag.
                  if ((footer.Flags & FooterFlags.IsHeader) == 0)
                        file.Seek (position + Footer.Size - footer.TagSize);
                  
                  Parse (file.ReadBlock ((int)(footer.TagSize - Footer.Size)));
            }
            
            /// <summary>
            ///    Populates the current instance by parsing the contents of
            ///    a raw APEv2 tag, minus the header and footer.
            /// </summary>
            /// <param name="data">
            ///    A <see cref="ByteVector" /> object containing the content
            ///    of an APEv2 tag, minus the header and footer.
            /// </param>
            /// <remarks>
            ///    This method must only be called after the internal
            ///    footer has been read from the file, otherwise the data
            ///    cannot be parsed correctly.
            /// </remarks>
00641             protected void Parse (ByteVector data)
            {
                  if (data == null)
                        throw new ArgumentNullException ("data");
                  
                  int pos = 0;
                  
                  try {
                        // 11 bytes is the minimum size for an APE item
                        for (uint i = 0; i < footer.ItemCount &&
                              pos <= data.Count - 11; i++) {
                              Item item = new Item (data, pos);
                              SetItem (item);
                              pos += item.Size;
                        }
                  } catch (CorruptFileException) {
                        // A corrupt item was encountered, considered
                        // the tag finished with what has been read.
                  }
            }
            
            #endregion
            
            
            
            #region Private Methods
            
            /// <summary>
            ///    Gets the index of an item in the current instance.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key to look
            ///    for in the current instance.
            /// </param>
            /// <returns>
            ///    A <see cref="int" /> value containing the index in <see
            ///    cref="items" /> at which the item appears, or -1 if the
            ///    item was not found.
            /// </returns>
            /// <remarks>
            ///    Keys are compared in a case insensitive manner.
            /// </remarks>
00683             private int GetItemIndex (string key)
            {
                  StringComparison comparison =
                        StringComparison.InvariantCultureIgnoreCase;
                  
                  for (int i = 0; i < items.Count; i ++)
                        if (key.Equals (items [i].Key, comparison))
                              return i;
                  
                  return -1;
            }
            
            /// <summary>
            ///    Gets the text value from a specified item.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key of the
            ///    item to get the value from.
            /// </param>
            /// <returns>
            ///    A <see cref="string" /> object containing the text of the
            ///    specified frame, or <see langword="null" /> if no value
            ///    was found.
            /// </returns>
00707             private string GetItemAsString (string key)
            {
                        Item item = GetItem (key);
                        return item != null ? item.ToString () : null;
            }
            
            /// <summary>
            ///    Gets the text values from a specified item.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key of the
            ///    item to get the value from.
            /// </param>
            /// <returns>
            ///    A <see cref="string[]" /> containing the text of the
            ///    specified frame, or an empty array if no values were
            ///    found.
            /// </returns>
00725             private string [] GetItemAsStrings (string key)
            {
                  Item item = GetItem (key);
                  return item != null ?
                        item.ToStringArray () : new string [0];
            }
            
            /// <summary>
            ///    Gets an integer value from a "/" delimited list in a
            ///    specified item.
            /// </summary>
            /// <param name="key">
            ///    A <see cref="string" /> object containing the key of the
            ///    item to get the value from.
            /// </param>
            /// <param name="index">
            ///    A <see cref="int" /> value specifying the index in the
            ///    integer list of the value to return.
            /// </param>
            /// <returns>
            ///    A <see cref="uint" /> value read from the list in the
            ///    frame, or 0 if the value wasn't found.
            /// </returns>
00748             private uint GetItemAsUInt32 (string key, int index)
            {
                  string text = GetItemAsString (key);
                  
                  if (text == null)
                        return 0;
                  
                  string [] values = text.Split (new char [] {'/'},
                        index + 2);
                  
                  if (values.Length < index + 1)
                        return 0;
                  
                  uint result;
                  if (uint.TryParse (values [index], out result))
                        return result;
                  
                  return 0;
            }
            
            #endregion
            
            
            
            #region IEnumerable
            
            /// <summary>
            ///    Gets the enumerator for the current instance.
            /// </summary>
            /// <returns>
            ///    A <see cref="T:System.Collections.Generic.IEnumerator`1" /> object enumerating through
            ///    the item keys stored in the current instance.
            /// </returns>
00781             public IEnumerator<string> GetEnumerator ()
            {
                  foreach (Item item in items)
                        yield return item.Key;
            }
            
            /// <summary>
            ///    Gets the enumerator for the current instance.
            /// </summary>
            /// <returns>
            ///    A <see cref="IEnumerator" /> object enumerating through
            ///    the item keys stored in the current instance.
            /// </returns>
00794             IEnumerator IEnumerable.GetEnumerator()
            {
                  return GetEnumerator ();
            }
            
            #endregion
            
            
            
            #region TagLib.Tag
            
            /// <summary>
            ///    Gets the tag types contained in the current instance.
            /// </summary>
            /// <value>
            ///    Always <see cref="TagTypes.Ape" />.
            /// </value>
00811             public override TagTypes TagTypes {
                  get {return TagTypes.Ape;}
            }
            
            /// <summary>
            ///    Gets and sets the title for the media described by the
            ///    current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the title for
            ///    the media described by the current instance or <see
            ///    langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Title" item.
            /// </remarks>
00827             public override string Title {
                  get { return GetItemAsString ("Title"); }
                  set {SetValue ("Title", value);}
            }

            /// <summary>
            ///    Gets and sets the sort names of the Title of the
            ///    media represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> containing the sort names for
            ///    the Title of the media described by the current instance,
            ///    or null if no value is present. 
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "TitleSort" item.
            /// </remarks>
00844             public override string TitleSort {
                  get { return GetItemAsString ("TitleSort"); }
                  set { SetValue ("TitleSort", value); }
            }

            /// <summary>
            ///    Gets and sets the performers or artists who performed in
            ///    the media described by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string[]" /> containing the performers or
            ///    artists who performed in the media described by the
            ///    current instance or an empty array if no value is
            ///    present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Artist" item.
            /// </remarks>
00862             public override string [] Performers {
                  get {return GetItemAsStrings ("Artist");}
                  set {SetValue ("Artist", value);}
            }

            /// <summary>
            ///    Gets and sets the sort names of the performers or artists
            ///    who performed in the media described by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> array containing the sort names for
            ///    the performers or artists who performed in the media
            ///    described by the current instance, or an empty array if
            ///    no value is present. 
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "ArtistSort" field.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
00881             public override string[] PerformersSort {
                  get { return GetItemAsStrings ("ArtistSort"); }
                  set { SetValue ("ArtistSort", value); }
            }

            /// <summary>
            ///    Gets and sets the band or artist who is credited in the
            ///    creation of the entire album or collection containing the
            ///    media described by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string[]" /> containing the band or artist
            ///    who is credited in the creation of the entire album or
            ///    collection containing the media described by the current
            ///    instance or an empty array if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Album Artist"
            ///    item, and "AlbumArtist" as a backup property if it exists.
            /// </remarks>
00901             public override string [] AlbumArtists {
                  get {
                        string[] list = GetItemAsStrings("Album Artist");
                        if (list.Length == 0)
                              list = GetItemAsStrings("AlbumArtist");
                        return list;
                  }
                  set {
                        SetValue("Album Artist", value);
                        // compatibility
                        if (HasItem("AlbumArtist"))
                              SetValue("AlbumArtist", value);
                        }
            }

            /// <summary>
            ///    Gets and sets the sort names for the band or artist who
            ///    is credited in the creation of the entire album or
            ///    collection containing the media described by the
            ///    current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> array containing the sort names
            ///    for the band or artist who is credited in the creation
            ///    of the entire album or collection containing the media
            ///    described by the current instance or an empty array if
            ///    no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "AlbumArtistSort"
            ///    field.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
00934             public override string[] AlbumArtistsSort {
                  get { return GetItemAsStrings ("AlbumArtistSort"); }
                  set { SetValue ("AlbumArtistSort", value); }
            }

            /// <summary>
            ///    Gets and sets the composers of the media represented by
            ///    the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string[]" /> containing the composers of the
            ///    media represented by the current instance or an empty
            ///    array if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Composer" item.
            /// </remarks>
00951             public override string [] Composers {
                  get {return GetItemAsStrings ("Composer");}
                  set {SetValue ("Composer", value);}
            }

            /// <summary>
            ///    Gets and sets the sort names for the composers of
            ///    the media described by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> array containing the sort names
            ///    for the composer of the media described by the current
            ///    instance or an empty array if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "ComposerSort"
            ///    field.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
00970             public override string[] ComposersSort {
                  get { return GetItemAsStrings ("ComposerSort"); }
                  set { SetValue ("ComposerSort", value); }
            }

            /// <summary>
            ///    Gets and sets the album of the media represented by the
            ///    current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the album of
            ///    the media represented by the current instance or <see
            ///    langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Album" item.
            /// </remarks>
00987             public override string Album {
                  get {return GetItemAsString ("Album");}
                  set {SetValue ("Album", value);}
            }

            /// <summary>
            ///    Gets and sets the sort names for the Album Title of
            ///    the media described by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> containing the sort name of 
            ///    the Album Title of the media described by the current
            ///    instance or null if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "AlbumSort"
            ///    field.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
01006             public override string AlbumSort {
                  get { return GetItemAsString ("AlbumSort"); }
                  set { SetValue ("AlbumSort", value); }
            }

            /// <summary>
            ///    Gets and sets a user comment on the media represented by
            ///    the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing user comments
            ///    on the media represented by the current instance or <see
            ///    langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Comment" item.
            /// </remarks>
01023             public override string Comment {
                  get {return GetItemAsString ("Comment");}
                  set {SetValue ("Comment", value);}
            }
            
            /// <summary>
            ///    Gets and sets the genres of the media represented by the
            ///    current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string[]" /> containing the genres of the
            ///    media represented by the current instance or an empty
            ///    array if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Genre" item.
            /// </remarks>
01040             public override string [] Genres {
                  get {return GetItemAsStrings ("Genre");}
                  set {SetValue ("Genre", value);}
            }
            
            /// <summary>
            ///    Gets and sets the year that the media represented by the
            ///    current instance was recorded.
            /// </summary>
            /// <value>
            ///    A <see cref="uint" /> containing the year that the media
            ///    represented by the current instance was created or zero
            ///    if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Year" item.
            /// </remarks>
01057             public override uint Year {
                  get {
                        string text = GetItemAsString ("Year");
                        
                        if (text == null || text.Length == 0)
                              return 0;
                        
                        uint value;
                        if (uint.TryParse (text, out value) ||
                              (text.Length >= 4 && uint.TryParse (
                                    text.Substring (0, 4),
                                    out value)))
                              return value;
                        
                        return 0;
                  }
                  set {SetValue ("Year", value, 0);}
            }
            
            /// <summary>
            ///    Gets and sets the position of the media represented by
            ///    the current instance in its containing album.
            /// </summary>
            /// <value>
            ///    A <see cref="uint" /> containing the position of the
            ///    media represented by the current instance in its
            ///    containing album or zero if not specified.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Track" item.
            /// </remarks>
01088             public override uint Track {
                  get {return GetItemAsUInt32 ("Track", 0);}
                  set {SetValue ("Track", value, TrackCount);}
            }
            
            /// <summary>
            ///    Gets and sets the number of tracks in the album
            ///    containing the media represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="uint" /> containing the number of tracks in
            ///    the album containing the media represented by the current
            ///    instance or zero if not specified.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Track" item.
            /// </remarks>
01105             public override uint TrackCount {
                  get {return GetItemAsUInt32 ("Track", 1);}
                  set {SetValue ("Track", Track, value);}
            }
            
            /// <summary>
            ///    Gets and sets the number of the disc containing the media
            ///    represented by the current instance in the boxed set.
            /// </summary>
            /// <value>
            ///    A <see cref="uint" /> containing the number of the disc
            ///    containing the media represented by the current instance
            ///    in the boxed set.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Disc" item.
            /// </remarks>
01122             public override uint Disc {
                  get {return GetItemAsUInt32 ("Disc", 0);}
                  set {SetValue ("Disc", value, DiscCount);}
            }
            
            /// <summary>
            ///    Gets and sets the number of discs in the boxed set
            ///    containing the media represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="uint" /> containing the number of discs in
            ///    the boxed set containing the media represented by the
            ///    current instance or zero if not specified.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Disc" item.
            /// </remarks>
01139             public override uint DiscCount {
                  get {return GetItemAsUInt32 ("Disc", 1);}
                  set {SetValue ("Disc", Disc, value);}
            }
            
            /// <summary>
            ///    Gets and sets the lyrics or script of the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the lyrics or
            ///    script of the media represented by the current instance
            ///    or <see langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Lyrics" item.
            /// </remarks>
01156             public override string Lyrics {
                  get {return GetItemAsString ("Lyrics");}
                  set {SetValue ("Lyrics", value);}
            }
            
            /// <summary>
            ///    Gets and sets the grouping on the album which the media
            ///    in the current instance belongs to.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the grouping on
            ///    the album which the media in the current instance belongs
            ///    to or <see langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Grouping" item.
            /// </remarks>
01173             public override string Grouping {
                  get {return GetItemAsString ("Grouping");}
                  set {SetValue ("Grouping", value);}
            }
            
            /// <summary>
            ///    Gets and sets the number of beats per minute in the audio
            ///    of the media represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="uint" /> containing the number of beats per
            ///    minute in the audio of the media represented by the
            ///    current instance, or zero if not specified.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "BPM" item.
            /// </remarks>
01190             public override uint BeatsPerMinute {
                  get {
                        string text = GetItemAsString ("BPM");
                        
                        if (text == null)
                              return 0;
                        
                        double value;
                        
                        if (double.TryParse (text, out value))
                              return (uint) Math.Round (value);
                        
                        return 0;
                  }
                  set {SetValue ("BPM", value, 0);}
            }
            
            /// <summary>
            ///    Gets and sets the conductor or director of the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the conductor
            ///    or director of the media represented by the current
            ///    instance or <see langword="null" /> if no value present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Conductor" item.
            /// </remarks>
01219             public override string Conductor {
                  get {return GetItemAsString ("Conductor");}
                  set {SetValue ("Conductor", value);}
            }
            
            /// <summary>
            ///    Gets and sets the copyright information for the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the copyright
            ///    information for the media represented by the current
            ///    instance or <see langword="null" /> if no value present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Copyright" item.
            /// </remarks>
01236             public override string Copyright {
                  get {return GetItemAsString ("Copyright");}
                  set {SetValue ("Copyright", value);}
            }

            /// <summary>
            ///    Gets and sets the MusicBrainz Artist ID of the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the MusicBrainz
            ///    ArtistID for the media represented by the current instance
            ///    or <see langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "MUSICBRAINZ_ARTISTID" item.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
01254             public override string MusicBrainzArtistId {
                  get {return GetItemAsString ("MUSICBRAINZ_ARTISTID");}
                  set {SetValue ("MUSICBRAINZ_ARTISTID", value);}
            }

            /// <summary>
            ///    Gets and sets the MusicBrainz Release ID of the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the MusicBrainz
            ///    ReleaseID for the media represented by the current instance
            ///    or <see langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "MUSICBRAINZ_ALBUMID" item.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
01272             public override string MusicBrainzReleaseId {
                  get {return GetItemAsString ("MUSICBRAINZ_ALBUMID");}
                  set {SetValue ("MUSICBRAINZ_ALBUMID", value);}
            }

            /// <summary>
            ///    Gets and sets the MusicBrainz Release Artist ID of the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the MusicBrainz
            ///    ReleaseArtistID for the media represented by the current instance
            ///    or <see langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "MUSICBRAINZ_ALBUMARTISTID" item.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
01290             public override string MusicBrainzReleaseArtistId {
                  get {return GetItemAsString ("MUSICBRAINZ_ALBUMARTISTID");}
                  set {SetValue ("MUSICBRAINZ_ALBUMARTISTID", value);}
            }

            /// <summary>
            ///    Gets and sets the MusicBrainz Track ID of the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the MusicBrainz
            ///    TrackID for the media represented by the current instance
            ///    or <see langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "MUSICBRAINZ_TRACKID" item.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
01308             public override string MusicBrainzTrackId {
                  get {return GetItemAsString ("MUSICBRAINZ_TRACKID");}
                  set {SetValue ("MUSICBRAINZ_TRACKID", value);}
            }

            /// <summary>
            ///    Gets and sets the MusicBrainz Disc ID of the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the MusicBrainz
            ///    DiscID for the media represented by the current instance
            ///    or <see langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "MUSICBRAINZ_DISCID" item.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
01326             public override string MusicBrainzDiscId {
                  get {return GetItemAsString ("MUSICBRAINZ_DISCID");}
                  set {SetValue ("MUSICBRAINZ_DISCID", value);}
            }

            /// <summary>
            ///    Gets and sets the MusicIP PUID of the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the MusicIPPUID
            ///    for the media represented by the current instance
            ///    or <see langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "MUSICIP_PUID" item.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
01344             public override string MusicIpId {
                  get {return GetItemAsString ("MUSICIP_PUID");}
                  set {SetValue ("MUSICIP_PUID", value);}
            }

            /// <summary>
            ///    Gets and sets the Amazon ID of the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the AmazonID
            ///    for the media represented by the current instance
            ///    or <see langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "ASIN" item.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
01362             public override string AmazonId {
                  get {return GetItemAsString ("ASIN");}
                  set {SetValue ("ASIN", value);}
            }

            /// <summary>
            ///    Gets and sets the MusicBrainz Release Status of the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the MusicBrainz
            ///    ReleaseStatus for the media represented by the current instance
            ///    or <see langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "MUSICBRAINZ_ALBUMSTATUS" item.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
01380             public override string MusicBrainzReleaseStatus {
                  get {return GetItemAsString ("MUSICBRAINZ_ALBUMSTATUS");}
                  set {SetValue ("MUSICBRAINZ_ALBUMSTATUS", value);}
            }

            /// <summary>
            ///    Gets and sets the MusicBrainz Release Type of the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the MusicBrainz
            ///    ReleaseType for the media represented by the current instance
            ///    or <see langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "MUSICBRAINZ_ALBUMTYPE" item.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
01398             public override string MusicBrainzReleaseType {
                  get {return GetItemAsString ("MUSICBRAINZ_ALBUMTYPE");}
                  set {SetValue ("MUSICBRAINZ_ALBUMTYPE", value);}
            }

            /// <summary>
            ///    Gets and sets the MusicBrainz ReleaseCountry of the media
            ///    represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the MusicBrainz
            ///    ReleaseCountry for the media represented by the current instance
            ///    or <see langword="null" /> if no value is present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "RELEASECOUNTRY" item.
            ///    http://musicbrainz.org/doc/PicardTagMapping
            /// </remarks>
01416             public override string MusicBrainzReleaseCountry {
                  get {return GetItemAsString ("RELEASECOUNTRY");}
                  set {SetValue ("RELEASECOUNTRY", value);}
            }

            /// <summary>
            ///    Gets and sets a collection of pictures associated with
            ///    the media represented by the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="IPicture[]" /> containing a collection of
            ///    pictures associated with the media represented by the
            ///    current instance or an empty array if none are present.
            /// </value>
            /// <remarks>
            ///    This property is implemented using the "Cover Art" items
            ///    and supports only one picture per type.
            /// </remarks>
01434             public override IPicture [] Pictures {
                  get {
                        List<IPicture> pictures = new List<IPicture> ();
                        
                        for (int i = 0; i < picture_item_names.Length;
                              i++) {
                              Item item = GetItem (
                                    picture_item_names [i]);
                              
                              if (item == null ||
                                    item.Type != ItemType.Binary)
                                    continue;
                              
                              int index = item.Value.Find (
                                    ByteVector.TextDelimiter (
                                          StringType.UTF8));
                              
                              if (index < 0)
                                    continue;
                              
                              Picture pic = new Picture (
                                    item.Value.Mid (index + 1));
                              
                              pic.Description = item.Value
                                    .ToString (StringType.UTF8, 0,
                                          index);
                              
                              pic.Type = (PictureType) i;
                              
                              pictures.Add (pic);
                        }
                        
                        return pictures.ToArray ();
                  }
                  set {
                        foreach (string item_name in picture_item_names)
                              RemoveItem (item_name);
                        
                        if (value == null || value.Length == 0)
                              return;
                        
                        foreach (IPicture pic in value) {
                              int type = (int) pic.Type;
                              
                              if (type >= picture_item_names.Length)
                                    type = 0;
                              
                              string name = picture_item_names [type];
                              
                              if (GetItem (name) != null)
                                    continue;
                              
                              ByteVector data = ByteVector
                                    .FromString (
                                          pic.Description,
                                          StringType.UTF8);
                              data.Add (ByteVector.TextDelimiter (
                                    StringType.UTF8));
                              data.Add (pic.Data);
                              
                              SetItem (new Item (name, data));
                        }
                  }
            }
            
            /// <summary>
            ///    Gets whether or not the current instance is empty.
            /// </summary>
            /// <value>
            ///    <see langword="true" /> if the current instance does not
            ///    any values. Otherwise <see langword="false" />.
            /// </value>
01506             public override bool IsEmpty {
                  get {return items.Count == 0;}
            }
            
            /// <summary>
            ///    Clears the values stored in the current instance.
            /// </summary>
01513             public override void Clear ()
            {
                  items.Clear ();
            }
            
            /// <summary>
            ///    Copies the values from the current instance to another
            ///    <see cref="TagLib.Tag" />, optionally overwriting
            ///    existing values.
            /// </summary>
            /// <param name="target">
            ///    A <see cref="TagLib.Tag" /> object containing the target
            ///    tag to copy values to.
            /// </param>
            /// <param name="overwrite">
            ///    A <see cref="bool" /> specifying whether or not to copy
            ///    values over existing one.
            /// </param>
            /// <remarks>
            ///    <para>If <paramref name="target" /> is of type <see
            ///    cref="TagLib.Ape.Tag" /> a complete copy of all values
            ///    will be performed. Otherwise, only standard values will
            ///    be copied.</para>
            /// </remarks>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="target" /> is <see langword="null" />.
            /// </exception>
01540             public override void CopyTo (TagLib.Tag target, bool overwrite)
            {
                  if (target == null)
                        throw new ArgumentNullException ("target");
                  
                  TagLib.Ape.Tag match = target as TagLib.Ape.Tag;
                  
                  if (match == null) {
                        base.CopyTo (target, overwrite);
                        return;
                  }
                  
                  foreach (Item item in items) {
                        if (!overwrite &&
                              match.GetItem (item.Key) != null)
                              continue;
                        
                        match.items.Add (item.Clone ());
                  }
            }
            
#endregion
      }
}

Generated by  Doxygen 1.6.0   Back to index