Nancy Street

NTag

Click to see the Site Map
HomeInfoMusicGalleryPetsGeoHobbiesGeo
Site MapWhat's NewRecent ChangesContactsServer StatisticsSite Information Home « Computers « NTag

Introduction

26-Jul-2008 : NTag V4.0 and Onyx V5.1 are released, containing many bug fixes, new features, simplified project structure and dependencies. See the notes at the bottom of the page.

The NTag project is a general purpose library that manipulates the tags in audio files. The library is written using the C# language with the .NET Framework 2.0 compilers and runtime under Visual Studio 2008.

The project was started in July 2005 to be a replacement for the tagnetlib project, and the first working and usable version was created in May 2006. The Onyx/tagnetlib Notes page describes the deficencies of the previous projects and the proposed features of the new NTag library. The Technical Notes below give an overview of how NTag uses a Plug-In architecture to make it extensible and flexible. The NTag project download also includes the Onyx V5 project which is the early draft of a Windows application for tag editing. Onyx internally uses the NTag library for parsing and updating tagged files.

Current Status (26-Jul-2008)

  • The library includes an ID3 tag processor that is capable of parsing most ID3 V1, V2.2, V2.3 and V2.4 frames (a full list is at the bottom of the page). This processor was created first because it is one of the most popular tag formats. Unfortunately, the ID3 standard is quite complex, so the resulting code is very dense and complex.
  • Reading compressed and synchronized frames is supported.
  • The ID3 processor does not support V2.4 extended headers yet.
  • The ID3 processor can update a file with an ID3 V1.x and V2.3 tag (updating V2.4 is not supported yet).
  • Writing an ID3 tag with extended header, synchronized frames or compressed frames is not supported yet.
  • A WMA tag processor is in the early stages of experimental development and is starting to work. The most familiar 'attributes' of WMA files can be parsed, but not written yet.

Except for the limitations listed above, the library is in an acceptable and working state that can parse and write a large subset of the ID3 tag specification. The downloadable solution contains a simple Windows application that demonstrates how to call NTag. Also supplied is a suite of NUnit tests that fully exercise the library in various ways over standard test files.

Technical Details

As described on the Onyx/tagnetlib Notes page, my original hobby project called tagnetlib was flawed due to the fact that it could only deal with ID3V3.2 tag data and was not extensible. The replacement NTag project is designed to be flexible and extensible through the use of plug-in tag processors. A plug-in processor is a class written by any .NET language that is decorated with the [TagProcessor] attribute and implements the ITagProcessor interface. When the library starts, it searches through DLL files in the runtime current folder looking for plug-in processor classes and dynamically loads them. Each plug-in is expected to know how to parse tag data of a certain format out of files and to write the tag data back to files. There are 3 tag processors in the download:

Orthogonal.NTag.Processor.ID3 Can read and write most popular ID3 tags and frames.
Orthogonal.NTag.Processor.WMA Can read most WMA (ASF) attributes but can't yet write them yet.
Orthogonal.NTag.Processor.Lyrics A code stub that doesn't do anything uey.

A tag processor plug-in recognises tags of specific types in files and parses their contents into a collection of meta-frames which have a neutral format. Each meta-frame represents information that is commonly found in a tag such as artist name, album title, music genre, etc, and it holds the information is a neutral way that is not tied to any specific tag format. A tag processor must know how to create meta-frames from a tagged file and how to convert them back to their original format in the file.

The following figure shows how an application calls the NTag library to process tagged files. NTag then delegates the work to the plug-ins to perform the actual scanning and parsing of the Tag data from various types of tagged files.

In this new NTag library structure, the hard work of analysing and parsing the contents of tagged files is delegated to the plug-in tag processors which can be written in any .NET language. The NTag library now reduces to being little more than a container for IMetaFrame objects that are passed to-and-from the plug-ins. Parent applications are responsible for displaying and editing the IMetaFrame objects.

