superstar_v2/CommandHandler.cs
jasonchenwork 732572bda2 202508130945
更換播放器 使用VLC
加入dbChange,situation
調整全部靜音寫法
2025-08-13 09:51:11 +08:00

621 lines
22 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 readonly SQLManager songListManager;
public CommandHandler(SQLManager songListManager)
{
this.songListManager = songListManager;
}
/// <summary>
/// 遙控器接收資料
/// </summary>
public Task ProcessData(string indata)
{
AddToHistory(indata);
// 遙控器測試
// Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 遙控器: {indata}");
switch (indata)
{
case "A261A4": // 輸入
HandleInput("a");
break;
case "A262A4": // 插播
HandleInput("b");
break;
case "A263A4":
ClearDisplay();
_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.ShowTopRightLabelTime("音量 ↑ "));
break;
case "A2B4A4":
SafeInvokeAction("A2B4A4",() => OverlayForm.MainForm.ShowTopRightLabelTime("音量 ↓ "));
break;
case "A2B5A4":
SafeInvokeAction("A2B5A4",() => OverlayForm.MainForm.ShowTopRightLabelTime("麥克風 ↑ "));
break;
case "A2B6A4":
SafeInvokeAction("A2B6A4",() => OverlayForm.MainForm.ShowTopRightLabelTime("麥克風 ↓ "));
break;
case "A2C2A4":
SafeInvokeAction("A2C2A4",() => OverlayForm.MainForm.ShowTopRightEchoLabel("標準迴音"));
break;
case "A2C3A4":
SafeInvokeAction("A2C3A4",() => OverlayForm.MainForm.ShowTopRightEchoLabel("專業迴音"));
break;
case "A2C4A4":
SafeInvokeAction("A2C4A4",() => OverlayForm.MainForm.ShowTopRightEchoLabel("廣場迴音"));
break;
case "A2C1A4":
SafeInvokeAction("A2C1A4",() => OverlayForm.MainForm.ShowTopRightEchoLabel("唱將迴音"));
break;
case "A2D5A4":
SafeInvokeAction("A2D5A4",() => OverlayForm.MainForm.ShowTopRightLabelTime(" 明亮 "));
break;
case "A2D7A4":
SafeInvokeAction("A2D7A4",() => OverlayForm.MainForm.ShowTopRightLabelTime(" 浪漫 "));
break;
case "A2D6A4":
SafeInvokeAction("A2D6A4",() => OverlayForm.MainForm.ShowTopRightLabelTime(" 柔和 "));
break;
case "A2D8A4":
SafeInvokeAction("A2D8A4",() => OverlayForm.MainForm.ShowTopRightLabelTime(" 動感 "));
break;
case "A275A4":
SafeInvokeAction("A275A4",() => OverlayForm.MainForm.ShowTopRightLabelTime(" 調色 "));
break;
case "A283A4":
SafeInvokeAction("A283A4",() => OverlayForm.MainForm.ShowTopRightLabelTime("↑升4調 "));
break;
case "A282A4":
SafeInvokeAction("A282A4",() => OverlayForm.MainForm.ShowTopRightLabelTime("↑升3調 "));
break;
case "A281A4":
SafeInvokeAction("A281A4",() => OverlayForm.MainForm.ShowTopRightLabelTime("↑升2調 "));
break;
case "A280A4":
SafeInvokeAction("A280A4",() => OverlayForm.MainForm.ShowTopRightLabelTime("↑升1調 "));
break;
case "A27FA4":
SafeInvokeAction("A27FA4",() => OverlayForm.MainForm.ShowTopRightLabelTime(" 標準調 "));
break;
case "A27EA4":
SafeInvokeAction("A27EA4",() => OverlayForm.MainForm.ShowTopRightLabelTime("↓降1調 "));
break;
case "A27DA4":
SafeInvokeAction("A27EA4",() => OverlayForm.MainForm.ShowTopRightLabelTime("↓降2調 "));
break;
case "A27CA4":
SafeInvokeAction("A27CA4",() => OverlayForm.MainForm.ShowTopRightLabelTime("↓降3調 "));
break;
case "A27BA4":
SafeInvokeAction("A27BA4",() => OverlayForm.MainForm.ShowTopRightLabelTime("↓降4調 "));
break;
case "A266A4":
SafeInvokeAction("A266A4",() => OverlayForm.MainForm.ShowTopRightLabel("服務鈴"));
break;
default:
if (Regex.IsMatch(indata, @"^A23\d+A4$"))
{
HandleNumberInput(indata);
}
break;
}
return Task.CompletedTask;
}
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();
}
}
static void InvokeAction(Action action)
{
if (OverlayForm.MainForm.InvokeRequired)
{
OverlayForm.MainForm.Invoke(action);
}
else
{
action();
}
}
private void SkipToNextSong()
{
InvokeAction(() => PrimaryForm.Instance.videoPlayerForm.PlayNextSong());
InvokeAction(() => OverlayForm.MainForm.ShowTopRightEchoLabel("標準迴音"));
}
private void ReplayCurrentSong()
{
InvokeAction(() => PrimaryForm.Instance.videoPlayerForm.ReplayCurrentSong());
}
private static void PauseOrResumeSong()
{
InvokeAction(() => 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.Mute(false);
VideoPlayerForm.Instance.isMuted = false;
OverlayForm.MainForm.Invoke(new System.Action(() => OverlayForm.MainForm.HideMuteLabel()));
}
else
{
VideoPlayerForm.Instance.Mute(true);
VideoPlayerForm.Instance.isMuted = true;
OverlayForm.MainForm.Invoke(new System.Action(() => OverlayForm.MainForm.ShowMuteLabel()));
}
}
}
private void HandleInput(string input)
{
if (readyForSongListInput)
{
InvokeAction(() =>
{
Console.WriteLine("F sign for input :" + input);
OverlayForm.MainForm.OnUserInput(input);
});
}
else
{
InvokeAction(() =>
{
OverlayForm.displayTimer.Stop();
string songNumber = OverlayForm.ReadSongNumber();
var song = songListManager.SearchSongByNumber(songNumber);
ClearDisplay();
if (song != null)
{
song.getBasic().setNameTest(".");
if (Program.room.IsOpen())
{
if (input.Equals("a"))
{
OverlayForm.MainForm.displayLabel.Text = String.Format("已點歌曲:{0}", song);
SongList.Add(song);
}
else
{
OverlayForm.MainForm.displayLabel.Text = String.Format("插播歌曲:{0}", song);
SongList.Insert(song);
}
}
else
{
OverlayForm.MainForm.displayLabel.Text = "包廂己關閉";
}
_indataHistory.Clear(); // 清空歷史紀錄
}
else
OverlayForm.MainForm.displayLabel.Text = check_control();
OverlayForm.MainForm.topLeftLabel.Visible = false;
OverlayForm.displayTimer.Start();
});
}
}
private string check_control(){
string str = "";
foreach (string item in _indataHistory)
{
if (item == "A261A4")
str += "#";
else if (item == "A262A4")
str += "*";
}
return str;
}
/// <summary>
/// 清除 OverlayForm 上除特定保留控制項外的所有控制項,並重設顯示狀態
/// </summary>
private static void ClearDisplay()
{
// 停止顯示用的計時器
OverlayForm.displayTimer.Stop();
// 判斷是否需要透過 Invoke 回 UI 執行緒執行
InvokeAction(() => ClearControlsAndReset());
}
/// <summary>
/// 實際執行移除不需要的控制項並重設 UI 狀態
/// </summary>
private static void ClearControlsAndReset()
{
// 保留不刪除的控制項列表
var preservedControls = new HashSet<Control>
{
OverlayForm.MainForm.displayLabel,
OverlayForm.MainForm.pauseLabel,
OverlayForm.MainForm.muteLabel,
OverlayForm.MainForm.topRightLabel,
OverlayForm.MainForm.blackBackgroundPanel,
OverlayForm.MainForm.topLeftLabel
};
// 將所有不在保留清單內的控制項移除並釋放資源
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();
// 設定歌曲總數為已播放歌曲的數量
List<SongData> history= SongList.GetHistory();
List<SongData> historySongs = new List<SongData>();
OverlayForm.MainForm.totalSongs = SongList.GetHistory().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 的兩個清單:歌曲資料與播放狀態
for (int i = startIndex; i < endIndex; i++) {
historySongs.Add(history[i]);
}
// 錨點 遙控器
// 安全更新 UI若非 UI 執行緒則使用 Invoke 切換
InvokeAction(() =>
{
// 更新主畫面的歷史播放顯示區
OverlayForm.MainForm.UpdateHistoryLabel(historySongs, OverlayForm.MainForm.currentPage, totalPages);
// 隱藏下一首提示
OverlayForm.MainForm.topLeftLabel.Visible = false;
});
// 切換 UI 狀態為播放歷史模式(可做為內部狀態管理用途)
OverlayForm.SetUIState(OverlayForm.UIState.PlayHistory);
}
private static void PreviousPage()
{
if (OverlayForm.CurrentUIState == OverlayForm.UIState.SelectingSong)
{
InvokeAction(() =>OverlayForm.MainForm.PreviousPage());
}
else if (OverlayForm.CurrentUIState == OverlayForm.UIState.SelectingArtist)
{
InvokeAction(() =>OverlayForm.MainForm.PreviousPage());
}
else if (OverlayForm.CurrentUIState == OverlayForm.UIState.PlayHistory)
{
if (OverlayForm.MainForm.currentPage > 1)
{
OverlayForm.MainForm.currentPage--;
InvokeAction(() => DisplaySongHistory());
}
}
else
{
Console.WriteLine("Page turning is not allowed in the current state.");
}
}
private static void NextPage()
{
if (OverlayForm.CurrentUIState == OverlayForm.UIState.SelectingSong)
{
InvokeAction(() => OverlayForm.MainForm.NextPage());
}
else if (OverlayForm.CurrentUIState == OverlayForm.UIState.SelectingArtist)
{
InvokeAction(() => 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)
{
InvokeAction(() => 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)
{
InvokeAction(() =>
{
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.topRightLabel &&
control != OverlayForm.MainForm.blackBackgroundPanel &&
control != OverlayForm.MainForm.topLeftLabel)
{
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)
{
InvokeAction(() =>
{
Console.WriteLine("D sign for number :" + number);
OverlayForm.MainForm.OnUserInput(number);
});
}
else
{
InvokeAction(() =>
{
OverlayForm.MainForm.HideTopRightLabels();
OverlayForm.DisplayNumberAtTopLeft(number);
});
}
}
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);
}
}
}
}