id3

package module
v0.0.0-...-8f3d6cd Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 22, 2015 License: MIT Imports: 9 Imported by: 1

README

This library is in development, there's no release yet, don't use it yet.

The API isn't stable, it might eat your files, and I reserve the right to rewrite history.

Documentation

Overview

Package id3 implements a decoder and encoder for ID3 tags.

Nomenclature

ID3 uses nomenclature that might be counterintuitive to people not familiar with it. Because this library uses the same choice of words the following list of clarifications is included.

tag: In ID3, tag means the entire set of metadata, not just one
     field of it.

frame: A frame describes a single piece of information, for example
       a song's title.

Supported versions

This library supports reading v2.3 and v2.4 tags, but only writing v2.4 tags.

The primary reason for not allowing writing older versions is that they cannot represent all data that is available with v2.4, and designing the API in a way that's both user friendly and able to reject data is not worth the trouble.

Automatic upgrading

The library's internal representation of tags matches that of v2.4. When tags with an older version are being read, they will be automatically converted to v2.4.

One consequence of this is that when you read a file with v2.3 tags and immediately save it, it will now be a file with valid v2.4 tags.

The upgrade process makes the following changes to the tags:

  • TYER, TDAT and TIME get replaced by TDRC
  • TORY gets replaced by TDOR
  • XDOR gets replaced by TDOR
  • The slash as a separator for multiple values gets replaced by null bytes

One special case is the TRDA frame because there is no way to automatically convert it to v2.4. The upgrade process will not directly delete the frame, so that you can manually upgrade it if desired, but it won't be written back to the file. The frame is rarely used and insignificant, so it's not a big loss.

Accessing and manipulating frames

There are two ways to access frames: Using provided getter and setter methods (there is one for every standard frame), and working directly with the underlying frames.

For frames that usually support multiple values, e.g. languages, there will be two different setters and getters: One that operates on slices and one that operates on single values. When getting a single value, it will return the first value from the underlying list. When setting a single value, it will overwrite the list with a single value.

Text frames and user text frames can be manipulated with the GetTextFrame* and SetTextFrame* class of functions. There are special methods for working with integers, slices and times. This class of functions expects the raw frame names (e.g. "TLEN"), with the special case of user text frames ("TXXX") where it expects a format of the kind "TXXX:The frame description" to address a specific user text frame.

Encodings

While ID3v2 allows a variety of encodings (ISO-8859-1, UTF-16 and in v2.4 also UTF-8), this library only supports writing UTF-8. When reading frames with different encodings, they will be converted to UTF-8.

The rationale behind this is that UTF-8 is the encoding assumed by most of the Go standard library, and that the other encodings have no realistic benefits over UTF-8.

Behaviour when encountering invalid data

There are two kinds of invalid data that can be encountered: Data that doesn't look like a valid frame, and data that is invalid in the context of its frame.

An example for the first case is a frame identifier that doesn't consist of only A-Z0-9. That usually happens when other programs wrote invalid data. One common case are wrongly encoded sizes, which will cause us to read random binary data.

An example for the second case is text that isn't valid according to the specified encoding.

In the first case, parsing of the entire tag will be aborted because it cannot be ensured that bad things won't happen.

In the second case only that specific frame will be dropped.

Unsupported frames

Unsupported frames, like extensions by Apple, will be left untouched, meaning that they will be read and written as raw byte slices. If you know how to handle them, you can write your own function to parse and modify the content. All unsupported frames will be of type UnsupportedFrame.

Index

Constants

View Source
const TimeFormat = "2006-01-02T15:04:05"

Variables