Plug-ins need to reference the Orthogonal.NTag library which contains all of the interface definitions and utility classes that an external author can use to create a tag processor. Any class that is decorated with the [TagProcessor] attribute and implements the ITagProcessor interface can be placed in the runtime folder and it will be loaded and can be used to recognise and parse tagged files.

The ID3 processor plug-in currently fully parses the following ID3 frames into meta-frames:

MCDI PCNT TDLY TBPM TLEN CNT TDY TBP TLE PIC APIC TCON TCO TRK TRCK TMCL TIPL POPM POP RVRB REV RVAD RVA GEOB PRIV UFID RBUF BUF ENCR GRID AENC OWNE TALB TAL TSOA TFLT TFT TPE2 TP2 TCOM TCM TPE3 TP3 TIT1 TT1 TCOP TCR TENC TEN TSSE TSS TOWN TKEY TKE TIPL TLAN TLA TPE1 TP1 TEXT TXT TMED TMT TPE4 TP4 TMOO TRSO TRSN TOAL TOT TOPE TOA TOFN TOF TOLY TOL TPOS TPA TSOP TPRO TPUB TPB TSRC TSC TIT3 TT3 TIT2 TT2 TSOT TXXX TXX COMM COM USLT ULT WOAR WAR WOAF WAF WOAS WAS WCOM WCM WCOP WCP WPAY WPUB WPB WORS WXXX WXX USER TYE TYER TOR TORY TDRC TDOR TDEN TDRL TDTG

The following ID3 tags are not parsed yet and are read and written as a single binary blob:

COMR COMR EQU EQUA ETC ETCO ETCO IPL IPLS LNK LINK LINK MLL MLLT MLLT POSS POSS SLT SYLT SYLT STC SYTC SYTC TDA TDAT TIM TIME TSI TSIZ TSS TSSE TSSE ASPI CRM EQU2 SEEK TSST SIGN RVA2

Frame Editors

Builds after 3.0.0.43 contain a new FrameEditors project which is designed to collect user controls that know how to edit meta-frames of different types. In the same way that the NTag library can be extended by adding tag processors, this FrameEditors library can be extended by adding UserControl derived classes that know how to display a UI for editing different meta-frame types. Frame editors exist for all text, time and numeric frames as well as a many complex specialised frames. See the Technical Notes on the Onyx page for more information.

Downloads

tagger_proj.zip - A zip of the full Visual Studio 2008 solution which contains the following projects:

  • The NTag library.
  • NUnit tests that fully exercise the library against standard test files.
  • A simple demonstration forms application that calls the NTag library to parse a folder of files for tags and displays the results in a grid.
  • A stub of a new forms application called Onyx V5. This application will eventually become a general-purpose file tagging utility that uses a plug-in architecture to display and edit tags. Onyx uses NTag for the underlying file processing.
onyx51.msi - A standard Windows installer file for Onyx V5. The application isn't finished, but it is quite capable of editing ID3 tags (typically associated with mp3 files). It's already better than most competitive shareware programs. The only usable tag viewer currently uses a grid/spreadsheet format to enable efficient bulk editing of tag data.

Onyx Version Notes

Version
Date
Notes
5.1.0.7 26‑Jul‑08 The Open Advanced dialog is expanded and fully functional, including optional pattern matching on file names.
5.1.0.6 12‑Jul‑08 FIX: The Open Advanced dialog would crash if the maximum files to open was greater than the spinner control maximum value (which was 1000). BUG: This dialog seems to be ignoring the File Patterns.
5.1.0.5 20‑Jun‑08 The tag type icon now correctly shows if an ID3 V1.x frame exists. The media frame now uses a specialised editor instead of the generic text editor. A Tools | Processor Options menu now opens a dialog specifically designed to edit the options for each tag processor (they are not persisted yet). A Clear command will clear or reset the contents of selected cells. File scan processing has been broken into dedicated classes with a much simpler and more logical structure. A unit test project has been created for Onyx. A new Picture Manager dialog can bulk assign pictures to tags. A sample Tool is provided but it doesn't do anything yet. Hash code calculation bug in RowEditorWindow fixed.
5.0.0.9 02‑Sep‑07 The GenericCA project was removed. Projects share links to a common OnyxAssemblyInfo.cs file to supply common assembly attributes. The build process is more reliable. The initial window position is nicer.
5.0.0.8 01‑Sep‑07 The dummy TreeViewer control shows Artist and Title information correctly, but remains only for demonstration purposes.

