1039 lines
41 KiB
C#
1039 lines
41 KiB
C#
using System.IO;
|
||
using System.Text.RegularExpressions;
|
||
using System.Diagnostics;
|
||
using DBObj;
|
||
using OverlayFormObj;
|
||
using NAudio.Wave;
|
||
namespace DualScreenDemo
|
||
{
|
||
public class CommandHandler
|
||
{
|
||
public static bool readyForSongListInput = false;
|
||
/* 關機 queue */
|
||
private readonly int _maxHistoryLength = 6; // 最多保留 6 筆
|
||
public static readonly Queue<string> _indataHistory = new Queue<string>();
|
||
/* 顯示按鈕設定 */
|
||
private int _wrongInputCountfor62 = 0; // 錯誤輸入計數器
|
||
private int _wrongInputCountfor61 = 0; // 錯誤輸入計數器
|
||
private const int MaxWrongLimit = 3; // 錯誤輸入限制次數
|
||
private readonly SongListManager songListManager;
|
||
|
||
public CommandHandler(SongListManager songListManager)
|
||
{
|
||
this.songListManager = songListManager;
|
||
}
|
||
/// <summary>
|
||
/// 遙控器接收資料
|
||
/// </summary>
|
||
public async Task ProcessData(string indata)
|
||
{ AddToHistory(indata);
|
||
// 遙控器測試
|
||
// Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 遙控器: {indata}");
|
||
switch (indata)
|
||
{
|
||
case "A261A4": // 輸入
|
||
HandleInputA();
|
||
break;
|
||
case "A262A4": // 插播
|
||
HandleInputB();
|
||
break;
|
||
case "A263A4":
|
||
ClearDisplay();
|
||
_wrongInputCountfor62 = 0; // 重置計數器
|
||
_wrongInputCountfor61 = 0; // 重置計數器
|
||
_indataHistory.Clear(); // 清空歷史紀錄
|
||
break;
|
||
case "A268A4":
|
||
OverlayForm.MainForm.currentPage = 1;
|
||
DisplaySongHistory();
|
||
break;
|
||
case "A26AA4":
|
||
PreviousPage();
|
||
break;
|
||
case "A26BA4":
|
||
NextPage();
|
||
break;
|
||
case "A271A4":
|
||
HandleNewSongAnnouncements();
|
||
break;
|
||
case "A273A4":
|
||
HandleHotSongAnnouncements();
|
||
break;
|
||
case "A267A4":
|
||
SkipToNextSong();
|
||
ClearDisplay();
|
||
break;
|
||
case "A269A4":
|
||
ReplayCurrentSong();
|
||
break;
|
||
// 原唱
|
||
case "A26CA4":
|
||
Console.WriteLine("ToggleVocalRemoval Invoked");
|
||
SafeInvokeAction("A26CA4",() => VideoPlayerForm.Instance.ToggleVocalRemoval());
|
||
break;
|
||
// 導唱
|
||
case "A26EA4":
|
||
SafeInvokeAction("A26EA4",() => VideoPlayerForm.Instance.ToggleVocalRemoval());
|
||
break;
|
||
case "A26DA4":
|
||
PauseOrResumeSong();
|
||
break;
|
||
case "A276A4":
|
||
ToggleMute();
|
||
break;
|
||
case "A274A4":
|
||
OverlayForm.MainForm.currentPage = 1;
|
||
HandleArtistAnnouncements();
|
||
break;
|
||
case "A2B3A4":
|
||
SafeInvokeAction("A2B3A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A2B3A4",() => OverlayForm.MainForm.ShowVolumeUpLabel());
|
||
break;
|
||
case "A2B4A4":
|
||
SafeInvokeAction("A2B4A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A2B4A4",() => OverlayForm.MainForm.ShowVolumeDownLabel());
|
||
break;
|
||
case "A2B5A4":
|
||
SafeInvokeAction("A2B5A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A2B5A4",() => OverlayForm.MainForm.ShowMicUpLabel());
|
||
break;
|
||
case "A2B6A4":
|
||
SafeInvokeAction("A2B6A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A2B6A4",() => OverlayForm.MainForm.ShowMicDownLabel());
|
||
break;
|
||
case "A2C2A4":
|
||
SafeInvokeAction("A2C2A4",() => OverlayForm.MainForm.HidemicLabels());
|
||
SafeInvokeAction("A2C2A4",() => OverlayForm.MainForm.ShowStandardLabel());
|
||
break;
|
||
case "A2C3A4":
|
||
SafeInvokeAction("A2C3A4",() => OverlayForm.MainForm.HidemicLabels());
|
||
SafeInvokeAction("A2C3A4",() => OverlayForm.MainForm.ShowProfessionalLabel());
|
||
break;
|
||
case "A2C4A4":
|
||
SafeInvokeAction("A2C4A4",() => OverlayForm.MainForm.HidemicLabels());
|
||
SafeInvokeAction("A2C4A4",() => OverlayForm.MainForm.ShowSquareLabel());
|
||
break;
|
||
case "A2C1A4":
|
||
SafeInvokeAction("A2C1A4",() => OverlayForm.MainForm.HidemicLabels());
|
||
SafeInvokeAction("A2C1A4",() => OverlayForm.MainForm.ShowSingDownLabel());
|
||
break;
|
||
case "A2D5A4":
|
||
SafeInvokeAction("A2D5A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A2D5A4",() => OverlayForm.MainForm.ShowBrightLabel());
|
||
break;
|
||
case "A2D7A4":
|
||
SafeInvokeAction("A2D7A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A2D7A4",() => OverlayForm.MainForm.ShowRomanticLabel());
|
||
break;
|
||
/* case "A27CA4":
|
||
InvokeAction(() => OverlayForm.MainForm.ShowMaleKeyLabel());
|
||
break;
|
||
case "A282A4":
|
||
InvokeAction(() => OverlayForm.MainForm.ShowFemaleKeyLabel());
|
||
break;*/
|
||
case "A2D6A4":
|
||
SafeInvokeAction("A2D6A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A2D6A4",() => OverlayForm.MainForm.ShowSoftLabel());
|
||
break;
|
||
case "A2D8A4":
|
||
SafeInvokeAction("A2D8A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A2D8A4",() => OverlayForm.MainForm.ShowDynamicLabel());
|
||
break;
|
||
case "A275A4":
|
||
SafeInvokeAction("A275A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A275A4",() => OverlayForm.MainForm.ShowTintLabel());
|
||
break;
|
||
case "A283A4":
|
||
SafeInvokeAction("A283A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A283A4",() => OverlayForm.MainForm.ShowKeyUpLabel("↑升4調"));
|
||
break;
|
||
case "A282A4":
|
||
SafeInvokeAction("A282A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A282A4",() => OverlayForm.MainForm.ShowKeyUpLabel("↑升3調"));
|
||
break;
|
||
case "A281A4":
|
||
SafeInvokeAction("A281A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A281A4",() => OverlayForm.MainForm.ShowKeyUpLabel("↑升2調"));
|
||
break;
|
||
case "A280A4":
|
||
SafeInvokeAction("A280A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A280A4",() => OverlayForm.MainForm.ShowKeyUpLabel("↑升1調"));
|
||
break;
|
||
case "A27FA4":
|
||
SafeInvokeAction("A27FA4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A27FA4",() => OverlayForm.MainForm.ShowStandardKeyLabel());
|
||
break;
|
||
case "A27EA4":
|
||
SafeInvokeAction("A27EA4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A27EA4",() => OverlayForm.MainForm.ShowKeyDownLabel("↓降1調"));
|
||
break;
|
||
case "A27DA4":
|
||
SafeInvokeAction("A27EA4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A27EA4",() => OverlayForm.MainForm.ShowKeyDownLabel("↓降2調"));
|
||
break;
|
||
case "A27CA4":
|
||
SafeInvokeAction("A27CA4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A27CA4",() => OverlayForm.MainForm.ShowKeyDownLabel("↓降3調"));
|
||
break;
|
||
case "A27BA4":
|
||
SafeInvokeAction("A27BA4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A27BA4",() => OverlayForm.MainForm.ShowKeyDownLabel("↓降4調"));
|
||
break;
|
||
case "A266A4":
|
||
SafeInvokeAction("A266A4",() => OverlayForm.MainForm.HideAllLabels());
|
||
SafeInvokeAction("A266A4",() => OverlayForm.MainForm.ShowServiceBell());
|
||
break;
|
||
default:
|
||
if (Regex.IsMatch(indata, @"^A23\d+A4$"))
|
||
{
|
||
HandleNumberInput(indata);
|
||
}
|
||
break;
|
||
}
|
||
|
||
}
|
||
private void SafeInvokeAction(string commandKey, Action action)
|
||
{
|
||
// 真正執行 UI 操作
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.BeginInvoke(action);
|
||
}
|
||
else
|
||
{
|
||
action();
|
||
}
|
||
}
|
||
|
||
private void AddToHistory(string indata)
|
||
{
|
||
if (_indataHistory.Count >= _maxHistoryLength)
|
||
{
|
||
_indataHistory.Dequeue(); // 移除最舊的項目
|
||
}
|
||
_indataHistory.Enqueue(indata); // 添加新的項目
|
||
CheckSequenceforClose(); // 每次更新完 queue 後檢查
|
||
}
|
||
private void CheckSequenceforClose()
|
||
{
|
||
string[] targetSequence = { "A262A4", "A262A4", "A262A4", "A261A4", "A261A4", "A261A4" };
|
||
|
||
if (_indataHistory.Count == targetSequence.Length &&
|
||
_indataHistory.SequenceEqual(targetSequence))
|
||
{
|
||
Console.WriteLine("Shutdown condition met. Application will now close.");
|
||
ShutdownComputer();
|
||
}
|
||
}
|
||
|
||
void InvokeAction(Action action)
|
||
{
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(action);
|
||
}
|
||
else
|
||
{
|
||
action();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
private static void SkipToNextSong()
|
||
{
|
||
if (PrimaryForm.Instance.InvokeRequired)
|
||
{
|
||
PrimaryForm.Instance.Invoke(new System.Action(() => PrimaryForm.Instance.videoPlayerForm.SkipToNextSong()));
|
||
}
|
||
else
|
||
{
|
||
PrimaryForm.Instance.videoPlayerForm.SkipToNextSong();
|
||
}
|
||
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
OverlayForm.MainForm.ShowStandardLabel();
|
||
}));
|
||
}
|
||
|
||
|
||
private static void ReplayCurrentSong()
|
||
{
|
||
if (PrimaryForm.Instance.InvokeRequired)
|
||
{
|
||
PrimaryForm.Instance.Invoke(new System.Action(() => PrimaryForm.Instance.videoPlayerForm.ReplayCurrentSong()));
|
||
}
|
||
else
|
||
{
|
||
PrimaryForm.Instance.videoPlayerForm.ReplayCurrentSong();
|
||
}
|
||
}
|
||
|
||
private static void PauseOrResumeSong()
|
||
{
|
||
if (PrimaryForm.Instance.InvokeRequired)
|
||
{
|
||
PrimaryForm.Instance.Invoke(new System.Action(() => PrimaryForm.Instance.videoPlayerForm.PauseOrResumeSong()));
|
||
}
|
||
else
|
||
{
|
||
PrimaryForm.Instance.videoPlayerForm.PauseOrResumeSong();
|
||
}
|
||
}
|
||
|
||
public static void ToggleMute()
|
||
{
|
||
if (VideoPlayerForm.Instance.InvokeRequired)
|
||
{
|
||
VideoPlayerForm.Instance.Invoke(new System.Action(ToggleMute));
|
||
}
|
||
else
|
||
{
|
||
if (VideoPlayerForm.Instance.isMuted)
|
||
{
|
||
|
||
VideoPlayerForm.Instance.SetVolume(VideoPlayerForm.Instance.previousVolume);
|
||
|
||
VideoPlayerForm.Instance.isMuted = false;
|
||
OverlayForm.MainForm.Invoke(new System.Action(() => OverlayForm.MainForm.HideMuteLabel()));
|
||
}
|
||
else
|
||
{
|
||
|
||
VideoPlayerForm.Instance.previousVolume = VideoPlayerForm.Instance.GetVolume();
|
||
VideoPlayerForm.Instance.SetVolume(-10000);
|
||
|
||
VideoPlayerForm.Instance.isMuted = true;
|
||
OverlayForm.MainForm.Invoke(new System.Action(() => OverlayForm.MainForm.ShowMuteLabel()));
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
private void HandleInputA()
|
||
{
|
||
|
||
|
||
OverlayForm.displayTimer.Stop();
|
||
string input = "a";
|
||
|
||
// 輸入歌曲
|
||
string songNumber = OverlayForm.ReadSongNumber();
|
||
//Console.WriteLine("輸入A " + songNumber + " readyForSongListInput : " + readyForSongListInput);
|
||
var song = songListManager.SearchSongByNumber(songNumber);
|
||
|
||
|
||
|
||
if (readyForSongListInput)
|
||
{
|
||
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
Console.WriteLine("F sign for input :" + input);
|
||
OverlayForm.MainForm.OnUserInput(input);
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("A sign for input :" + input);
|
||
OverlayForm.MainForm.OnUserInput(input);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
if (song != null)
|
||
{
|
||
ClearDisplay();
|
||
OverlayForm.MainForm.displayLabel.Text = String.Format("已點歌曲:{0}", song);
|
||
OverlayForm.MainForm.AddSongToPlaylist(song);
|
||
OverlayForm.MainForm.nextSongLabel.Visible = false;
|
||
OverlayForm.displayTimer.Start();
|
||
}
|
||
else
|
||
{
|
||
ClearDisplay();
|
||
_wrongInputCountfor61++;
|
||
if(_wrongInputCountfor61 <= MaxWrongLimit)
|
||
{
|
||
string old ="";
|
||
OverlayForm.MainForm.displayLabel.Text = check_control(old);
|
||
}
|
||
else
|
||
{
|
||
OverlayForm.MainForm.displayLabel.Text = "輸入錯誤!!!";
|
||
_indataHistory.Clear(); // 清空歷史紀錄
|
||
_wrongInputCountfor61 = 0; // 重置計數器
|
||
}
|
||
OverlayForm.MainForm.nextSongLabel.Visible = false;
|
||
OverlayForm.displayTimer.Start();
|
||
}
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
if (song != null)
|
||
{
|
||
ClearDisplay();
|
||
OverlayForm.MainForm.displayLabel.Text = String.Format("{0}", song);
|
||
OverlayForm.MainForm.AddSongToPlaylist(song);
|
||
OverlayForm.MainForm.nextSongLabel.Visible = false;
|
||
OverlayForm.displayTimer.Start();
|
||
}
|
||
else
|
||
{
|
||
ClearDisplay();
|
||
_wrongInputCountfor61++;
|
||
if(_wrongInputCountfor61 <= MaxWrongLimit)
|
||
{
|
||
string old ="";
|
||
OverlayForm.MainForm.displayLabel.Text = check_control(old);
|
||
}
|
||
else
|
||
{
|
||
OverlayForm.MainForm.displayLabel.Text = "輸入錯誤!!!";
|
||
_indataHistory.Clear(); // 清空歷史紀錄
|
||
_wrongInputCountfor61 = 0; // 重置計數器
|
||
}
|
||
OverlayForm.MainForm.nextSongLabel.Visible = false;
|
||
OverlayForm.displayTimer.Start();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
private string check_control(string old){
|
||
foreach(string item in _indataHistory)
|
||
{
|
||
if(item == "A261A4")
|
||
old += "#";
|
||
else if(item == "A262A4")
|
||
old += "*";
|
||
}
|
||
return old;
|
||
}
|
||
|
||
|
||
private void HandleInputB()
|
||
{
|
||
|
||
OverlayForm.displayTimer.Stop();
|
||
string input = "b";
|
||
|
||
|
||
string songNumber = OverlayForm.ReadSongNumber();
|
||
var song = songListManager.SearchSongByNumber(songNumber);
|
||
|
||
|
||
|
||
if (readyForSongListInput)
|
||
{
|
||
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
Console.WriteLine("B sign for input :" + input);
|
||
OverlayForm.MainForm.OnUserInput(input);
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("C sign for input :" + input);
|
||
OverlayForm.MainForm.OnUserInput(input);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
if (song != null)
|
||
{
|
||
ClearDisplay();
|
||
OverlayForm.MainForm.displayLabel.Text = String.Format("插播歌曲{0}", song);
|
||
OverlayForm.MainForm.InsertSongToPlaylist(song);
|
||
OverlayForm.MainForm.nextSongLabel.Visible = false;
|
||
OverlayForm.displayTimer.Start();
|
||
}
|
||
else
|
||
{
|
||
ClearDisplay();
|
||
_wrongInputCountfor62++;
|
||
if(_wrongInputCountfor62 <= MaxWrongLimit)
|
||
{
|
||
string old ="";
|
||
OverlayForm.MainForm.displayLabel.Text = check_control(old);
|
||
}
|
||
else
|
||
{
|
||
OverlayForm.MainForm.displayLabel.Text = "輸入錯誤!!!";
|
||
_indataHistory.Clear(); // 清空歷史紀錄
|
||
_wrongInputCountfor62 = 0; // 重置計數器
|
||
}
|
||
OverlayForm.MainForm.nextSongLabel.Visible = false;
|
||
OverlayForm.displayTimer.Start();
|
||
}
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
if (song != null)
|
||
{
|
||
ClearDisplay();
|
||
OverlayForm.MainForm.displayLabel.Text = String.Format("已點歌曲:{0}", song);
|
||
OverlayForm.MainForm.nextSongLabel.Visible = false;
|
||
}
|
||
else
|
||
{
|
||
ClearDisplay();
|
||
_wrongInputCountfor62++;
|
||
if(_wrongInputCountfor62 <= MaxWrongLimit)
|
||
{
|
||
string old ="";
|
||
OverlayForm.MainForm.displayLabel.Text = check_control(old);
|
||
}
|
||
else
|
||
{
|
||
OverlayForm.MainForm.displayLabel.Text = "輸入錯誤!!!";
|
||
_indataHistory.Clear(); // 清空歷史紀錄
|
||
_wrongInputCountfor62 = 0; // 重置計數器
|
||
}
|
||
OverlayForm.MainForm.nextSongLabel.Visible = false;
|
||
OverlayForm.displayTimer.Start();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除 OverlayForm 上除特定保留控制項外的所有控制項,並重設顯示狀態
|
||
/// </summary>
|
||
private static void ClearDisplay()
|
||
{
|
||
// 停止顯示用的計時器
|
||
OverlayForm.displayTimer.Stop();
|
||
|
||
// 判斷是否需要透過 Invoke 回 UI 執行緒執行
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new Action(ClearControlsAndReset));
|
||
}
|
||
else
|
||
{
|
||
ClearControlsAndReset();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 實際執行移除不需要的控制項並重設 UI 狀態
|
||
/// </summary>
|
||
private static void ClearControlsAndReset()
|
||
{
|
||
// 保留不刪除的控制項列表
|
||
var preservedControls = new HashSet<Control>
|
||
{
|
||
OverlayForm.MainForm.displayLabel,
|
||
OverlayForm.MainForm.pauseLabel,
|
||
OverlayForm.MainForm.muteLabel,
|
||
OverlayForm.MainForm.volumeUpLabel,
|
||
OverlayForm.MainForm.volumeDownLabel,
|
||
OverlayForm.MainForm.micUpLabel,
|
||
OverlayForm.MainForm.micDownLabel,
|
||
OverlayForm.MainForm.standardKeyLabel,
|
||
OverlayForm.MainForm.keyUpLabel,
|
||
OverlayForm.MainForm.keyDownLabel,
|
||
OverlayForm.MainForm.maleKeyLabel,
|
||
OverlayForm.MainForm.femaleKeyLabel,
|
||
OverlayForm.MainForm.squareLabel,
|
||
OverlayForm.MainForm.professionalLabel,
|
||
OverlayForm.MainForm.standardLabel,
|
||
OverlayForm.MainForm.singDownLabel,
|
||
OverlayForm.MainForm.brightLabel,
|
||
OverlayForm.MainForm.softLabel,
|
||
OverlayForm.MainForm.autoLabel,
|
||
OverlayForm.MainForm.romanticLabel,
|
||
OverlayForm.MainForm.dynamicLabel,
|
||
OverlayForm.MainForm.tintLabel,
|
||
OverlayForm.MainForm.blackBackgroundPanel,
|
||
OverlayForm.MainForm.nextSongLabel
|
||
};
|
||
|
||
// 將所有不在保留清單內的控制項移除並釋放資源
|
||
foreach (var control in OverlayForm.MainForm.Controls.OfType<Control>().ToArray())
|
||
{
|
||
if (!preservedControls.Contains(control))
|
||
{
|
||
OverlayForm.MainForm.Controls.Remove(control);
|
||
control.Dispose();
|
||
}
|
||
}
|
||
|
||
// 清空主顯示區的文字
|
||
OverlayForm.MainForm.displayLabel.Text = "";
|
||
Console.WriteLine("ClearDisplay called.");
|
||
|
||
// 重設狀態標記與 UI 狀態
|
||
// 嘗試 true
|
||
readyForSongListInput = true;
|
||
OverlayForm.SetUIState(OverlayForm.UIState.Initial);
|
||
Console.WriteLine("Display cleared.");
|
||
}
|
||
|
||
private static void DisplaySongHistory()
|
||
{
|
||
// 清除畫面上現有的顯示內容
|
||
ClearDisplay();
|
||
|
||
// 設定歌曲總數為已播放歌曲的數量
|
||
OverlayForm.MainForm.totalSongs = PrimaryForm.playedSongsHistory.Count;
|
||
|
||
// 若無任何播放紀錄,直接顯示訊息並返回,不執行後續動作
|
||
if (OverlayForm.MainForm.totalSongs == 0)
|
||
{
|
||
Console.WriteLine("No song history available.");
|
||
return;
|
||
}
|
||
|
||
// 計算總頁數,每頁顯示 songsPerPage 首歌,使用天花板函數確保不足一頁也算一頁
|
||
int totalPages = (int)Math.Ceiling(OverlayForm.MainForm.totalSongs / (double)OverlayForm.MainForm.songsPerPage);
|
||
|
||
// 計算當前頁面要顯示的歌的起始與結束索引
|
||
int startIndex = (OverlayForm.MainForm.currentPage - 1) * OverlayForm.MainForm.songsPerPage;
|
||
int endIndex = Math.Min(startIndex + OverlayForm.MainForm.songsPerPage, OverlayForm.MainForm.totalSongs);
|
||
|
||
// 準備要傳給 UpdateHistoryLabel 的兩個清單:歌曲資料與播放狀態
|
||
List<SongData> historySongs = new List<SongData>();
|
||
List<PlayState> playStates = new List<PlayState>();
|
||
// 錨點 遙控器
|
||
// 從播放紀錄中取出當前頁面應顯示的歌曲與狀態
|
||
int completedCount = PrimaryForm.currentSongIndexInHistory;
|
||
// 判斷是否正在播放公播歌單 (若用戶點播歌單為空,則播放公播歌單)
|
||
bool isPlayingPublicList = PrimaryForm.userRequestedSongs.Count == 0 ||
|
||
(PrimaryForm.currentSongIndexInHistory >= PrimaryForm.userRequestedSongs.Count - 1 && PrimaryForm.Instance.videoPlayerForm.IsPlayingPublicSong);
|
||
if (isPlayingPublicList)
|
||
{
|
||
for (int i = startIndex; i < endIndex; i++)
|
||
{
|
||
historySongs.Add(PrimaryForm.playedSongsHistory[i]); // 加入歌曲
|
||
playStates.Add(PlayState.Played);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int i = startIndex; i < endIndex; i++)
|
||
{
|
||
|
||
historySongs.Add(PrimaryForm.playedSongsHistory[i]); // 加入歌曲
|
||
if (i < completedCount)
|
||
{
|
||
playStates.Add(PlayState.Played);
|
||
}
|
||
else if (i == completedCount)
|
||
{
|
||
playStates.Add(PlayState.Playing);
|
||
}
|
||
else
|
||
{
|
||
playStates.Add(PlayState.NotPlayed);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
// 安全更新 UI:若非 UI 執行緒則使用 Invoke 切換
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
// 更新主畫面的歷史播放顯示區
|
||
OverlayForm.MainForm.UpdateHistoryLabel(historySongs, playStates, OverlayForm.MainForm.currentPage, totalPages);
|
||
|
||
// 隱藏下一首提示
|
||
OverlayForm.MainForm.nextSongLabel.Visible = false;
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
// 若已在 UI 執行緒,直接操作
|
||
OverlayForm.MainForm.UpdateHistoryLabel(historySongs, playStates, OverlayForm.MainForm.currentPage, totalPages);
|
||
OverlayForm.MainForm.nextSongLabel.Visible = false;
|
||
}
|
||
|
||
// 切換 UI 狀態為播放歷史模式(可做為內部狀態管理用途)
|
||
OverlayForm.SetUIState(OverlayForm.UIState.PlayHistory);
|
||
}
|
||
|
||
|
||
|
||
|
||
private static void PreviousPage()
|
||
{
|
||
if (OverlayForm.CurrentUIState == OverlayForm.UIState.SelectingSong)
|
||
{
|
||
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
|
||
OverlayForm.MainForm.PreviousPage();
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
|
||
OverlayForm.MainForm.PreviousPage();
|
||
}
|
||
}
|
||
else if (OverlayForm.CurrentUIState == OverlayForm.UIState.SelectingArtist)
|
||
{
|
||
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
|
||
OverlayForm.MainForm.PreviousPage();
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
|
||
OverlayForm.MainForm.PreviousPage();
|
||
}
|
||
}
|
||
else if (OverlayForm.CurrentUIState == OverlayForm.UIState.PlayHistory)
|
||
{
|
||
if (OverlayForm.MainForm.currentPage > 1)
|
||
{
|
||
OverlayForm.MainForm.currentPage--;
|
||
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
DisplaySongHistory();
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
DisplaySongHistory();
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("Page turning is not allowed in the current state.");
|
||
}
|
||
}
|
||
|
||
private static void NextPage()
|
||
{
|
||
if (OverlayForm.CurrentUIState == OverlayForm.UIState.SelectingSong)
|
||
{
|
||
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
|
||
OverlayForm.MainForm.NextPage();
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
|
||
OverlayForm.MainForm.NextPage();
|
||
}
|
||
}
|
||
else if (OverlayForm.CurrentUIState == OverlayForm.UIState.SelectingArtist)
|
||
{
|
||
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
|
||
OverlayForm.MainForm.NextPage();
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
|
||
OverlayForm.MainForm.NextPage();
|
||
}
|
||
}
|
||
else if (OverlayForm.CurrentUIState == OverlayForm.UIState.PlayHistory)
|
||
{
|
||
if (OverlayForm.MainForm.currentPage * OverlayForm.MainForm.songsPerPage < OverlayForm.MainForm.totalSongs)
|
||
{
|
||
OverlayForm.MainForm.currentPage++;
|
||
if (OverlayForm.CurrentUIState == OverlayForm.UIState.PlayHistory)
|
||
{
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
DisplaySongHistory();
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
DisplaySongHistory();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("Page turning is not allowed in the current state.");
|
||
}
|
||
}
|
||
|
||
private static void HandleNewSongAnnouncements()
|
||
{
|
||
ClearDisplay();
|
||
|
||
|
||
OverlayForm.CurrentCategory = OverlayForm.Category.NewSongs;
|
||
|
||
|
||
string[] messages = new string[]
|
||
{
|
||
"新歌快訊",
|
||
"1. 國語",
|
||
"2. 台語",
|
||
"3. 粵語",
|
||
"4. 英語",
|
||
"5. 日語",
|
||
"6. 韓語",
|
||
};
|
||
|
||
|
||
readyForSongListInput = true;
|
||
|
||
|
||
OverlayForm.SetUIState(OverlayForm.UIState.SelectingLanguage);
|
||
|
||
|
||
UpdateDisplayLabels(messages);
|
||
}
|
||
|
||
private static void HandleHotSongAnnouncements()
|
||
{
|
||
ClearDisplay();
|
||
|
||
|
||
OverlayForm.CurrentCategory = OverlayForm.Category.HotSongs;
|
||
|
||
|
||
string[] messages = new string[]
|
||
{
|
||
"熱門排行",
|
||
"1. 國語",
|
||
"2. 台語",
|
||
"3. 粵語",
|
||
"4. 英語",
|
||
"5. 日語",
|
||
"6. 韓語",
|
||
};
|
||
|
||
|
||
readyForSongListInput = true;
|
||
|
||
|
||
OverlayForm.SetUIState(OverlayForm.UIState.SelectingLanguage);
|
||
|
||
|
||
UpdateDisplayLabels(messages);
|
||
}
|
||
|
||
private static void HandleArtistAnnouncements()
|
||
{
|
||
ClearDisplay();
|
||
|
||
|
||
OverlayForm.CurrentCategory = OverlayForm.Category.Artists;
|
||
|
||
|
||
string[] messages = new string[]
|
||
{
|
||
"歌星選歌",
|
||
"1.男歌星",
|
||
"2.女歌星",
|
||
"3.團體",
|
||
"4.外語",
|
||
"5.全部",
|
||
};
|
||
|
||
|
||
readyForSongListInput = true;
|
||
|
||
|
||
OverlayForm.SetUIState(OverlayForm.UIState.SelectingArtistCategory);
|
||
|
||
|
||
UpdateDisplayLabels(messages);
|
||
}
|
||
|
||
private static void UpdateDisplayLabels(string[] messages)
|
||
{
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
|
||
foreach (var control in OverlayForm.MainForm.Controls.OfType<Control>().ToArray())
|
||
{
|
||
if (control != OverlayForm.MainForm.displayLabel &&
|
||
control != OverlayForm.MainForm.pauseLabel &&
|
||
control != OverlayForm.MainForm.muteLabel &&
|
||
control != OverlayForm.MainForm.volumeUpLabel &&
|
||
control != OverlayForm.MainForm.volumeDownLabel &&
|
||
control != OverlayForm.MainForm.micUpLabel &&
|
||
control != OverlayForm.MainForm.micDownLabel &&
|
||
control != OverlayForm.MainForm.standardKeyLabel &&
|
||
control != OverlayForm.MainForm.keyUpLabel &&
|
||
control != OverlayForm.MainForm.keyDownLabel &&
|
||
control != OverlayForm.MainForm.maleKeyLabel &&
|
||
control != OverlayForm.MainForm.femaleKeyLabel &&
|
||
control != OverlayForm.MainForm.squareLabel &&
|
||
control != OverlayForm.MainForm.professionalLabel &&
|
||
control != OverlayForm.MainForm.standardLabel &&
|
||
control != OverlayForm.MainForm.singDownLabel &&
|
||
control != OverlayForm.MainForm.brightLabel &&
|
||
control != OverlayForm.MainForm.softLabel &&
|
||
control != OverlayForm.MainForm.autoLabel &&
|
||
control != OverlayForm.MainForm.romanticLabel &&
|
||
control != OverlayForm.MainForm.dynamicLabel &&
|
||
control != OverlayForm.MainForm.tintLabel &&
|
||
control != OverlayForm.MainForm.blackBackgroundPanel &&
|
||
control != OverlayForm.MainForm.nextSongLabel)
|
||
{
|
||
OverlayForm.MainForm.Controls.Remove(control);
|
||
control.Dispose();
|
||
}
|
||
}
|
||
OverlayForm.MainForm.UpdateDisplayLabels(messages);
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
|
||
foreach (var control in OverlayForm.MainForm.Controls.OfType<Control>().ToArray())
|
||
{
|
||
if (control != OverlayForm.MainForm.displayLabel &&
|
||
control != OverlayForm.MainForm.pauseLabel &&
|
||
control != OverlayForm.MainForm.muteLabel &&
|
||
control != OverlayForm.MainForm.volumeUpLabel &&
|
||
control != OverlayForm.MainForm.volumeDownLabel &&
|
||
control != OverlayForm.MainForm.micUpLabel &&
|
||
control != OverlayForm.MainForm.micDownLabel &&
|
||
control != OverlayForm.MainForm.standardKeyLabel &&
|
||
control != OverlayForm.MainForm.keyUpLabel &&
|
||
control != OverlayForm.MainForm.keyDownLabel &&
|
||
control != OverlayForm.MainForm.maleKeyLabel &&
|
||
control != OverlayForm.MainForm.femaleKeyLabel &&
|
||
control != OverlayForm.MainForm.squareLabel &&
|
||
control != OverlayForm.MainForm.professionalLabel &&
|
||
control != OverlayForm.MainForm.standardLabel &&
|
||
control != OverlayForm.MainForm.singDownLabel &&
|
||
control != OverlayForm.MainForm.brightLabel &&
|
||
control != OverlayForm.MainForm.softLabel &&
|
||
control != OverlayForm.MainForm.autoLabel &&
|
||
control != OverlayForm.MainForm.romanticLabel &&
|
||
control != OverlayForm.MainForm.dynamicLabel &&
|
||
control != OverlayForm.MainForm.tintLabel &&
|
||
control != OverlayForm.MainForm.blackBackgroundPanel &&
|
||
control != OverlayForm.MainForm.nextSongLabel)
|
||
{
|
||
OverlayForm.MainForm.Controls.Remove(control);
|
||
control.Dispose();
|
||
}
|
||
}
|
||
OverlayForm.MainForm.UpdateDisplayLabels(messages);
|
||
}
|
||
}
|
||
|
||
private static void HandleNumberInput(string trimmedData)
|
||
{
|
||
string number = trimmedData;
|
||
|
||
|
||
var match = Regex.Match(trimmedData, @"^A23(\d)A4$");
|
||
if (match.Success)
|
||
{
|
||
number = match.Groups[1].Value;
|
||
|
||
Console.WriteLine($"Handling number: {number}");
|
||
|
||
}
|
||
|
||
|
||
if (readyForSongListInput)
|
||
{
|
||
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
Console.WriteLine("D sign for number :" + number);
|
||
OverlayForm.MainForm.OnUserInput(number);
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("E sign for number :" + number);
|
||
OverlayForm.MainForm.OnUserInput(number);
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
|
||
if (OverlayForm.MainForm.InvokeRequired)
|
||
{
|
||
OverlayForm.MainForm.Invoke(new System.Action(() =>
|
||
{
|
||
OverlayForm.DisplayNumberAtTopLeft(number);
|
||
OverlayForm.MainForm.HideAllLabels();
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
OverlayForm.DisplayNumberAtTopLeft(number);
|
||
OverlayForm.MainForm.HideAllLabels();
|
||
}
|
||
}
|
||
}
|
||
|
||
public static void ShutdownComputer()
|
||
{
|
||
try
|
||
{
|
||
ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd.exe", "/c shutdown /s /f /t 0")
|
||
{
|
||
CreateNoWindow = true,
|
||
UseShellExecute = false,
|
||
RedirectStandardOutput = true
|
||
};
|
||
Process process = Process.Start(processStartInfo);
|
||
process.WaitForExit();
|
||
Console.WriteLine("Computer is shutting down...");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine("Error shutting down computer: " + ex.Message);
|
||
}
|
||
}
|
||
}
|
||
} |