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
+64
View File
@@ -0,0 +1,64 @@
using System;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using MusicMetaTagger.UI.Properties;
namespace MusicMetaTagger.UI
{
public partial class About : Form
{
public About()
{
InitializeComponent();
}
private void closeButton_Click(object sender, EventArgs e)
{
Close();
}
private void About_Load(object sender, EventArgs e)
{
var thisAssembly = Assembly.GetExecutingAssembly();
var assemblyName = thisAssembly.GetName();
var friendlyVersion = string.Format("{0:D}.{1:D2}.{2:D4}", assemblyName.Version.Major, assemblyName.Version.Minor,
assemblyName.Version.Build);
Array attribute = thisAssembly.GetCustomAttributes(false);
var title = "Unknown Application";
var copywrite = "Unknown Copyright";
foreach (object o in attribute)
{
if (o is AssemblyTitleAttribute)
{
title = ((AssemblyTitleAttribute) o).Title;
}
else if (o is AssemblyCopyrightAttribute)
{
copywrite = ((AssemblyCopyrightAttribute) o).Copyright;
}
}
Text = "About " + title;
var sb = new StringBuilder();
sb.Append(title);
sb.Append(" version ");
sb.Append(friendlyVersion);
sb.Append(" (");
sb.Append(assemblyName.Version.ToString());
sb.Append(")\n\n");
sb.Append(copywrite);
textLabel.Text = sb.ToString();
textBox.Text = Settings.Default.AboutText;
}
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
}
}
}
+97
View File
@@ -0,0 +1,97 @@
namespace MusicMetaTagger.UI
{
partial class About
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(About));
this.closeButton = new System.Windows.Forms.Button();
this.textBox = new System.Windows.Forms.TextBox();
this.textLabel = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// closeButton
//
this.closeButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.closeButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.closeButton.Location = new System.Drawing.Point(106, 235);
this.closeButton.Name = "closeButton";
this.closeButton.Size = new System.Drawing.Size(75, 23);
this.closeButton.TabIndex = 0;
this.closeButton.Text = "Close";
this.closeButton.UseVisualStyleBackColor = true;
this.closeButton.Click += new System.EventHandler(this.closeButton_Click);
//
// textBox
//
this.textBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBox.Location = new System.Drawing.Point(13, 53);
this.textBox.Multiline = true;
this.textBox.Name = "textBox";
this.textBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.textBox.Size = new System.Drawing.Size(267, 176);
this.textBox.TabIndex = 1;
this.textBox.WordWrap = false;
this.textBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox_KeyDown);
//
// textLabel
//
this.textLabel.AutoSize = true;
this.textLabel.Location = new System.Drawing.Point(13, 13);
this.textLabel.Name = "textLabel";
this.textLabel.Size = new System.Drawing.Size(0, 13);
this.textLabel.TabIndex = 2;
//
// About
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.closeButton;
this.ClientSize = new System.Drawing.Size(292, 270);
this.Controls.Add(this.textLabel);
this.Controls.Add(this.textBox);
this.Controls.Add(this.closeButton);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "About";
this.Text = "About";
this.Load += new System.EventHandler(this.About_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button closeButton;
private System.Windows.Forms.TextBox textBox;
private System.Windows.Forms.Label textLabel;
}
}
+1787
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
@@ -0,0 +1,11 @@
May 21st, 2006
Qs Eclipse WMP 11. Size: 256px .png and 16px-128px XP icon. I've always wanted to make a WMP icon. It's not the greatest, but it kind of matches the new WMP11 Eclipse skin. I recommend Avedesk to display this icon. Just do a google search for Avedesk to find the latest download.
Tools: PhotoShopCS.
My deviantART Gallery: http://webtrance.deviantart.com/gallery/
Webtrance (aka Qx9) Webtrance@cox.net
Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