NTag Version Notes

Version
Date
Notes
4.0.0.7 11‑Jun‑08 The project structure has been simplified with less dependencies across projects. MediaSource frames now have special behaviour and are not treated as simple text frames. Tag processors now expose their options via the IProcessorOptions interface and an underlying collection. There are new methods and convenient generic methods for finding frames inside a tag. Much more code has been simplified, clarified and documented. The meta frame base and derived classes implement many ComponentModel binding related interfaces, but it's only experimental at the moment. A new console command line application demonstrates shows how to call the NTag library in the simplest possible way.
3.0.0.67 19‑Apr‑08 A report arrived that you can attempt to add a frame with an ID that does not match the type (creating a TextFrame with ID=ReleaseDate for example). The compiler does not stop this, but adding the frame would throw a cast exception at runtime. Calls to the new method ID3Utils CheckFrameType were added in all of the ID3 code where frames are written to throw an InvalidOperationException with a helpful message in this situation. It doesn't add much value other than a nicer message, so this whole issue needs to be examined to see if it's possible to tighten the overall logic.
3.0.0.66 25‑Oct‑07 The ITagProcessor now defines a method called GetAudioData which allows callers to get the raw bytes out of any audio data in a file. Only the ID3 processor implements the method at the moment. Thanks to Neils W for suggesting this addition.
3.0.0.65 09‑Sep‑07 The code in the WMA processor is expanded and much tidier, in preparation for making it capable of reading and updating WMA files. A bug in genre parsing from the description is corrected.
3.0.0.64 02‑Sep‑07 Small changes to simplify builds. Projects share links to a common NTagAssemblyInfo.cs file to supply common assembly attributes.
3.0.0.63 16‑Nov‑06 NEW - The PictureFrame class now has extra methods to load images from multiple sources, including image files.
    BUG FIX - Images were stupidly being saved in the bloated and space inefficient Bmp format. The images are now saved as Gif image format if they have a palette, and Jpeg format otherwise.
    BUG FIX - Thanks to a report from Hans-Christian, it was found that loading the plugin processors from an ASP.NET application would fail because the "current" folder was a Windows system folder. To work around this, a property has been added to the ProcessorManager class which gets a reference to a ProcessorOptions class. This new options class contains a PluginFolder property which can point the processor to a specific folder which will be searched for plugins. See the comments in the ProcessorOptions source code for how this works, especially in an ASP.NET application where you can use Server.MapPath to point to a local folder for plugins.
    BUG FIX - The TagV1 class has a TagVersion property which reports 1.0 or 1.1 after it has been loaded.
