This weekend I spent some time trying to find a web service that would lookup album information. To my frustration I was unable to find anything useful. Yahoo has a web service, but the information it provides is limited. The Musicbrainz code is a bunch of crazy C that I just don't want to deal with. Therefore I whipped together some code to query CDDB and parse the results. It doesn't support the full range of options that I can imagine so I might add those in the future. If you grab this code and make additions, send it back to me and I'll post the updated code. Here's the source:
using System; using System.IO; using System.Collections.Generic; using System.Text; using System.Net; using System.Text.RegularExpressions; namespace CDLookup { public class AlbumReference { private String m_strName; private String m_strUrl; internal AlbumReference(String name, String url) { this.m_strName = name; this.m_strUrl = url; } public String Name { get { return this.m_strName; } } public AlbumInfo GetInfo() { return CDDBLookup.GetAlbumInfo(this.m_strUrl); } } public class AlbumInfo { private String m_strArtist; private String m_strAlbum; private String m_strLabel; private String m_strYear; private List m_strTracks; internal AlbumInfo(String artist, String album, String label, String year, List tracks) { this.m_strArtist = artist; this.m_strAlbum = album; this.m_strLabel = label; this.m_strYear = year; this.m_strTracks = tracks; } public String Artist { get { return this.m_strArtist; } } public String Album { get { return this.m_strAlbum; } } public String Label { get { return this.m_strLabel; } } public String Year { get { return this.m_strYear; } } public List Tracks { get { return this.m_strTracks; } } } public static class CDDBLookup { private static String s_baseInfoUrl = "http://www.gracenote.com/music/album.html/"; private static String s_baseQueryUrl = "http://www.gracenote.com/music/search-adv.html?q=&qartist={ARTIST}&qdisc={ALBUM}&qtrack=&n=10&x=39&y=6"; private static String s_queryRegex = ".*)\".*>(?.*) "; private static String s_infoRegex = "(?.*) Label:(?.*) Year:(?.*) "; private static String s_altInfoRegex = "(?.*) "; private static String s_trackRegex = ".* (?.*) "; private static String s_notFoundRegex = "Your search could not be completed"; public static List Lookup(String artist, String album) { String strUrl = s_baseQueryUrl.Replace("{ARTIST}", artist).Replace("{ALBUM}", album); WebRequest request = WebRequest.Create(strUrl); WebResponse response = request.GetResponse(); String strResponse = new StreamReader(response.GetResponseStream()).ReadToEnd(); List references = new List(); Regex regexNotFound = new Regex(s_notFoundRegex); if (regexNotFound.Match(strResponse).Success) return references; Regex regexBase = new Regex(s_queryRegex); MatchCollection matches = regexBase.Matches(strResponse); if (matches.Count != 0) { foreach (Match match in matches) { String url = match.Groups["Url"].Value; String name = match.Groups["Name"].Value; references.Add(new AlbumReference(name, url)); } } else { Regex regexInfo = new Regex(s_infoRegex); Match match = regexInfo.Match(strResponse); if (!match.Success) { Regex regexAltInfo = new Regex(s_altInfoRegex, RegexOptions.Multiline); match = regexAltInfo.Match(strResponse); if (!match.Success) throw new ArgumentException("Unable to parse response."); } references.Add(new AlbumReference( match.Groups["Name"].Value, response.ResponseUri.AbsoluteUri.Substring(s_baseInfoUrl.Length))); } return references; } internal static AlbumInfo GetAlbumInfo(String subUrl) { String strUrl = s_baseInfoUrl + subUrl; WebRequest request = WebRequest.Create(strUrl); WebResponse response = request.GetResponse(); String strResponse = new StreamReader(response.GetResponseStream()).ReadToEnd(); Regex regexInfo = new Regex(s_infoRegex); Match match = regexInfo.Match(strResponse); if (!match.Success) { Regex regexAltInfo = new Regex(s_altInfoRegex, RegexOptions.Multiline); match = regexAltInfo.Match(strResponse); if (!match.Success) throw new ArgumentException("Unable to parse response."); } Regex regexTracks = new Regex(s_trackRegex); List tracks = new List(); foreach (Match matchTrack in regexTracks.Matches(strResponse)) { tracks.Add(matchTrack.Groups["Track"].Value); } int iSlash = match.Groups["Name"].Value.IndexOf('/'); return new AlbumInfo( match.Groups["Name"].Value.Substring(0, iSlash).Trim(), match.Groups["Name"].Value.Substring(iSlash+1).Trim(), GetGroupValue(match, "Label"), GetGroupValue(match, "Year"), tracks); } private static String GetGroupValue(Match match, String groupName) { Group group = match.Groups[groupName]; if (group == null) return ""; return group.Value; } } }