第34回 データベース再構築をキャンセル可能にする

今回は曲情報を保管するためのデータベース再構築処理をスレッドに載せてキャンセル可能にします。

変更作業は「第29回 再生フォルダ読み込みをキャンセル可能にする」と同様です。
ついでに少しだけデータベースの処理を効率化させました。まだまだ無駄が多いですがその辺は放置。

■MP3Info.cs
		//追加
		/// <summary>
		/// DBにある情報の更新日時を取得
		/// 
		/// ZIPファイル向けにエントリーインデックスを指定せずに使えるようにしたもの
		/// </summary>
		static bool SQL_FindDateInfo(AudioItem item, out DateTime dtLastWrite)
		{
			//引数で渡されたstrFileは音楽フォルダーのパスを含んだものかもしれないので、その部分を除外
			string strFile = Form1._option.RemoveMP3FolderName(item.strFile);

			try
			{
				using (SQLiteCommand cmd = _conn.CreateCommand())
				{
					cmd.CommandText = @"SELECT lastwritedate, title, artist, album FROM TagInfo WHERE file=@file;";
					cmd.Parameters.Add(new SQLiteParameter("@file", strFile));
					cmd.Prepare();

					using (SQLiteDataReader reader = cmd.ExecuteReader())
					{
						while (reader.Read())
						{
							try
							{
								dtLastWrite = new DateTime(reader.GetInt64(0));
								return true;
							}
							catch (Exception)
							{
							}
						}
					}
				}
			}
			catch (Exception)
			{
			}

			dtLastWrite = DateTime.MinValue;
			return false;
		}


		/// <summary>
		/// DBへのデータ保存
		/// </summary>
		static bool SQL_SetTagInfo(AudioItem item, DateTime dtLastWrite, string strTitle, string strArtist, string strAlbum)
		{
			//引数で渡されたstrFileは音楽フォルダーのパスを含んだものかもしれないので、その部分を除外
			string strFile = Form1._option.RemoveMP3FolderName(item.strFile);

			try
			{
				int nID = -1;
				DateTime dtLastWriteDB = DateTime.MinValue;		//追加

				//DB中にデータがすでにあるかどうかチェック。あればIDと日時を取得
				using (SQLiteCommand cmd = _conn.CreateCommand())
				{
					cmd.CommandText = @"SELECT id, lastwritedate FROM TagInfo WHERE file=@file and entryindex=@entryindex;";		//変更
					cmd.Parameters.Add(new SQLiteParameter("@file", strFile));
					cmd.Parameters.Add(new SQLiteParameter("@entryindex", item.nEntryIndex));
					cmd.Prepare();

					using (SQLiteDataReader reader = cmd.ExecuteReader())
					{
						while (reader.Read())
						{
							try
							{
								nID = reader.GetInt32(0);
								dtLastWriteDB = new DateTime(reader.GetInt64(1));		//追加
								break;
							}
							catch (Exception)
							{
							}
						}
					}
				}

				//IDがなかった=データがない=新規追加
				if (nID < 0)
					return SQL_AddNewTagInfo(item, dtLastWrite, strTitle, strArtist, strAlbum);

				//変更
				//IDが見つかった=データがある=古いなら更新
				if (dtLastWriteDB < dtLastWrite)
					return SQL_UpdateTagInfo(nID, dtLastWrite, strTitle, strArtist, strAlbum);
				else
					return true;		//更新の必要なし
			}
			catch (Exception)
			{
			}

			return false;
		}



		//変更
		/// <summary>
		/// DB情報の構築
		/// </summary>
		public static int RefreshAllInfo(bool bAllClear, ProgressForm dlg)		//変更
		{
			int nCount = 0;

			// サブ・ディレクトも含める
			IEnumerable<string> listFiles = Directory.EnumerateFiles(Form1._option.strFolder, "*.*", SearchOption.AllDirectories);

			bool ret;
			string strArtist;
			string strTitle;
			string strAlbum;

			if (bAllClear)
			{
				//既存のDBデータを全削除
				try
				{
					using (SQLiteCommand cmd = _conn.CreateCommand())
					{
						cmd.CommandText = @"TRUNCATE TABLE TagInfo;";
						cmd.ExecuteNonQuery();
					}
				}
				catch (Exception)
				{
				}
			}


			foreach (string strFile in listFiles)
			{
				//追加
				if (dlg != null)
				{
					if (dlg.bCancel)
						break;
					dlg.strProgress = "" + nCount;
				}

				string strExt = Path.GetExtension(strFile).ToLower();
				if (strExt == "")
					continue;

				if (strExt == ".mp3" || strExt == ".m4a")
				{
					//タグ情報読み込み
					ret = GetMp3Info(strFile, out strTitle, out strArtist, out strAlbum);
					if (ret)
					{
						DateTime dtLastWrite = File.GetLastWriteTime(strFile);

						//DBへ追加
						if (bAllClear)
							ret = SQL_AddNewTagInfo(new AudioItem(strFile), dtLastWrite, strTitle, strArtist, strAlbum);
						else
							ret = SQL_SetTagInfo(new AudioItem(strFile), dtLastWrite, strTitle, strArtist, strAlbum);
						if (ret)
							nCount++;
					}
					continue;
				}

				//ZIPファイルなら再生できそうな全エントリーを追加
				if (strExt == ".zip")
				{
					try
					{
						DateTime dtLastWriteDB;		//追加
						DateTime dtLastWrite = File.GetLastWriteTime(strFile);

						//追加
						if (bAllClear == false)
						{
							SQL_FindDateInfo(new AudioItem(strFile), out dtLastWriteDB);
							if (dtLastWriteDB >= dtLastWrite)
								continue;		//情報更新の必要なし
						}

						using (ZipArchive archive = ZipFile.OpenRead(strFile))
						{
							for (int i = 0; i < archive.Entries.Count; i++)
							{
								//追加
								if (dlg != null)
								{
									if (dlg.bCancel)
										break;
									dlg.strProgress = "" + nCount;
								}

								strExt = Path.GetExtension(archive.Entries[i].FullName).ToLower();
								if (strExt == ".mp3" || strExt == ".m4a")
								{
									try
									{
										//解凍
										string strTmpFile = Utility.GetTmpFile() + strExt;
										archive.Entries[i].ExtractToFile(strTmpFile, true);

										//タグ情報読み込み
										ret = GetMp3Info(strTmpFile, out strTitle, out strArtist, out strAlbum);
										if (ret)
										{
											//DBへ追加
											if (bAllClear)
												ret = SQL_AddNewTagInfo(new AudioItem(strFile, i), dtLastWrite, strTitle, strArtist, strAlbum);
											else
												ret = SQL_SetTagInfo(new AudioItem(strFile, i), dtLastWrite, strTitle, strArtist, strAlbum);
											if (ret)
												nCount++;
										}

										//解凍したファイルの削除
										File.Delete(strTmpFile);
									}
									catch (Exception)
									{
									}
								}
							}
						}
					}
					catch (Exception)
					{
					}
				}

			}
			return nCount;
		}