View Source
var FrameNames = map[FrameType]string{
	"AENC": "Audio encryption",
	"APIC": "Attached picture",
	"ASPI": "Audio seek point index",
	"COMM": "Comments",
	"COMR": "Commercial frame",

	"ENCR": "Encryption method registration",
	"EQU2": "Equalisation (2)",
	"ETCO": "Event timing codes",

	"GEOB": "General encapsulated object",
	"GRID": "Group identification registration",

	"LINK": "Linked information",

	"MCDI": "Music CD identifier",
	"MLLT": "MPEG location lookup table",

	"OWNE": "Ownership frame",

	"PRIV": "Private frame",
	"PCNT": "Play counter",
	"POPM": "Popularimeter",
	"POSS": "Position synchronisation frame",

	"RBUF": "Recommended buffer size",
	"RVA2": "Relative volume adjustment (2)",
	"RVRB": "Reverb",

	"SEEK": "Seek frame",
	"SIGN": "Signature frame",
	"SYLT": "Synchronised lyric/text",
	"SYTC": "Synchronised tempo codes",

	"TALB": "Album/Movie/Show title",
	"TBPM": "BPM (beats per minute)",
	"TCOM": "Composer",
	"TCON": "Content type",
	"TCOP": "Copyright message",
	"TDEN": "Encoding time",
	"TDLY": "Playlist delay",
	"TDOR": "Original release time",
	"TDRC": "Recording time",
	"TDRL": "Release time",
	"TDTG": "Tagging time",
	"TENC": "Encoded by",
	"TEXT": "Lyricist/Text writer",
	"TFLT": "File type",
	"TIPL": "Involved people list",
	"TIT1": "Content group description",
	"TIT2": "Title/songname/content description",
	"TIT3": "Subtitle/Description refinement",
	"TKEY": "Initial key",
	"TLAN": "Language(s)",
	"TLEN": "Length",
	"TMCL": "Musician credits list",
	"TMED": "Media type",
	"TMOO": "Mood",
	"TOAL": "Original album/movie/show title",
	"TOFN": "Original filename",
	"TOLY": "Original lyricist(s)/text writer(s)",
	"TORY": "Original release year",
	"TOPE": "Original artist(s)/performer(s)",
	"TOWN": "File owner/licensee",
	"TPE1": "Lead performer(s)/Soloist(s)",
	"TPE2": "Band/orchestra/accompaniment",
	"TPE3": "Conductor/performer refinement",
	"TPE4": "Interpreted, remixed, or otherwise modified by",
	"TPOS": "Part of a set",
	"TPRO": "Produced notice",
	"TPUB": "Publisher",
	"TRCK": "Track number/Position in set",
	"TRSN": "Internet radio station name",
	"TRSO": "Internet radio station owner",
	"TSOA": "Album sort order",
	"TSOP": "Performer sort order",
	"TSOT": "Title sort order",
	"TSO2": "Album Artist sort order",
	"TSOC": "Composer sort oder",
	"TSRC": "ISRC (international standard recording code)",
	"TSSE": "Software/Hardware and settings used for encoding",
	"TSST": "Set subtitle",
	"TYER": "Year",
	"TXXX": "User defined text information frame",

	"UFID": "Unique file identifier",
	"USER": "Terms of use",
	"USLT": "Unsynchronised lyric/text transcription",

	"WCOM": "Commercial information",
	"WCOP": "Copyright/Legal information",
	"WOAF": "Official audio file webpage",
	"WOAR": "Official artist/performer webpage",
	"WOAS": "Official audio source webpage",
	"WORS": "Official Internet radio station homepage",
	"WPAY": "Payment",
	"WPUB": "Publishers official webpage",
	"WXXX": "User defined URL link frame",
}
View Source
var Genres = []string{}/* 126 elements not displayed */
View Source
var Magic = []byte("ID3")
View Source
var PictureTypes = []string{
	"Other",
	"32x32 pixels 'file icon' (PNG only)",
	"Other file icon",
	"Cover (front)",
	"Cover (back)",
	"Leaflet page",
	"Media (e.g. label side of CD)",
	"Lead artist/lead performer/soloist",
	"Artist/performer",
	"Conductor",
	"Band/Orchestra",
	"Composer",
	"Lyricist/text writer",
	"Recording Location",
	"During recording",
	"During performance",
	"Movie/video screen capture",
	"A bright coloured fish",
	"Illustration",
	"Band/artist logotype",
	"Publisher/Studio logotype",
}

