Initial commit — AllMusicGuide scraper and music metadata tagger

This commit is contained in:
2026-05-10 02:49:16 +00:00
commit 4a541ca04b
194 changed files with 46364 additions and 0 deletions
+234
View File
@@ -0,0 +1,234 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using MusicMetaTagger.Core.Utility;
using iTunesLib;
namespace MusicMetaTagger.UI
{
public class ItunesLibraryInterface : IMusicLibraryInterface, IDisposable
{
private iTunesApp _iTunesApp;
private Dictionary<TrackQueryStatus, IITTrack> _trackQueryTracks;
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Marshal.ReleaseComObject(_iTunesApp);
_iTunesApp = null;
GC.Collect();
}
#region IMusicLibraryInterface Members
/// <summary>
/// Gets the track queries.
/// </summary>
/// <param name = "libraryQuery">The library query.</param>
/// <param name = "callback">The callback.</param>
/// <returns></returns>
public List<TrackQueryStatus> GetTrackQueries(LibraryQuery libraryQuery, IProgressCallback callback)
{
if (_trackQueryTracks == null)
_trackQueryTracks = new Dictionary<TrackQueryStatus, IITTrack>();
var trackQueries = new List<TrackQueryStatus>();
callback.SetText("Opening iTunes Library");
if (_iTunesApp == null)
_iTunesApp = new iTunesApp();
callback.SetText("Getting tracks");
var tracks = _iTunesApp.LibraryPlaylist.Tracks;
var trackCount = libraryQuery.ScanLimit <= 0 ? tracks.Count : Math.Min(tracks.Count, libraryQuery.ScanLimit);
callback.SetRange(0, trackCount);
for (var i = 1; i <= trackCount; i++)
{
callback.Increment(1);
if (i%5 == 0 || i == trackCount)
callback.SetText(string.Format("Scanning iTunes track# {0} / {1}, Found {2} matches", i, trackCount,
trackQueries.Count));
if (callback.IsAborting)
break;
var track = tracks[i];
var trackQuery = new TrackQueryStatus
{
TrackTitle = track.Name,
AlbumTitle = track.Album,
ArtistName = track.Artist,
TrackNumber = track.TrackNumber,
TrackLength = StringUtility.ConvertTimeSpan(track.Time),
AlbumYear = track.Year,
AlbumPartOfCompilation = track.Compilation,
AlbumGenre = track.Genre//,
//AlbumArtistName = track.AlbumArtist
};
if (libraryQuery.AddedAfter > track.DateAdded)
continue;
if (libraryQuery.BlankGenre && !string.IsNullOrEmpty(track.Genre))
continue;
if (libraryQuery.BlankRating && track.Rating > 0)
continue;
if (libraryQuery.BlankYear && track.Year > 0)
continue;
if (!libraryQuery.MatchTrackQuery(trackQuery))
continue;
// skip pod casts
if (track.Genre == "Podcast" || track.Genre == "Voice Memo" ) // || track.VideoKind != 0 || track.Podcast)
continue;
trackQueries.Add(trackQuery);
_trackQueryTracks.Add(trackQuery, track);
}
return trackQueries;
}
/// <summary>
/// Updates the album art.
/// </summary>
/// <param name = "trackQuery">The track query.</param>
/// <param name = "albumArt">The album art file info.</param>
/// <param name = "overwrite">if set to <c>true</c> [overwrite].</param>
/// <returns>True if update was successful, false otherwise</returns>
public bool UpdateAlbumArt(TrackQueryStatus trackQuery, FileInfo albumArt, bool overwrite)
{
var iTrack = GetTrack(trackQuery);
if (albumArt == null)
return false;
if (iTrack.Artwork.Count == 0 || overwrite)
{
if (overwrite && iTrack.Artwork.Count > 0)
{
while (iTrack.Artwork.Count > 0)
iTrack.Artwork[1].Delete();
}
iTrack.AddArtworkFromFile(albumArt.FullName);
return true;
}
return false;
}
/// <summary>
/// Tries to update the genre.
/// </summary>
/// <param name = "trackQuery">The track query.</param>
/// <param name = "genre">The genre.</param>
/// <param name = "overwrite">if set to <c>true</c> [overwrite].</param>
/// <returns>True if update was successful, false otherwise</returns>
public bool UpdateGenre(TrackQueryStatus trackQuery, string genre, bool overwrite)
{
var iTrack = GetTrack(trackQuery);
if (string.IsNullOrEmpty(iTrack.Genre) || overwrite)
{
try
{
iTrack.Genre = genre;
return true;
}
catch
{
}
}
return false;
}
/// <summary>
/// Updates the year.
/// </summary>
/// <param name = "trackQuery">The track query.</param>
/// <param name = "year">The year.</param>
/// <param name = "overwrite">if set to <c>true</c> [overwrite].</param>
/// <returns>True if update was successful, false otherwise</returns>
public bool UpdateYear(TrackQueryStatus trackQuery, int year, bool overwrite)
{
var iTrack = GetTrack(trackQuery);
if (iTrack.Year == 0 || overwrite)
{
iTrack.Year = year;
return true;
}
return false;
}
/// <summary>
/// Updates the rating.
/// </summary>
/// <param name = "trackQuery">The track query.</param>
/// <param name = "rating">The rating from 0 to 100.</param>
/// <param name = "overwrite">if set to <c>true</c> overwrite existing value.</param>
/// <returns>True if update was successful, false otherwise</returns>
public bool UpdateRating(TrackQueryStatus trackQuery, int rating, bool overwrite)
{
var iTrack = GetTrack(trackQuery);
if (iTrack.Rating == 0 || overwrite)
{
iTrack.Rating = rating;
return true;
}
return false;
}
public bool AddComment(TrackQueryStatus trackQuery, string comment)
{
var iTrack = GetTrack(trackQuery);
if (iTrack.Comment == null)
{
iTrack.Comment = comment;
return true;
}
if (!iTrack.Comment.Contains(comment))
{
iTrack.Comment += comment;
return true;
}
return false;
}
/// <summary>
/// Returns true if the trackQuery represents an Mp3.
/// </summary>
/// <returns></returns>
public bool IsMp3(TrackQueryStatus trackQuery)
{
var iTrack = GetTrack(trackQuery);
return iTrack.KindAsString == "MPEG audio file";
}
/// <summary>
/// Returns the Mp3 represented by this trackQuery
/// </summary>
/// <param name = "trackQuery"></param>
/// <returns></returns>
public FileInfo GetMp3FileInfo(TrackQueryStatus trackQuery)
{
var file = (IITFileOrCDTrack) GetTrack(trackQuery);
return file.Location != null ? new FileInfo(file.Location) : null;
}
#endregion
private IITTrack GetTrack(TrackQueryStatus trackQueryStatus)
{
if (!_trackQueryTracks.ContainsKey(trackQueryStatus))
throw new ApplicationException("Doesn't contain track" + trackQueryStatus.TrackTitle);
return _trackQueryTracks[trackQueryStatus];
}
}
}