前の10件 1  2  3  4  5  6  7  8  9  10  11

記事一覧

第21回 レーティングを設定/保存する

今回は曲とアーティストのレーティング設定/保存処理を作成します。

「レーティング」は本来であればファイルのプロパティ情報として、
他のアプリケーションなどからも見れるように保存すべきものです。
しかし今回は独自情報として保持するカタチにしました。

ついでにNGワードのデフォルト値登録が重複登録されるバグがあったためそれの修正もしています。

■Option.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace MP3Player
{
	[Serializable]
	public class AudioItem
	{
		public string strFile = "";
		public int nEntryIndex = -1;

		public AudioItem()
		{
		}

		public AudioItem(string strFile, int nEntryIndex = -1)
		{
			this.strFile = strFile;
			this.nEntryIndex = nEntryIndex;
		}
	}

	//以下を追加
	[Serializable]
	public class RatingItem : AudioItem
	{
		public int nRating = 0;

		public RatingItem()
		{
		}

		public RatingItem(string strFile, int nEntryIndex, int nRating)
			: base(strFile, nEntryIndex)
		{
			this.nRating = nRating;
		}
	}

	//以下を追加
	[Serializable]
	public class RatingArtistItem
	{
		public string strArtist = "";
		public int nRating = 0;

		public RatingArtistItem()
		{
		}

		public RatingArtistItem(string strArtist, int nRating)
		{
			this.strArtist = strArtist;
			this.nRating = nRating;
		}
	}


	[Serializable]
	public class Option
	{
		void AfterLoaded()		//変更
		{
			//デフォルトでカラオケ曲などをNG指定
			AddNGWord("カラオケ");
			AddNGWord("karaoke");
			AddNGWord("inst.");
			AddNGWord("instrum");
			AddNGWord("トイレの神様");
		}

		public int nVolume
		{
			get { return _nVolume; }
			set { _nVolume = value; }
		}
		int _nVolume = 20;


		public string strFolder
		{
			get { return _strFolder; }
			set { _strFolder = value; }
		}
		string _strFolder = @"G:\Desktop\mp3\";


		//以下を追加
		/// <summary>
		/// 曲のレーティング情報
		/// </summary>
		public List<RatingItem> listRating
		{
			get { return _listRating; }
			set { _listRating = value; }
		}
		List<RatingItem> _listRating = new List<RatingItem>();


		//以下を追加
		/// <summary>
		/// アーティストのレーティング情報
		/// </summary>
		public List<RatingArtistItem> listRatingArtist
		{
			get { return _listRatingArtist; }
			set { _listRatingArtist = value; }
		}
		List<RatingArtistItem> _listRatingArtist = new List<RatingArtistItem>();


		//以下を追加
		/// <summary>
		/// 曲レーティングの設定
		/// </summary>
		public void SetRating(AudioItem item, int nRating)
		{
			string strFile = RemoveMP3FolderName(item.strFile);		//MP3フォルダ部を削除して比較処理に回す

			//すでにレーティングのついている曲ならレーティングを上書きもしくは削除
			for (int i = 0; i < _listRating.Count; i++)
			{
				if (string.Compare(_listRating[i].strFile, strFile, true) != 0)
					continue;

				if (_listRating[i].nEntryIndex != item.nEntryIndex)
					continue;

				if (nRating > 0)
					_listRating[i].nRating = nRating;
				else
					_listRating.RemoveAt(i);
				return;
			}

			if (nRating > 0)
			{
				//新しくレーティングを追加
				_listRating.Add(new RatingItem(strFile, item.nEntryIndex, nRating));
			}
		}


		//以下を追加
		/// <summary>
		/// 曲レーティングの取得
		/// </summary>
		public int GetRating(AudioItem item)
		{
			string strFile = RemoveMP3FolderName(item.strFile);		//MP3フォルダ部を削除して比較処理に回す

			foreach (RatingItem current in _listRating)
			{
				if (string.Compare(current.strFile, strFile, true) != 0)
					continue;

				if (current.nEntryIndex != item.nEntryIndex)
					continue;

				return current.nRating;;
			}
			return 0;
		}




		//以下を追加
		/// <summary>
		/// アーティストレーティングの設定(ignoreCaseで比較)
		/// </summary>
		public void SetRatingArtist(string strArtist, int nRating)
		{
			if (strArtist == "")
				return;

			//すでにレーティングのついているアーティストならレーティングを上書きもしくは削除
			for (int i = 0; i < _listRatingArtist.Count; i++)
			{
				if (string.Compare(_listRatingArtist[i].strArtist, strArtist, true) != 0)
					continue;

				if (nRating > 0)
					_listRatingArtist[i].nRating = nRating;
				else
					_listRatingArtist.RemoveAt(i);
				return;
			}

			if (nRating > 0)
			{
				//新しくレーティングを追加
				_listRatingArtist.Add(new RatingArtistItem(strArtist, nRating));
			}
		}


		//以下を追加
		/// <summary>
		/// アーティストレーティングの取得(ignoreCaseで比較)
		/// </summary>
		public int GetRatingArtist(string strArtist)
		{
			if (strArtist == "")
				return 0;

			foreach (RatingArtistItem current in _listRatingArtist)
			{
				if (string.Compare(current.strArtist, strArtist, true) != 0)
					continue;

				return current.nRating;
			}
			return 0;
		}






		public List<string> listNGWords
		{
			get { return _listNGWords; }
			set { _listNGWords = value; }
		}
		List<string> _listNGWords = new List<string>();

		public List<string> listNGArtists
		{
			get { return _listNGArtists; }
			set { _listNGArtists = value; }
		}
		List<string> _listNGArtists = new List<string>();


		public List<AudioItem> listNGFiles
		{
			get { return _listNGFiles; }
			set { _listNGFiles = value; }
		}
		List<AudioItem> _listNGFiles = new List<AudioItem>();


		/// <summary>
		/// NGワードの追加
		/// </summary>
		public void AddNGWord(string strKeyword)
		{
			if (strKeyword == "")
				return;

			//すでにNGリストに含まれるかチェック
			if (IsNGWord(strKeyword))
				return;

			_listNGWords.Add(strKeyword);
		}


		/// <summary>
		/// NGワードかどうかチェック(OrdinalIgnoreCase比較、含むかどうか比較)
		/// </summary>
		public bool IsNGWord(string strTitle)
		{
			strTitle = strTitle.ToLower();
			string find = _listNGWords.Find(cmp =>
				{
					cmp = cmp.ToLower();
					if (strTitle.IndexOf(cmp, StringComparison.OrdinalIgnoreCase) >= 0)
						return true;
					return false;
				});

			return (find != null && find != "") ? true : false;
		}


		/// <summary>
		/// NGアーティストの追加
		/// </summary>
		public void AddNGArtist(string strArtist)
		{
			if (strArtist == "")
				return;

			//すでにNGリストに含まれるかチェック
			if (IsNGArtist(strArtist))
				return;

			_listNGArtists.Add(strArtist);
		}


		/// <summary>
		/// NGアーティストかどうかチェック(ignoreCase比較、スペース無視)
		/// 
		/// アーティストの苗字と名前の間にスペースが入っているケースがあるため、スペースを除去して比較している
		/// これによりまったく別人アーティストが同一と判定される可能性もある
		/// </summary>
		public bool IsNGArtist(string strArtist)
		{
			strArtist = strArtist.Replace(" ", "");		//半角スペース除去
			strArtist = strArtist.Replace(" ", "");	//全角スペース除去

			string find = _listNGArtists.Find(cmp =>
				{
					cmp = cmp.Replace(" ", "");		//半角スペース除去
					cmp = cmp.Replace(" ", "");	//全角スペース除去
					if (string.Compare(cmp, strArtist, true) == 0)
						return true;
					return false;
				});

			return (find != null && find != "") ? true : false;
		}





		/// <summary>
		/// NGファイルの追加
		/// </summary>
		public void AddNGFile(AudioItem item)
		{
			//すでにNGファイルリストに含まれるかチェック
			if (IsNGFile(item))
				return;

			//MP3フォルダ部を削除して追加
			_listNGFiles.Add(new AudioItem(RemoveMP3FolderName(item.strFile), item.nEntryIndex));
		}


		/// <summary>
		/// NGファイルかどうかチェック(ignoreCase比較)
		/// </summary>
		public bool IsNGFile(AudioItem item)
		{
			string strFile = RemoveMP3FolderName(item.strFile);		//MP3フォルダ部を削除して比較処理に回す

			AudioItem find = _listNGFiles.Find(cmp =>
				{
					if (string.Compare(cmp.strFile, strFile, true) != 0)
						return false;			//ファイル名が違うなら無視
					if (cmp.nEntryIndex == item.nEntryIndex)
						return true;			//同じならNG
					if (cmp.nEntryIndex == -1)
						return true;			//-1がNGリストにあった場合はNG(zipファイル自体がNG指定されているケースが該当)
					return false;
				});

			return (find != null) ? true : false;
		}





		/// <summary>
		/// strFileとして渡されたパスから、mp3保存用フォルダー名部分だけを削除する(完全にファイル名のみにするわけではない)
		/// </summary>
		public string RemoveMP3FolderName(string strFile)
		{
			if (strFile == "" || _strFolder == "" || strFile.Length < _strFolder.Length)
				return strFile;

			if (strFile.Substring(0, _strFolder.Length).ToLower() == _strFolder.ToLower())
				return strFile.Substring(_strFolder.Length);

			return strFile;
		}





		/// <summary>
		/// このクラスをXMLとして保存
		/// </summary>
		public bool Save(string strFilePath)
		{
			try
			{
				XmlSerializer serializer = new XmlSerializer(typeof(Option));
				using (FileStream fs = new FileStream(strFilePath, FileMode.Create))
				{
					serializer.Serialize(fs, this);
					fs.Close();
				}
				return true;
			}
			catch (Exception)
			{
			}
			return false;
		}



		/// <summary>
		/// このクラスをXMLから読み込み
		/// </summary>
		/// <returns>成功時true、失敗時false=new Option()で返す</returns>
		public static bool Load(out Option option, string strFilePath)
		{
			try
			{
				//↓で例外が発生するが、無視してOK 「型 'System.IO.FileNotFoundException' の初回例外が mscorlib.dll で発生しました」
				//http://yk.tea-nifty.com/netdev/2009/03/xmlserializer-a.html
				XmlSerializer serializer = new XmlSerializer(typeof(Option));
#if DEBUG
				Debug.WriteLine("↑'System.IO.FileNotFoundException'の例外が発生しても無視してOK");
#endif
				using (FileStream fs = new FileStream(strFilePath, FileMode.Open, FileAccess.Read))
				{
					option = (Option)serializer.Deserialize(fs);
					fs.Close();
				}

				option.AfterLoaded();		//追加

				return true;
			}
			catch (Exception)
			{
			}
			option = new Option();		//失敗時は新しいのを作る
			return false;
		}

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

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

		Timer _timer = new 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フォルダの作成


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


			//フォームが表示されたときの処理
			Shown += delegate
			{
				//シークバーにフォーカスがあると、再生位置が表示されないのでここで再生ボタンにフォーカスを与える
				buttonPlay.Focus();
			};


			//フォーム右クリックメニューの設定
			{
				ContextMenuStrip menu = new ContextMenuStrip();

				ToolStripItem[] stripItem = new ToolStripMenuItem[]
				{
					new ToolStripMenuItem("曲レーティング",null,new ToolStripMenuItem[]
					{
						new ToolStripMenuItem("なし", null, delegate
							{
								SetRating(0);		//追加
							}),
						new ToolStripMenuItem("★", null, delegate
							{
								SetRating(1);		//追加
							}),
						new ToolStripMenuItem("★★", null, delegate
							{
								SetRating(2);		//追加
							}),
						new ToolStripMenuItem("★★★", null, delegate
							{
								SetRating(3);		//追加
							}),
						new ToolStripMenuItem("★★★★", null, delegate
							{
								SetRating(4);		//追加
							}),
						new ToolStripMenuItem("★★★★★", null, delegate
							{
								SetRating(5);		//追加
							}),
					}),
					new ToolStripMenuItem("アーティストレーティング",null,new ToolStripMenuItem[]
					{
						new ToolStripMenuItem("なし", null, delegate
							{
								SetRatingArtist(0);	//追加
							}),
						new ToolStripMenuItem("★", null, delegate
							{
								SetRatingArtist(1);	//追加
							}),
						new ToolStripMenuItem("★★", null, delegate
							{
								SetRatingArtist(2);	//追加
							}),
						new ToolStripMenuItem("★★★", null, delegate
							{
								SetRatingArtist(3);	//追加
							}),
						new ToolStripMenuItem("★★★★", null, delegate
							{
								SetRatingArtist(4);	//追加
							}),
						new ToolStripMenuItem("★★★★★", null, delegate
							{
								SetRatingArtist(5);	//追加
							}),
					}),
					new ToolStripMenuItem("NG登録", null, delegate
						{
							if (_nCurrentIndex >= 0)
							{
								AddNGForm dlg = new AddNGForm(_listFiles[_nCurrentIndex], labelTitle.Text, labelArtist.Text);
								dlg.ShowDialog();
							}
						}),
					new ToolStripMenuItem("再生設定", null, delegate
						{
						}),
					new ToolStripMenuItem("エクスプローラー", null, delegate
						{
							if (_nCurrentIndex >= 0)
							{
								Process.Start("explorer.exe","/select,\"" + _listFiles[_nCurrentIndex].strFile + "\"");
							}
						}),
					new ToolStripMenuItem("最小化", null, delegate
						{
							if (WindowState == FormWindowState.Normal)
								WindowState = FormWindowState.Minimized;
						}),
					new ToolStripMenuItem("終了", null, delegate
						{
							Close();
						}),
				};
				menu.Items.AddRange(stripItem);

				ContextMenuStrip = menu;
			}



			//終了時処理
			FormClosed += delegate
			{
				Utility.CleanTempFolder();			//tmpフォルダ内の削除

				//設定の保存
				_option.Save(Utility.GetExeFolder() + "option.txt");
			};


			//再生位置のシーク
			trackBarSeek.ValueChanged += delegate
			{
				if (trackBarSeek.Focused)
				{
					_mediaPlayer.controls.currentPosition = (double)trackBarSeek.Value / 100;
				}
			};


			//音量の調節
			_mediaPlayer.settings.volume = _option.nVolume;
			trackBarVolume.Maximum = 100;			//音量はゼロから100
			trackBarVolume.Value = _mediaPlayer.settings.volume;
			trackBarVolume.ValueChanged += delegate
			{
				_option.nVolume = (int)trackBarVolume.Value;
				_mediaPlayer.settings.volume = _option.nVolume;
			};


			_timer.Interval = 300;			//300msecごとに処理を実行
			_timer.Tick += delegate
			{
				if (_mediaPlayer.playState == WMPPlayState.wmppsPlaying || _mediaPlayer.playState == WMPPlayState.wmppsPaused)
				{
					trackBarSeek.Maximum = (int)(_mediaPlayer.controls.currentItem.duration * 100);
					//シークバーにフォーカスがないときだけ再生位置を表示する
					if (trackBarSeek.Focused == false)
					{
						try
						{
							//シークバーに再生位置を表示
							//曲変更タイミングによっては例外出る可能性ある
							trackBarSeek.Value = (int)(_mediaPlayer.controls.currentPosition * 100);
						}
						catch (Exception)
						{
						}
					}

					//再生時間の表示
					labelTime.Text = _mediaPlayer.controls.currentPositionString;
				}

				//止まっていたら再び再生。ただし停止ボタンが押されている場合は無視
				if (_mediaPlayer.playState == WMPPlayState.wmppsStopped)
				{
					if (_bStopButtonPushed == false)
						Play();
				}
			};
			_timer.Start();


			_mediaPlayer.PlayStateChange += delegate(int nNewState)
			{
				WMPPlayState state = (WMPPlayState)nNewState;

				switch (state)
				{
					case WMPPlayState.wmppsStopped:
						buttonPlay.Text = ">";
						trackBarSeek.Value = 0;
						break;

					case WMPPlayState.wmppsPaused:
						_timer.Stop();
						buttonPlay.Text = ">";
						break;

					case WMPPlayState.wmppsPlaying:
						_bStopButtonPushed = false;
						buttonPlay.Text = "||";
						_timer.Start();
						break;

					case WMPPlayState.wmppsTransitioning:
						break;
				}
			};

			Play();
		}


		//以下を追加
		/// <summary>
		/// 曲レーティング設定
		/// </summary>
		void SetRating(int nRating)
		{
			if (_nCurrentIndex < 0)
				return;
			_option.SetRating(_listFiles[_nCurrentIndex], nRating);
		}

		//以下を追加
		/// <summary>
		/// アーティストレーティング設定
		/// </summary>
		void SetRatingArtist(int nRating)
		{
			if (_nCurrentIndex < 0)
				return;
			_option.SetRatingArtist(labelArtist.Text, nRating);
		}


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

第20回 右クリックメニューを用意する

これまでの作業ではフォームを右クリックするだけでNG登録画面が表示されるようにしていました。
今回はメインウインドウに右クリックメニューを用意して、そこから開くようにします。

ついでに次回以降のためにレーティング用や再生設定用のメニュー項目、
エクスプローラーで開いたり、最小化、終了するためのメニュー項目も用意しました。

using System;
using System.Collections.Generic;
using System.Diagnostics;			//追加
using System.IO;
using System.IO.Compression;
using System.Windows.Forms;
using WMPLib;

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

		Timer _timer = new 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フォルダの作成


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


			//フォームが表示されたときの処理
			Shown += delegate
			{
				//シークバーにフォーカスがあると、再生位置が表示されないのでここで再生ボタンにフォーカスを与える
				buttonPlay.Focus();
			};

			//以下を削除
			////暫定的に右クリックでNG登録画面を呼び出す
			//MouseClick +=  (sender, e) =>
			//{
			//	if (e.Button == MouseButtons.Right)
			//	{
			//		if (_nCurrentIndex >= 0)
			//		{
			//			AddNGForm dlg = new AddNGForm(_listFiles[_nCurrentIndex], labelTitle.Text, labelArtist.Text);
			//			dlg.ShowDialog();
			//		}
			//	}
			//};

			//以下を追加
			//フォーム右クリックメニューの設定
			{
				ContextMenuStrip menu = new ContextMenuStrip();

				ToolStripItem[] stripItem = new ToolStripMenuItem[]
				{
					new ToolStripMenuItem("曲レーティング",null,new ToolStripMenuItem[]
					{
						new ToolStripMenuItem("なし", null, delegate
							{
							}),
						new ToolStripMenuItem("★", null, delegate
							{
							}),
						new ToolStripMenuItem("★★", null, delegate
							{
							}),
						new ToolStripMenuItem("★★★", null, delegate
							{
							}),
						new ToolStripMenuItem("★★★★", null, delegate
							{
							}),
						new ToolStripMenuItem("★★★★★", null, delegate
							{
							}),
					}),
					new ToolStripMenuItem("アーティストレーティング",null,new ToolStripMenuItem[]
					{
						new ToolStripMenuItem("なし", null, delegate
							{
							}),
						new ToolStripMenuItem("★", null, delegate
							{
							}),
						new ToolStripMenuItem("★★", null, delegate
							{
							}),
						new ToolStripMenuItem("★★★", null, delegate
							{
							}),
						new ToolStripMenuItem("★★★★", null, delegate
							{
							}),
						new ToolStripMenuItem("★★★★★", null, delegate
							{
							}),
					}),
					new ToolStripMenuItem("NG登録", null, delegate
						{
							if (_nCurrentIndex >= 0)
							{
								AddNGForm dlg = new AddNGForm(_listFiles[_nCurrentIndex], labelTitle.Text, labelArtist.Text);
								dlg.ShowDialog();
							}
						}),
					new ToolStripMenuItem("再生設定", null, delegate
						{
						}),
					new ToolStripMenuItem("エクスプローラー", null, delegate
						{
							if (_nCurrentIndex >= 0)
							{
								Process.Start("explorer.exe","/select,\"" + _listFiles[_nCurrentIndex].strFile + "\"");
							}
						}),
					new ToolStripMenuItem("最小化", null, delegate
						{
							if (WindowState == FormWindowState.Normal)
								WindowState = FormWindowState.Minimized;
						}),
					new ToolStripMenuItem("終了", null, delegate
						{
							Close();
						}),
				};
				menu.Items.AddRange(stripItem);

				ContextMenuStrip = menu;
			}

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

第19回 NGアーティスト/NGワードの利用処理を入れる

前回「第18回 NGアーティスト/NGワード登録処理を作る」はNG指定機能を作りました。
今回は登録されたNG情報に基づいて再生スキップする処理を追加します。

■Utility.csへ以下を追加
		/// <summary>
		/// MP3ファイルからの曲名情報取得
		/// </summary>
		public static bool GetMp3Info(AudioItem item, out string strTitle, out string strArtist, out string strAlbum)
		{
			//zipファイル以外はそのまま情報取得
			if (item.nEntryIndex < 0)
				return GetMp3Info(item.strFile, out strTitle, out strArtist, out strAlbum);

			//zipファイルは解凍して取得
			try
			{
				bool ret;
				string strFile;

				strArtist = "";
				strTitle = "";
				strAlbum = "";

				ret = ExtractFileFromZip(item.strFile, item.nEntryIndex, GetTmpFile(), out strFile);

				if (ret)
					ret = GetMp3Info(strFile, out strTitle, out strArtist, out strAlbum);

				File.Delete(strFile);

				return ret;
			}
			catch (Exception)
			{
			}
			strArtist = "";
			strTitle = "";
			strAlbum = "";
			return false;
		}
■Form1.csのGetNextIndex()を以下のように変更
		/// <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;
				Utility.GetMp3Info(_listFiles[nIndex], out strTitle, out strArtist, out strAlbum);

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

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

				break;
			}

			return nIndex;
		}

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