Functions

func Check

func Check(r Peeker) (bool, error)

Check reports whether r looks like it starts with an ID3 tag.

Types

type Comment

type Comment struct {
	Language    string
	Description string
	Text        string
}

type CommentFrame

type CommentFrame struct {
	FrameHeader
	Language    string
	Description string
	Text        string
}

func (CommentFrame) Encode

func (f CommentFrame) Encode() []byte

func (CommentFrame) Size

func (f CommentFrame) Size() int

func (CommentFrame) Value

func (f CommentFrame) Value() string

type Decoder

type Decoder struct {
	// contains filtered or unexported fields
}

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

func (*Decoder) Parse

func (d *Decoder) Parse() (*Tag, error)

Parse parses a tag.

Parse will always return a valid tag. In the case of an error, the tag will be empty.

If Parse successfully parsed a tag, the reader will be positioned immediately after the tag, which usually is directly before audio data. If there wasn't a valid tag, however, the position of the reader is undefined. If you're not sure if your reader starts with a tag at all, consider using Check first.

Parse cannot be called if either ParseHeader or ParseFrame have been called for the current tag.

func (*Decoder) ParseFrame

func (d *Decoder) ParseFrame() (Frame, error)

ParseFrame reads the next ID3 frame. When it reaches padding, it will read and discard all of it and return io.EOF. This should set the reader immediately before the audio data.

ParseHeader must be called before calling ParseFrame.

func (*Decoder) ParseHeader

func (d *Decoder) ParseHeader() (Header, error)

ParseHeader parses only the ID3 header.

type Encoder

type Encoder struct {

	// The amount of padding that will be added after the last frame.
	Padding int
	// contains filtered or unexported fields
}

func NewEncoder

func NewEncoder(w io.Writer) *Encoder

func (*Encoder) WriteFrame

func (e *Encoder) WriteFrame(f Frame) error

func (*Encoder) WriteHeader

func (e *Encoder) WriteHeader(size int) error

func (*Encoder) WritePadding

func (e *Encoder) WritePadding() error

func (*Encoder) WriteTag

func (e *Encoder) WriteTag(t *Tag) error

type Encoding

type Encoding byte

func (Encoding) String

func (e Encoding) String() string

type Frame

type Frame interface {
	ID() FrameType // TODO consider renaming to Type()
	Header() FrameHeader
	Value() string
	Encode() []byte
	Size() int
}

type FrameFlags

type FrameFlags uint16

func (FrameFlags) Compressed

func (f FrameFlags) Compressed() bool

func (FrameFlags) Encrypted

func (f FrameFlags) Encrypted() bool

func (FrameFlags) Grouped

func (f FrameFlags) Grouped() bool

func (FrameFlags) PreserveFileAlteration

func (f FrameFlags) PreserveFileAlteration() bool

func (FrameFlags) PreserveTagAlteration

func (f FrameFlags) PreserveTagAlteration() bool

func (FrameFlags) ReadOnly

func (f FrameFlags) ReadOnly() bool

type FrameHeader

type FrameHeader struct {
	// contains filtered or unexported fields
}

func (FrameHeader) Header

func (h FrameHeader) Header() FrameHeader

func (FrameHeader) ID

func (f FrameHeader) ID() FrameType

type FrameType

type FrameType string

func (FrameType) String

func (f FrameType) String() string

type FramesMap

type FramesMap map[FrameType][]Frame

func (FramesMap) Size

func (fm FramesMap) Size() int
type Header struct {
	Version Version
	Flags   HeaderFlags
	Size    int // The size of the tag (exluding the size of the header)
}

type HeaderFlags

type HeaderFlags byte

func (HeaderFlags) Experimental

func (f HeaderFlags) Experimental() bool

func (HeaderFlags) ExtendedHeader

func (f HeaderFlags) ExtendedHeader() bool

func (HeaderFlags) UndefinedSet

func (f HeaderFlags) UndefinedSet() bool

func (HeaderFlags) Unsynchronisation

