第26回 データベースの曲情報を利用する

今回はデータベースへ保存した曲名/アーティスト名の情報を実際に利用します。

単純に読みだすだけではなくデータベース上の曲情報が古くなっている(更新されていない)場合は
データベースから読み出すのではなく音楽ファイルから読み出し、データベース上の曲情報をアップデートします。

データが更新されているかどうかは、ファイルの更新日時情報を利用して判定しました。

Utility.cs内で定義していた、
GetMp3Info()
GetMp3Info()
class AudioFileAbstraction
の3つを削除して、Mp3Info.csへ移動/変更します。
あとはGetMp3Info()を参照していたForm1内の箇所を修正するだけです。

■Mp3Info.cs
		/// <summary>
		/// DB情報の構築
		/// </summary>
		public static int RefreshAllInfo(bool bAllClear = false)
		{
			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)
			{
				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 dtLastWrite = File.GetLastWriteTime(strFile);
						using (ZipArchive archive = ZipFile.OpenRead(strFile))
						{
							for (int i = 0; i < archive.Entries.Count; i++)
							{
								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;
		}



		//Utilityから移動/変更
		/// <summary>
		/// MP3ファイルからの曲名情報取得(DB/zip対応)
		/// </summary>
		public static bool GetMp3Info(AudioItem item, out string strTitle, out string strArtist, out string strAlbum)
		{
			bool ret;

			DateTime dtLastWriteDB;
			DateTime dtLastWriteCurrent = File.GetLastWriteTime(item.strFile);

			//DBから取得を試みる
			ret = SQL_FindTagInfo(item, out dtLastWriteDB, out strTitle, out strArtist, out strAlbum);
			if (ret)
			{
				//mp3ファイルが更新されていなければDBの情報をそのまま返す
				//(更新されていれば、新しい情報を読み込む)
				if (dtLastWriteCurrent <= dtLastWriteDB)
					return true;
			}

			if (item.nEntryIndex < 0)
			{
				//zipファイル以外はそのまま情報取得
				ret = GetMp3Info(item.strFile, out strTitle, out strArtist, out strAlbum);
			}
			else
			{
				//zipファイルは解凍して取得
				try
				{
					string strFile;

					ret = Utility.ExtractFileFromZip(item.strFile, item.nEntryIndex, Utility.GetTmpFile(), out strFile);
					if (ret)
						ret = GetMp3Info(strFile, out strTitle, out strArtist, out strAlbum);

					File.Delete(strFile);
				}
				catch (Exception)
				{
					ret = false;
				}
			}

			if (ret)
			{
				//DBに情報を入れておく
				SQL_SetTagInfo(item, dtLastWriteCurrent, strTitle, strArtist, strAlbum);
				return true;
			}

			strArtist = "";
			strTitle = "";
			strAlbum = "";
			return false;
		}


		//Utilityから移動/変更
		/// <summary>
		/// MP3ファイルからの曲名情報取得(ファイルから直接取得)
		/// 
		/// TagLib# Portable利用
		/// https://github.com/timheuer/taglib-sharp-portable
		/// </summary>
		static bool GetMp3Info(string strFile, out string strTitle, out string strArtist, out string strAlbum)
		{
			strArtist = "";
			strTitle = "";
			strAlbum = "";
			try
			{
				using (FileStream fs = new FileStream(strFile, FileMode.Open, FileAccess.Read))
				{
					AudioFileAbstraction abstraction = new AudioFileAbstraction(strFile, fs);

					using (TagLib.File file = TagLib.File.Create(abstraction))
					{
						strTitle = file.Tag.Title;
						strAlbum = file.Tag.Album;
						strArtist = file.Tag.FirstPerformer;

						if (strArtist == null || strArtist == "")
						{
							if (file.Tag.AlbumArtists.Length > 0)
								strArtist = file.Tag.AlbumArtists[0];
						}

						if (strArtist == null || strArtist == "")
							strArtist = file.Tag.FirstArtist;		//古いのも使う
						if (strArtist == null || strArtist == "")
							strArtist = file.Tag.FirstComposer;
						if (strArtist == null || strArtist == "")
							strArtist = file.Tag.JoinedAlbumArtists;

						file.Dispose();
					}
				}

				if (strArtist == null)
					strArtist = "";
				if (strTitle == null)
					strTitle = "";
				if (strAlbum == null)
					strAlbum = "";

				return true;
			}
			catch (Exception)
			{
			}
			strArtist = "";
			strTitle = "";
			strAlbum = "";
			return false;
		}



		/// <summary>
		/// TagLibからの情報取得用
		/// </summary>
		class AudioFileAbstraction : TagLib.File.IFileAbstraction
		{
			string _strName = "";
			Stream _stream = null;

			public AudioFileAbstraction(string Name, Stream Stream)
			{
				_strName = Name;
				_stream = Stream;
			}

			void TagLib.File.IFileAbstraction.CloseStream(Stream stream)
			{
				stream.Close();
			}

			string TagLib.File.IFileAbstraction.Name
			{
				get { return _strName; }
			}

			Stream TagLib.File.IFileAbstraction.ReadStream
			{
				get { return _stream; }
			}

			Stream TagLib.File.IFileAbstraction.WriteStream
			{
				get { return _stream; }
			}
		}
	}
}
■Form1.cs
		/// <summary>
		/// 曲を再生する
		/// </summary>
		void Play(bool bPlayNext = true)
		{
			if (_listFiles.Count == 0)
				return;

			if (bPlayNext || _listPlayHistory.Count == 0)
			{
				//次の曲を再生する
				if (_nCurrentIndex >= 0)
				{
					_listPlayHistory.Add(_nCurrentIndex);					//今の曲を履歴として保存
					if (_listPlayHistory.Count > 100)						//履歴の最大保存数は100
						_listPlayHistory.RemoveAt(0);
				}

				_nCurrentIndex = GetNextIndex();
			}
			else
			{
				//前の曲を再生する
				if (_nCurrentIndex >= 0)
					_listPlayNext.Insert(0, _nCurrentIndex);					//今の曲を次の曲として保存
				_nCurrentIndex = _listPlayHistory[_listPlayHistory.Count - 1];	//一番最新の履歴曲を今の曲とする
				_listPlayHistory.RemoveAt(_listPlayHistory.Count - 1);			//一番最新の履歴曲を削除
			}

			Utility.CleanTempFolder();			//tmpフォルダ内の削除

			string strFile = _listFiles[_nCurrentIndex].strFile;
			if (_listFiles[_nCurrentIndex].nEntryIndex >= 0)
			{
				//zip書庫ならtmpフォルダに解凍する
				bool ret = Utility.ExtractFileFromZip(strFile, _listFiles[_nCurrentIndex].nEntryIndex, Utility.GetTmpFile(), out strFile);
				if (ret == false)
					return;
			}

			_mediaPlayer.URL = strFile;			//再生曲をセット
			_mediaPlayer.controls.play();

			//曲名/タイトルの表示
			{
				string strTitle;
				string strArtist;
				string strAlbum;

				MP3Info.GetMp3Info(_listFiles[_nCurrentIndex], out strTitle, out strArtist, out strAlbum);		//変更

				labelTitle.Text = strTitle;
				labelArtist.Text = strArtist;

				ShowRating();		//追加
			}
		}

		//以下を追加
		/// <summary>
		/// レーティングの表示
		/// </summary>
		void ShowRating()
		{
			if (_nCurrentIndex < 0)
			{
				labelRating.Text = "";
				labelRatingArtist.Text = "";
				return;
			}

			int nRating = _option.GetRating(_listFiles[_nCurrentIndex]);
			int nRatingArtist = _option.GetRatingArtist(labelArtist.Text);

			labelRating.Text = GetRatingString(nRating);
			labelRatingArtist.Text = GetRatingString(nRatingArtist);
		}


		//以下を追加
		/// <summary>
		/// レーティング文字列「★」~「★★★★★」の作成
		/// </summary>
		string GetRatingString(int nRating)
		{
			if (nRating > 5)
				nRating = 5;
			if (nRating < 0)
				nRating = 0;

			string str = "";
			for (int i = 0; i < nRating; i++)
				str += "★";
			for (int i = nRating; i < 5; i++)
				str += " ";

			return str;
		}




		/// <summary>
		/// 次の再生曲インデックスを決める
		/// </summary>
		int GetNextIndex()
		{
			if (_listFiles.Count == 0)
				return -1;

			int nIndex;
			Random rnd = new Random(Environment.TickCount);

			while (true)
			{
				if (_listPlayNext.Count == 0)
				{
					//未来の曲リストが空ならランダムで曲を決定
					nIndex = rnd.Next(0, _listFiles.Count);
				}
				else
				{
					//未来の曲リストから次の曲を決定
					nIndex = _listPlayNext[0];
					_listPlayNext.RemoveAt(0);
				}

				//同じ曲は連続で演奏しない
				if (nIndex == _nCurrentIndex)
					continue;

				//NGファイル指定されていないかチェック
				if (_option.IsNGFile(_listFiles[nIndex]))
					continue;

				//mp3情報を取得
				string strTitle;
				string strArtist;
				string strAlbum;
				MP3Info.GetMp3Info(_listFiles[nIndex], out strTitle, out strArtist, out strAlbum);		//変更

				//アーティストがNG指定されていないかチェック
				if (_option.IsNGArtist(strArtist))
					continue;

				//曲名がNGワードを含まないかチェック
				if (_option.IsNGWord(strTitle))
					continue;

				//ファイル追加日時が再生条件を満たすかチェック
				if (_option.IsPlayDayTermOK(_listFiles[nIndex]) == false)
					continue;

				break;
			}

			return nIndex;
		}

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


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