第18回 NGアーティスト/NGワード登録処理を作る

前回「第17回 NG登録画面を作る」までに曲(ファイル)指定でのNG処理ができました。
今回はアーティスト名/キーワードのNG登録機能を作ります。
実際のNG処理は次回以降に持ち越しです。

処理自体はNGファイルとほぼ同じです。
比較処理だけが若干異なります。

■Option.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace MP3Player
{
	[Serializable]
	public class AudioItem
	{
		public string strFile = "";
		public int nEntryIndex = -1;

		public AudioItem()
		{
		}

		public AudioItem(string strFile, int nEntryIndex = -1)
		{
			this.strFile = strFile;
			this.nEntryIndex = nEntryIndex;
		}
	}


	[Serializable]
	public class Option
	{
		//以下を追加
		public Option()
		{
			//デフォルトでカラオケ曲などをNG指定
			AddNGWord("カラオケ");
			AddNGWord("karaoke");
			AddNGWord("inst.");
			AddNGWord("instrum");
			AddNGWord("トイレの神様");
		}


		public int nVolume
		{
			get { return _nVolume; }
			set { _nVolume = value; }
		}
		int _nVolume = 20;


		public string strFolder
		{
			get { return _strFolder; }
			set { _strFolder = value; }
		}
		string _strFolder = @"G:\Desktop\mp3\";


		//以下を追加
		public List<string> listNGWords
		{
			get { return _listNGWords; }
			set { _listNGWords = value; }
		}
		List<string> _listNGWords = new List<string>();

		//以下を追加
		public List<string> listNGArtists
		{
			get { return _listNGArtists; }
			set { _listNGArtists = value; }
		}
		List<string> _listNGArtists = new List<string>();


		public List<AudioItem> listNGFiles
		{
			get { return _listNGFiles; }
			set { _listNGFiles = value; }
		}
		List<AudioItem> _listNGFiles = new List<AudioItem>();


		//以下を追加
		/// <summary>
		/// NGワードの追加
		/// </summary>
		public void AddNGWord(string strKeyword)
		{
			if (strKeyword == "")
				return;

			//すでにNGリストに含まれるかチェック
			if (IsNGWord(strKeyword))
				return;

			_listNGWords.Add(strKeyword);
		}


		//以下を追加
		/// <summary>
		/// NGワードかどうかチェック(OrdinalIgnoreCase比較、含むかどうか比較)
		/// </summary>
		public bool IsNGWord(string strTitle)
		{
			strTitle = strTitle.ToLower();
			string find = _listNGWords.Find(cmp =>
				{
					cmp = cmp.ToLower();
					if (strTitle.IndexOf(cmp, StringComparison.OrdinalIgnoreCase) >= 0)
						return true;
					return false;
				});

			return (find != null && find != "") ? true : false;
		}


		//以下を追加
		/// <summary>
		/// NGアーティストの追加
		/// </summary>
		public void AddNGArtist(string strArtist)
		{
			if (strArtist == "")
				return;

			//すでにNGリストに含まれるかチェック
			if (IsNGArtist(strArtist))
				return;

			_listNGArtists.Add(strArtist);
		}


		//以下を追加
		/// <summary>
		/// NGアーティストかどうかチェック(ignoreCase比較、スペース無視)
		/// 
		/// アーティストの苗字と名前の間にスペースが入っているケースがあるため、スペースを除去して比較している
		/// これによりまったく別人アーティストが同一と判定される可能性もある
		/// </summary>
		public bool IsNGArtist(string strArtist)
		{
			strArtist = strArtist.Replace(" ", "");		//半角スペース除去
			strArtist = strArtist.Replace(" ", "");	//全角スペース除去

			string find = _listNGArtists.Find(cmp =>
				{
					cmp = cmp.Replace(" ", "");		//半角スペース除去
					cmp = cmp.Replace(" ", "");	//全角スペース除去
					if (string.Compare(cmp, strArtist, true) == 0)
						return true;
					return false;
				});

			return (find != null && find != "") ? true : false;
		}

■AddNGForm.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MP3Player
{
	public partial class AddNGForm : Form
	{
		AudioItem _item = null;

		public AddNGForm(AudioItem item, string strTitle, string strArtist)
		{
			InitializeComponent();

			labelTitle.Text = strTitle;
			labelArtist.Text = strArtist;
			labelFile.Text = Form1._option.RemoveMP3FolderName(item.strFile);
			_item = item;
		}


		private void buttonAddFile_Click(object sender, EventArgs e)
		{
			DialogResult ret = MessageBox.Show("NG登録しますか?\nファイル名:" + labelFile.Text, "NG登録", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
			if (ret == DialogResult.OK)
			{
				Form1._option.AddNGFile(_item);
				Close();
			}
		}

		private void buttonAddArtist_Click(object sender, EventArgs e)
		{
			//以下を追加
			DialogResult ret = MessageBox.Show("NG登録しますか?\nアーティスト名:" + labelArtist.Text, "NG登録", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
			if (ret == DialogResult.OK)
			{
				Form1._option.AddNGArtist(labelArtist.Text);
				Close();
			}
		}

		private void buttonAddKeyword_Click(object sender, EventArgs e)
		{
			//以下を追加
			if (textBoxKeyword.Text == "")
				return;
			DialogResult ret = MessageBox.Show("NG登録しますか?\nNGワード:" + textBoxKeyword.Text, "NG登録", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
			if (ret == DialogResult.OK)
			{
				Form1._option.AddNGWord(textBoxKeyword.Text);
				Close();
			}
		}
	}
}

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

第17回 NG登録画面を作る

前回「第16回 NGファイル処理を作る」はNGファイル関連処理を実装しました。
今回はその処理を使ってNG登録するための画面を作成します。

「プロジェクト」メニューから「Windowsフォームの追加」を選択し、「AddNGForm.cs」を追加します。
追加したフォーム上には
アーティスト名を表示するラベル「labelArtist」
曲名を教示するラベル「labelTitle」
ファイルパスを表示するラベル「labelFile」
NGファイルを追加するボタン「buttonAddFile」
NGアーティストを追加するボタン「buttonAddArtist」
NGワードを入力するテキストボックス「textboxKeyword」
NGワードを追加するボタン「buttonAddKeyword」
を配置し、ボタンはそれぞれダブルクリックしてイベントハンドラーを自動生成させておきます。

017_01.png

せっかくなのでついでにNGファイルへの追加処理も書きます。
今回は暫定的にメインウインドウを右クリックしたらNG登録画面が表示されるようにしました。
NGワードやNGアーティストは次回以降へ持ち越しです。

■AddNGForm.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MP3Player
{
	public partial class AddNGForm : Form
	{
		AudioItem _item = null;			//追加

		public AddNGForm(AudioItem item, string strTitle, string strArtist)		//変更
		{
			InitializeComponent();

			//以下を追加
			labelTitle.Text = strTitle;
			labelArtist.Text = strArtist;
			labelFile.Text = Form1._option.RemoveMP3FolderName(item.strFile);
			_item = item;
		}


		private void buttonAddFile_Click(object sender, EventArgs e)
		{
			//以下を追加
			DialogResult ret = MessageBox.Show("NG登録しますか?\nファイル名:" + labelFile.Text, "NG登録", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
			if (ret == DialogResult.OK)
			{
				Form1._option.AddNGFile(_item);
				Close();
			}
		}

		private void buttonAddArtist_Click(object sender, EventArgs e)
		{

		}

		private void buttonAddKeyword_Click(object sender, EventArgs e)
		{

		}
	}
}
■Form1.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Windows.Forms;
using WMPLib;

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

		Timer _timer = new 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フォルダの作成


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


			//フォームが表示されたときの処理
			Shown += delegate
			{
				//シークバーにフォーカスがあると、再生位置が表示されないのでここで再生ボタンにフォーカスを与える
				buttonPlay.Focus();
			};

			//以下を追加
			//暫定的に右クリックでNG登録画面を呼び出す
			MouseClick +=  (sender, e) =>
			{
				if (e.Button == MouseButtons.Right)
				{
					if (_nCurrentIndex >= 0)
					{
						AddNGForm dlg = new AddNGForm(_listFiles[_nCurrentIndex], labelTitle.Text, labelArtist.Text);
						dlg.ShowDialog();
					}
				}
			};

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

第16回 NGファイル処理を作る

前回「第15回 設定ファイルを作成する」は設定の保存処理を実装しました。
今回はNGファイル処理を作ります。
「NGファイル」に指定した音楽ファイルは再生しない=指定した特定の曲を再生しない機能です。
NGファイルのリストは設定ファイル内に保存することにしました。

OptionクラスにNGファイルへの追加処理、NGファイルかどうかの判定処理、NGファイルリストを追加し、
Form1で再生時にNGファイルのチェック処理をします。
NGファイルへの登録処理は次回以降へ持ち越しです。

■Option.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace MP3Player
{
	//Form1から移動/変更
	[Serializable]
	public class AudioItem
	{
		public string strFile = "";
		public int nEntryIndex = -1;

		public AudioItem()
		{
		}

		public AudioItem(string strFile, int nEntryIndex = -1)
		{
			this.strFile = strFile;
			this.nEntryIndex = nEntryIndex;
		}
	}


	[Serializable]
	public class Option
	{

		public int nVolume
		{
			get { return _nVolume; }
			set { _nVolume = value; }
		}
		int _nVolume = 20;


		public string strFolder
		{
			get { return _strFolder; }
			set { _strFolder = value; }
		}
		string _strFolder = @"G:\Desktop\mp3\";


		//以下を追加
		public List<AudioItem> listNGFiles
		{
			get { return _listNGFiles; }
			set { _listNGFiles = value; }
		}
		List<AudioItem> _listNGFiles = new List<AudioItem>();



		//以下を追加
		/// <summary>
		/// NGファイルの追加
		/// </summary>
		public void AddNGFile(AudioItem item)
		{
			//すでにNGファイルリストに含まれるかチェック
			if (IsNGFile(item))
				return;

			//MP3フォルダ部を削除して追加
			_listNGFiles.Add(new AudioItem(RemoveMP3FolderName(item.strFile), item.nEntryIndex));
		}


		//以下を追加
		/// <summary>
		/// NGファイルかどうかチェック(ignoreCase比較)
		/// </summary>
		public bool IsNGFile(AudioItem item)
		{
			string strFile = RemoveMP3FolderName(item.strFile);		//MP3フォルダ部を削除して比較処理に回す

			AudioItem find = _listNGFiles.Find(cmp =>
				{
					if (string.Compare(cmp.strFile, strFile, true) != 0)
						return false;			//ファイル名が違うなら無視
					if (cmp.nEntryIndex == item.nEntryIndex)
						return true;			//同じならNG
					if (cmp.nEntryIndex == -1)
						return true;			//-1がNGリストにあった場合はNG(zipファイル自体がNG指定されているケースが該当)
					return false;
				});

			return (find != null) ? true : false;
		}





		//以下を追加
		/// <summary>
		/// strFileとして渡されたパスから、mp3保存用フォルダー名部分だけを削除する(完全にファイル名のみにするわけではない)
		/// </summary>
		public string RemoveMP3FolderName(string strFile)
		{
			if (strFile == "" || _strFolder == "" || strFile.Length < _strFolder.Length)
				return strFile;

			if (strFile.Substring(0, _strFolder.Length).ToLower() == _strFolder.ToLower())
				return strFile.Substring(_strFolder.Length);

			return strFile;
		}
■Form1.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Windows.Forms;
using WMPLib;

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

		Timer _timer = new Timer();

		public static Option _option = new Option();



		//Option.csへ移動
		//class AudioItem
		//{
		//	public string strFile = "";
		//	public int nEntryIndex = -1;

		//	public AudioItem(string strFile, int nEntryIndex = -1)
		//	{
		//		this.strFile = strFile;
		//		this.nEntryIndex = nEntryIndex;
		//	}
		//}


		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フォルダの作成


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


			//フォームが表示されたときの処理
			Shown += delegate
			{
				//シークバーにフォーカスがあると、再生位置が表示されないのでここで再生ボタンにフォーカスを与える
				buttonPlay.Focus();
			};


			//終了時処理
			FormClosed += delegate
			{
				Utility.CleanTempFolder();			//tmpフォルダ内の削除

				//設定の保存
				_option.Save(Utility.GetExeFolder() + "option.txt");
			};


			//再生位置のシーク
			trackBarSeek.ValueChanged += delegate
			{
				if (trackBarSeek.Focused)
				{
					_mediaPlayer.controls.currentPosition = (double)trackBarSeek.Value / 100;
				}
			};


			//音量の調節
			_mediaPlayer.settings.volume = _option.nVolume;
			trackBarVolume.Maximum = 100;			//音量はゼロから100
			trackBarVolume.Value = _mediaPlayer.settings.volume;
			trackBarVolume.ValueChanged += delegate
			{
				_option.nVolume = (int)trackBarVolume.Value;
				_mediaPlayer.settings.volume = _option.nVolume;
			};


			_timer.Interval = 300;			//300msecごとに処理を実行
			_timer.Tick += delegate
			{
				if (_mediaPlayer.playState == WMPPlayState.wmppsPlaying || _mediaPlayer.playState == WMPPlayState.wmppsPaused)
				{
					trackBarSeek.Maximum = (int)(_mediaPlayer.controls.currentItem.duration * 100);
					//シークバーにフォーカスがないときだけ再生位置を表示する
					if (trackBarSeek.Focused == false)
					{
						try
						{
							//シークバーに再生位置を表示
							//曲変更タイミングによっては例外出る可能性ある
							trackBarSeek.Value = (int)(_mediaPlayer.controls.currentPosition * 100);
						}
						catch (Exception)
						{
						}
					}

					//再生時間の表示
					labelTime.Text = _mediaPlayer.controls.currentPositionString;
				}

				//止まっていたら再び再生。ただし停止ボタンが押されている場合は無視
				if (_mediaPlayer.playState == WMPPlayState.wmppsStopped)
				{
					if (_bStopButtonPushed == false)
						Play();
				}
			};
			_timer.Start();


			_mediaPlayer.PlayStateChange += delegate(int nNewState)
			{
				WMPPlayState state = (WMPPlayState)nNewState;

				switch (state)
				{
					case WMPPlayState.wmppsStopped:
						buttonPlay.Text = ">";
						trackBarSeek.Value = 0;
						break;

					case WMPPlayState.wmppsPaused:
						_timer.Stop();
						buttonPlay.Text = ">";
						break;

					case WMPPlayState.wmppsPlaying:
						_bStopButtonPushed = false;
						buttonPlay.Text = "||";
						_timer.Start();
						break;

					case WMPPlayState.wmppsTransitioning:
						break;
				}
			};

			Play();
		}





		/// <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;

				Utility.GetMp3Info(strFile, out strTitle, out strArtist, out strAlbum);

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



		/// <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;

				break;
			}

			return nIndex;
		}

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

2016年03月09日

第15回 設定ファイルを作成する

今回はxml形式での設定ファイルの保存/読み込み処理を作成します。
保存項目は現状では再生するフォルダ名と音量の2項目だけ。

「プロジェクト」メニューにある「クラスの追加」で「Option.cs」を追加して「Option」クラスを作成。
そこへ設定項目のプロパティと保存/読み込み処理を追加、
Form1内でそれを使うようにします。

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Windows.Forms;
using WMPLib;

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

		Timer _timer = new Timer();

		public static Option _option = new Option();		//追加


		class AudioItem
		{
			public string strFile = "";
			public int nEntryIndex = -1;

			public AudioItem(string strFile, int nEntryIndex = -1)
			{
				this.strFile = strFile;
				this.nEntryIndex = nEntryIndex;
			}
		}


		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フォルダの作成

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


			//フォームが表示されたときの処理
			Shown += delegate
			{
				//シークバーにフォーカスがあると、再生位置が表示されないのでここで再生ボタンにフォーカスを与える
				buttonPlay.Focus();
			};


			//終了時処理
			FormClosed += delegate
			{
				Utility.CleanTempFolder();			//tmpフォルダ内の削除

				//追加
				//設定の保存
				_option.Save(Utility.GetExeFolder() + "option.txt");
			};


			//再生位置のシーク
			trackBarSeek.ValueChanged += delegate
			{
				if (trackBarSeek.Focused)
				{
					_mediaPlayer.controls.currentPosition = (double)trackBarSeek.Value / 100;
				}
			};


			//音量の調節
			_mediaPlayer.settings.volume = _option.nVolume;				//変更
			trackBarVolume.Maximum = 100;			//音量はゼロから100
			trackBarVolume.Value = _mediaPlayer.settings.volume;
			trackBarVolume.ValueChanged += delegate
			{
				_option.nVolume = (int)trackBarVolume.Value;		//追加
				_mediaPlayer.settings.volume = _option.nVolume;		//変更
			};


			_timer.Interval = 300;			//300msecごとに処理を実行
			_timer.Tick += delegate
			{
				if (_mediaPlayer.playState == WMPPlayState.wmppsPlaying || _mediaPlayer.playState == WMPPlayState.wmppsPaused)
				{
					trackBarSeek.Maximum = (int)(_mediaPlayer.controls.currentItem.duration * 100);
					//シークバーにフォーカスがないときだけ再生位置を表示する
					if (trackBarSeek.Focused == false)
					{
						try
						{
							//シークバーに再生位置を表示
							//曲変更タイミングによっては例外出る可能性ある
							trackBarSeek.Value = (int)(_mediaPlayer.controls.currentPosition * 100);
						}
						catch (Exception)
						{
						}
					}

					//再生時間の表示
					labelTime.Text = _mediaPlayer.controls.currentPositionString;
				}

				//止まっていたら再び再生。ただし停止ボタンが押されている場合は無視
				if (_mediaPlayer.playState == WMPPlayState.wmppsStopped)
				{
					if (_bStopButtonPushed == false)
						Play();
				}
			};
			_timer.Start();


			_mediaPlayer.PlayStateChange += delegate(int nNewState)
			{
				WMPPlayState state = (WMPPlayState)nNewState;

				switch (state)
				{
					case WMPPlayState.wmppsStopped:
						buttonPlay.Text = ">";
						trackBarSeek.Value = 0;
						break;

					case WMPPlayState.wmppsPaused:
						_timer.Stop();
						buttonPlay.Text = ">";
						break;

					case WMPPlayState.wmppsPlaying:
						_bStopButtonPushed = false;
						buttonPlay.Text = "||";
						_timer.Start();
						break;

					case WMPPlayState.wmppsTransitioning:
						break;
				}
			};

			Play();
		}

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace MP3Player
{
	[Serializable]
	public class Option
	{

		public int nVolume
		{
			get { return _nVolume; }
			set { _nVolume = value; }
		}
		int _nVolume = 20;


		public string strFolder
		{
			get { return _strFolder; }
			set { _strFolder = value; }
		}
		string _strFolder = @"G:\Desktop\mp3\";




		/// <summary>
		/// このクラスをXMLとして保存
		/// </summary>
		public bool Save(string strFilePath)
		{
			try
			{
				XmlSerializer serializer = new XmlSerializer(typeof(Option));
				using (FileStream fs = new FileStream(strFilePath, FileMode.Create))
				{
					serializer.Serialize(fs, this);
					fs.Close();
				}
				return true;
			}
			catch (Exception)
			{
			}
			return false;
		}



		/// <summary>
		/// このクラスをXMLから読み込み
		/// </summary>
		/// <returns>成功時true、失敗時false=new Option()で返す</returns>
		public static bool Load(out Option option, string strFilePath)
		{
			try
			{
				//↓で例外が発生するが、無視してOK 「型 'System.IO.FileNotFoundException' の初回例外が mscorlib.dll で発生しました」
				//http://yk.tea-nifty.com/netdev/2009/03/xmlserializer-a.html
				XmlSerializer serializer = new XmlSerializer(typeof(Option));
#if DEBUG
				Debug.WriteLine("↑'System.IO.FileNotFoundException'の例外が発生しても無視してOK");
#endif
				using (FileStream fs = new FileStream(strFilePath, FileMode.Open, FileAccess.Read))
				{
					option = (Option)serializer.Deserialize(fs);
					fs.Close();
				}

				return true;
			}
			catch (Exception)
			{
			}
			option = new Option();		//失敗時は新しいのを作る
			return false;
		}

	}
}

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

第14回 ソースコードを整理する

これまでに指定したフォルダ内にあるmp3/m4aファイルとzip書庫内のmp3/m4aファイルをランダム再生できるようになった。
しかし何も考えずにどんどん処理を追加したのでソースコードがぐちゃぐちゃ。
今回は少しソースコードを整理します。

と言ってもやるのは少しだけ。
「プロジェクト」メニューにある「クラスの追加」で「Utility.cs」を追加して「Utility」クラスを作成。
そこへForm1内にあったpublic staticな関数を移動するだけです。

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

第13回 ZIP書庫内の曲を再生する

前回「第12回 ZIP書庫内の曲を再生する準備」は音楽ファイルの管理にint情報を追加してzip書庫内の再生準備をした。
今回は一気にzip書庫内のファイル再生までを実装します。

zip書庫の解凍には.NET Framework 4.5で追加されたZipFileクラスを利用します。
これを利用するためにプロジェクトメニューにある「参照の追加」を選択して「参照マネージャー」を開き、
「アセンブリ」の中にある
System.IO.Compression
System.IO.Compression.FileSystem
の2項目にチェックをいれて参照の追加をする。

ZIPファイルに含まれる曲の再生の流れは、
実行ファイルのあるフォルダの下にtmpフォルダを作成し、
そこに音楽ファイルを解凍/再生している。
Windows Media Playerのコントロールでは再生時に勝手に音楽ファイルのある場所にファイルを書き出すことがあるため、
解凍したファイルだけを削除するのではなく、tmpフォルダ内に含まれるすべてのファイルを削除しています。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Compression;		//追加
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WMPLib;

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

		Timer _timer = new Timer();



		class AudioItem
		{
			public string strFile = "";
			public int nEntryIndex = -1;

			public AudioItem(string strFile, int nEntryIndex = -1)
			{
				this.strFile = strFile;
				this.nEntryIndex = nEntryIndex;
			}
		}


		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();

			CreateTmpFolder();			//tmpフォルダの作成		//追加

			_listFiles = EnumFiles(@"G:\Desktop\mp3\");		//再生したいmp3保存フォルダを指定


			//フォームが表示されたときの処理
			Shown += delegate
			{
				//シークバーにフォーカスがあると、再生位置が表示されないのでここで再生ボタンにフォーカスを与える
				buttonPlay.Focus();
			};

			//追加
			//終了時処理
			FormClosed += delegate
			{
				CleanTempFolder();			//tmpフォルダ内の削除
			};


			//再生位置のシーク
			trackBarSeek.ValueChanged += delegate
			{
				if (trackBarSeek.Focused)
				{
					_mediaPlayer.controls.currentPosition = (double)trackBarSeek.Value / 100;
				}
			};


			//音量の調節
			_mediaPlayer.settings.volume = 20;
			trackBarVolume.Maximum = 100;			//音量はゼロから100
			trackBarVolume.Value = _mediaPlayer.settings.volume;
			trackBarVolume.ValueChanged += delegate
			{
				_mediaPlayer.settings.volume = (int)trackBarVolume.Value;
			};


			_timer.Interval = 300;			//300msecごとに処理を実行
			_timer.Tick += delegate
			{
				if (_mediaPlayer.playState == WMPPlayState.wmppsPlaying || _mediaPlayer.playState == WMPPlayState.wmppsPaused)
				{
					trackBarSeek.Maximum = (int)(_mediaPlayer.controls.currentItem.duration * 100);
					//シークバーにフォーカスがないときだけ再生位置を表示する
					if (trackBarSeek.Focused == false)
					{
						try
						{
							//シークバーに再生位置を表示
							//曲変更タイミングによっては例外出る可能性ある
							trackBarSeek.Value = (int)(_mediaPlayer.controls.currentPosition * 100);
						}
						catch (Exception)
						{
						}
					}

					//再生時間の表示
					labelTime.Text = _mediaPlayer.controls.currentPositionString;
				}

				//止まっていたら再び再生。ただし停止ボタンが押されている場合は無視
				if (_mediaPlayer.playState == WMPPlayState.wmppsStopped)
				{
					if (_bStopButtonPushed == false)
						Play();
				}
			};
			_timer.Start();


			_mediaPlayer.PlayStateChange += delegate(int nNewState)
			{
				WMPPlayState state = (WMPPlayState)nNewState;

				switch (state)
				{
					case WMPPlayState.wmppsStopped:
						buttonPlay.Text = ">";
						trackBarSeek.Value = 0;
						break;

					case WMPPlayState.wmppsPaused:
						_timer.Stop();
						buttonPlay.Text = ">";
						break;

					case WMPPlayState.wmppsPlaying:
						_bStopButtonPushed = false;
						buttonPlay.Text = "||";
						_timer.Start();
						break;

					case WMPPlayState.wmppsTransitioning:
						break;
				}
			};

			Play();
		}





		/// <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);			//一番最新の履歴曲を削除
			}

			//追加
			CleanTempFolder();			//tmpフォルダ内の削除

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

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

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

				GetMp3Info(strFile, out strTitle, out strArtist, out strAlbum);		//変更

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



		/// <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;

				break;
			}

			return nIndex;
		}



		/// <summary>
		/// フォルダ内のファイルを一覧して返す
		/// </summary>
		List<AudioItem> EnumFiles(string strFolder)
		{
			List<AudioItem> ret = new List<AudioItem>();

			//指定フォルダ以下の全子フォルダから全ファイルを抜き出す
			IEnumerable<string> listFiles = Directory.EnumerateFiles(strFolder, "*.*", SearchOption.AllDirectories);

			foreach (string strFile in listFiles)
			{
				//見つかったファイルの拡張子を取り出し
				string strExt = Path.GetExtension(strFile).ToLower();
				if (strExt == "")
					continue;

				//変更
				//mp3/m4aならそのまま追加
				if (strExt == ".mp3" || strExt == ".m4a")
				{
					ret.Add(new AudioItem(strFile));
					continue;
				}

				//追加
				//ZIPファイルなら書庫に含まれるmp3/m4aファイルのエントリーを追加
				if (strExt == ".zip")
				{
					try
					{
						using (ZipArchive archive = ZipFile.OpenRead(strFile))
						{
							for (int i = 0; i < archive.Entries.Count; i++)
							{
								string strExtension = Path.GetExtension(archive.Entries[i].FullName).ToLower();
								if (strExtension == ".mp3" || strExtension == ".m4a")
								{
									ret.Add(new AudioItem(strFile, i));
								}
							}
						}
					}
					catch (Exception)
					{
					}
				}
			}

			return ret;
		}



		//追加
		/// <summary>
		/// テンポラリフォルダ内の削除
		/// </summary>
		public static void CleanTempFolder()
		{
			//テンポラリフォルダ内を全削除
			IEnumerable<string> listFiles = Directory.EnumerateFiles(GetTmpFolder(), "*", SearchOption.TopDirectoryOnly);
			foreach (string file in listFiles)
			{
				try
				{
					File.Delete(file);
				}
				catch (Exception)
				{
				}
			}
		}

		//追加
		/// <summary>
		/// tmpフォルダの作成
		/// </summary>
		public static void CreateTmpFolder()
		{
			try
			{
				Directory.CreateDirectory(GetTmpFolder());
			}
			catch (Exception)
			{
			}
		}

		
		//追加
		/// <summary>
		/// テンポラリファイル名の作成
		/// </summary>
		public static string GetTmpFile()
		{
			return GetTmpFolder() + DateTime.Now.Ticks;
		}

		//追加
		/// <summary>
		/// テンポラリフォルダを返す
		/// </summary>
		public static string GetTmpFolder()
		{
			return GetExeFolder() + @"tmp\";
		}


		//追加
		/// <summary>
		/// 実行ファイルのあるフォルダパスを返す
		/// </summary>
		public static string GetExeFolder()
		{
			FileInfo cFileInfo2 = new FileInfo(Application.ExecutablePath);		//実行ファイルのあるフォルダを取得するために実行ファイルの詳細を取得
			return cFileInfo2.DirectoryName + @"\";
		}


		//追加
		/// <summary>
		/// ZIPファイルからの1ファイル解凍
		/// </summary>
		/// <param name="strZipFile">解凍したいzipファイルへのパス</param>
		/// <param name="nEntryIndex">zip書庫内のエントリーインデックス</param>
		/// <param name="strOutFileName">解凍先のフォルダ名+ファイル名(拡張子なしで指定)</param>
		/// <param name="strOutFilePath">解凍先ファイルのフルパス。↑に拡張子が付加される</param>
		/// <returns></returns>
		public static bool ExtractFileFromZip(string strZipFile, int nEntryIndex, string strOutFileName, out string strOutFilePath)
		{
			strOutFilePath = "";
			if (strZipFile == "" || strOutFileName == "" || nEntryIndex < 0)
				return false;
			try
			{
				bool ret = false;

				using (ZipArchive archive = ZipFile.OpenRead(strZipFile))
				{
					if (nEntryIndex < archive.Entries.Count)
					{
						string strExtension = Path.GetExtension(archive.Entries[nEntryIndex].FullName);
						archive.Entries[nEntryIndex].ExtractToFile(strOutFileName + strExtension, true);
						strOutFilePath = strOutFileName + strExtension;
						ret = true;
					}
				}
				return ret;
			}
			catch (Exception)
			{
			}
			return false;
		}




		private void buttonPlay_Click(object sender, EventArgs e)
		{
			if (_mediaPlayer.playState == WMPPlayState.wmppsPlaying)
				_mediaPlayer.controls.pause();
			else if (_nCurrentIndex >= 0)
				_mediaPlayer.controls.play();
		}

		private void buttonStop_Click(object sender, EventArgs e)
		{
			if (_mediaPlayer.playState == WMPPlayState.wmppsPlaying || _mediaPlayer.playState == WMPPlayState.wmppsPaused)
			{
				_bStopButtonPushed = true;
				_mediaPlayer.controls.stop();
			}
		}

		private void buttonNext_Click(object sender, EventArgs e)
		{
			Play();
		}

		private void buttonBack_Click(object sender, EventArgs e)
		{
			Play(false);		//前の曲を再生
		}






		/// <summary>
		/// MP3ファイルからの曲名情報取得
		/// 
		/// TagLib# Portable利用
		/// https://github.com/timheuer/taglib-sharp-portable
		/// </summary>
		public 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; }
			}
		}


	}
}

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