func (f HeaderFlags) Unsynchronisation() bool

type InvalidFrameHeaderError

type InvalidFrameHeaderError struct {
	Bytes struct {
		ID    [4]byte
		Size  [4]byte
		Flags [2]byte
	}
}

func (InvalidFrameHeaderError) Error

func (err InvalidFrameHeaderError) Error() string

type InvalidTagHeaderError

type InvalidTagHeaderError struct {
	Magic []byte
}

func (InvalidTagHeaderError) Error

func (err InvalidTagHeaderError) Error() string

type MusicCDIdentifierFrame

type MusicCDIdentifierFrame struct {
	FrameHeader
	TOC []byte
}

func (MusicCDIdentifierFrame) Encode

func (f MusicCDIdentifierFrame) Encode() []byte

func (MusicCDIdentifierFrame) Size

func (f MusicCDIdentifierFrame) Size() int

func (MusicCDIdentifierFrame) Value

func (f MusicCDIdentifierFrame) Value() string

type Peeker

type Peeker interface {
	Peek(n int) ([]byte, error)
}

type PictureFrame

type PictureFrame struct {
	FrameHeader
	MIMEType    string
	PictureType PictureType
	Description string
	Data        []byte
}

func (PictureFrame) Encode

func (f PictureFrame) Encode() []byte

func (PictureFrame) Size

func (f PictureFrame) Size() int

func (PictureFrame) Value

func (f PictureFrame) Value() string

type PictureType

type PictureType byte

func (PictureType) String

func (p PictureType) String() string

type PrivateFrame

type PrivateFrame struct {
	FrameHeader
	Owner []byte
	Data  []byte
}

func (PrivateFrame) Encode

func (f PrivateFrame) Encode() []byte

func (PrivateFrame) Size

func (f PrivateFrame) Size() int

func (PrivateFrame) Value

func (f PrivateFrame) Value() string

type Tag

type Tag struct {
	Flags  HeaderFlags
	Frames FramesMap
}

func NewTag

func NewTag() *Tag

NewTag returns an empty tag.

func (*Tag) Album

func (t *Tag) Album() string

func (*Tag) AlbumSortOrder

func (t *Tag) AlbumSortOrder() string

func (*Tag) Artist

func (t *Tag) Artist() string

func (*Tag) Artists

func (t *Tag) Artists() []string

func (*Tag) BPM

func (t *Tag) BPM() int

func (*Tag) Band

func (t *Tag) Band() string

func (*Tag) Clear

func (t *Tag) Clear()

Clear removes all tags from the file.

func (*Tag) Comments

func (t *Tag) Comments() []Comment

func (*Tag) Composer

func (t *Tag) Composer() string

func (*Tag) Composers

func (t *Tag) Composers() []string

func (*Tag) Conductor

func (t *Tag) Conductor() string

func (*Tag) EncodingTime

func (t *Tag) EncodingTime() time.Time

func (*Tag) GetTextFrame

func (t *Tag) GetTextFrame(name FrameType) string

GetTextFrame returns the text frame specified by name.

To access user text frames, specify the name like "TXXX:The description".

func (*Tag) GetTextFrameNumber

func (t *Tag) GetTextFrameNumber(name FrameType) int

func (*Tag) GetTextFrameSlice

func (t *Tag) GetTextFrameSlice(name FrameType) []string

func (*Tag) GetTextFrameTime

func (t *Tag) GetTextFrameTime(name FrameType) time.Time

func (*Tag) HasFrame

func (t *Tag) HasFrame(name FrameType) bool

func (*Tag) ISRC

func (t *Tag) ISRC() string

func (*Tag) Language

func (t *Tag) Language() string

func (*Tag) Languages

func (t *Tag) Languages() []string

func (*Tag) Length

func (t *Tag) Length() time.Duration

func (*Tag) Mood

func (t *Tag) Mood() string

func (*Tag) OriginalArtist

func (t *Tag) OriginalArtist() string

func (*Tag) OriginalArtists

func (t *Tag) OriginalArtists() []string

func (*Tag) OriginalFilename

