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 _trackQueryTracks; /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { Marshal.ReleaseComObject(_iTunesApp); _iTunesApp = null; GC.Collect(); } #region IMusicLibraryInterface Members /// /// Gets the track queries. /// /// The library query. /// The callback. /// public List GetTrackQueries(LibraryQuery libraryQuery, IProgressCallback callback) { if (_trackQueryTracks == null) _trackQueryTracks = new Dictionary(); var trackQueries = new List(); 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; } /// /// Updates the album art. /// /// The track query. /// The album art file info. /// if set to true [overwrite]. /// True if update was successful, false otherwise 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; } /// /// Tries to update the genre. /// /// The track query. /// The genre. /// if set to true [overwrite]. /// True if update was successful, false otherwise 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; } /// /// Updates the year. /// /// The track query. /// The year. /// if set to true [overwrite]. /// True if update was successful, false otherwise 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; } /// /// Updates the rating. /// /// The track query. /// The rating from 0 to 100. /// if set to true overwrite existing value. /// True if update was successful, false otherwise 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; } /// /// Returns true if the trackQuery represents an Mp3. /// /// public bool IsMp3(TrackQueryStatus trackQuery) { var iTrack = GetTrack(trackQuery); return iTrack.KindAsString == "MPEG audio file"; } /// /// Returns the Mp3 represented by this trackQuery /// /// /// 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]; } } }