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

RelativeVolumeFrame.cs

//
// RelativeVolumeFrame.cs:
//
// Author:
//   Brian Nickel (brian.nickel@gmail.com)
//
// Original Source:
//   textidentificationframe.cpp from TagLib
//
// Copyright (C) 2005-2007 Brian Nickel
// Copyright (C) 2004 Scott Wheeler (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.Collections;
using System.Collections.Generic;
using System;

namespace TagLib.Id3v2 {
      /// <summary>
      ///    Specified the type of channel data to get from or set to a
      ///    <see cref="RelativeVolumeFrame" /> object.
      /// </summary>
00037       public enum ChannelType {
            /// <summary>
            ///    The channel data is for some other speaker.
            /// </summary>
            Other = 0x00,
            
            /// <summary>
            ///    The channel data is for the master volume.
            /// </summary>
            MasterVolume = 0x01,
            
            /// <summary>
            ///    The channel data is for the front right speaker.
            /// </summary>
            FrontRight = 0x02,
            
            /// <summary>
            ///    The channel data is for the front left speaker.
            /// </summary>
            FrontLeft = 0x03,
            
            /// <summary>
            ///    The channel data is for the back right speaker.
            /// </summary>
            BackRight = 0x04,
            
            /// <summary>
            ///    The channel data is for the back left speaker.
            /// </summary>
            BackLeft = 0x05,
            
            /// <summary>
            ///    The channel data is for the front center speaker.
            /// </summary>
            FrontCentre = 0x06,
            
            /// <summary>
            ///    The channel data is for the back center speaker.
            /// </summary>
            BackCentre = 0x07,
            
            /// <summary>
            ///    The channel data is for the subwoofer.
            /// </summary>
            Subwoofer = 0x08
      }
      
