mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
MusicBrainz tagging.
This commit is contained in:
@@ -26,7 +26,9 @@ using System.Text;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Xml;
|
||||||
using AudioCodecsDotNet;
|
using AudioCodecsDotNet;
|
||||||
using HDCDDotNet;
|
using HDCDDotNet;
|
||||||
#if !MONO
|
#if !MONO
|
||||||
@@ -428,6 +430,8 @@ namespace CUEToolsLib
|
|||||||
private uint? _minDataTrackLength;
|
private uint? _minDataTrackLength;
|
||||||
private string _accurateRipId;
|
private string _accurateRipId;
|
||||||
private string _accurateRipIdActual;
|
private string _accurateRipIdActual;
|
||||||
|
private string _mbDiscId;
|
||||||
|
private string _mbReleaseId;
|
||||||
private string _eacLog;
|
private string _eacLog;
|
||||||
private string _cuePath;
|
private string _cuePath;
|
||||||
private NameValueCollection _albumTags;
|
private NameValueCollection _albumTags;
|
||||||
@@ -1378,6 +1382,123 @@ namespace CUEToolsLib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CalculateMusicBrainzDiscID() {
|
||||||
|
StringBuilder mbSB = new StringBuilder();
|
||||||
|
byte[] hashBytes;
|
||||||
|
uint trackOffset = 150;
|
||||||
|
|
||||||
|
for (int iTrack = 0; iTrack < TrackCount; iTrack++) {
|
||||||
|
TrackInfo track = _tracks[iTrack];
|
||||||
|
|
||||||
|
trackOffset += track.IndexLengths[0];
|
||||||
|
mbSB.AppendFormat("{0:X8}", trackOffset);
|
||||||
|
|
||||||
|
for (int iIndex = 1; iIndex <= track.LastIndex; iIndex++)
|
||||||
|
trackOffset += track.IndexLengths[iIndex];
|
||||||
|
}
|
||||||
|
mbSB.Insert(0, String.Format("{0:X2}{1:X2}{2:X8}", 1, TrackCount, trackOffset));
|
||||||
|
mbSB.Append(new string('0', (99 - TrackCount) * 8));
|
||||||
|
|
||||||
|
hashBytes = (new SHA1CryptoServiceProvider()).ComputeHash(Encoding.ASCII.GetBytes(mbSB.ToString()));
|
||||||
|
_mbDiscId = Convert.ToBase64String(hashBytes).Replace('+', '.').Replace('/', '_').Replace('=', '-');
|
||||||
|
System.Diagnostics.Debug.WriteLine(_mbDiscId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GetMetadataFromMusicBrainz() {
|
||||||
|
if (_mbDiscId == null) return;
|
||||||
|
|
||||||
|
using (Stream respStream = HttpGetToStream(
|
||||||
|
"http://musicbrainz.org/ws/1/release/?type=xml&limit=1&discid=" + _mbDiscId))
|
||||||
|
{
|
||||||
|
XmlDocument xd = GetXmlDocument(respStream);
|
||||||
|
XmlNode xn;
|
||||||
|
|
||||||
|
xn = xd.SelectSingleNode("/metadata/release-list/release");
|
||||||
|
if (xn != null)
|
||||||
|
_mbReleaseId = xn.Attributes["id"].InnerText;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_mbReleaseId == null) return;
|
||||||
|
|
||||||
|
using (Stream respStream = HttpGetToStream(String.Format(
|
||||||
|
"http://musicbrainz.org/ws/1/release/{0}?type=xml&inc=artist+tracks", _mbReleaseId)))
|
||||||
|
{
|
||||||
|
string discArtist = null;
|
||||||
|
string discTitle = null;
|
||||||
|
XmlDocument xd = GetXmlDocument(respStream);
|
||||||
|
XmlNode xn;
|
||||||
|
|
||||||
|
XmlNode xnRelease = xd.DocumentElement.SelectSingleNode("/metadata/release");
|
||||||
|
if (xnRelease == null) return;
|
||||||
|
|
||||||
|
XmlNodeList xnlTracks = xnRelease.SelectNodes("track-list/track");
|
||||||
|
if (xnlTracks.Count != TrackCount) return;
|
||||||
|
|
||||||
|
xn = xnRelease.SelectSingleNode("title");
|
||||||
|
if (xn != null)
|
||||||
|
discTitle = xn.InnerText;
|
||||||
|
|
||||||
|
xn = xnRelease.SelectSingleNode("artist/name");
|
||||||
|
if (xn != null)
|
||||||
|
discArtist = xn.InnerText;
|
||||||
|
|
||||||
|
Artist = discArtist;
|
||||||
|
Title = discTitle;
|
||||||
|
|
||||||
|
for (int iTrack = 0; iTrack < TrackCount; iTrack++) {
|
||||||
|
string trackArtist = null;
|
||||||
|
string trackTitle = null;
|
||||||
|
XmlNode xnTrack = xnlTracks[iTrack];
|
||||||
|
TrackInfo trackInfo = Tracks[iTrack];
|
||||||
|
|
||||||
|
xn = xnTrack.SelectSingleNode("title");
|
||||||
|
if (xn != null)
|
||||||
|
trackTitle = xn.InnerText;
|
||||||
|
|
||||||
|
xn = xnTrack.SelectSingleNode("artist/name");
|
||||||
|
if (xn != null)
|
||||||
|
trackArtist = xn.InnerText;
|
||||||
|
|
||||||
|
trackInfo.Artist = trackArtist ?? discArtist;
|
||||||
|
trackInfo.Title = trackTitle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private XmlDocument GetXmlDocument(Stream stream) {
|
||||||
|
XmlDocument xd = new XmlDocument();
|
||||||
|
|
||||||
|
xd.Load(stream);
|
||||||
|
|
||||||
|
if (xd.DocumentElement.NamespaceURI.Length > 0) {
|
||||||
|
// Strip namespace to simplify xpath expressions
|
||||||
|
XmlDocument xdNew = new XmlDocument();
|
||||||
|
xd.DocumentElement.SetAttribute("xmlns", String.Empty);
|
||||||
|
xdNew.LoadXml(xd.OuterXml);
|
||||||
|
xd = xdNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream HttpGetToStream(string url) {
|
||||||
|
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
|
||||||
|
req.UserAgent = "CUE Tools";
|
||||||
|
try {
|
||||||
|
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
|
||||||
|
return resp.GetResponseStream();
|
||||||
|
}
|
||||||
|
catch (WebException ex) {
|
||||||
|
if (ex.Status == WebExceptionStatus.ProtocolError) {
|
||||||
|
HttpStatusCode code = ((HttpWebResponse)ex.Response).StatusCode;
|
||||||
|
if (code == HttpStatusCode.NotFound) {
|
||||||
|
throw new HttpNotFoundException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe private void CalculateAccurateRipCRCsSemifast(int* samples, uint count, int iTrack, uint currentOffset, uint previousOffset, uint trackLength)
|
unsafe private void CalculateAccurateRipCRCsSemifast(int* samples, uint count, int iTrack, uint currentOffset, uint previousOffset, uint trackLength)
|
||||||
{
|
{
|
||||||
fixed (uint* CRCsA = iTrack != 0 ? _tracks[iTrack - 1].OffsetedCRC : null,
|
fixed (uint* CRCsA = iTrack != 0 ? _tracks[iTrack - 1].OffsetedCRC : null,
|
||||||
@@ -2564,6 +2685,9 @@ namespace CUEToolsLib
|
|||||||
CUELine line = General.FindCUELine(_attributes, "PERFORMER");
|
CUELine line = General.FindCUELine(_attributes, "PERFORMER");
|
||||||
return (line == null) ? String.Empty : line.Params[1];
|
return (line == null) ? String.Empty : line.Params[1];
|
||||||
}
|
}
|
||||||
|
set {
|
||||||
|
General.SetCUELine(_attributes, "PERFORMER", value, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Title {
|
public string Title {
|
||||||
@@ -2571,6 +2695,9 @@ namespace CUEToolsLib
|
|||||||
CUELine line = General.FindCUELine(_attributes, "TITLE");
|
CUELine line = General.FindCUELine(_attributes, "TITLE");
|
||||||
return (line == null) ? String.Empty : line.Params[1];
|
return (line == null) ? String.Empty : line.Params[1];
|
||||||
}
|
}
|
||||||
|
set {
|
||||||
|
General.SetCUELine(_attributes, "TITLE", value, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int WriteOffset {
|
public int WriteOffset {
|
||||||
@@ -2829,4 +2956,7 @@ namespace CUEToolsLib
|
|||||||
public StopException() : base() {
|
public StopException() : base() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HttpNotFoundException : Exception {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user