第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;
		}

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


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