      /// <summary>
      ///    This class extends <see cref="Frame" />, implementing support for
      ///    ID3v2 Relative Volume (RVA2) Frames.
      /// </summary>
00088       public class RelativeVolumeFrame : Frame
      {
#region Private Fields
            
            /// <summary>
            ///    Contains the frame identification.
            /// </summary>
00095             private string identification = null;
            
            /// <summary>
            ///    Contains the channel data.
            /// </summary>
00100             private ChannelData [] channels = new ChannelData [9];
            
#endregion
            
            
            
#region Constructors
            
            /// <summary>
            ///    Constructs and initializes a new instance of <see
            ///    cref="RelativeVolumeFrame" /> with a specified
            ///    identifier.
            /// </summary>
            /// <param name="identification">
            ///    A <see cref="string" /> object containing the
            ///    identification to use for the new frame.
            /// </param>
00117             public RelativeVolumeFrame (string identification)
                  : base (FrameType.RVA2, 4)
            {
                  this.identification = identification;
            }
            
            /// <summary>
            ///    Constructs and initializes a new instance of <see
            ///    cref="RelativeVolumeFrame" /> by reading its raw data in
            ///    a specified ID3v2 version.
            /// </summary>
            /// <param name="data">
            ///    A <see cref="ByteVector" /> object starting with the raw
            ///    representation of the new frame.
            /// </param>
            /// <param name="version">
            ///    A <see cref="byte" /> indicating the ID3v2 version the
            ///    raw frame is encoded in.
            /// </param>
00136             public RelativeVolumeFrame (ByteVector data, byte version)
                  : base (data, version)
            {
                  SetData (data, 0, version, true);
            }
            
            /// <summary>
            ///    Constructs and initializes a new instance of <see
            ///    cref="RelativeVolumeFrame" /> by reading its raw data in
            ///    a specified ID3v2 version.
            /// </summary>
            /// <param name="data">
            ///    A <see cref="ByteVector" /> object containing the raw
            ///    representation of the new frame.
            /// </param>
            /// <param name="offset">
            ///    A <see cref="int" /> indicating at what offset in
            ///    <paramref name="data" /> the frame actually begins.
            /// </param>
            /// <param name="header">
            ///    A <see cref="FrameHeader" /> containing the header of the
            ///    frame found at <paramref name="offset" /> in the data.
            /// </param>
            /// <param name="version">
            ///    A <see cref="byte" /> indicating the ID3v2 version the
            ///    raw frame is encoded in.
            /// </param>
00163             protected internal RelativeVolumeFrame (ByteVector data,
                                                    int offset,
                                                    FrameHeader header,
                                                    byte version)
                  : base(header)
            {
                  SetData (data, offset, version, false);
            }
            
#endregion
            
            
            
#region Public Properties
            
            /// <summary>
            ///    Gets the identification used for the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="string" /> object containing the
            ///    identification used for the current instance.
            /// </value>
00185             public string Identification {
                  get {return identification;}
            }
            
            /// <summary>
            ///    Gets a list of the channels in the current instance that
            ///    contain a value.
            /// </summary>
            /// <value>
            ///    A <see cref="ChannelType[]" /> containing the channels
            ///    which have a value set in the current instance.
            /// </value>
00197             public ChannelType [] Channels {
                  get {
                        List<ChannelType> types = new List<ChannelType> ();
                        for (int i = 0; i < 9; i ++)
                              if (channels [i].IsSet)
                                    types.Add ((ChannelType) i);
                        return types.ToArray ();
                  }
            }
            
#endregion
            
            
            
#region Public Methods
            
            /// <summary>
            ///    Creates a text description of the current instance.
            /// </summary>
            /// <returns>
            ///    A <see cref="string" /> object containing a description
            ///    of the current instance.
            /// </returns>
00220             public override string ToString ()
            {
                  return identification;
            }
            
            /// <summary>
            ///    Gets the volume adjustment index for a specified channel.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="ChannelType" /> value specifying which
            ///    channel to get the value for.
            /// </param>
            /// <returns>
            ///    A <see cref="short" /> value containing the volume
            ///    adjustment index.
            /// </returns>
            /// <remarks>
            ///    The volume adjustment index is simply the volume
            ///    adjustment multiplied by 512.
            /// </remarks>
            /// <seealso cref="SetVolumeAdjustmentIndex"/>
            /// <seealso cref="GetVolumeAdjustment"/>
00242             public short GetVolumeAdjustmentIndex (ChannelType type)
            {
                  return channels [(int) type].VolumeAdjustmentIndex;
            }
            
            /// <summary>
            ///    Sets the volume adjustment index for a specified channel.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="ChannelType" /> value specifying which
            ///    channel to set the value for.
            /// </param>
            /// <param name="index">
            ///    A <see cref="short" /> value containing the volume
            ///    adjustment index.
            /// </param>
            /// <seealso cref="GetVolumeAdjustmentIndex"/>
            /// <seealso cref="SetVolumeAdjustment"/>
00260             public void SetVolumeAdjustmentIndex (ChannelType type,
                                                  short index)
            {
                  channels [(int) type].VolumeAdjustmentIndex = index;
            }
            
            /// <summary>
            ///    Gets the volume adjustment for a specified channel.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="ChannelType" /> value specifying which
            ///    channel to get the value for.
            /// </param>
            /// <returns>
            ///    A <see cref="float" /> value containing the volume
            ///    adjustment in decibles.
            /// </returns>
            /// <remarks>
            ///    The value can be between -64dB and +64dB.
            /// </remarks>
            /// <seealso cref="SetVolumeAdjustment"/>
            /// <seealso cref="GetVolumeAdjustmentIndex"/>
00282             public float GetVolumeAdjustment (ChannelType type)
            {
                  return channels [(int) type].VolumeAdjustment;
            }
            
            /// <summary>
            ///    Sets the volume adjustment for a specified channel.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="ChannelType" /> value specifying which
            ///    channel to set the value for.
            /// </param>
            /// <param name="adjustment">
            ///    A <see cref="float" /> value containing the volume
            ///    adjustment in decibles.
            /// </param>
            /// <remarks>
            ///    The value can be between -64dB and +64dB.
            /// </remarks>
            /// <seealso cref="GetVolumeAdjustment"/>
            /// <seealso cref="SetVolumeAdjustmentIndex"/>
00303             public void SetVolumeAdjustment (ChannelType type,
                                             float adjustment)
            {
                  channels [(int) type].VolumeAdjustment = adjustment;
            }
            
            /// <summary>
            ///    Gets the peak volume index for a specified channel.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="ChannelType" /> value specifying which
            ///    channel to get the value for.
            /// </param>
            /// <returns>
            ///    A <see cref="ulong" /> value containing the peak volume
            ///    index.
            /// </returns>
            /// <remarks>
            ///    The peak volume index is simply the peak volume
            ///    multiplied by 512.
            /// </remarks>
            /// <seealso cref="SetPeakVolumeIndex"/>
            /// <seealso cref="GetPeakVolume"/>
00326             public ulong GetPeakVolumeIndex (ChannelType type)
            {
                  return channels [(int) type].PeakVolumeIndex;
            }
            
            /// <summary>
            ///    Sets the peak volume index for a specified channel.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="ChannelType" /> value specifying which
            ///    channel to set the value for.
            /// </param>
            /// <param name="index">
            ///    A <see cref="ulong" /> value containing the peak volume
            ///    index.
            /// </param>
            /// <remarks>
            ///    The peak volume index is simply the peak volume
            ///    multiplied by 512.
            /// </remarks>
            /// <seealso cref="GetPeakVolumeIndex"/>
            /// <seealso cref="SetPeakVolume"/>
00348             public void SetPeakVolumeIndex (ChannelType type, ulong index)
            {
                  channels [(int) type].PeakVolumeIndex = index;
            }
            
            /// <summary>
            ///    Gets the peak volume for a specified channel.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="ChannelType" /> value specifying which
            ///    channel to get the value for.
            /// </param>
            /// <returns>
            ///    A <see cref="double" /> value containing the peak volume.
            /// </returns>
            /// <seealso cref="SetPeakVolume"/>
            /// <seealso cref="GetPeakVolumeIndex"/>
00365             public double GetPeakVolume (ChannelType type)
            {
                  return channels [(int) type].PeakVolume;
            }
            
            /// <summary>
            ///    Sets the peak volume for a specified channel.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="ChannelType" /> value specifying which
            ///    channel to set the value for.
            /// </param>
            /// <param name="peak">
            ///    A <see cref="double" /> value containing the peak volume.
            /// </param>
            /// <seealso cref="GetPeakVolume"/>
            /// <seealso cref="SetPeakVolumeIndex"/>
00382             public void SetPeakVolume (ChannelType type, double peak)
            {
                  channels [(int) type].PeakVolume = peak;
            }
            
#endregion
            
            
            
#region Public Static Methods
            
            /// <summary>
            ///    Gets a specified volume adjustment frame from the
            ///    specified tag, optionally creating it if it does not
            ///    exist.
            /// </summary>
            /// <param name="tag">
            ///    A <see cref="Tag" /> object to search in.
            /// </param>
            /// <param name="identification">
            ///    A <see cref="string" /> specifying the identification to
            ///    match.
            /// </param>
            /// <param name="create">
            ///    A <see cref="bool" /> specifying whether or not to create
            ///    and add a new frame to the tag if a match is not found.
            /// </param>
            /// <returns>
            ///    A <see cref="RelativeVolumeFrame" /> object containing
            ///    the matching frame, or <see langword="null" /> if a match
            ///    wasn't found and <paramref name="create" /> is <see
            ///    langword="false" />.
            /// </returns>
00415             public static RelativeVolumeFrame Get (Tag tag,
                                                   string identification,
                                                   bool create)
            {
                  RelativeVolumeFrame rva2;
                  foreach (Frame frame in tag.GetFrames (FrameType.RVA2)) {
                        rva2 = frame as RelativeVolumeFrame;
                        
                        if (rva2 == null)
                              continue;
                        
                        if (rva2.Identification != identification)
                              continue;
                        
                        return rva2;
                  }
                  
                  if (!create)
                        return null;
                  
                  rva2 = new RelativeVolumeFrame (identification);
                  tag.AddFrame (rva2);
                  return rva2;
            }
            
#endregion
            
            
            
#region Protected Properties
            
            /// <summary>
            ///    Populates the values in the current instance by parsing
            ///    its field data in a specified version.
            /// </summary>
            /// <param name="data">
            ///    A <see cref="ByteVector" /> object containing the
            ///    extracted field data.
            /// </param>
            /// <param name="version">
            ///    A <see cref="byte" /> indicating the ID3v2 version the
            ///    field data is encoded in.
            /// </param>
            /// <exception cref="CorruptFileException">
            ///    <paramref name="data" /> contains less than 5 bytes.
            /// </exception>
00461             protected override void ParseFields (ByteVector data,
                                                 byte version)
            {
                  int pos = data.Find (ByteVector.TextDelimiter (
                        StringType.Latin1));
                  if (pos < 0)
                        return;
                  
                  identification = data.ToString (StringType.Latin1, 0,
                        pos++);
                  
                  // Each channel is at least 4 bytes.
                  
                  while (pos <= data.Count - 4) {
                        int type = data [pos++];
                        
                        unchecked {
                              channels [type].VolumeAdjustmentIndex =
                                    (short) data.Mid (pos,
                                          2).ToUShort ();
                        }
                        pos += 2;
                        
                        int bytes = BitsToBytes (data [pos++]);
                        
                        if (data.Count < pos + bytes)
                              break;
                        
                        channels [type].PeakVolumeIndex = data.Mid (pos,
                              bytes).ToULong ();
                        pos += bytes;
                  }
            }
            
            /// <summary>
            ///    Renders the values in the current instance into field
            ///    data for a specified version.
            /// </summary>
            /// <param name="version">
            ///    A <see cref="byte" /> indicating the ID3v2 version the
            ///    field data is to be encoded in.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector" /> object containing the
            ///    rendered field data.
            /// </returns>
00507             protected override ByteVector RenderFields (byte version)
            {
                  ByteVector data = new ByteVector ();
                  data.Add (ByteVector.FromString (identification,
                        StringType.Latin1));
                  data.Add (ByteVector.TextDelimiter(StringType.Latin1));
                  
                  for (byte i = 0; i < 9; i ++) {
                        if (!channels [i].IsSet)
                              continue;
                        
                        data.Add (i);
                        unchecked {
                              data.Add (ByteVector.FromUShort (
                                    (ushort) channels [i]
                                          .VolumeAdjustmentIndex));
                        }
                        
                        byte bits = 0;
                        
                        for (byte j = 0; j < 64; j ++)
                              if ((channels [i].PeakVolumeIndex &
                                    (1UL << j)) != 0)
                                    bits = (byte)(j + 1);
                        
                        data.Add (bits);
                        
                        if (bits > 0)
                              data.Add (ByteVector.FromULong (
                                    channels [i].PeakVolumeIndex)
                                          .Mid (8 - BitsToBytes (bits)));
                  }
                  
                  return data;
            }
            
#endregion
            
            
            
#region ICloneable
            
            /// <summary>
            ///    Creates a deep copy of the current instance.
            /// </summary>
            /// <returns>
            ///    A new <see cref="Frame" /> object identical to the
            ///    current instance.
            /// </returns>
00556             public override Frame Clone ()
            {
                  RelativeVolumeFrame frame =
                        new RelativeVolumeFrame (identification);
                  for (int i = 0; i < 9; i ++)
                        frame.channels [i] = channels [i];
                  return frame;
            }
            
#endregion
            
            
            
#region Private Static Methods
            
            private static int BitsToBytes (int i)
            {
                  return i % 8 == 0 ? i / 8 : (i - i % 8) / 8 + 1;
            }
            
            #endregion
            
            
            
            #region Classes
            
00582             private struct ChannelData
            {
                  public short VolumeAdjustmentIndex;
                  public ulong PeakVolumeIndex;
                  
                  public bool IsSet {
                        get {
                              return VolumeAdjustmentIndex != 0 ||
                                    PeakVolumeIndex != 0;
                        }
                  }
                  
                  public float VolumeAdjustment {
                        get {return VolumeAdjustmentIndex / 512f;}
                        set {
                              VolumeAdjustmentIndex =
                                    (short) (value * 512f);
                        }
                  }
                  
                  public double PeakVolume {
                        get {return PeakVolumeIndex / 512.0;}
                        set {PeakVolumeIndex = (ulong) (value * 512.0);}
                  }
            }
            
            #endregion
      }
}

Generated by  Doxygen 1.6.0   Back to index