3.0.0.62 17‑Oct‑06 Fixes a stupid string.Format bug that Jim found which throws when the mp3 tag has no padding and the loop through the frames stop exactly at the 0xFF that starts the data.
3.0.0.61 10‑Sep‑06 Some small changes for Onyx version 5.0.0.5.
3.0.0.51 13‑Aug‑06 All XML serialization code is removed, to be replaced by a general method at a later time.
3.0.0.50 30‑Jul‑06 The FramesManager includes a PictureFrame editor and a One-to-Many editor for InvolvedPeople and MusicianCredits frames.
3.0.0.49 28‑Jul‑06 Fix crash when parsing an ID3 tag with no frames. Saving an ID3 tagged file with zero frames now causes all V1 and V2 frames and the tag to be removed. TypeConverter derived classes are no longer needed or used for the TrackNum or Text meta-frames, all frame specific utility code is static in the meta-frame class or the corresponding IFrameDataConverter class.
3.0.0.48   TYER frame is now saved correctly. Correct meta-frame IDs set in new frames. Assembly attributes are taken from a shared file via a link in the csproj files.
3.0.0.47   A weird UI bug with the enabling of an OK button was traced to inconsistent representation of line-feeds in a text property. A string with CRLF line-feeds was going into a rich text box and coming out with LF only, so the before and after strings weren't equal. I have decided to canonicalize all strings held in meta-frames. The protected ToCanonicalString method forces the set of all string properties into a standard format where all multi-line strings are delimited by a LF (0x0a) only. All writers or readers of meta-frames can be certain that string properties will be in the standard canonical format.
3.0.0.45   The frames editor has been expanded and all editors improved.
3.0.0.44   Clicking the grid viewer icon opens the frames editor. Hash calculation bug in genres editor fixed. Text editor boxes have scrolling and a comment about unsupported fields is optionally visible.
3.0.0.43   The FramesManager (Frame UI Editor) project now contains editors for these frame types: Genres, Track Number, all text frames and all time frames.

Developer Notes

Coming here soon will be a technical description of the NTag library, how it works internally and (most importantly) how developers can write their own plug-in tag processors and meta-frames and incorporate them into the library.

Quick Start

The solution download contains a source file called ID3Tests.cs which runs a comprehensive set of NUnit tests of the NTag library against some standard test files which are included in the TestData folder. This file should be used as the definitive guide to current progress on how the library is used.

However, reading a large NUnit test file can be hard work, so I'll supply some quick start instructions on how the library is used by application at the higher-level.

The following skeleton C# code shows how an application would call the NTag library to read and display the tag contents of an mp3 file.

1 using Orthogonal.NTag;
2 string myFile = "Blah Blah Example.mp3";
3 ProcessorManager manager = new ProcessorManager();
4 manager.Startup();
5 ITagProcessor processor = manager.GetProcessorForFile(myFile);
6 ParseResults results = processor.OpenParse(myFile);
7 foreach (IMetaFrame frame in results.Tag.Frames)
{
  string s = string.Format("Frame.{0} {1}", i, frame);
  Debug.WriteLine(s);
}
8 processor.Close();
9 manager.Shutdown();

Explanation

1 Reference the NTag library.
2 An imaginary file mp3 name to parse for tag information.
3 Create an instance of the ProcessorManager class, which is the highest-level one that applications use to work with tagged files.
4 The Startup method tells the library to initialise itself. At this time the library searches for plug-in tag processors and loads them ready for use.
5 We ask the processor manager if it has a plug-in tag processor that recognises the file name. If it does then we get a reference to an object that implements the ITagProcessor interface and should be capable of parsing the tagged file. A null return indicates that the file name is not recognised. Other methods are provided that get references to specific tag processors or all that are available.
6 The OpenParse method of a tag processor opens and parses the file for tag information. The results of the parsing are returned in a ParseResults object which contains detailed information about the file (file name, file size, processor name, tag contents, etc).
7 A loop through the IMetaFrame collection displays each one parsed from the file. There are many types of objects that implement the IMetaFrame interface, each one representing a different piece of information held in the tag (artist name, album name, music genre, track number, picture, etc). This sample uses the ToString method of each frame to dump the frame contents in a one-line compact form.
8 The processor closes the file that it opened and parsed. A file could be updated before it is closed, but code for this is skipped in this simple example.
9 The library is shutdown and all plug-in processors are closed and released.

To be continued...


Contact Information | PGP Keys | Site Map | What's New | Visitor Book
Last Updated: 26-Jul-2008 16:10
Copyright © 1999-2007 Orthogonal Programming