第12回 ZIP書庫内の曲を再生する準備

前回までにmp3/m4aファイルに限ればほぼ十分な機能を実装できました。
今回はzip書庫内に含まれるmp3/m4aファイルを再生する準備作業を行います。

これまではファイルの管理はファイル名(string)のみで行っていました。
これだとzip書庫を扱うのに都合が悪いため、int情報を追加したAudioItemクラスを作成してそのクラスで管理することにします。
int情報はzip書庫内のファイル位置(エントリーインデックス)を格納するのに利用します。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WMPLib;

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

		Timer _timer = new Timer();


		//追加
		class AudioItem
		{
			public string strFile = "";
			public int nEntryIndex = -1;

			public AudioItem(string strFile, int nEntryIndex = -1)
			{
				this.strFile = strFile;
				this.nEntryIndex = nEntryIndex;
			}
		}


		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();

			_listFiles = EnumFiles(@"G:\Desktop\mp3\");		//再生したいmp3保存フォルダを指定	//変更


			//フォームが表示されたときの処理
			Shown += delegate
			{
				//シークバーにフォーカスがあると、再生位置が表示されないのでここで再生ボタンにフォーカスを与える
				buttonPlay.Focus();
			};


			//再生位置のシーク
			trackBarSeek.ValueChanged += delegate
			{
				if (trackBarSeek.Focused)
				{
					_mediaPlayer.controls.currentPosition = (double)trackBarSeek.Value / 100;
				}
			};


			//音量の調節
			_mediaPlayer.settings.volume = 20;
			trackBarVolume.Maximum = 100;			//音量はゼロから100
			trackBarVolume.Value = _mediaPlayer.settings.volume;
			trackBarVolume.ValueChanged += delegate
			{
				_mediaPlayer.settings.volume = (int)trackBarVolume.Value;
			};


			_timer.Interval = 300;			//300msecごとに処理を実行
			_timer.Tick += delegate
			{
				if (_mediaPlayer.playState == WMPPlayState.wmppsPlaying || _mediaPlayer.playState == WMPPlayState.wmppsPaused)
				{
					trackBarSeek.Maximum = (int)(_mediaPlayer.controls.currentItem.duration * 100);
					//シークバーにフォーカスがないときだけ再生位置を表示する
					if (trackBarSeek.Focused == false)
					{
						try
						{
							//シークバーに再生位置を表示
							//曲変更タイミングによっては例外出る可能性ある
							trackBarSeek.Value = (int)(_mediaPlayer.controls.currentPosition * 100);
						}
						catch (Exception)
						{
						}
					}

					//再生時間の表示
					labelTime.Text = _mediaPlayer.controls.currentPositionString;
				}

				//止まっていたら再び再生。ただし停止ボタンが押されている場合は無視
				if (_mediaPlayer.playState == WMPPlayState.wmppsStopped)
				{
					if (_bStopButtonPushed == false)
						Play();
				}
			};
			_timer.Start();


			_mediaPlayer.PlayStateChange += delegate(int nNewState)
			{
				WMPPlayState state = (WMPPlayState)nNewState;

				switch (state)
				{
					case WMPPlayState.wmppsStopped:
						buttonPlay.Text = ">";
						trackBarSeek.Value = 0;
						break;

					case WMPPlayState.wmppsPaused:
						_timer.Stop();
						buttonPlay.Text = ">";
						break;

					case WMPPlayState.wmppsPlaying:
						_bStopButtonPushed = false;
						buttonPlay.Text = "||";
						_timer.Start();
						break;

					case WMPPlayState.wmppsTransitioning:
						break;
				}
			};

			Play();
		}





		/// <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);			//一番最新の履歴曲を削除
			}

			_mediaPlayer.URL = _listFiles[_nCurrentIndex].strFile;			//最初の再生曲をセット		//変更
			_mediaPlayer.controls.play();

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

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

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



		/// <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;

				break;
			}

			return nIndex;
		}



		/// <summary>
		/// フォルダ内のファイルを一覧して返す
		/// </summary>
		List<AudioItem> EnumFiles(string strFolder)				//変更
		{
			List<AudioItem> ret = new List<AudioItem>();		//変更

			//指定フォルダ以下の全子フォルダから全ファイルを抜き出す
			IEnumerable<string> listFiles = Directory.EnumerateFiles(strFolder, "*.*", SearchOption.AllDirectories);

			foreach (string strFile in listFiles)
			{
				//見つかったファイルの拡張子を取り出し
				string strExt = Path.GetExtension(strFile).ToLower();
				if (strExt == "")
					continue;

				//mp3/m4a以外なら無視
				if (strExt != ".mp3" && strExt != ".m4a")
					continue;

				ret.Add(new AudioItem(strFile));		//変更
			}

			return ret;
		}



		private void buttonPlay_Click(object sender, EventArgs e)
		{
			if (_mediaPlayer.playState == WMPPlayState.wmppsPlaying)
				_mediaPlayer.controls.pause();
			else if (_nCurrentIndex >= 0)
				_mediaPlayer.controls.play();
		}

		private void buttonStop_Click(object sender, EventArgs e)
		{
			if (_mediaPlayer.playState == WMPPlayState.wmppsPlaying || _mediaPlayer.playState == WMPPlayState.wmppsPaused)
			{
				_bStopButtonPushed = true;
				_mediaPlayer.controls.stop();
			}
		}

		private void buttonNext_Click(object sender, EventArgs e)
		{
			Play();
		}

		private void buttonBack_Click(object sender, EventArgs e)
		{
			Play(false);		//前の曲を再生
		}






		/// <summary>
		/// MP3ファイルからの曲名情報取得
		/// 
		/// TagLib# Portable利用
		/// https://github.com/timheuer/taglib-sharp-portable
		/// </summary>
		public 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; }
			}
		}
	}
}

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

前の10件 1  2  3  4  5  6  7  8  9  10  11