+67
View File
@@ -0,0 +1,67 @@
using System.Collections.Generic;
using System.IO;
namespace MusicMetaTagger.UI
{
public interface IMusicLibraryInterface
{
/// <summary>
/// Gets the track information from a library query.
/// </summary>
/// <param name = "libraryQuery">The library query.</param>
/// <param name = "callback">The callback.</param>
/// <returns></returns>
List<TrackQueryStatus> GetTrackQueries(LibraryQuery libraryQuery, IProgressCallback callback);
/// <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>
bool UpdateAlbumArt(TrackQueryStatus trackQuery, FileInfo albumArt, bool overwrite);
/// <summary>
/// Updates 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>
bool UpdateGenre(TrackQueryStatus trackQuery, string genre, bool overwrite);
/// <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>
bool UpdateYear(TrackQueryStatus trackQuery, int year, bool overwrite);
/// <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>
bool UpdateRating(TrackQueryStatus trackQuery, int rating, bool overwrite);
bool AddComment(TrackQueryStatus trackQuery, string comment);
/// <summary>
/// Returns true if the trackQuery represents an Mp3.
/// </summary>
/// <returns></returns>
bool IsMp3(TrackQueryStatus trackQuery);
/// <summary>
/// Returns the Mp3 represented by this trackQuery
/// </summary>
/// <param name = "trackQuery"></param>
/// <returns></returns>
FileInfo GetMp3FileInfo(TrackQueryStatus trackQuery);
}
}
+35
View File
@@ -0,0 +1,35 @@
using System;
namespace MusicMetaTagger.UI
{
/// <summary>
/// This defines an interface which can be implemented by UI elements which indicate the progress of a long operation. (See ProgressWindow for a typical implementation)
/// </summary>
public interface IProgressCallback
{
/// <summary>
/// If this property is true, then you should abort work
/// </summary>
bool IsAborting { get; }
/// <summary>
/// Call this method from the worker thread to initialize the progress callback, without setting the range
/// </summary>
void Begin();
/// <summary>
/// Call this method from the worker thread to reset the range in the progress callback
/// </summary>
void SetRange(int minimum, int maximum);
/// <summary>
/// Call this method from the worker thread to update the progress text.
/// </summary>
void SetText(String text);
/// <summary>
/// Call this method from the worker thread to step the progress meter to a particular value.
/// </summary>
void Increment(int val);
}
}
+455
View File
@@ -0,0 +1,455 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
using Autofac;
using BitFactory.Logging;
using MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess;
using MusicMetaTagger.Client.AllMusicGuide.Services;
using MusicMetaTagger.Core.Model;
using MusicMetaTagger.Core.Services;
using IContainer = Autofac.IContainer;
namespace MusicMetaTagger.UI
{
public partial class Interface : Form, IProgressCallback
{
#region Private members
private const string LogFilename = "tagger.log";
private readonly Logger _logger;
private readonly BindingList<TrackQueryStatus> _trackQueryStatuses;
private CancellationTokenSource _cancellationTokenSource;
private bool _exitClicked;
private IMusicGuide _musicGuide;
private ITrackSearcher _trackSearcher;
private IMusicLibraryInterface _musicLibraryInterface;
private ITrackRater _trackRater;
private Options _options;
private readonly IContainer _container;
private ITrackOriginalRelease _trackOriginalRelease;
#endregion
#region Form Event Handlers
/// <summary>
/// Initializes a new instance of the <see cref = "Interface" /> class.
/// </summary>
public Interface()
{
InitializeComponent();
_trackQueryStatuses = new BindingList<TrackQueryStatus>();
logDataGridView.DataSource = _trackQueryStatuses;
_logger = new FileLogger(LogFilename);
_cancellationTokenSource = new CancellationTokenSource();
var builder = new ContainerBuilder();
builder
.RegisterAssemblyTypes(typeof(MusicGuideScraper).Assembly)
.AsImplementedInterfaces()
.Except<MusicGuideScraper>()
.Except<MusicGuideCache>();
builder.RegisterType<TrackSearcher>().As<ITrackSearcher>();
builder.RegisterType<MusicGuideScraper>().Named<IMusicGuide>("MusicGuideScraper");
builder.RegisterDecorator<IMusicGuide>((c, inner) => new MusicGuideCache(inner), fromKey: "MusicGuideScraper");
_container = builder.Build();
}
/// <summary>
/// Handles the Load event of the Interface control.
/// </summary>
/// <param name = "sender">The source of the event.</param>
/// <param name = "e">The <see cref = "System.EventArgs" /> instance containing the event data.</param>
private void Interface_Load(object sender, EventArgs e)
{
_options = new Options();
components.Add(_options);
optionsLabel.Text = _options.LibraryQuery.ToString();
var t = new Thread(OpenOrCreateAllMusicGuide);
t.Start();
}
/// <summary>
/// Handles the Click event of the startButton control.
/// </summary>
/// <param name = "sender">The source of the event.</param>
/// <param name = "e">The <see cref = "System.EventArgs" /> instance containing the event data.</param>
private void startButton_Click(object sender, EventArgs e)
{
librarySelector.Enabled = false;
startButton.Enabled = false;
optionsButton.Enabled = false;
_musicLibraryInterface = librarySelector.SelectedLibrary;
var t = new Thread(LibraryProcess);
t.Start();
}
/// <summary>
/// Handles the Click event of the cancelButton control.
/// </summary>
/// <param name = "sender">The source of the event.</param>
/// <param name = "e">The <see cref = "System.EventArgs" /> instance containing the event data.</param>
private void cancelButton_Click(object sender, EventArgs e)
{
UiInvoke(() => { toolStripStatusLabel.Text = "Cancelling..."; });
cancelButton.Enabled = false;
_cancellationTokenSource.Cancel();
}
/// <summary>
/// Handles the FormClosing event of the Interface control.
/// </summary>
/// <param name = "sender">The source of the event.</param>
/// <param name = "e">The <see cref = "System.Windows.Forms.FormClosingEventArgs" /> instance containing the event data.</param>
private void Interface_FormClosing(object sender, FormClosingEventArgs e)
{
if (!exitButton.Enabled)
{
_exitClicked = true;
_cancellationTokenSource.Cancel();
e.Cancel = true;
}
}
/// <summary>
/// Handles the Click event of the exitButton control.
/// </summary>
/// <param name = "sender">The source of the event.</param>
/// <param name = "e">The <see cref = "System.EventArgs" /> instance containing the event data.</param>
private void exitButton_Click(object sender, EventArgs e)
{
Close();
}
private void optionsButton_Click(object sender, EventArgs e)
{
_options.ShowDialog();
optionsLabel.Text = _options.LibraryQuery.ToString();
}
#endregion
#region Music Guide threaded methods
private void OpenOrCreateAllMusicGuide()
{
UiInvoke(() => { startButton.Enabled = false; });
UiInvoke(() => { exitButton.Enabled = false; });
UiInvoke(() => { toolStripStatusLabel.Text = "Loading DataLayer..."; });
UiInvoke(() => { toolStripStatusLabel.Text = "Loading Complete."; });
UiInvoke(() => { startButton.Enabled = true; });
UiInvoke(() => { exitButton.Enabled = true; });
_musicGuide = _container.Resolve<IMusicGuide>();
_trackSearcher = _container.Resolve<ITrackSearcher>();
_trackRater = _container.Resolve<ITrackRater>();
_trackOriginalRelease = _container.Resolve<ITrackOriginalRelease>();
if (_exitClicked)
{
UiInvoke(() => { toolStripStatusLabel.Text = "Exiting..."; });
UiInvoke(() => exitButton_Click(this, new EventArgs()));
}
}
#endregion
#region Utility Methods
private void LogStatusUpdate(StatusEventArgs data)
{
_logger.LogInfo(data.Status);
}
private static string ConcatToString(string original, string additional)
{
return !string.IsNullOrEmpty(original) ? string.Join(", ", additional, original) : additional;
}
#endregion
#region Library Process methods
private Track SearchTrack(TrackQueryStatus trackQuery)
{
_trackSearcher.SearchStatusUpdate += trackQuery.UpdateStatus;
_trackSearcher.SearchStatusUpdate += LogStatusUpdate;
var result = _trackSearcher.SearchTrack(trackQuery, _cancellationTokenSource.Token);
_trackSearcher.SearchStatusUpdate -= trackQuery.UpdateStatus;
_trackSearcher.SearchStatusUpdate -= LogStatusUpdate;
return result;
}
/// <summary>
/// Updates the track information to the library.
/// </summary>
/// <param name = "trackQuery">The track query.</param>
/// <param name = "track">The track info.</param>
private void UpdateTrack(TrackQueryStatus trackQuery, Track track)
{
var updateText = "";
var albumInfo = string.IsNullOrEmpty(track.AlbumId)
? null
: _musicGuide.GetAlbum(track.AlbumId);
var artistInfo = string.IsNullOrEmpty(track.PerformerIds[0])
? null
: _musicGuide.GetArtist(track.PerformerIds[0]);
// If Track is not null, update ActualTrack from Track
if (albumInfo != null)
{
// set album artwork
if (!string.IsNullOrEmpty(albumInfo.CoverUrl))
{
try
{
// TODO: Cover Art Reimplementation
//var fileInfo = albumInfo.DownloadCoverArt();
//if (fileInfo != null)
//{
// if (_musicLibraryInterface.UpdateAlbumArt(trackQuery, fileInfo, _options.LibraryUpdate.AlbumArtOverwrite))
// {
// updateText = ConcatToString(updateText, "Added artwork");
// trackQuery.SetText(updateText);
// }
// if (mp3FileInfo != null)
// _mp3Interface.UpdateAlbumArt(mp3FileInfo, fileInfo, _options.LibraryUpdate.AlbumArtOverwrite);
//}
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
updateText = ConcatToString(updateText, "Artwork error: " + ex.Message);
trackQuery.Status = updateText;
}
}
if (artistInfo != null)
{
if (_options.LibraryUpdate.GenreUpdate)
{
// set genre
string genre;
if (artistInfo.Genre == "Rock" && albumInfo.Styles != null && albumInfo.Styles.Count > 0)
genre = albumInfo.Styles[0];
else
genre = artistInfo.Genre;
if (_musicLibraryInterface.UpdateGenre(trackQuery, genre, _options.LibraryUpdate.GenreOverwrite))
{
updateText = ConcatToString(updateText, "Genre: " + genre);
trackQuery.Status = updateText;
}
}
}
// set year
if (_options.LibraryUpdate.YearUpdate && !string.IsNullOrEmpty(albumInfo.ReleaseDate))
{
var year = albumInfo.GetReleaseYear();
if (_musicLibraryInterface.UpdateYear(trackQuery, year, _options.LibraryUpdate.YearOverwrite))
{
updateText = ConcatToString(updateText, "Year: " + year);
trackQuery.Status = updateText;
}
}
}
if (_options.LibraryUpdate.RatingUpdate)
{
// update rating
var rating = _trackRater.RateTrack(track);
if (!rating.HasValue)
{
updateText = ConcatToString(updateText, "Track has no rating");
trackQuery.Status = updateText;
}
else
{
if (track.Pick)
_musicLibraryInterface.AddComment(trackQuery, "-AMG Pick-");
var ratingInt = Convert.ToInt32(rating.Value*10);
if (_musicLibraryInterface.UpdateRating(trackQuery, ratingInt, _options.LibraryUpdate.RatingOverwrite))
{
updateText = ConcatToString(updateText, "Rating: " + ratingInt + " / 100");
trackQuery.Status = updateText;
}
}
}
}
private void UiInvoke(Action action)
{
BeginInvoke(new MethodInvoker(action));
}
private void LibraryProcess()
{
UiInvoke(
() =>
{
cancelButton.Enabled = true;
cancelButton.Visible = true;
exitButton.Enabled = false;
});
Begin();
// Use LibraryQuery to build a list of trackQueries
List<TrackQueryStatus> trackQueries;
try
{
trackQueries = _musicLibraryInterface.GetTrackQueries(_options.LibraryQuery, this);
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
trackQueries = new List<TrackQueryStatus>();
UiInvoke(() => MessageBox.Show(ex.Message));
}
End();
SetRange(0, trackQueries.Count);
StepTo(0);
// Search for TrackQuery
var i = 1;
foreach (var trackQuery in trackQueries)
{
Increment(1);
SetText(string.Format("{0} / {1}", i++, trackQueries.Count));
if (_cancellationTokenSource.IsCancellationRequested)
break;
try
{
// add the row to the dataview
var trackQueryStatus = trackQuery;
UiInvoke(() => _trackQueryStatuses.Add(trackQueryStatus));
// scroll the row if it's at the bottom
UiInvoke(
() =>
{
if (logDataGridView.RowCount > 2
&& logDataGridView.Rows[logDataGridView.RowCount - 2].Displayed)
{
logDataGridView.FirstDisplayedScrollingRowIndex = logDataGridView.RowCount - 1;
}
});
// run the track query
var track = SearchTrack(trackQuery);
if (_cancellationTokenSource.IsCancellationRequested)
break;
// no results, continue on to the next track
if (track == null)
{
trackQuery.Status = "Track not found";
continue;
}
// check that this is not a compilation track
if (_options.LibraryUpdate.FindCompilationTrackOrigins)
{
track = _trackOriginalRelease.
GetTrackOriginalRelease(track) ?? track;
}
UpdateTrack(trackQuery, track);
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
trackQuery.Status = ex.Message;
}
}
if (_cancellationTokenSource.IsCancellationRequested)
{
SetText("Cancel complete.");
_cancellationTokenSource = new CancellationTokenSource();
}
UiInvoke(
() =>
{
exitButton.Enabled = true;
cancelButton.Enabled = false;
cancelButton.Visible = false;
startButton.Enabled = true;
librarySelector.Enabled = true;
optionsButton.Enabled = true;
});
if (_exitClicked)
{
SetText("Exiting...");
UiInvoke(() => exitButton_Click(this, new EventArgs()));
}
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
var a = new About();
a.ShowDialog(this);
}
#endregion
#region IProgressCallback
public void Begin()
{
UiInvoke(() => toolStripProgressBar.Value = toolStripProgressBar.Minimum);
}
public void SetRange(int minimum, int maximum)
{
UiInvoke(() => toolStripProgressBar.Minimum = minimum);
UiInvoke(() => toolStripProgressBar.Maximum = maximum);
}
public void SetText(string text)
{
UiInvoke(() => toolStripStatusLabel.Text = text);
}
public void StepTo(int val)
{
UiInvoke(() => toolStripProgressBar.Value = val);
}
public void Increment(int val)
{
UiInvoke(() => toolStripProgressBar.Value += val);
}
public bool IsAborting
{
get { return _cancellationTokenSource.IsCancellationRequested; }
}
public void End()
{
StepTo(toolStripProgressBar.Maximum);
}
#endregion
}
}
+322
View File
@@ -0,0 +1,322 @@
namespace MusicMetaTagger.UI
{
partial class Interface
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Interface));
this.startButton = new System.Windows.Forms.Button();
this.exitButton = new System.Windows.Forms.Button();
this.cancelButton = new System.Windows.Forms.Button();
this.logDataGridView = new System.Windows.Forms.DataGridView();
this.trackTitleDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.ArtistName = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.albumTitleDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Status = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.trackQueryStatusBindingSource = new System.Windows.Forms.BindingSource(this.components);
this.statusStrip = new System.Windows.Forms.StatusStrip();
this.toolStripProgressBar = new System.Windows.Forms.ToolStripProgressBar();
this.toolStripStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.optionsButton = new System.Windows.Forms.Button();
this.optionsLabel = new System.Windows.Forms.Label();
this.imageList = new System.Windows.Forms.ImageList(this.components);
this.menuStrip = new System.Windows.Forms.MenuStrip();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.librarySelector = new MusicMetaTagger.UI.LibrarySelector();
((System.ComponentModel.ISupportInitialize)(this.logDataGridView)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trackQueryStatusBindingSource)).BeginInit();
this.statusStrip.SuspendLayout();
this.menuStrip.SuspendLayout();
this.SuspendLayout();
//
// startButton
//
this.startButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.startButton.Location = new System.Drawing.Point(551, 260);
this.startButton.Name = "startButton";
this.startButton.Size = new System.Drawing.Size(58, 23);
this.startButton.TabIndex = 0;
this.startButton.Text = "Start";
this.startButton.UseVisualStyleBackColor = true;
this.startButton.Click += new System.EventHandler(this.startButton_Click);
//
// exitButton
//
this.exitButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.exitButton.Location = new System.Drawing.Point(615, 260);
this.exitButton.Name = "exitButton";
this.exitButton.Size = new System.Drawing.Size(57, 23);
this.exitButton.TabIndex = 1;
this.exitButton.Text = "Exit";
this.exitButton.UseVisualStyleBackColor = true;
this.exitButton.Click += new System.EventHandler(this.exitButton_Click);
//
// cancelButton
//
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cancelButton.Enabled = false;
this.cancelButton.Location = new System.Drawing.Point(615, 260);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(57, 23);
this.cancelButton.TabIndex = 3;
this.cancelButton.Text = "Cancel";
this.cancelButton.UseVisualStyleBackColor = true;
this.cancelButton.Visible = false;
this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
//
// logDataGridView
//
this.logDataGridView.AllowUserToAddRows = false;
this.logDataGridView.AllowUserToDeleteRows = false;
this.logDataGridView.AllowUserToResizeRows = false;
this.logDataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.logDataGridView.AutoGenerateColumns = false;
this.logDataGridView.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.logDataGridView.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.None;
dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control;
dataGridViewCellStyle1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.logDataGridView.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
this.logDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.logDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.trackTitleDataGridViewTextBoxColumn,
this.ArtistName,
this.albumTitleDataGridViewTextBoxColumn,
this.Status});
this.logDataGridView.DataSource = this.trackQueryStatusBindingSource;
dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Window;
dataGridViewCellStyle2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.ControlText;
dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this.logDataGridView.DefaultCellStyle = dataGridViewCellStyle2;
this.logDataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
this.logDataGridView.EnableHeadersVisualStyles = false;
this.logDataGridView.Location = new System.Drawing.Point(13, 27);
this.logDataGridView.Name = "logDataGridView";
this.logDataGridView.ReadOnly = true;
this.logDataGridView.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single;
dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle3.BackColor = System.Drawing.SystemColors.Control;
dataGridViewCellStyle3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle3.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle3.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle3.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.logDataGridView.RowHeadersDefaultCellStyle = dataGridViewCellStyle3;
this.logDataGridView.RowHeadersVisible = false;
this.logDataGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.logDataGridView.Size = new System.Drawing.Size(659, 221);
this.logDataGridView.TabIndex = 6;
//
// trackTitleDataGridViewTextBoxColumn
//
this.trackTitleDataGridViewTextBoxColumn.DataPropertyName = "TrackTitle";
this.trackTitleDataGridViewTextBoxColumn.HeaderText = "Track";
this.trackTitleDataGridViewTextBoxColumn.MinimumWidth = 100;
this.trackTitleDataGridViewTextBoxColumn.Name = "trackTitleDataGridViewTextBoxColumn";
this.trackTitleDataGridViewTextBoxColumn.ReadOnly = true;
this.trackTitleDataGridViewTextBoxColumn.Width = 120;
//
// ArtistName
//
this.ArtistName.DataPropertyName = "ArtistName";
this.ArtistName.HeaderText = "Artist";
this.ArtistName.MinimumWidth = 100;
this.ArtistName.Name = "ArtistName";
this.ArtistName.ReadOnly = true;
this.ArtistName.Width = 120;
//
// albumTitleDataGridViewTextBoxColumn
//
this.albumTitleDataGridViewTextBoxColumn.DataPropertyName = "AlbumTitle";
this.albumTitleDataGridViewTextBoxColumn.HeaderText = "Album";
this.albumTitleDataGridViewTextBoxColumn.MinimumWidth = 100;
this.albumTitleDataGridViewTextBoxColumn.Name = "albumTitleDataGridViewTextBoxColumn";
this.albumTitleDataGridViewTextBoxColumn.ReadOnly = true;
//
// Status
//
this.Status.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
this.Status.DataPropertyName = "Status";
this.Status.HeaderText = "Status";
this.Status.MinimumWidth = 136;
this.Status.Name = "Status";
this.Status.ReadOnly = true;
this.Status.ToolTipText = "Status";
//
// trackQueryStatusBindingSource
//
this.trackQueryStatusBindingSource.DataSource = typeof(MusicMetaTagger.UI.TrackQueryStatus);
//
// statusStrip
//
this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripProgressBar,
this.toolStripStatusLabel});
this.statusStrip.Location = new System.Drawing.Point(0, 296);
this.statusStrip.Name = "statusStrip";
this.statusStrip.Size = new System.Drawing.Size(684, 22);
this.statusStrip.TabIndex = 7;
this.statusStrip.Text = "statusStrip";
//
// toolStripProgressBar
//
this.toolStripProgressBar.Name = "toolStripProgressBar";
this.toolStripProgressBar.Size = new System.Drawing.Size(350, 16);
this.toolStripProgressBar.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
//
// toolStripStatusLabel
//
this.toolStripStatusLabel.Name = "toolStripStatusLabel";
this.toolStripStatusLabel.Size = new System.Drawing.Size(39, 17);
this.toolStripStatusLabel.Text = "Status";
//
// optionsButton
//
this.optionsButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.optionsButton.Location = new System.Drawing.Point(216, 260);
this.optionsButton.Name = "optionsButton";
this.optionsButton.Size = new System.Drawing.Size(75, 23);
this.optionsButton.TabIndex = 8;
this.optionsButton.Text = "Options";
this.optionsButton.UseVisualStyleBackColor = true;
this.optionsButton.Click += new System.EventHandler(this.optionsButton_Click);
//
// optionsLabel
//
this.optionsLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.optionsLabel.Location = new System.Drawing.Point(297, 265);
this.optionsLabel.Name = "optionsLabel";
this.optionsLabel.Size = new System.Drawing.Size(248, 18);
this.optionsLabel.TabIndex = 9;
this.optionsLabel.Text = "Current Options";
//
// imageList
//
this.imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList.ImageStream")));
this.imageList.TransparentColor = System.Drawing.Color.Transparent;
this.imageList.Images.SetKeyName(0, "iTunes.ico");
this.imageList.Images.SetKeyName(1, "wmplayer.ico");
//
// menuStrip
//
this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.aboutToolStripMenuItem});
this.menuStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow;
this.menuStrip.Location = new System.Drawing.Point(0, 0);
this.menuStrip.Name = "menuStrip";
this.menuStrip.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
this.menuStrip.Size = new System.Drawing.Size(684, 24);
this.menuStrip.TabIndex = 11;
//
// aboutToolStripMenuItem
//
this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
this.aboutToolStripMenuItem.Size = new System.Drawing.Size(52, 20);
this.aboutToolStripMenuItem.Text = "About";
this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
//
// librarySelector
//
this.librarySelector.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.librarySelector.Location = new System.Drawing.Point(13, 254);
this.librarySelector.MinimumSize = new System.Drawing.Size(120, 38);
this.librarySelector.Name = "librarySelector";
this.librarySelector.Size = new System.Drawing.Size(197, 38);
this.librarySelector.TabIndex = 10;
//
// Interface
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(684, 318);
this.Controls.Add(this.librarySelector);
this.Controls.Add(this.optionsLabel);
this.Controls.Add(this.statusStrip);
this.Controls.Add(this.menuStrip);
this.Controls.Add(this.logDataGridView);
this.Controls.Add(this.optionsButton);
this.Controls.Add(this.cancelButton);
this.Controls.Add(this.exitButton);
this.Controls.Add(this.startButton);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MainMenuStrip = this.menuStrip;
this.MinimumSize = new System.Drawing.Size(670, 300);
this.Name = "Interface";
this.Text = "Meta Music Tagger";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Interface_FormClosing);
this.Load += new System.EventHandler(this.Interface_Load);
((System.ComponentModel.ISupportInitialize)(this.logDataGridView)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trackQueryStatusBindingSource)).EndInit();
this.statusStrip.ResumeLayout(false);
this.statusStrip.PerformLayout();
this.menuStrip.ResumeLayout(false);
this.menuStrip.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button startButton;
private System.Windows.Forms.Button exitButton;
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.DataGridView logDataGridView;
private System.Windows.Forms.BindingSource trackQueryStatusBindingSource;
private System.Windows.Forms.StatusStrip statusStrip;
private System.Windows.Forms.ToolStripProgressBar toolStripProgressBar;
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel;
private System.Windows.Forms.Button optionsButton;
private System.Windows.Forms.Label optionsLabel;
private System.Windows.Forms.ImageList imageList;
private LibrarySelector librarySelector;
private System.Windows.Forms.MenuStrip menuStrip;
private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
private System.Windows.Forms.DataGridViewTextBoxColumn TrackTitle;
private System.Windows.Forms.DataGridViewTextBoxColumn ArtistName;
private System.Windows.Forms.DataGridViewTextBoxColumn AlbumTitle;
private System.Windows.Forms.DataGridViewTextBoxColumn Status;
private System.Windows.Forms.DataGridViewTextBoxColumn trackTitleDataGridViewTextBoxColumn;
private System.Windows.Forms.DataGridViewTextBoxColumn albumTitleDataGridViewTextBoxColumn;
}
}
+2025
View File
File diff suppressed because it is too large Load Diff
+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];
}
}
}
+101
View File
@@ -0,0 +1,101 @@
using System;
using System.ComponentModel;
using System.Xml.Serialization;
using MusicMetaTagger.Core.Queries;
using MusicMetaTagger.Core.Utility;
namespace MusicMetaTagger.UI
{
public class LibraryQuery
{
[Category("Name Searches")]
[Browsable(true)]
[Description("Search by Artist Name")]
[XmlAttribute]
public string ArtistName { get; set; }
[Category("Name Searches")]
[Browsable(true)]
[Description("Search by Album Title")]
[XmlAttribute]
public string AlbumTitle { get; set; }
[Category("Name Searches")]
[Browsable(true)]
[Description("Search by Track Title")]
[XmlAttribute]
public string TrackTitle { get; set; }
[Category("Date")]
[Browsable(true)]
[Description("Search by the Most Recently Added Entries")]
[XmlAttribute]
public DateTime AddedAfter { get; set; }
[Category("Blank Fields")]
[Browsable(true)]
[Description("Search by those with Blank Rating field")]
[DefaultValue(false)]
[XmlAttribute]
public bool BlankRating { get; set; }
[Category("Blank Fields")]
[Browsable(true)]
[Description("Search by those with Blank Genre field")]
[DefaultValue(false)]
[XmlAttribute]
public bool BlankGenre { get; set; }
[Category("Blank Fields")]
[Browsable(true)]
[Description("Search by those with Blank Year field")]
[DefaultValue(false)]
[XmlAttribute]
public bool BlankYear { get; set; }
[Category("General")]
[Browsable(true)]
[Description("Limit the number of tracks scanned in the library - use this for a trial run")]
[DefaultValue(0)]
[XmlAttribute]
public int ScanLimit { get; set; }
/// <summary>
/// Returns true if the given track query matches this library query
/// </summary>
public bool MatchTrackQuery(TrackQuery trackQuery)
{
Func<string, string, bool> isMatch =
(s1, s2) => string.IsNullOrEmpty(s1)
|| string.IsNullOrEmpty(s2)
|| StringUtility.Similarity(s1, s2) > .5
|| StringUtility.ContainsString(s1, s2);
return isMatch(trackQuery.ArtistName, ArtistName)
&& isMatch(trackQuery.AlbumTitle, AlbumTitle)
&& isMatch(trackQuery.TrackTitle, TrackTitle);
}
public override string ToString()
{
var description = "";
if (!string.IsNullOrEmpty(ArtistName))
description = StringUtility.ConcatToString(description, "Artist:[" + ArtistName + "]");
if (!string.IsNullOrEmpty(AlbumTitle))
description = StringUtility.ConcatToString(description, "Album:[" + AlbumTitle + "]");
if (!string.IsNullOrEmpty(TrackTitle))
description = StringUtility.ConcatToString(description, "Track:[" + TrackTitle + "]");
if (AddedAfter != DateTime.MinValue)
description = StringUtility.ConcatToString(description, "Added After:" + AddedAfter.ToShortDateString());
if (BlankRating)
description = StringUtility.ConcatToString(description, "Blank Rating");
if (BlankGenre)
description = StringUtility.ConcatToString(description, "Blank Genre");
if (BlankYear)
description = StringUtility.ConcatToString(description, "Blank Year");
if (ScanLimit > 0)
description = StringUtility.ConcatToString(description, "Scan Limit:" + ScanLimit);
return description;
}
}
}
+99
View File
@@ -0,0 +1,99 @@
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
namespace MusicMetaTagger.UI
{
/// <summary>
/// GUI object for selecting an IMusicLibraryinterface
/// </summary>
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof (IDesigner))]
public partial class LibrarySelector : UserControl
{
public event PropertyChangedEventHandler LibraryNameChanged;
/// <summary>
/// Text assocatied with the imageList array objects
/// </summary>
private static readonly string[] LibraryNames = new[] {"iTunes", "Windows Media Player"};
/// <summary>
/// Gets the currently selected library.
/// </summary>
/// <value>The selected library.</value>
public IMusicLibraryInterface SelectedLibrary { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref = "LibrarySelector" /> class.
/// </summary>
public LibrarySelector()
{
InitializeComponent();
}
/// <summary>
/// Handles the SelectionChangeCommitted event of the libraryTypeComboBox control.
/// </summary>
/// <param name = "sender">The source of the event.</param>
/// <param name = "e">The <see cref = "System.EventArgs" /> instance containing the event data.</param>
private void libraryTypeComboBox_SelectionChangeCommitted(object sender, EventArgs e)
{
if (libraryTypeComboBox.SelectedIndex == 0)
{
SelectedLibrary = new ItunesLibraryInterface();
pictureBox.Image = imageList.Images[0];
}
else if (libraryTypeComboBox.SelectedIndex == 1)
{
SelectedLibrary = new MediaPlayerLibraryInterface();
pictureBox.Image = imageList.Images[1];
}
if (LibraryNameChanged != null)
LibraryNameChanged.Invoke(this, new PropertyChangedEventArgs("SelectedLibrary"));
}
/// <summary>
/// Handles the Click event of the LibrarySelector control.
/// </summary>
/// <param name = "sender">The source of the event.</param>
/// <param name = "e">The <see cref = "System.EventArgs" /> instance containing the event data.</param>
private void LibrarySelector_Click(object sender, EventArgs e)
{
libraryTypeComboBox.DroppedDown = !libraryTypeComboBox.DroppedDown;
}
/// <summary>
/// Handles the Click event of the pictureBox control.
/// </summary>
/// <param name = "sender">The source of the event.</param>
/// <param name = "e">The <see cref = "System.EventArgs" /> instance containing the event data.</param>
private void pictureBox_Click(object sender, EventArgs e)
{
libraryTypeComboBox.DroppedDown = !libraryTypeComboBox.DroppedDown;
}
/// <summary>
/// Handles the Load event of the LibrarySelector control.
/// </summary>
/// <param name = "sender">The source of the event.</param>
/// <param name = "e">The <see cref = "System.EventArgs" /> instance containing the event data.</param>
private void LibrarySelector_Load(object sender, EventArgs e)
{
libraryTypeComboBox.Items.AddRange(LibraryNames);
libraryTypeComboBox.SelectedIndex = 0;
libraryTypeComboBox_SelectionChangeCommitted(this, e);
}
/// <summary>
/// Handles the KeyDown event of the libraryTypeComboBox control.
/// </summary>
/// <param name = "sender">The source of the event.</param>
/// <param name = "e">The <see cref = "System.Windows.Forms.KeyEventArgs" /> instance containing the event data.</param>
private void libraryTypeComboBox_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
}
}
}
+88
View File
@@ -0,0 +1,88 @@
namespace MusicMetaTagger.UI
{
partial class LibrarySelector
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LibrarySelector));
this.pictureBox = new System.Windows.Forms.PictureBox();
this.imageList = new System.Windows.Forms.ImageList(this.components);
this.libraryTypeComboBox = new System.Windows.Forms.ComboBox();
((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit();
this.SuspendLayout();
//
// pictureBox
//
this.pictureBox.Location = new System.Drawing.Point(3, 3);
this.pictureBox.Name = "pictureBox";
this.pictureBox.Size = new System.Drawing.Size(32, 32);
this.pictureBox.TabIndex = 11;
this.pictureBox.TabStop = false;
this.pictureBox.Click += new System.EventHandler(this.pictureBox_Click);
//
// imageList
//
this.imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList.ImageStream")));
this.imageList.TransparentColor = System.Drawing.Color.Transparent;
this.imageList.Images.SetKeyName(0, "iTunes.ico");
this.imageList.Images.SetKeyName(1, "Qs Eclipse WMP11.ico");
//
// libraryTypeComboBox
//
this.libraryTypeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.libraryTypeComboBox.Location = new System.Drawing.Point(42, 8);
this.libraryTypeComboBox.Name = "libraryTypeComboBox";
this.libraryTypeComboBox.Size = new System.Drawing.Size(67, 21);
this.libraryTypeComboBox.TabIndex = 12;
this.libraryTypeComboBox.SelectionChangeCommitted += new System.EventHandler(this.libraryTypeComboBox_SelectionChangeCommitted);
this.libraryTypeComboBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.libraryTypeComboBox_KeyDown);
//
// LibrarySelector
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.libraryTypeComboBox);
this.Controls.Add(this.pictureBox);
this.MinimumSize = new System.Drawing.Size(120, 38);
this.Name = "LibrarySelector";
this.Size = new System.Drawing.Size(122, 40);
this.Load += new System.EventHandler(this.LibrarySelector_Load);
this.Click += new System.EventHandler(this.LibrarySelector_Click);
((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.PictureBox pictureBox;
private System.Windows.Forms.ImageList imageList;
private System.Windows.Forms.ComboBox libraryTypeComboBox;
}
}
+339
View File
@@ -0,0 +1,339 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="imageList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="imageList.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADI
MAAAAk1TRnQBSQFMAgEBAgEAAQQBAAEEAQABIAEAASABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAGA
AwABIAMAAQEBAAEgBgABQCYAAQIDAQECAwEBAwIBAQIBBAIBAQQBBwIBAQcBCQIBAQoBDAIBAg4CAQER
ARACAQETARICAQIWAgEBHAEbAgEBJAEdAgEBJwEcAgEBJgEZAgEBIAEUAgEBGgESAgEBFgEPAgEBEgEK
AgEBDAEHAgEBBwEDAgEBAwECAwEBAgMBQAABCAIBAQkBJAIBATIBNAIBAVIBOwIBAWUBOwIBAWMBMgIB
AU4BHwIBASsBBQIBAQX/ADUAAQIDAQECAwEBAwIBAQIBAwIBAQMBBQIBAQUBCQIBAQoBDgIBAREBFAIB
ARoBGwIBASQBIAIBASwBJgIBATcBMwIBAU8BQgIBAXIBTQICAZIBWAICAbABXwIDAcMBYAIDAcgBXQID
AcIBVwICAa8BTQICAZABQAIBAWwBLwIBAUgBIQIBAS0BGQIBASABEAIBARQBCQIBAQoBBAIBAQQBAgMB
AQIDASwAAQsCAQENATsCAQFlAU0BDAEKAbwBUwEyASgB9gFqAUgBOwH/AXUBTAE8Af8BdQFKAToB/wF1
AUoBOgH/AXQBTAE9Af8BZgFGAToB/wFUASsBJgHxAU4CCAGuATUCAQFUAQUCAQEF/wAlAAEDAgEBAgED
AgEBAgEEAgEBBAEHAgEBBwEMAgEBDgEUAgEBGQEeAgEBKAEmAgEBNwEtAgEBQwE2AgEBVgFJAgIBgwFa
AgIBvAFsAREBDwHoAcsBxAG9Af8B2AHPAcUB/wHbAdEBxQH/AdoBzwHCAf8B2AHOAcEB/wHZAckBxQH/
AdkBwQHDAf8B1AK6Af8BmwFfAV4B+QFmAgUB2wFTAgIBogE5AgEBXAEkAgEBMwEaAgEBIwEPAgEBEgEH
AgEBBwEDAgECAgMBIAABBwIBAQgBQgICAXcBTgEkAR4B7AFqAUIBMwH/AXEBOAEhAf8BegExARMB/wFx
ASoBDQH/AWQBJQELAf8BXQEiAQsB/wFdASIBCwH/AWQBJQELAf8BcQErAQ0B/wF4ATIBFQH/AW8BOQEk
Af8BaQFCATMB/wFMARsBFgHfATkCAQFfAQMCAQEC/wAdAAEDAgEBAwEGAgEBBgEKAgEBCwERAgEBFQEd
AgEBJwEpAgEBPAEyAgEBTgE5AgEBXQFLAgIBjAFjAgMB0gG9AbABrAH+Ae0B5QHaAf8B6AHcAcwB/wHf
AdABvwH/AdoBygG4Af8B2AHHAbQB/wHWAcYBtAH/AdQBxQG2Af8B1AG8AboB/wHTAa4BsgH/AdIBogGk
Af8B1wGeAZsB/wHkAa4BmgH/AegBwAGoAf8BbQEQAQ4B5wFPAgIBlAEtAgEBRAEfAgEBKgESAgEBFgEH
AgEBBwEDAgECAgMBGAABIgIBATABSgEQAQ4B1AFdATcBKgH/AWYBLAEUAf8BYQEkAQoB/wFkATQBDAH/
AYEBYwEMAf8BqgGQAQoB/wHOAbgBCQH/AeEB0wEIAf8B4gHWAQkB/wHMAbwBCQH/AacBkgELAf8BgAFj
AQwB/wFjATIBDAH/AWwBJwEKAf8BawEvARYB/wFcATgBKgH/AUwCCAG9ARUCAQEb/wAZAAEGAgEBBgEK
AgEBDAESAgEBFwEfAgEBKwEtAgEBQwE2AgEBVQFBAgEBbwFdAgIBvQGmAYcBgwH7AeoB2QHMAf8BzgGJ
AXEB/wHJAXYBOAH/AcYBcgEzAf8BwwGAAVUB/wHVAa0BjwH/Ad0BwQGnAf8B2wHCAasB/wHYAcEBrwH/
AdYBtgG0Af8B1QGqAawB/wHXAqMB/wHgAakBnQH/AekBtgGZAf8B7QGxAY4B/wHsAbcBgQH/AeUB0AGc
Af8BWgICAbkBLwIBAUgBHAIBASUBDgIBAREBBAIBAQQBAgMBFAABMwIBAVABQQEgARwB9AFUAScBFgH/
AWMBJAEJAf8BYAE0AQwB/wGlAXcBCQH/AdoBqgEIAf8B5gHFARAB/wHxAd4BOQH/AfgB7QFQAf8B+wH0
AVoB/wH7AfQBWQH/AfgB7wFQAf8B8gHiATYB/wHoAcoBDQH/AdoBrwEIAf8BnAF0AQoB/wFhATIBDAH/
AWoBJgEJAf8BVQEqARkB/wFEARYBEwHmASQCAQEy/wAVAAEHAgEBCAEOAgEBEQEaAgEBIwEoAgEBOgEw
AgEBSgFBAgEBcQFiAgQB2QHxAekB4QH/AfAB5AHXAf8BwgFrATgB/wHlAYEBDQH/AfYBoAENAf8B9wGt
AQ4B/wHrAZYBDgH/AckBbAEYAf8B0QGXAXcB/wHdAbsBmgH/AdsBvQGpAf8B2QGxAa4B/wHYAqUB/wHd
AaMBngH/AegBswGbAf8B8QG+AZwB/wHyAcEBjQH/Ae4BxAGBAf8B6QHBAW4B/wHuAd8BhwH/AV0CAgG/
ASYCAQE3ARICAQEXAQcCAQEHAQIDARAAATMCAQFRAToBGAEVAfkBTAEeAQwB/wFbASQBCwH/AYQBUgEL
Af8B0QGPAQgB/wHhAaoBCQH/AfABygEMAf8B9wHfATIB/wH6AekBRwH/AfwB7QFHAf8B/AHxAUcB/wH8
AfEBRwH/AfwB7wFHAf8B+wHrAUcB/wH4AeEBLQH/AfEBzwEMAf8B4wGuAQgB/wHPAY0BBwH/AXoBSgEM
Af8BYgElAQoB/wFJAR4BDgH/ATwBFQESAe4BIgIBATD/ABEAAQcCAQEIARECAQEVARwCAQEmASQCAQEy
AToCAQFfAWoCCgHhAf8B+wH0Av8B/AHvAf8B3AGxAZkB/wHMAVgBEAH/Ae4BgQEaAf8B9wGFARIB/wH5
AYwBDQH/AfcBmQENAf8B7QGQAQ4B/wG5AWoBLAH/AdYBswGSAf8B2QG5AagB/wHZAqwB/wHaAaIBoAH/
AeUBqQGbAf8B8AG8AZwB/wHwAbcBhgH/AdUBgQFIAf8BzgF0ASYB/wHLAXQBJAH/Ac4BgQE0Af8B5wHe
AYEB/wFUAgIBpQETAgEBGAEHAgEBCAECAwEMAAEjAgEBMQEuAQ0BCwH0AUMBGgEJAf8BWQElAQwB/wGf
AV8BCwH/AdMBiAEKAf8B4wGgAQoB/wHtAbcBCgH/AfEByQENAf8B9QHWARgB/wH3Ad8BIwH/AfkB5AEj
Af8B+gHnASMB/wH6AegBIwH/AfoB5gEjAf8B+AHhASMB/wH1AdgBFgH/AfIBzAENAf8B7gG8AQoB/wHl
AaUBCQH/AdEBgwEJAf8BjgFRAQwB/wFfASYBCwH/AT4BGQEKAf8BOgELAQYB4gESAgEBF/8ADQABBwIB
AQcBEQIBARUBFgIBARwBKgIBAT0BYgIGAdkC/wH8B/8B+AH/AeIBuQGhAf8B2QGBAUUB/wH8AbYBaQH/
AfoBoQFOAf8B9wGSATcB/wHtAYEBHAH/AeEBfAENAf8BswFeARsB/wHSAboBogH/AdQBtgGuAf8B1gGn
AakB/wHdAaABnAH/AewBsAGYAf8B8gG3AYsB/wHGAWUBJgH/AeUBgQENAf8B9gGgAQ0B/wH3Aa0BDgH/
AesBlgEOAf8BywFzARUB/wHWAc4BgQH/AT0CAQFlBAABAgMBCAABCAIBAQkBOgEGAQQB1QEyARUBCQH/
AVwBJAELAf8BnAFXARQB/wHSAYABEwH/AeEBjwEMAf8B5QGdAQoB/wHrAbEBCgH/Ae8BvgEMAf8B8gHM
AQ4B/wH1AdQBEAH/AfYB2gERAf8B9wHdAREB/wH3Ad4BEQH/AfYB3AERAf8B9QHXARAB/wHyAc4BDgH/
Ae8BwgEMAf8B7AG1AQoB/wHmAaIBCgH/AeIBlAELAf8BzgF0AQwB/wGGAUMBDQH/AWQBJgEKAf8BLgET
AQkB/wFGAQMBAgGyAQIDAf8ACQABBgIBAQYBDQIBARABFAIBARkBWgICAbkB/AH3AewD/wH7Cf8B/QH3
AewB/wHQAYkBaAH/AfsB4AGZAf8B+wHQAYEB/wHyAboBcQH/AekBqgFeAf8B1QF8ASAB/wGlAVQBHAH/
Ac8BwAGwAf8B0QG0AbMB/wHUAaEBpQH/AeEBoAGWAf8B8gGyAZMB/wHeAZEBZAH/AcwBWAEQAf8B7gGB
ARoB/wH3AYUBEgH/AfkBjAENAf8B9wGZAQ0B/wHtAZABDgH/AbQBeAEhAf8BZAIHAdoBEAIBARQMAAFC
AgEBewEbAQ8BCgH/AVsBIwEKAf8BfgFCARkB/wHPAXYBJQH/AdsBfgESAf8B4AGJAQ4B/wHjAZQBDAH/
AecBowEMAf8B7QG3ARgB/wHwAcIBHQH/AfABxgESAf8B8QHMAQ4B/wHyAc8BDgH/AfIB0AEOAf8B8QHN
AQ0B/wHwAcgBDAH/Ae8BwAELAf8B7QG3AQoB/wHoAacBCgH/AeQBmQELAf8B4QGNAQ4B/wHdAYEBEAH/
AcQBXQEQAf8BawEvAQ8B/wFgASUBCQH/ARcBDgEKAf8BMgIBAU//AAkAAQQCAQEEAQMCAQEDAUMCAQF2
Ae4B6AHfAf8B/gH5AewB/wH+AfgB7AL/AfwB8gP/AfwF/wH2AeYB1gH/AdIBlAF7Af8B5QG7AYEB/wHq
AcEBgQH/AdoBoAFoAf8BzwF7AS0B/wGhAVoBJAH/Ac0BwQG2Af8B0AGvAbMB/wHUAZsBnQH/AeYBnwGO
Af8B8wGwAYIB/wHgAZYBXAH/AdkBgQFFAf8B/AG2AWkB/wH6AaEBTgH/AfcBkgE3Af8B7QGBARwB/wHh
AXwBDQH/AbEBYgEWAf8BwQHpAY4B/wE+AgEBZwgAAQ0CAQEQASICBwHtAT8BGwEKAf8BXQEqARIB/wHN
AXEBNgH/AdMBbAEbAf8B2QF2ARUB/wHdAYEBEgH/AeEBigEPAf8B5gGbARkB/wH3Ad4BpgH/AfsB8AHK
Af8B9AHUAWgB/wHwAcMBIQH/Ae8BwQEMAf8B7gHAAQkB/wHuAb4BCQH/Ae0BuQEJAf8B6gGwAQkB/wHn
AaQBCgH/AeQBmQEMAf8B4gGPAQ4B/wHfAYQBEQH/AdsBewEUAf8B1AFtARcB/wGxAUcBEgH/AV8BJwEO
Af8BOAEZAQoB/wE7AQUBAwHPAQIDAf8ACQABGQIBASABbQEWARMB6QHzAe0B4QH/AfMB7gHiAf8B9gHw
AeMB/wH5AfIB5gH/Af0B+AHqAv8B/gH3Bf8B/gH5Ae8B/wHyAekB3AH/AesB4gHYAf8B6gHgAdUB/wHJ
AYEBSgH/AaMBXwEqAf8B0AHDAbsB/wHTAakBrwH/AdoBlQGRAf8B6AGbAYEB/wHtAa0BdgH/AfMBxgFx
Af8B0QGIAVAB/wH7AeABmQH/AfsB0AGBAf8B8gG6AXEB/wHpAaoBXgH/AdUBfAEgAf8BowFYARoB/wGw
AfoBnwH/AVoCAgG8AQMCAQEDBAABPQIBAWsBGgERAQwB/wFcASUBCwH/AZYBUAEuAf8B0AFoATEB/wHR
AWIBGgH/AdYBbQEYAf8B2gF3ARYB/wHeAYEBEwH/AeUBkwElAf8B+wHsAdUD/wH+Av8B/gH7Af8B+QHn
AbgB/wHvAcIBTQH/AesBrwEYAf8B6AGnAQsB/wHmAaEBCgH/AeUBnAEMAf8B5AGVAQ4B/wHhAYwBEAH/
Ad8BhAETAf8B3AF8ARUB/wHYAXEBGAH/AdMBZwEaAf8BwwFUARsB/wF0AS0BEwH/AWUBJwEKAf8BFgEQ
AQwB/wEqAgEBPv8ACQABRwIBAX8B7wHqAeAB/wHrAecB3AH/AeoB5QHaAf8B7AHmAdoB/wHvAekB3AH/
AfMB7AHfAf8B+QHxAeMB/wH+AfoB8AP/Af4B/wH8AfcB7QH/Ae8B5gHaAf8B7QHkAdoB/wHLAYEBTwH/
AaIBXwErAf8BugGlAaIB/wG8AYUBigH/AdIBgwF/Af8B4gGYAWwB/wHiAbIBYgH/AekB3gFzAf8B3AHj
AXsB/wHIAZkBYgH/AeUBuwGBAf8B6gHBAYEB/wHaAaABZwH/Ac8BewEtAf8BnwFeASUB/wGhAf8BxAH/
AXQBHwEcAewBGAIBAR8EAAFAAgUBwgEwARgBDAH/AVwBJwEQAf8B2QF3AU0B/wHGAVIBIQH/AcwBWgEd
Af8B0QFjARwB/wHWAW0BGgH/AdoBdgEYAf8B4wGIASoB/wH7AeoB1gP/Af4H/wH+Af8B/gH6AfIB/wH2
AdcBnQH/AewBqwE9Af8B5gGWARgB/wHjAY4BEgH/AeABhwEUAf8B3gGBARYB/wHbAXkBGAH/AdgBcAEa
Af8B0wFnARwB/wHPAV4BHQH/AcoBVgEgAf8BpwE7ARkB/wFfAScBDgH/ASkBFgEMAf8BRwICAZb/AAUA
AQkCAQEKAWICBAHXAe0B6gHeAf8B6AHkAdkB/wHmAeIB1wH/AeUB4QHVAf8B5gHgAdQB/wHoAeIB1QH/
AewB5QHYAf8B8wHqAd0B/wH7AfUB6AP/AfsB/wH9AfcB7QH/Ad0B0gHIAf8BxQGBAUkB/wGhAV4BKgH/
AX4BNAEyAfQBggEzATIB9QGWAU0BQAH7AaYBgQE7Af8BxgHAAVoB/wHFAecBegH/AbgB7wGHAf8BuQH4
AZ0B/wG8AfwBsAH/AbwB/gHDAf8BuAH+AdEB/wHAAYEBTAH/AaEBYQErAf8BmAHtAdQB/wGnAb4BtQH+
ASsCAQFAAQ0CAQEPARkBDgENAfkBTwEiAQwB/wF8AT8BJwH/AdgBbgFIAf8BwQFIAR8B/wHHAVEBHwH/
AcwBWQEfAf8B0QFiAR8B/wHVAWoBHQH/AeEBfwEuAf8B/AHoAdcL/wH+Cf8B/QHyAeQB/wHzAcABgQH/
AecBjwEzAf8B3gF+AR4B/wHaAXQBHAH/AdcBbQEdAf8B0wFlAR8B/wHOAV0BHwH/AckBVQEfAf8BxAFM
AR8B/wG3AUQBIQH/AWsBKAERAf8BRAEfAQwB/wE1AgcB2v8ABQABKQIBATwBzgG+AboB/gHoAeUB3QH/
AeYB4gHZAf8B5AHgAdYB/wHjAd8B0wH/AeIB3QHRAf8B4QHbAc8B/wHhAdsBzgH/AeQB3QHPAf8B6gHi
AdQB/wH1Ae4B4QH/Ae4B5QHbAf8BqAF3AXMB+gGeAVEBJgH7AaIBPwEqAf0BZgEIAQcB2wFkAQQBAwHV
AWICBgHZAXMBHAEUAe0BgQGcAVMB/wGcAeIBgQH/AaIB8wGdAf8BqAH6AbgB/wGpAfoBzgH/AagB9gHa
Af8BpAHuAd8B/wG/AYEBUwH/AaABYAEtAf8BlgHOAd4B/wG5Ad4B6QH/ATYCAQFVASkCAQE8ARcBEQEO
Af8BYwEnAQwB/wGcAVgBQAH/Ac0BXAE7Af8BuwFBAR4B/wHBAUgBIAH/AcYBUAEhAf8BywFXASEB/wHP
AV4BIQH/Ad0BcwEyAf8B/AHmAdcb/wH+Af8B+wHiAcwB/wHwAaEBaQH/Ad4BdQEwAf8B0gFjASMB/wHN
AVoBIgH/AcgBUwEiAf8BwwFMASEB/wG9AUQBHwH/AboBRQEmAf8BbwEpARgB/wFjASgBDAH/ARUBDwEO
Af4BDgIBARH/AAEAAUICAQFyAe4B6gHtAf8B4AHeAeIB/wHgAdwB3wH/Ad8C2wH/Ad4B2QHXAf8B3QHY
AdQB/wHdAdcB0QH/AdwB1gHNAf8B3AHVAcoB/wHfAdgBywH/AdUBywG+Af8BpQF0AW8B+gFqAgsB4QGI
AS0BHQH1AaEBPwEqAf0BWgICAbkBXgIDAccBYQIDAcwBXwIDAcsBdQEsASMB8gGBAckBkAH/AZIB7QHH
Af8BlAHiAdQB/wGYAdwB3QH/AZwB1wHgAf8BoAHUAeEB/wHAAYEBVQH/AaEBYgEvAf8BqQHaAd0B/wHI
AegB5gH/ATcCAQFXATgCAQFeARwBEwEPAf8BYwEpAQ4B/wHDAXIBVQH/AcIBTwEzAf8BtAE5AR0B/wG6
AUABIAH/Ab8BRwEhAf8BxAFNASMB/wHIAVMBIwH/AdkBaQE0Af8B/QHkAdYi/wH7AfkB/wH6AcwBswH/
AeYBgQFQAf8BygFVASgB/wHCAUkBIgH/Ab0BQwEhAf8BtgE8AR4B/wG+AUgBLAH/AX4BMAEgAf8BcAEs
AQ0B/wEXARIBDwH/ASMCAQEx/wABAAFQAgIBlQHmAesB9QH/AdcB3QHqAf8B1wHaAecB/wHUAdcB5QH/
AdMB1AHiAf8C0QHgAf8B0AHPAd0B/wHPAcwB2gH/Ac8BywHYAf8BzgHJAdMB/wG7AbEBtwH/AXACFwHp
AV4CAwHKAYEBGwEUAfEBfAEkAQ4B9gEKAgEBCwEoAgEBOQFbAgIBuAFfAgMBwwFoAg0B5AF/AacBowH/
AZcBzwHgAf8BnwHOAd8B/wGoAdMB3wH/Aa4B2AHgAf8BtAHcAd8B/wHFAYEBVgH/AaMBYwExAf8BuQHg
AeMB/wHRAecB6AH/AS4CAQFFAUACAQFyASIBGAESAf8BZwEsAREB/wHUAZUBfQH/Af0BtAGTAf8B8QGU
AXIB/wHhAXYBUgH/AdMBXwE8Af8ByAFRAS0B/wHCAUoBJQH/AdMBXwE0Af8B/QHjAdYp/wH9AeYB2wH/
AdIBXAE2Af8ByQFUATMB/wHYAW8BTgH/Ae0BlwF5Af8B/gHEAacB/wGoAWsBVwH/AXIBMAEQAf8BHAEW
ARMB/wEtAgEBRP8AAQABVQICAacB2wHvAfsB/wHOAeMB8AH/Ac0B4QHvAf8BywHeAe0B/wHHAdwB6wH/
AcQB2QHpAf8BwQHXAegB/wG9AdUB5gH/AbkB0gHmAf8BrwHIAd4B/wGLAX8BkAH8AWQCBgHZAWMCAwHS
AWUBBwEEAd8BewEeAQsB9AgAAVcCAgGrAV8CAwHLAW0CEAHnAY8BoQG1Af8BuQHRAeQB/wG6AdEB4gH/
Ab4B1AHjAf8BwAHVAeQB/wHCAdcB5QH/AcgBgQFYAf8BowFkATEB/wHEAdsB6AH/AYsBRwFJAfQBHQIB
AScBQAICAXIBNwEuASkB/wFuATUBGgH/AdQBnAGFAf8B/gG2AZUB/wH9AacBgwH/Af0BmgF1Af8B/AGO
AWcB/wH4AYQBXAH/Ae8BfAFTAf8B7gF9AVMB/wH+AeYB2yb/AfoB9wH/Af4BywG0Af8B/AGYAXEB/wH9
AZ0BdwH/Af0BqQGEAf8B/QG2AZUB/wH+AccBrAH/AbUBhAFyAf8BeAE3ARkB/wEpASMBIQH/AS4CAQFF
/wABAAFUAgIBowHTAfQB+AH/AcQB6AHsAf8BxAHoAeoB/wHCAeYB5wH/Ab0C5AH/AbcB4AHjAf8BrwHb
AeEB/wGnAdUB4AH/AZ0B0QHgAf8BkgHLAdMB/wF/AYwBfQH8AWMCAwHSAWICAwHPAW0BCwEFAeUBewEe
AQsB9AEGAgEBBgE+AgEBZgFfAgMBywFgAgMB0wGAATIBMQHzAbcBsAG6Af8B0QHPAdoB/wHOAcwB2gH/
Ac4BzQHbAf8CzwHdAf8BzwHRAd8B/wHKAYEBWAH/AaQBZAEyAf8B0wHYAeUB/wFhAgMB0QEHAgEBBwE5
AgEBXwF0AW4BagH/AZkBYwFIAf8BwAGPAX0B/wH+AbkBmgH/Af4BqwGIAf8B/gGeAXoB/wH+AZEBbAH/
AfsBhgFfAf8B8wF/AVcB/wH2AYMBXAH/Af4B6AHeHv8B/gH9Af8B/gHdAc4B/wH9AaYBggH/Af0BkQFr
Af8B/QGUAW4B/wH+AZ8BewH/Af4BrAGJAf8B/gG6AZsB/wH+AcsBsgH/AaUBgAFvAf8BqQFxAVMB/wFt
AWkBZwH/ASQCAQEy/wABAAFLAgIBiwHNAfcB8gH/AbgB5wHkAf8BtQHjAeUB/wGwAd0B5QH/AakB1wHj
Af8BoQHTAeEB/wGbAdQB3gH/AZUB2wHYAf8BkgHmAc4B/wGQAeoBugH/AZIBxQGMAf8BaQINAeQBYAID
AckBiAEtAR0B9QGHATcBIQH8AVgCAgGyAWECAwHRAWECAwHRAXYCHAHrAb0BmAGNAf0B4QHaAc4B/wHh
AdoB0QH/Ad4B2AHRAf8B3gHYAdMB/wHdAdgB1QH/Ad0B2QHYAf8BzgGBAVgB/wGlAWQBMQH/AeMB3gHh
Af8BSwICAY0EAAErAgEBPwF9AXkBdwH/AbABfAFgAf8BngF5AWkC/wHCAaQC/wG0AZQB/wH+AacBhAH/
Af4BnAF4Af8B/gGRAWwB/wH9AYgBYQH/Af0BjQFnAv8B6gHgGv8B6wHhAf8B/gG1AZYB/wH+AZEBagH/
Af4BiwFlAf8B/gGTAW0B/wH+AZ0BeQH/Af4BqQGFAf8B/gG1AZQC/wHDAaYC/wHTAb0B/wGUAXMBYQH/
Aa4BgQFpAf8BawFnAWYB/gEPAgEBEv8AAQABPQIBAWUBwgHnAfcB/wGhAdMB6AH/AaIB1QHnAf8BoAHb
AeUB/wGgAeQB4AH/AZ8B7gHYAf8BnwH4Ac4B/wGeAfwBvQH/AZsB9QGlAf8BnAHqAYsB/wGmAc0BfAH/
AZkBcwFMAfsBbgIOAeUBmwE+ASgB+AGiAT8BKwH9AWsCCwHgAWoCCwHhAXwCKwHwAb0BmwGQAfwB9AHv
AegB/wH5AfQB6AH/Ae8B6gHdAf8B6QHkAdgB/wHmAeIB1gH/AeYB4QHWAf8B5QHiAdcB/wHQAYMBWAH/
AaYBZAExAf8BqQF2AXIB+QEjAgEBMQQAAQ8CAQESAXACZgH5Aa8BigF4Af8BiwFlAVIC/wHJAa0C/wHA
AaMC/wG0AZMC/wGpAYYC/wGfAXwB/wH+AZYBcgH/Af4BmgF2Av8B7AHjEv8B9QHxAf8B/gHGAa4B/wH+
AZkBdQH/Af4BjQFnAf8B/gGQAWoB/wH+AZcBcgH/Af4BoAF9Av8BqQGGAv8BtQGUAv8BwAGjAv8BzQG0
Av8B2wHHAf8BigFkAU4B/wGkAYoBfgH/AV0CMgHdAQIDAf8AAQABIQIBAS4BnwGGAY4B+gGdAeoB4gH/
AaMB9AHdAf8BpAH8AdgB/wGmAf8B0AH/AacB/wHAAf8BpgH5AaoB/wGjAewBlgH/AaYB4gGEAf8BuwHh
AYEB/wHXAdIBdwH/AdMBqAF2Af8BuQF/AXsB/gG/AVgBOQH9AZYBUQEqAf4BiAFFAUMB9QGiAXMBbgH6
AdcBzgHFAf8B9wH0AewH/wH7Af8B/gH7AfEB/wH5AfUB6QH/AfMB7wHjAf8B7wHrAd8B/wHsAekB3gH/
AdMBhwFcAf8BpwFkATAB/wFVAgIBpwwAAVoCIQHHAaYBlgGNAf8BiAFfAUcB/wHzAcUBrQL/AckBrwL/
AcABowL/AbYBlgL/Aa0BiwL/AaUBgQL/AacBhAL/Ae8B5wr/AfwB+wL/AdwBzAL/AasBiQL/AZYBcgL/
AZQBcAL/AZkBdQL/AZ8BfAL/AaUBggL/Aa0BjAL/AbcBlwL/AcABpAL/AcsBsgL/AdkBxgH/AeIBxAG0
Af8BlQFqAVAB/wGgAZYBjwH/AU0CCQGZ/wAFAAEDAgEBAwFeAgMBxQGqAf8B4wH/AagB/wHJAf8BqAH/
AbwB/wGoAfoBrAH/AacB8AGeAf8BqAHmAZIB/wGzAeQBiAH/AckB5gGBAf8B4AHYAYEB/wHkAbgBgQH/
AeoBqgGGAf8B6AGqAaQB/wHJAYABSgH/Ac8BgQFBAf8BtwGGAXgB/wHcAcwBvAH/AfgB8QHmAv8B+gHy
Av8B/gH3C/8B+gL/AfwB8wH/AfwB+QHuAf8B+QH1AeoB/wHXAYwBXwH/AZsBVgEuAf4BHAIBASYMAAFA
AgMBcAGnAaMBoAH/AcEBkwF6Af8BnwGDAXYC/wHQAbgC/wHNAbUC/wHEAagC/wG7AZ0C/wG0AZMC/wG0
AZUC/wHwAegD/wH+Av8B6wHhAv8BwAGlAv8BpwGEAv8BoAF+Av8BoQF/Av8BpAGBAv8BqAGGAv8BrgGM
Av8BtAGUAv8BvAGdAv8BxAGoAv8BzQG0Av8B1wHDAv8B4gHTAf8BjwF6AW4B/wHKAZ4BgwH/AaABnAGb
Af8BLAIBAUL/AAkAATkCAQFdAcIB/wHjAf8BowH6AaYB/wGnAfEBngH/AaYB5wGWAf8BrAHkAZAB/wG8
AegBiwH/AdQB6wGFAf8B5gHcAYEB/wHlAb4BgQH/AeYBsAGGAf8B7wGwAaQB/wHoArsB/wHMAYEBUAH/
AecBnwFXAf8BzQFnAQ0B/wHUAW4BFAH/AdgBfAEsAf8B2QGBAU4B/wHcAZYBdAH/AeIBsgGUAf8B6wHO
Ab0B/wH1AecB3wH/Af0B+gH3A/8B+wP/AfkB/wHWAYoBWwH/AYgBLQESAfgQAAEQAgEBFAGCAW8BbgHw
AccBsQGkAf8BhgFpAVMB/wHxAcoBtAL/AdcBwgL/AdIBugL/AckBsAL/AcMBpgL/Ab8BogL/Ac8BuAL/
AdABugL/AbsBnQL/AbEBkQL/Aa8BjgL/AbABjwL/AbIBkQL/AbQBlQL/AbgBmQL/Ab0BnwL/AcMBpwL/
AckBrwL/AdEBugL/AdoBxgL/AeMB1AH/AeEByAG6Af8BkgFuAVQB/wHDAbEBpwH/AWcCNAHUAQMCAQEC
/wAJAAEHAgEBBwFeAgMBxQGrAfsBrwH/AacB4gGOAf8BsQHkAY0B/wHDAeoBigH/AdoB7AGGAf8B5wHd
AYEB/wHkAcIBgQH/AeQBtQGIAf8B7wGzAaAB/wHuAbwBuAH/AeYCxQH/AcwBgQFRAf8B7gGvAWkB/wHl
AZoBRgH/Ad8BgQEdAf8B4gGBAQ8B/wHmAYEBDQH/AekBgQENAf8B6QGBAQ0B/wHmAX8BDQH/AeABewEW
Af8B2wGAATAB/wHZAYIBUwH/AdgBlwF3Af8BhAEiAQsB9AFzARMBCAHvFAABSAIFAYMBwQG9AboB/wHW
AbEBlwH/AYQBcQFjAv8B2QHDAv8B3gHMAv8B2AHDAv8B0gG7Av8BzAGzAv8ByAGuAv8BxAGpAv8BwQGl
Av8BwAGjAv8BwAGjAv8BwAGjAv8BwgGlAv8BxAGoAv8BxwGtAv8BywGyAv8B0QG6Av8B1wHDAv8B3gHM
Av8B5gHYAf8B/AHiAdMB/wF8AWYBVwH/AdwBtwGeAf8BugG2AbQB/wE1AgEBVf8AEQABIgIBATABdwEt
AScB7wG2AfYBkgH/AcoB6wGGAf8B3gHsAYUB/wHnAdwBgQH/AeQBwgGBAf8B4gG3AYcB/wHrAbYBmgH/
AfEBuwG1Af8B6QHEAcEB/wHmAc0B0AH/AcwBgQFSAf8B4wGUAVkB/wHoAaQBYQH/AekBpgFhAf8B5wGh
AVgB/wHkAZcBSQH/AeABiwE1Af8B3gGBASEB/wHfAYEBEQH/AeIBgQENAf8B6AGBAQ0B/wHqAYEBDQH/
AeEBgQENAf8B0wF1AQ0B/wFtAQ0BBgHqFAABCwIBAQ0BdQJJAdsB0wHIAcEB/wG/AZ4BgQH/AZ4BiQF+
Av8B3QHJAv8B5AHUAv8B3wHOAv8B2gHIAv8B1gHCAv8B0wG+Av8B0QG6Av8B0AG5Av8BzwG4Av8B0AG5
Av8B0QG6Av8B0wG9Av8B1gHBAv8B2gHHAv8B3wHOAv8B5AHVAv8B6gHeAv8B5gHXAf8BiwF5AW0B/wHO
AagBigH/AdEByAHDAf8BXAIcAbgBAwIBAQL/ABUAATICAQFOAY0BTgFBAfQB4gH8AYQB/wHlAdgBgQH/
AeMBwwGBAf8B4QG4AYUB/wHoAbcBkgH/AfIBuAGuAf8B7QHCAbwB/wHmAscB/wHmAdIB1gH/AcwBgQFT
Af8B2gGCAU0B/wHeAYoBUAH/AeABjgFTAf8B4wGVAVgB/wHmAZ0BXwH/AegBpAFkAf8B6QGnAWQB/wHn
AaEBWwH/AeABkAFHAf8B1gGBASgB/wHPAXIBDwH/AdIBdAENAf8B0wF1AQ4B/wFtAQ0BBgHqGAABKAIB
AToBqwKbAfcB2wHKAcAB/wG0AZQBeQH/AZwBiAF+Av8B3wHNAv8B5wHbAv8B5wHaAv8B5AHVAv8B4QHR
Av8B3wHPAv8B3gHNAv8B3gHMAv8B3gHNAv8B3wHOAv8B4QHRAv8B5AHVAv8B5wHaAv8B6gHfAv8B7QHj
Af8B/AHjAdUB/wGLAXkBbQH/AcMBngGBAf8B2AHLAcIB/wGIAmYB5wEVAgEBG/8AHQABLQIBAUQBawEL
AQoB4AHuAdsBjwH/Ad4BswGBAf8B5QG2AYsB/wHxAbcBpwH/AfEBwAG5Af8B6AHFAcAB/wHmAcoBzQH/
AecB1gHaAf8BzAGBAVMB/wHKAXIBNgH/AdEBfAE8Af8B1QGBAUEB/wHYAYEBRgH/AdwBhAFMAf8B3gGK
AVAB/wHgAY8BUwH/AeMBlgFZAf8B5wGfAWEB/wHpAaQBZAH/AeIBlQFVAf8BzQF4ASoB/wHDAV8BDQH/
AWsBDAEGAeocAAE4AgIBXAG2Aa8BrgH7AdoBygHBAf8BwwGjAYYB/wGBAXEBYwH/AewB0AHAAv8B5wHZ
Av8B7QHjAv8B7QHjAv8B6wHgAv8B6gHgAv8B6gHfAv8B6gHfAv8B6wHgAv8B7AHjAv8B7gHmAv8B8AHo
Av8B6wHfAf8B4QHJAbsB/wF8AWYBWAH/Ac4BqQGLAf8B2QHLAcMB/wGcAogB8QEnAgEBOP8AJQABFwIB
AR4BUgICAZ4BpwFpAVgB+AH3AcQBqAH/AfYBugGxAf8B6wHCAbYB/wHmAsQB/wHmAc4B0QH/AegB2gHd
Af8BygGcAYoB/wHLAYEBVwH/Ac8BgQFTAf8BzwGBAU0B/wHPAYABRgH/AdABfgFBAf8B0AF8AT4B/wHS
AX8BPgH/AdUBgQFBAf8B2QGBAUYB/wHcAYYBTAH/AeIBkgFWAf8B5gGcAV4B/wHVAYEBPQH/AWsBDAEG
AeogAAE5AgIBXQGsAZ4BnQH3AdUBywHFAf8B3wHBAacB/wGNAXcBYAH/AZYBgwF6Af8B6wHQAcEC/wHn
AdkC/wHsAeAC/wHvAeUC/wHwAegC/wHxAegC/wHwAecC/wHtAeMC/wHpAdwB/wHiAcoBvQH/AY4BewFw
Af8BkQFzAVoB/wHiAcIBqgH/AdMBywHGAf8BkAJzAesBKAIBATv/ADEAASQCAQEzAU0CAgGQAWUCBgHY
AcYBogGcAfwB8gLZAf8B8gHfAeEB/wHzAegB6gH/Ae8B6wHjAf8B4wHUAcgB/wHfAcMBtAH/AdgBsAGe
Af8BhwEyASwB9AFuAQ4BDAHoAW4BDAEKAeYBhgEoARsB8wHRAYEBVwH/AdIBgQFSAf8B0gGBAUsB/wHT
AYEBRgH/AdQBgQFDAf8B3AGCAUoB/wF0AQ8BBwHrJAABKAIBATsBfAJPAdwBzgHLAckB/wHbAcsBwgH/
AdsBvgGiAf8BmAF+AWQB/wGLAXMBYAH/AZUBgQF2Af8BrAGaAY8B/wG9AakBnQH/AbwBqAGcAf8BqQGX
AY0B/wGUAX8BcwH/AYkBbgFcAf8BnQF9AWMB/wHeAbsBnwH/AdwBywHAAf8BzQHKAccB/wFnAiwBxgEa
AgEBIv8APQABCQIBAQoBJAIBATMBOwIBAWABSQICAYQBTwICAZMBTwICAZMBSgICAYcBPgIBAWcBKgIB
AT0BEQIBARUEAAEGAgEBBgEXAgEBHQEoAgECOwIBAWEBSwICAYkBWAICAbABYwIDAdIBigEzASIB9QFi
AgQB2SgAAQwCAQEOAUkCBgGFAZwBiQGIAfEBzgHLAckB/wHWAcsBxQH/AeIBzQG7Af8B5QHEAagB/wHY
AbEBlAH/Ac4BpgGIAf8BzwGnAYkB/wHaAbMBlgH/AeUBxgGsAf8B4QHNAb0B/wHWAcsBxQH/Ac4BywHJ
Af8BiQJmAeYBPgIDAWsBBQIBAQX/AH0AAQcCAQEIARkCAQEhASsCAQFAAUECAQFuATsCAQFhMAABEQIB
ARUBQgIDAXMBawIxAckBrwKmAfoBzALKAf8BzgHLAckB/wHQAcsByAH/AdABywHIAf8BzgHLAckB/wHL
AckByAH/AaEClAH2AWECIgG7ATsCAgFhAQoCAQEL/wDRAAECAwEBEAIBARMBKwIBAUABOgICAWABQgIE
AXIBQQIDAXABOQICAVwBJwIBATgBCgIBAQz/ADEAAUIBTQE+BwABPgMAASgDAAGAAwABIAMAAQEBAAEB
BgABAhYAA/8BAAH4AgABDwH/AfABDwH/CAABgAIAAQMB/wGAAQEB/wsAAQEB/gIAAX8MAAH8AgABPwwA
AfgCAAEfDAAB8AIAAQ8MAAHgAgABBwsAAQIBwAIAAQMLAAEBAcACAAEDCwABAQGAAgABAQgAAYADAAGA
AgABAQgAAYADAAGAAgABAQ8AAQE6AAHAIAABAQ8AAQEPAAEDAYACAAEBCwABAwGAAgABAQgAAYACAAEH
AYACAAEBCAABgAIAAQcBwAIAAQMIAAHAAgABBwHAAgABAwgAAeACAAEHAeACAAEHCAAB8AIAAQcB8AIA
AQ8IAAH4AgABBwH4AgABHwgAAf4CAAEHAfwCAAE/CAAB/wGAARABBwH+AgABfwgAA/8BBwH/AYABAQH/
CAAF/wHgAQ8B/wgACw==
</value>
</data>
</root>
+111
View File
@@ -0,0 +1,111 @@
using System.ComponentModel;
using System.Xml.Serialization;
namespace MusicMetaTagger.UI
{
public class LibraryUpdate
{
private bool _findCompilationTrackOrigins = true;
private bool _genreUpdate = true;
private bool _ratingOverwrite;
private bool _ratingUpdate = true;
private bool _yearUpdate = true;
[Category("Field Options")]
[Browsable(true)]
[Description("Update blank ratings fields")]
[DefaultValue(true)]
[XmlAttribute]
public bool RatingUpdate
{
get { return _ratingUpdate; }
set
{
_ratingUpdate = value;
if (!value)
_ratingOverwrite = false;
}
}
[Category("Field Options")]
[Browsable(true)]
[Description("Overwrite existing ratings")]
[DefaultValue(false)]
[XmlAttribute]
public bool RatingOverwrite
{
get { return _ratingOverwrite; }
set
{
_ratingOverwrite = value;
if (value)
_ratingUpdate = true;
}
}
[Category("General")]
[Browsable(true)]
[Description("Try to find the original album on which a compilation track appears.")]
[DefaultValue(true)]
[XmlAttribute]
public bool FindCompilationTrackOrigins
{
get { return _findCompilationTrackOrigins; }
set { _findCompilationTrackOrigins = value; }
}
//[Category("General")]
//[Browsable(true)]
//[Description("As well as updating the library, also updates the underlying .MP3 file ID3 fields")]
//[DefaultValue(true)]
//[XmlAttribute]
//public bool UpdateMp3Id3
//{
// get { return _updateMp3Id3; }
// set { _updateMp3Id3 = value; }
//}
[Category("Field Options")]
[Browsable(true)]
[Description("Overwrite any existing album art")]
[DefaultValue(false)]
[XmlAttribute]
public bool AlbumArtOverwrite { get; set; }
[Category("Field Options")]
[Browsable(true)]
[Description("Update the year field")]
[DefaultValue(true)]
[XmlAttribute]
public bool YearUpdate
{
get { return _yearUpdate; }
set { _yearUpdate = value; }
}
[Category("Field Options")]
[Browsable(true)]
[Description("Overwrite any existing year value.")]
[DefaultValue(false)]
[XmlAttribute]
public bool YearOverwrite { get; set; }
[Category("Field Options")]
[Browsable(true)]
[Description("Update the genre field")]
[DefaultValue(true)]
[XmlAttribute]
public bool GenreUpdate
{
get { return _genreUpdate; }
set { _genreUpdate = value; }
}
[Category("Field Options")]
[Browsable(true)]
[Description("Overwrite any existing genre value.")]
[DefaultValue(false)]
[XmlAttribute]
public bool GenreOverwrite { get; set; }
}
}
+262
View File
@@ -0,0 +1,262 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using WMPLib;
namespace MusicMetaTagger.UI
{
/// <summary>
/// </summary>
/// <remarks>
/// Attribute Reference http://msdn2.microsoft.com/en-us/library/bb248367.aspx
/// </remarks>
public class MediaPlayerLibraryInterface : IMusicLibraryInterface
{
#region Private members
/// <summary>
/// Relates TrackQuery object to the
/// </summary>
private Dictionary<TrackQueryStatus, IWMPMedia> _trackQueryTracks;
/// <summary>
/// Media player interface object (COM)
/// </summary>
private WindowsMediaPlayer _windowsMediaPlayer;
#endregion
#region Private methods
/// <summary>
/// Gets the IWMPMedia track from the associated TrackQueryStatus.
/// </summary>
/// <param name = "trackQueryStatus">The track query status.</param>
/// <returns></returns>
private IWMPMedia GetTrack(TrackQueryStatus trackQueryStatus)
{
if (!_trackQueryTracks.ContainsKey(trackQueryStatus))
throw new ApplicationException("Doesn't contain track" + trackQueryStatus.TrackTitle);
return _trackQueryTracks[trackQueryStatus];
}
#endregion
#region IMusicLibraryInterface methods
/// <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, IWMPMedia>();
var trackQueries = new List<TrackQueryStatus>();
callback.SetText("Opening Media Player Library");
_windowsMediaPlayer = new WindowsMediaPlayer();
var mediaCollection = _windowsMediaPlayer.mediaCollection;
callback.SetText("Getting tracks");
var playlist = mediaCollection.getAll();
var trackCount = libraryQuery.ScanLimit <= 0 ? playlist.count : Math.Min(playlist.count, libraryQuery.ScanLimit);
callback.SetRange(0, trackCount);
callback.Begin();
for (var i = 1; i <= trackCount; i++)
{
callback.Increment(1);
if (i%5 == 0 || i == trackCount)
callback.SetText(string.Format("Scanning track# {0} / {1}, Found {2} matches", i, trackCount, trackQueries.Count));
if (callback.IsAborting)
break;
var track = playlist.Item[i];
var trackQuery =
new TrackQueryStatus
{
TrackTitle = track.getItemInfo("Title"),
ArtistName = track.getItemInfo("Author"),
AlbumTitle = track.getItemInfo("AlbumId")
};
var durationString = track.getItemInfo("Duration");
if (string.IsNullOrEmpty(durationString))
durationString = "1";
trackQuery.TrackLength =
new TimeSpan(0, 0, 0, Convert.ToInt32(Convert.ToDouble(durationString)));
var originalIndexString = track.getItemInfo("OriginalIndex");
if (!string.IsNullOrEmpty(originalIndexString))
trackQuery.TrackNumber = Convert.ToInt32(originalIndexString);
var acquisitionTime = Convert.ToDateTime(track.getItemInfo("AcquisitionTime"));
if (libraryQuery.AddedAfter > acquisitionTime)
continue;
if (libraryQuery.BlankGenre && !string.IsNullOrEmpty(track.getItemInfo("Genre")))
continue;
if (libraryQuery.BlankRating && !string.IsNullOrEmpty(track.getItemInfo("UserRating")))
continue;
if (libraryQuery.BlankYear && !string.IsNullOrEmpty(track.getItemInfo("ReleaseDateYear")))
continue;
if (!libraryQuery.MatchTrackQuery(trackQuery))
continue;
trackQueries.Add(trackQuery);
_trackQueryTracks.Add(trackQuery, track);
}
return trackQueries;
}
/// <summary>
/// Updates the album art.
/// </summary>
/// <remarks>
/// http://msdn2.microsoft.com/en-us/library/aa392196.aspx
/// </remarks>
/// <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)
{
//IWMPMedia track = GetTrack(trackQuery);
//IWMPMedia3 t = track as IWMPMedia3;
//Object o = t.getItemInfoByType("WM/Picture", "", 0);
//int [] ha;
//WMPicture pic = new WMPicture();
//Marshal.Copy(ha., 0, pic, );
// http://www.ureader.com/message/33380790.aspx
return false;
}
/// <summary>
/// Updates 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 track = GetTrack(trackQuery);
if (string.IsNullOrEmpty(track.getItemInfo("WM/Genre")) || overwrite)
{
track.setItemInfo("WM/Genre", genre);
return true;
}
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 track = GetTrack(trackQuery);
if (track.isReadOnlyItem("WM/Year"))
return false;
if (string.IsNullOrEmpty(track.getItemInfo("WM/Year")) || overwrite)
{
track.setItemInfo("WM/Year", year.ToString(CultureInfo.InvariantCulture));
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 track = GetTrack(trackQuery);
if (Convert.ToInt32(track.getItemInfo("UserRating")) == 0 || overwrite)
{
track.setItemInfo("UserRating", rating.ToString(CultureInfo.InvariantCulture));
return true;
}
return false;
}
public bool AddComment(TrackQueryStatus trackQuery, string comment)
{
// TODO: implement
return false;
}
/// <summary>
/// Returns true if the trackQuery represents an Mp3.
/// </summary>
/// <returns></returns>
public bool IsMp3(TrackQueryStatus trackQuery)
{
var track = GetTrack(trackQuery);
try
{
var trackFileInfo = new FileInfo(track.sourceURL);
return trackFileInfo.Extension.ToUpper() == "MP3";
}
catch
{
}
return false;
}
/// <summary>
/// Returns the Mp3 represented by this trackQuery
/// </summary>
/// <param name = "trackQuery"></param>
/// <returns></returns>
public FileInfo GetMp3FileInfo(TrackQueryStatus trackQuery)
{
var track = GetTrack(trackQuery);
try
{
return new FileInfo(track.sourceURL);
}
catch
{
}
return null;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct WMPicture
{
public readonly IntPtr pwszMIMEType;
public readonly byte bPictureType;
public readonly IntPtr pwszDescription;
[MarshalAs(UnmanagedType.U4)] public readonly int dwDataLen;
public readonly IntPtr pbData;
}
#endregion
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

+109
View File
@@ -0,0 +1,109 @@
using System;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;
namespace MusicMetaTagger.UI
{
/// <summary>
/// Provides the user an interface for customizing program options
/// </summary>
internal partial class Options : Form, IDisposable
{
#region Private members
private const string LIBRARY_QUERY_FILENAME = "options_libraryQuery.xml";
private const string LIBRARY_UPDATE_FILENAME = "options_libraryUpdate.xml";
private LibraryQuery _libraryQuery;
private LibraryUpdate _libraryUpdate;
#endregion
#region Public Properties
public LibraryQuery LibraryQuery
{
get { return _libraryQuery; }
set { _libraryQuery = value; }
}
public LibraryUpdate LibraryUpdate
{
get { return _libraryUpdate; }
set { _libraryUpdate = value; }
}
#endregion
#region Constructor
public Options()
{
InitializeComponent();
// ConfigSectionObjects
var optionsLoaded = false;
if (File.Exists(LIBRARY_QUERY_FILENAME) && File.Exists(LIBRARY_UPDATE_FILENAME))
{
try
{
var libraryQuerySerializer = new XmlSerializer(typeof (LibraryQuery));
using (TextReader textReader = new StreamReader(LIBRARY_QUERY_FILENAME))
{
_libraryQuery = (LibraryQuery) libraryQuerySerializer.Deserialize(textReader);
}
var libraryUpdateSerializer = new XmlSerializer(typeof (LibraryUpdate));
using (TextReader textReader = new StreamReader(LIBRARY_UPDATE_FILENAME))
{
_libraryUpdate = (LibraryUpdate) libraryUpdateSerializer.Deserialize(textReader);
}
optionsLoaded = true;
}
catch
{
}
}
if (!optionsLoaded)
{
_libraryQuery = new LibraryQuery();
_libraryUpdate = new LibraryUpdate();
}
libraryQueryPropertyGrid.SelectedObject = _libraryQuery;
updatePropertyGrid.SelectedObject = _libraryUpdate;
}
#endregion
#region Event Handlers
private void Options_Load(object sender, EventArgs e)
{
}
private void closeButton_Click(object sender, EventArgs e)
{
Hide();
}
#endregion
#region IDisposable Members
void IDisposable.Dispose()
{
var libraryQuerySerializer = new XmlSerializer(typeof (LibraryQuery));
using (TextWriter textWriter = new StreamWriter(LIBRARY_QUERY_FILENAME))
{
libraryQuerySerializer.Serialize(textWriter, _libraryQuery);
}
var libraryUpdateSerializer = new XmlSerializer(typeof (LibraryUpdate));
using (TextWriter textWriter = new StreamWriter(LIBRARY_UPDATE_FILENAME))
{
libraryUpdateSerializer.Serialize(textWriter, _libraryUpdate);
}
}
#endregion
}
}
+151
View File
@@ -0,0 +1,151 @@
namespace MusicMetaTagger.UI
{
partial class Options
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Options));
this.splitContainer = new System.Windows.Forms.SplitContainer();
this.libraryQueryLabel = new System.Windows.Forms.Label();
this.libraryQueryPropertyGrid = new System.Windows.Forms.PropertyGrid();
this.label1 = new System.Windows.Forms.Label();
this.updatePropertyGrid = new System.Windows.Forms.PropertyGrid();
this.closeButton = new System.Windows.Forms.Button();
this.splitContainer.Panel1.SuspendLayout();
this.splitContainer.Panel2.SuspendLayout();
this.splitContainer.SuspendLayout();
this.SuspendLayout();
//
// splitContainer
//
this.splitContainer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.splitContainer.Location = new System.Drawing.Point(0, 0);
this.splitContainer.Name = "splitContainer";
//
// splitContainer.Panel1
//
this.splitContainer.Panel1.Controls.Add(this.libraryQueryLabel);
this.splitContainer.Panel1.Controls.Add(this.libraryQueryPropertyGrid);
//
// splitContainer.Panel2
//
this.splitContainer.Panel2.Controls.Add(this.label1);
this.splitContainer.Panel2.Controls.Add(this.updatePropertyGrid);
this.splitContainer.Size = new System.Drawing.Size(656, 252);
this.splitContainer.SplitterDistance = 326;
this.splitContainer.TabIndex = 1;
//
// libraryQueryLabel
//
this.libraryQueryLabel.AutoSize = true;
this.libraryQueryLabel.Location = new System.Drawing.Point(13, 13);
this.libraryQueryLabel.Name = "libraryQueryLabel";
this.libraryQueryLabel.Size = new System.Drawing.Size(111, 13);
this.libraryQueryLabel.TabIndex = 1;
this.libraryQueryLabel.Text = "Music Search Options";
//
// libraryQueryPropertyGrid
//
this.libraryQueryPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.libraryQueryPropertyGrid.Location = new System.Drawing.Point(0, 36);
this.libraryQueryPropertyGrid.Name = "libraryQueryPropertyGrid";
this.libraryQueryPropertyGrid.Size = new System.Drawing.Size(326, 216);
this.libraryQueryPropertyGrid.TabIndex = 0;
this.libraryQueryPropertyGrid.ToolbarVisible = false;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(3, 13);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(115, 13);
this.label1.TabIndex = 1;
this.label1.Text = "Library Update Options";
//
// updatePropertyGrid
//
this.updatePropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.updatePropertyGrid.Location = new System.Drawing.Point(0, 36);
this.updatePropertyGrid.Name = "updatePropertyGrid";
this.updatePropertyGrid.Size = new System.Drawing.Size(326, 216);
this.updatePropertyGrid.TabIndex = 1;
this.updatePropertyGrid.ToolbarVisible = false;
//
// closeButton
//
this.closeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.closeButton.Location = new System.Drawing.Point(569, 258);
this.closeButton.Name = "closeButton";
this.closeButton.Size = new System.Drawing.Size(75, 23);
this.closeButton.TabIndex = 2;
this.closeButton.Text = "Close";
this.closeButton.UseVisualStyleBackColor = true;
this.closeButton.Click += new System.EventHandler(this.closeButton_Click);
//
// Options
//
this.AcceptButton = this.closeButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(656, 293);
this.ControlBox = false;
this.Controls.Add(this.closeButton);
this.Controls.Add(this.splitContainer);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Options";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.Text = "Options";
this.Load += new System.EventHandler(this.Options_Load);
this.splitContainer.Panel1.ResumeLayout(false);
this.splitContainer.Panel1.PerformLayout();
this.splitContainer.Panel2.ResumeLayout(false);
this.splitContainer.Panel2.PerformLayout();
this.splitContainer.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.SplitContainer splitContainer;
private System.Windows.Forms.PropertyGrid libraryQueryPropertyGrid;
private System.Windows.Forms.Button closeButton;
private System.Windows.Forms.Label libraryQueryLabel;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.PropertyGrid updatePropertyGrid;
}
}
+1787
View File
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
using System;
using System.Windows.Forms;
namespace MusicMetaTagger.UI
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Interface());
}
}
}
+36
View File
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Music Meta Tagger")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Music Meta Tagger")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("bdb17661-2deb-4ad2-897b-19c48069c822")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+63
View File
@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.269
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MusicMetaTagger.UI.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MusicMetaTagger.UI.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}
+117
View File
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+55
View File
@@ -0,0 +1,55 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.17929
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MusicMetaTagger.UI.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute(@"The following libraries are used by this program:
iTunes COM for Windows SDK
Copyright (c) 2004 Apple Computer, Inc.
http://developer.apple.com/sdk/itunescomsdk.html
Windows Media SDK
http://msdn.microsoft.com/en-us/library/aa969732.aspx
Html Agility Pack
Microsoft Public License (Ms-PL)
http://htmlagilitypack.codeplex.com/
Icons adapted from:
Crystal Clear
LGPL
http://commons.wikimedia.org/wiki/Crystal_Clear
Qs Eclipse WMP 11 by Webtrance
http://webtrance.deviantart.com/gallery/")]
public string AboutText {
get {
return ((string)(this["AboutText"]));
}
}
}
}
+29
View File
@@ -0,0 +1,29 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="MusicMetaTagger.UI.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="AboutText" Type="System.String" Scope="Application">
<Value Profile="(Default)">The following libraries are used by this program:
iTunes COM for Windows SDK
Copyright (c) 2004 Apple Computer, Inc.
http://developer.apple.com/sdk/itunescomsdk.html
Windows Media SDK
http://msdn.microsoft.com/en-us/library/aa969732.aspx
Html Agility Pack
Microsoft Public License (Ms-PL)
http://htmlagilitypack.codeplex.com/
Icons adapted from:
Crystal Clear
LGPL
http://commons.wikimedia.org/wiki/Crystal_Clear
Qs Eclipse WMP 11 by Webtrance
http://webtrance.deviantart.com/gallery/</Value>
</Setting>
</Settings>
</SettingsFile>
+89
View File
@@ -0,0 +1,89 @@
using System.ComponentModel;
using MusicMetaTagger.Core.Model;
using MusicMetaTagger.Core.Queries;
namespace MusicMetaTagger.UI
{
public class TrackQueryStatus : TrackQuery, INotifyPropertyChanged
{
private int _percentProgress;
private string _status;
///<summary>
/// Occurs when a property value changes.
///</summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Gets or sets the status.
/// </summary>
/// <value>The status.</value>
public string Status
{
get { return _status; }
set
{
if (_status == null && value == null)
{
return;
}
if ((_status == null) || !_status.Equals(value))
{
_status = value + " <- " + _status;
SignalPropertyChanged("Status");
}
}
}
public void UpdateStatus(StatusEventArgs data)
{
Status = data.Status;
}
/// <summary>
/// Gets or sets the progress. 0 to 100.
/// </summary>
/// <value>The progress.</value>
public int PercentProgress
{
get { return _percentProgress; }
set { CheckPropertyChangedValueType("PercentProgress", ref _percentProgress, ref value); }
}
/// <summary>
/// Checks if the property (propertyName) has been updated or changed.
/// </summary>
/// <param name = "propertyName">Name of the property.</param>
/// <param name = "oldValue">The old value.</param>
/// <param name = "newValue">The new value.</param>
/// <returns>True if the value was updated, false otherwise.</returns>
protected bool CheckPropertyChangedValueType<T>(string propertyName, ref T oldValue, ref T newValue) where T : struct
{
if (!oldValue.Equals(newValue))
{
oldValue = newValue;
SignalPropertyChanged(propertyName);
return true;
}
return false;
}
/// <summary>
/// Creates the event that a property has changed value
/// </summary>
/// <param name = "propertyName"></param>
protected void SignalPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
+160
View File
@@ -0,0 +1,160 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{1F7B0D63-AB76-41E3-87B6-E4C2F13E410F}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MusicMetaTagger.UI</RootNamespace>
<AssemblyName>MusicMetaTagger.UI</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>MetaMusicTagger.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="Autofac">
<HintPath>..\packages\Autofac.2.6.3.862\lib\NET40\Autofac.dll</HintPath>
</Reference>
<Reference Include="Autofac.Configuration">
<HintPath>..\packages\Autofac.2.6.3.862\lib\NET40\Autofac.Configuration.dll</HintPath>
</Reference>
<Reference Include="BitFactory.Logging">
<HintPath>..\References\BitFactory.Logging.dll</HintPath>
</Reference>
<Reference Include="Interop.WMPLib">
<HintPath>..\References\Interop.WMPLib.dll</HintPath>
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="About.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="About.designer.cs">
<DependentUpon>About.cs</DependentUpon>
</Compile>
<Compile Include="IMusicLibraryInterface.cs" />
<Compile Include="Interface.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Interface.designer.cs">
<DependentUpon>Interface.cs</DependentUpon>
</Compile>
<Compile Include="IProgressCallback.cs" />
<Compile Include="ItunesLibraryInterface.cs" />
<Compile Include="LibraryQuery.cs" />
<Compile Include="LibrarySelector.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="LibrarySelector.designer.cs">
<DependentUpon>LibrarySelector.cs</DependentUpon>
</Compile>
<Compile Include="LibraryUpdate.cs" />
<Compile Include="MediaPlayerLibraryInterface.cs" />
<Compile Include="Options.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Options.designer.cs">
<DependentUpon>Options.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TrackQueryStatus.cs" />
<EmbeddedResource Include="About.resx">
<DependentUpon>About.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Interface.resx">
<DependentUpon>Interface.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="LibrarySelector.resx">
<DependentUpon>LibrarySelector.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Options.resx">
<DependentUpon>Options.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<Content Include="MetaMusicTagger.ico" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Client.AllMusicGuide\Client.AllMusicGuide.csproj">
<Project>{A86C05AB-9720-4D6E-AC5E-9CDE6364945A}</Project>
<Name>Client.AllMusicGuide</Name>
</ProjectReference>
<ProjectReference Include="..\Core\Core.csproj">
<Project>{EDA98A07-0BF5-4FEE-B341-D8A6A7E581F5}</Project>
<Name>Core</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<COMReference Include="iTunesLib">
<Guid>{9E93C96F-CF0D-43F6-8BA8-B807A3370712}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>13</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+35
View File
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="MusicMetaTagger.UI.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<MusicMetaTagger.UI.Properties.Settings>
<setting name="AboutText" serializeAs="String">
<value>The following libraries are used by this program:
iTunes COM for Windows SDK
Copyright (c) 2004 Apple Computer, Inc.
http://developer.apple.com/sdk/itunescomsdk.html
Windows Media SDK
http://msdn.microsoft.com/en-us/library/aa969732.aspx
Html Agility Pack
Microsoft Public License (Ms-PL)
http://htmlagilitypack.codeplex.com/
Icons adapted from:
Crystal Clear
LGPL
http://commons.wikimedia.org/wiki/Crystal_Clear
Qs Eclipse WMP 11 by Webtrance
http://webtrance.deviantart.com/gallery/</value>
</setting>
</MusicMetaTagger.UI.Properties.Settings>
</applicationSettings>
</configuration>
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Autofac" version="2.6.3.862" targetFramework="net40-Client" />
</packages>