func (t *Tag) OriginalFilename() string

func (*Tag) OriginalReleaseTime

func (t *Tag) OriginalReleaseTime() time.Time

func (*Tag) Owner

func (t *Tag) Owner() string

func (*Tag) PerformerSortOrder

func (t *Tag) PerformerSortOrder() string

func (*Tag) PlaylistDelay

func (t *Tag) PlaylistDelay() time.Duration

func (*Tag) Publisher

func (t *Tag) Publisher() string

func (*Tag) RecordingTime

func (t *Tag) RecordingTime() time.Time

func (*Tag) RemoveFrames

func (t *Tag) RemoveFrames(name FrameType)

func (*Tag) Sanitize

func (t *Tag) Sanitize()

Sanitize will remove all frames that aren't valid. Check the documentation of (*Tag).Validate() to see what "valid" means.

func (*Tag) SetAlbum

func (t *Tag) SetAlbum(album string)

func (*Tag) SetAlbumSortOrder

func (t *Tag) SetAlbumSortOrder(s string)

func (*Tag) SetArtist

func (t *Tag) SetArtist(artist string)

func (*Tag) SetArtists

func (t *Tag) SetArtists(artists []string)

func (*Tag) SetBPM

func (t *Tag) SetBPM(bpm int)

func (*Tag) SetBand

func (t *Tag) SetBand(band string)

func (*Tag) SetComments

func (t *Tag) SetComments(comments []Comment)

func (*Tag) SetComposer

func (t *Tag) SetComposer(composer string)

func (*Tag) SetComposers

func (t *Tag) SetComposers(composers []string)

func (*Tag) SetConductor

func (t *Tag) SetConductor(name string)

func (*Tag) SetEncodingTime

func (t *Tag) SetEncodingTime(et time.Time)

func (*Tag) SetISRC

func (t *Tag) SetISRC(isrc string)

func (*Tag) SetLanguage

func (t *Tag) SetLanguage(lang string)

func (*Tag) SetLanguages

func (t *Tag) SetLanguages(langs []string)

func (*Tag) SetLength

func (t *Tag) SetLength(d time.Duration)

func (*Tag) SetMood

func (t *Tag) SetMood(mood string)

func (*Tag) SetOriginalArtist

func (t *Tag) SetOriginalArtist(name string)

func (*Tag) SetOriginalArtists

func (t *Tag) SetOriginalArtists(names []string)

func (*Tag) SetOriginalFilename

func (t *Tag) SetOriginalFilename(name string)

func (*Tag) SetOriginalReleaseTime

func (t *Tag) SetOriginalReleaseTime(rt time.Time)

func (*Tag) SetOwner

func (t *Tag) SetOwner(owner string)

func (*Tag) SetPerformerSortOrder

func (t *Tag) SetPerformerSortOrder(s string)

func (*Tag) SetPlaylistDelay

func (t *Tag) SetPlaylistDelay(d time.Duration)

func (*Tag) SetPublisher

func (t *Tag) SetPublisher(publisher string)

func (*Tag) SetRecordingTime

func (t *Tag) SetRecordingTime(rt time.Time)

func (*Tag) SetStationName

func (t *Tag) SetStationName(name string)

func (*Tag) SetStationOwner

func (t *Tag) SetStationOwner(owner string)

func (*Tag) SetTextFrame

func (t *Tag) SetTextFrame(name FrameType, value string)

func (*Tag) SetTextFrameNumber

func (t *Tag) SetTextFrameNumber(name FrameType, value int)

func (*Tag) SetTextFrameSlice

func (t *Tag) SetTextFrameSlice(name FrameType, value []string)

func (*Tag) SetTextFrameTime

func (t *Tag) SetTextFrameTime(name FrameType, value time.Time)

func (*Tag) SetTitle

func (t *Tag) SetTitle(title string)

func (*Tag) SetTitleSortOrder

func (t *Tag) SetTitleSortOrder(s string)

func (*Tag) StationName

func (t *Tag) StationName() string

func (*Tag) StationOwner