■Form1.cs
sing System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Threading;
using System.Windows.Forms;
using WMPLib;

namespace MP3Player
{
	public partial class Form1 : Form
	{
		WindowsMediaPlayer _mediaPlayer = new WindowsMediaPlayer();

		System.Windows.Forms.Timer _timer = new System.Windows.Forms.Timer();

		public static Option _option = new Option();


		List<AudioItem> _listFiles;			//音楽ファイル一覧
		int _nCurrentIndex = -1;			//↑へのインデックス


		List<int> _listPlayHistory = new List<int>();		//過去の再生曲
		List<int> _listPlayNext = new List<int>();			//未来の再生曲。なければランダム


		bool _bStopButtonPushed = false;	//「停止」ボタンを押したらtrue

		public Form1()
		{
			InitializeComponent();

			//設定の読み込み
			Option.Load(out _option, Utility.GetExeFolder() + "option.txt");

			Utility.CreateTmpFolder();			//tmpフォルダの作成


			//ウインドウ表示位置設定
			//[Ctrl]キーが押されていないときのみ設定=表示位置を復元したくないときは[Ctrl]キーを押して起動する
			if ((Control.ModifierKeys & Keys.Control) != Keys.Control)
			{
				StartPosition = FormStartPosition.Manual;
				Location = _option.ptWindowPos;
			}


			//削除
			////DBに情報がなければ再構築する=>時間が非常にかかる!
			//if (MP3Info.GetCount() == 0)
			//{
			//	MP3Info.RefreshAllInfo(true);
			//}
		ProgressForm _dlgCreateFileList = new ProgressForm("再生フォルダの読み込み中");


		/// <summary>
		/// 設定フォルダから音楽ファイルリストを読み込む
		/// </summary>
		void CreateFileListAndPlay(bool bPlay)
		{
			buttonStop_Click(null, null);		//再生停止

			//再生リストのクリア
			_listPlayHistory.Clear();
			_listPlayNext.Clear();
			_nCurrentIndex = -1;

			_dlgCreateFileList.Init();
			_dlgCreateFileList.StartPosition = FormStartPosition.Manual;
			_dlgCreateFileList.Location = new Point(Location.X + 50, Location.Y + 50);
			_dlgCreateFileList.Show(this);

			Thread thread = new Thread(new ThreadStart(delegate
				{
					//追加
					{
						DialogResult ret = MessageBox.Show("ファイル読み込みだけでなく、DB更新もしますか?\n(時間がかかります)", "ファイル読み込み", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
						if (ret == DialogResult.OK)
						{
							//DB更新
							MP3Info.RefreshAllInfo(false, _dlgCreateFileList);
						}
					}

					//mp3フォルダからの音楽ファイルリスト読み込み
					_listFiles = EnumFiles(_option.strFolder, _dlgCreateFileList);

					try
					{
						Invoke((MethodInvoker)delegate
						{
							_dlgCreateFileList.Close();
						});
					}
					catch (Exception)
					{
					}

					if (bPlay)
					{
						Invoke((MethodInvoker)delegate
						{
							Play();		//再生開始
						});
					}
				}));

			thread.Start();
		}

プロジェクトファイルをダウンロード


カテゴリー「MP3プレーヤーを作る(C#)」 のエントリー