func (t *Tag) StationOwner() string

func (*Tag) Title

func (t *Tag) Title() string

func (*Tag) TitleSortOrder

func (t *Tag) TitleSortOrder() string

func (*Tag) UserTextFrames

func (t *Tag) UserTextFrames() []UserTextInformationFrame

UserTextFrames returns all TXXX frames.

func (*Tag) Validate

func (t *Tag) Validate() error

Validate checks whether the tags are conforming to the specification.

This entails two checks: Whether only frames that are covered by the specification are present and whether all values are within valid ranges.

It is well possible that reading existing files will result in invalid tags.

Calling Save() will not automatically validate the tags and will happily write invalid tags.

Assuming that the original file was valid and that only the getter/setter methods were used the generated tags should always be valid.

type TextInformationFrame

type TextInformationFrame struct {
	FrameHeader
	Text string
}

func (TextInformationFrame) Encode

func (f TextInformationFrame) Encode() []byte

func (TextInformationFrame) Size

func (f TextInformationFrame) Size() int

func (TextInformationFrame) Value

func (f TextInformationFrame) Value() string

type URLLinkFrame

type URLLinkFrame struct {
	FrameHeader
	URL string
}

func (URLLinkFrame) Encode

func (f URLLinkFrame) Encode() []byte

func (URLLinkFrame) Size

func (f URLLinkFrame) Size() int

func (URLLinkFrame) Value

func (f URLLinkFrame) Value() string

type UnimplementedFeatureError

type UnimplementedFeatureError struct {
	Feature string
}

func (UnimplementedFeatureError) Error

func (err UnimplementedFeatureError) Error() string

type UniqueFileIdentifierFrame

type UniqueFileIdentifierFrame struct {
	FrameHeader
	Owner      string
	Identifier []byte
}

func (UniqueFileIdentifierFrame) Encode

func (f UniqueFileIdentifierFrame) Encode() []byte

func (UniqueFileIdentifierFrame) Size

func (f UniqueFileIdentifierFrame) Size() int

func (UniqueFileIdentifierFrame) Value

type UnsupportedFrame

type UnsupportedFrame struct {
	FrameHeader
	Data []byte
}

func (UnsupportedFrame) Encode

func (f UnsupportedFrame) Encode() []byte

func (UnsupportedFrame) Size

func (f UnsupportedFrame) Size() int

func (UnsupportedFrame) Value

func (f UnsupportedFrame) Value() string

type UnsupportedVersionError

type UnsupportedVersionError struct {
	Version Version
}

func (UnsupportedVersionError) Error

func (err UnsupportedVersionError) Error() string

type UnsynchronisedLyricsFrame

type UnsynchronisedLyricsFrame struct {
	FrameHeader
	Language    string
	Description string
	Lyrics      string
}

func (UnsynchronisedLyricsFrame) Encode

func (f UnsynchronisedLyricsFrame) Encode() []byte

func (UnsynchronisedLyricsFrame) Size

func (f UnsynchronisedLyricsFrame) Size() int

func (UnsynchronisedLyricsFrame) Value

type UserDefinedURLLinkFrame

type UserDefinedURLLinkFrame struct {
	FrameHeader
	Description string
	URL         string
}

func (UserDefinedURLLinkFrame) Encode

func (f UserDefinedURLLinkFrame) Encode() []byte

func (UserDefinedURLLinkFrame) Size

func (f UserDefinedURLLinkFrame) Size() int

func (UserDefinedURLLinkFrame) Value

func (f UserDefinedURLLinkFrame) Value() string

type UserTextInformationFrame

type UserTextInformationFrame struct {
	FrameHeader
	Description string
	Text        string
}

func (UserTextInformationFrame) Encode

func (f UserTextInformationFrame) Encode() []byte

func (UserTextInformationFrame) Size

func (f UserTextInformationFrame) Size() int

func (UserTextInformationFrame) Value

func (f UserTextInformationFrame) Value() string

type Version

type Version int16

func (Version) String

func (v Version) String() string

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL