diff --git a/CommandHandler.cs b/CommandHandler.cs index 0b5f53d..39fa401 100644 --- a/CommandHandler.cs +++ b/CommandHandler.cs @@ -564,53 +564,64 @@ namespace DualScreenDemo 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; - } - - // 計算總頁數 - 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 historySongs = new List(); - List playStates = new List(); - - for (int i = startIndex; i < endIndex; i++) - { - historySongs.Add(PrimaryForm.playedSongsHistory[i]); - playStates.Add(PrimaryForm.playStates[i]); - } - - // 調用 UpdateHistoryLabel 顯示數據 - if (OverlayForm.MainForm.InvokeRequired) - { - OverlayForm.MainForm.Invoke(new System.Action(() => + private static void DisplaySongHistory() { - OverlayForm.MainForm.UpdateHistoryLabel(historySongs, playStates, OverlayForm.MainForm.currentPage, totalPages); - OverlayForm.MainForm.nextSongLabel.Visible = false; - })); - } - else - { - OverlayForm.MainForm.UpdateHistoryLabel(historySongs, playStates, OverlayForm.MainForm.currentPage, totalPages); - OverlayForm.MainForm.nextSongLabel.Visible = false; - } + // 清除畫面上現有的顯示內容 + 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 historySongs = new List(); + List playStates = new List(); + + // 從播放紀錄中取出當前頁面應顯示的歌曲與狀態 + for (int i = startIndex; i < endIndex; i++) + { + historySongs.Add(PrimaryForm.playedSongsHistory[i]); // 加入歌曲 + playStates.Add(PrimaryForm.playStates[i]); // 加入狀態 (已播、播放中、未播) + } + + + + // 安全更新 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); + } - // 設定 UI 狀態 - OverlayForm.SetUIState(OverlayForm.UIState.PlayHistory); -} diff --git a/OverlayFormObj/OverlayForm.cs b/OverlayFormObj/OverlayForm.cs index 293f0df..fc35553 100644 --- a/OverlayFormObj/OverlayForm.cs +++ b/OverlayFormObj/OverlayForm.cs @@ -440,29 +440,38 @@ private static void DisplayTimer_Tick(object sender, EventArgs e) displayTimer.Stop(); // 停止计时器 } +// 當 songDisplayTimer 計時完成時會呼叫此函式 private static void SongDisplayTimer_Elapsed(object sender, EventArgs e) { + // 檢查是否需要跨執行緒操作 UI 控制項 if (MainForm.InvokeRequired) { + // 如果目前不在 UI 執行緒上,必須透過 Invoke 安全執行 UI 更新邏輯 Console.WriteLine("SongDisplayTimer_Tick invoked on UI thread."); MainForm.Invoke(new System.Action(() => { + // 清除目前歌曲的顯示標籤文字 MainForm.songDisplayLabel.Text = ""; - MainForm.nextSongLabel.Visible = true; // 恢复显示 nextSongLabel + + // 顯示下一首歌的標籤 + MainForm.nextSongLabel.Visible = true; })); } else { + // 如果已經在 UI 執行緒,就直接更新 UI 控制項 Console.WriteLine("SongDisplayTimer_Tick invoked on background thread."); MainForm.songDisplayLabel.Text = ""; - MainForm.nextSongLabel.Visible = true; // 恢复显示 nextSongLabel + MainForm.nextSongLabel.Visible = true; } + // 停止計時器,避免重複觸發 songDisplayTimer.Stop(); } + private readonly object _lockObject = new object(); private async void UnifiedTimer_Elapsed(object sender, EventArgs e) @@ -1197,66 +1206,92 @@ private static void SongDisplayTimer_Elapsed(object sender, EventArgs e) } } } -public void UpdateHistoryLabel(List historySongs, List playStates, int currentPage, int totalPages) -{ - this.Controls.OfType().ToList().ForEach(p => this.Controls.Remove(p)); - string headerText = $"已點歌曲 ({currentPage} / {totalPages})"; - Font headerFont = new Font("Microsoft JhengHei", 50, FontStyle.Bold); - Bitmap headerBitmap = GenerateTextImage(headerText, headerFont, Color.White, Color.Transparent); - AddCenteredPicture(headerBitmap, 150); - - int startY = 230; - int verticalSpacing = 6; - int leftMargin = 100 ; - int rightMargin = this.Width - 100; - for (int i = 0; i < historySongs.Count; i++) - { - var song = historySongs[i]; - var state = playStates[i]; - string status; - Color textColor; - - switch (state) + public void UpdateHistoryLabel(List historySongs, List playStates, int currentPage, int totalPages) { - case PlayState.Played: - status = "(播畢)"; - textColor = Color.FromArgb(200, 75, 125); // RGB: (200, 75, 125) - break; - case PlayState.Playing: - status = "(播放中)"; - textColor = Color.LimeGreen; - break; - case PlayState.NotPlayed: - status = ""; - textColor = Color.White; - break; - default: - status = ""; - textColor = Color.White; - break; + + // 移除畫面上所有現有的 PictureBox(用於刷新內容) + this.Controls.OfType().ToList().ForEach(p => this.Controls.Remove(p)); + + // 建立標題文字,例如 "已點歌曲 (1 / 3)" + string headerText = $"已點歌曲 ({currentPage} / {totalPages})"; + Font headerFont = new Font("Microsoft JhengHei", 50, FontStyle.Bold); + + // 將標題文字轉為圖片 + Bitmap headerBitmap = GenerateTextImage(headerText, headerFont, Color.White, Color.Transparent); + + // 將標題圖片置中顯示在 Y=150 的位置 + AddCenteredPicture(headerBitmap, 150); + + // 設定歌名顯示的起始 Y 座標 + int startY = 230; + + // 歌名之間的垂直間距 + int verticalSpacing = 6; + + // 左右邊界,用來對齊歌名與狀態文字的位置 + int leftMargin = 100; + int rightMargin = this.Width - 100; + + // 逐一繪製歷史歌曲列表 + for (int i = 0; i < historySongs.Count; i++) + { + var song = historySongs[i]; // 歌曲資料 + var state = playStates[i]; // 對應的播放狀態 + + string status; // 播放狀態文字(如「播放中」) + Color textColor; // 對應的顏色 + + // 根據播放狀態決定狀態文字與顏色 + switch (state) + { + case PlayState.Played: + status = "(播畢)"; + textColor = Color.FromArgb(200, 75, 125); // 播畢顏色:紫紅色 + break; + case PlayState.Playing: + status = "(播放中)"; + textColor = Color.LimeGreen; // 播放中顏色:亮綠 + break; + case PlayState.NotPlayed: + status = ""; + textColor = Color.White; // 尚未播放:白色 + break; + default: + status = ""; + textColor = Color.White; + break; + } + + // 建立顯示的歌曲文字,例如 "1. 我的歌" + string songText = $"{i + 1}. {song.Song}"; + Font songFont = new Font("Microsoft JhengHei", 50, FontStyle.Bold); + + // 將歌名轉成圖片 + Bitmap songBitmap = GenerateTextImage(songText, songFont, textColor, Color.Transparent); + + Bitmap statusBitmap = null; + + // 如果有狀態文字,則也轉成圖片 + if (!string.IsNullOrEmpty(status)) + { + Font statusFont = new Font("Microsoft JhengHei", 50, FontStyle.Bold); + statusBitmap = GenerateTextImage(status, statusFont, textColor, Color.Transparent); + } + + // 計算目前這首歌的 Y 座標位置 + int y = startY + i * (songBitmap.Height + verticalSpacing); + + // 加入歌名圖片到畫面左側 + AddPicture(songBitmap, leftMargin, y); + + // 若有狀態圖片,則加入到畫面右側 + if (statusBitmap != null) + { + int statusX = rightMargin - statusBitmap.Width; + AddPicture(statusBitmap, statusX, y); + } + } } - string songText = $"{i + 1}. {song.Song}"; - Font songFont = new Font("Microsoft JhengHei", 50, FontStyle.Bold); - Bitmap songBitmap = GenerateTextImage(songText, songFont, textColor, Color.Transparent); - Bitmap statusBitmap = null; - if (!string.IsNullOrEmpty(status)) - { - Font statusFont = new Font("Microsoft JhengHei", 50, FontStyle.Bold); - statusBitmap = GenerateTextImage(status, statusFont, textColor, Color.Transparent); - } - - int y = startY + i * (songBitmap.Height + verticalSpacing); - AddPicture(songBitmap, leftMargin, y); - if (statusBitmap != null) - { - int statusX = rightMargin - statusBitmap.Width; - AddPicture(statusBitmap, statusX, y); - } - } -} - - - public void UpdateDisplayLabels(string[] messages)//新歌歌星排行首頁 { // 清除舊的圖片控件 @@ -1499,6 +1534,9 @@ private void DisplayArtists(List artists, int page)//歌星點進去後 PrimaryForm.userRequestedSongs.Add(songData); PrimaryForm.playedSongsHistory.Add(songData); PrimaryForm.playStates.Add(wasEmpty ? PlayState.Playing : PlayState.NotPlayed); + // 刷新頁面 + if(PrimaryForm.Instance.multiPagePanel.get_currentSongList() == PrimaryForm.playedSongsHistory) + PrimaryForm.Instance.multiPagePanel.LoadSongs(PrimaryForm.Instance.currentSongList); if (wasEmpty) { @@ -1522,51 +1560,65 @@ private void DisplayArtists(List artists, int page)//歌星點進去後 { try { + // 從 songData 中取得兩個可能的檔案路徑(主機1與主機2) var filePath1 = songData.SongFilePathHost1; var filePath2 = songData.SongFilePathHost2; - + + // 檢查兩個主機上的檔案是否皆不存在 if (!File.Exists(filePath1) && !File.Exists(filePath2)) { + // 若兩個都找不到,寫入 Log 並不加入歌單 PrimaryForm.WriteLog(String.Format("File not found on both hosts: {0} and {1}", filePath1, filePath2)); } else { + // 若其中一個存在,就用第一個存在的那個檔案 var pathToPlay = File.Exists(filePath1) ? filePath1 : filePath2; - Console.WriteLine("path to play"+pathToPlay); + Console.WriteLine("path to play" + pathToPlay); + + // 檢查目前使用者歌單是否為空 bool wasEmpty = PrimaryForm.userRequestedSongs.Count == 0; if (wasEmpty) { - PrimaryForm.userRequestedSongs.Add(songData); - VideoPlayerForm.Instance.SetPlayingSongList(PrimaryForm.userRequestedSongs); - PrimaryForm.playedSongsHistory.Add(songData); - PrimaryForm.playStates.Add(PlayState.Playing); - PrimaryForm.currentSongIndexInHistory += 1; + // 若是空的,代表是第一首歌,直接加入並設為正在播放 + PrimaryForm.userRequestedSongs.Add(songData); // 加入播放清單 + VideoPlayerForm.Instance.SetPlayingSongList(PrimaryForm.userRequestedSongs); // 傳給播放器 + PrimaryForm.playedSongsHistory.Add(songData); // 加入播放歷史 + PrimaryForm.playStates.Add(PlayState.Playing); // 設定狀態為正在播放 + PrimaryForm.currentSongIndexInHistory += 1; // 歷史索引 +1 } else if (PrimaryForm.userRequestedSongs.Count == 1) { + // 若清單中已有一首,插入新歌在 index 1 (即目前播放之後的位置) PrimaryForm.userRequestedSongs.Insert(1, songData); PrimaryForm.playedSongsHistory.Insert(PrimaryForm.currentSongIndexInHistory + 1, songData); - PrimaryForm.playStates.Insert(PrimaryForm.currentSongIndexInHistory + 1, PlayState.NotPlayed); + PrimaryForm.playStates.Insert(PrimaryForm.currentSongIndexInHistory + 1, PlayState.NotPlayed); // 尚未播放 } else { + // 若清單中超過一首,同樣插入在 index 1,也是在當前歌曲之後的位置 PrimaryForm.userRequestedSongs.Insert(1, songData); PrimaryForm.playedSongsHistory.Insert(PrimaryForm.currentSongIndexInHistory + 1, songData); PrimaryForm.playStates.Insert(PrimaryForm.currentSongIndexInHistory + 1, PlayState.NotPlayed); } + // 更新下一首即將播放的資訊(畫面或播放器邏輯用) VideoPlayerForm.Instance.UpdateNextSongFromPlaylist(); + + // 印出目前播放清單資訊到畫面或 console PrimaryForm.PrintPlayingSongList(); } } catch (Exception ex) { + // 捕捉所有例外並印出錯誤訊息(避免整個流程當掉) Console.WriteLine("Error occurred: " + ex.Message); } } + public int currentPage = 1; public int songsPerPage = 5; public int totalSongs = 0; diff --git a/PrimaryFormParts/HotSong/PrimaryForm.HotSong.cs b/PrimaryFormParts/HotSong/PrimaryForm.HotSong.cs index 2ea4e3f..aaaf740 100644 --- a/PrimaryFormParts/HotSong/PrimaryForm.HotSong.cs +++ b/PrimaryFormParts/HotSong/PrimaryForm.HotSong.cs @@ -55,7 +55,7 @@ namespace DualScreenDemo } } - private void HotPlayButton_Click(object sender, EventArgs e) + public void HotPlayButton_Click(object sender, EventArgs e) { UpdateButtonBackgrounds(hotPlayButton, hotPlayActiveBackground); UpdateHotSongButtons(guoYuButtonHotSong, guoYuHotSongActiveBackground); @@ -147,6 +147,8 @@ namespace DualScreenDemo if (pictureBoxQRCode != null) { pictureBoxQRCode.Visible = false; + } + if(closeQRCodeButton != null){ closeQRCodeButton.Visible = false; } } diff --git a/PrimaryFormParts/PrimaryForm.Favorite.cs b/PrimaryFormParts/PrimaryForm.Favorite.cs index 7dce729..7652a82 100644 --- a/PrimaryFormParts/PrimaryForm.Favorite.cs +++ b/PrimaryFormParts/PrimaryForm.Favorite.cs @@ -300,14 +300,19 @@ namespace DualScreenDemo FavoritePictureBox.Invalidate(); FavoritePictureBox.Refresh(); - - //SongListManager.Instance.IsUserLoggedIn = false; - //SongListManager.Instance.UserPhoneNumber = string.Empty; } private void CloseFavoriteButton_Click(object sender, EventArgs e) { + mobileNumber = string.Empty; + + + showError = false; + + + FavoritePictureBox.Invalidate(); + FavoritePictureBox.Refresh(); ToggleFavoritePictureBoxButtonsVisibility(); } diff --git a/PrimaryFormParts/PrimaryForm.MultiPagePanel.cs b/PrimaryFormParts/PrimaryForm.MultiPagePanel.cs index 80cdae7..c20854a 100644 --- a/PrimaryFormParts/PrimaryForm.MultiPagePanel.cs +++ b/PrimaryFormParts/PrimaryForm.MultiPagePanel.cs @@ -53,6 +53,9 @@ namespace DualScreenDemo } } private List currentSongList = new List(); + public List get_currentSongList(){ + return currentSongList; + } private List currentArtistList = new List(); private int _totalPages = 0; private Point mouseDownLocation; // 新增字段 @@ -182,7 +185,7 @@ namespace DualScreenDemo public void LoadSingers(List artists) { currentArtistList = artists; - currentSongList.Clear(); + //currentSongList.Clear(); currentPageIndex = 0; totalPages = (int)Math.Ceiling(artists.Count / (double)itemsPerPage); RefreshDisplayBase_Singer(); @@ -382,14 +385,15 @@ namespace DualScreenDemo // 若播放公播歌單,代表已點歌曲皆已播放完畢 hasBeenPlayed = true; songLabel.ForeColor = Color.Gray; - statusText = IsSimplified ? "(播毕)" : "(播畢)"; + statusText = IsSimplified ? "(播毕)" : "(播畢播畢)"; } else { // 計算已完成播放的歌曲數量 - int completedCount = 0; + int completedCount = currentSongIndexInHistory; + Console.WriteLine("currentSongIndexInHistory:" + currentSongIndexInHistory); // 遍歷已點歌曲歷史 - for (int i = 0; i <= currentSongIndexInHistory && i < playedSongsHistory.Count; i++) { + /*for (int i = 0; i <= currentSongIndexInHistory && i < playedSongsHistory.Count; i++) { if (i == currentSongIndexInHistory) { completedCount = i + 1; // 当前播放的歌曲 break; @@ -401,24 +405,23 @@ namespace DualScreenDemo } // 如果是切歌状态,不增加计数 } - } - + }*/ // 計算歌曲在歷史中的位置 int songPosition = pageOffset + index; // 判斷歌曲狀態 - if (songPosition < completedCount - 1) + if (songPosition < completedCount) { // 已播放完成 hasBeenPlayed = true; songLabel.ForeColor = Color.Gray; - statusText = IsSimplified ? "(播毕)" : "(播畢)"; + statusText = IsSimplified ? "(播毕)" : "(播畢播畢)"; } - else if (songPosition == completedCount - 1) + else if (songPosition == completedCount) { // 正在播放 isCurrentlyPlaying = true; songLabel.ForeColor = Color.LimeGreen; - statusText = IsSimplified ? "(播放中)" : "(播放中)"; + statusText = IsSimplified ? "(播放中)" : "(播放中播放中)"; } else { diff --git a/PrimaryFormParts/PrimaryForm.SQLSearch.cs b/PrimaryFormParts/PrimaryForm.SQLSearch.cs index 0fa7701..826eedd 100644 --- a/PrimaryFormParts/PrimaryForm.SQLSearch.cs +++ b/PrimaryFormParts/PrimaryForm.SQLSearch.cs @@ -163,6 +163,10 @@ namespace DualScreenDemo{ } return exists; } + public void logout(){ + isLoggedIn=false; + userPhone=string.Empty; + } private static int countforSearch = 0; private static void writeLogforSearchTime(long elapsedMs){ diff --git a/PrimaryFormParts/PrimaryForm.VodScreen.cs b/PrimaryFormParts/PrimaryForm.VodScreen.cs index 3000ad0..4f71f99 100644 --- a/PrimaryFormParts/PrimaryForm.VodScreen.cs +++ b/PrimaryFormParts/PrimaryForm.VodScreen.cs @@ -118,6 +118,7 @@ namespace DualScreenDemo private void VodButton_Click(object sender, EventArgs e) { + OverlayForm.MainForm.AddSongToPlaylist(currentSelectedSong); SetVodScreenPictureBoxAndButtonsVisibility(false); } diff --git a/PrimaryFormParts/PrimaryForm.cs b/PrimaryFormParts/PrimaryForm.cs index b805fb9..b04fcb1 100644 --- a/PrimaryFormParts/PrimaryForm.cs +++ b/PrimaryFormParts/PrimaryForm.cs @@ -2011,8 +2011,15 @@ namespace DualScreenDemo /// /// private void ShouYeButton_Click(object sender, EventArgs e) - { - if(currentSongList == playedSongsHistory) + { /*Console.WriteLine("playedSongsHistory"); + foreach(var song in playedSongsHistory){ + Console.WriteLine(song.ToString()); + } + Console.WriteLine("userRequestedSongs"); + foreach(var song in userRequestedSongs){ + Console.WriteLine(song.ToString()); + }*/ + if( multiPagePanel.get_currentSongList() == playedSongsHistory) return; autoRefreshTimer.Stop(); // 停止自动刷新 FindFirstNonEmptyText(inputBoxZhuYinSingers diff --git a/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.cs b/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.cs index 10e471d..cc16be4 100644 --- a/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.cs +++ b/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.cs @@ -35,8 +35,18 @@ namespace DualScreenDemo promotionsButton.BackgroundImage = promotionsNormalBackground; deliciousFoodButton.BackgroundImage = deliciousFoodNormalBackground; isOnOrderedSongsPage = false; + /* 清空搜尋欄 */ + ResetinputBox(); + string query = $"SELECT * FROM artists WHERE category = '男' LIMIT 100"; + var searchResult = SearchSingers_Mysql(query); + currentPage = 0; + currentArtistList = searchResult; + totalPages = (int)Math.Ceiling((double)searchResult.Count / itemsPerPage); + multiPagePanel.currentPageIndex = 0; + multiPagePanel.LoadSingers(currentArtistList); + SetHotSongButtonsVisibility(false); SetNewSongButtonsVisibility(false); SetSongSearchButtonsVisibility(false); diff --git a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.cs b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.cs index 4393487..ed6f546 100644 --- a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.cs +++ b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.cs @@ -48,6 +48,17 @@ namespace DualScreenDemo deliciousFoodButton.BackgroundImage = deliciousFoodNormalBackground; isOnOrderedSongsPage = false; + ResetinputBox(); + string query = $"SELECT * FROM song_library_cache WHERE language_name = '國語' LIMIT 100"; + var searchResult = SearchSongs_Mysql(query); + currentPage = 0; + currentSongList = searchResult; + totalPages = (int)Math.Ceiling((double)searchResult.Count / itemsPerPage); + + + multiPagePanel.currentPageIndex = 0; + multiPagePanel.LoadSongs(currentSongList); + // 隱藏其他 UI SetHotSongButtonsVisibility(false); SetNewSongButtonsVisibility(false); diff --git a/TCPServer.cs b/TCPServer.cs index a3a0433..1d94278 100644 --- a/TCPServer.cs +++ b/TCPServer.cs @@ -4,6 +4,7 @@ using System.Text; using System.Text.RegularExpressions; using System.IO; // 為 Path 和 File 提供支持 using DBObj; +using System.Diagnostics; using OverlayFormObj; namespace DualScreenDemo { @@ -169,8 +170,9 @@ namespace DualScreenDemo } VideoPlayerForm.Instance.PlayNextSong(); - + PrimaryForm.Instance.logout(); Console.WriteLine("已設置新的播放列表,包含當前歌曲和 CLOSE.MPG"); + } else { @@ -181,6 +183,7 @@ namespace DualScreenDemo }); UpdateStateFile(stateFilePath, "CLOSE"); + continue; } @@ -190,10 +193,13 @@ namespace DualScreenDemo { PrimaryForm.Instance.HideSendOffScreen(); }); + // 開台時跳至首頁 + PrimaryForm.Instance.HotPlayButton_Click(null, EventArgs.Empty); VideoPlayerForm.publicPlaylist = new List(); VideoPlayerForm.playingSongList = new List(); VideoPlayerForm.Instance.PlayPublicPlaylist(); UpdateStateFile(stateFilePath, "OPEN"); + continue; } } diff --git a/VideoPlayerForm.cs b/VideoPlayerForm.cs index 6e57873..ba27534 100644 --- a/VideoPlayerForm.cs +++ b/VideoPlayerForm.cs @@ -517,24 +517,38 @@ namespace DualScreenDemo public async Task SetPlayingSongList(List songList) { + // [1] 輸出 debug 訊息,方便開發時追蹤是否有呼叫此方法 Console.WriteLine("SetPlayingSongList called"); + + // [2] 停止當前播放,釋放資源(例如關閉影片播放器、清除緩衝) StopAndReleaseResources(); + // [3] 將新的播放清單指派給 `playingSongList` playingSongList = songList; + + // [4] 根據是否有歌,設定旗標為是否播放使用者點播清單 isUserPlaylistPlaying = playingSongList != null && playingSongList.Any(); - IsPlayingPublicSong = false; // 设置为不在播放公播 - + + // [5] 強制關閉公播狀態(意即現在進入點歌模式) + IsPlayingPublicSong = false; + + // [6] 若使用者點播清單有歌,就開始播放 if (isUserPlaylistPlaying) { + // [6.1] 設定當前歌曲索引為 -1(意味著即將播放第一首,從 `PlayNextSong` 開始) currentSongIndex = -1; + + // [6.2] 播放下一首歌(實際會遞增 index 為 0,並播放該首歌) await PlayNextSong(); } else { + // [7] 如果清單為空,回退播放預設的公播清單(通常是背景播放用) await InitializeAndPlayPublicPlaylist(); } } + public async Task PlayPublicPlaylist() { Console.WriteLine("開始播放公播清單..."); @@ -686,42 +700,62 @@ namespace DualScreenDemo public async Task PlayNextSong() { + // 等待初始化完成(例如播放器、串口等資源尚未就緒時) while (!isInitializationComplete) { await Task.Delay(100); } Console.WriteLine("開始播放下一首歌曲..."); + + // 根據目前播放模式(點歌 or 公播)決定要播放的清單 List currentPlaylist = isUserPlaylistPlaying ? playingSongList : publicPlaylist; + // 若播放清單是空的,直接返回(不執行播放) if (!currentPlaylist.Any()) return; if (!isUserPlaylistPlaying) { + // 公播模式下,正常循環播放(用 % 保證不會超出陣列界限) currentSongIndex = (currentSongIndex + 1) % currentPlaylist.Count; Console.WriteLine($"順序播放: currentSongIndex = {currentSongIndex}, currentPlaylist.Count = {currentPlaylist.Count}"); } else { + // 若是使用者點播模式,先送出升Key的串口指令 if (SerialPortManager.mySerialPort != null && SerialPortManager.mySerialPort.IsOpen) { byte[] commandBytesIncreasePitch1 = new byte[] { 0xA2, 0x7F, 0xA4 }; SerialPortManager.mySerialPort.Write(commandBytesIncreasePitch1, 0, commandBytesIncreasePitch1.Length); } + + // 同樣遞增 index 來播放下一首 currentSongIndex = (currentSongIndex + 1) % currentPlaylist.Count; } - var songToPlay = currentPlaylist[currentSongIndex]; - var pathToPlay = File.Exists(songToPlay.SongFilePathHost1) ? songToPlay.SongFilePathHost1 : songToPlay.SongFilePathHost2; - if (!File.Exists(pathToPlay)) - { - Console.WriteLine($"文件不存在:{pathToPlay}"); - return; - } - currentPlayingSong = songToPlay; - UpdateNextSongFromPlaylist(); - overlayForm.DisplayQRCodeOnOverlay(HttpServer.randomFolderPath); - overlayForm.HidePauseLabel(); + + var songToPlay = currentPlaylist[currentSongIndex]; + var pathToPlay = File.Exists(songToPlay.SongFilePathHost1) ? songToPlay.SongFilePathHost1 : songToPlay.SongFilePathHost2; + + // 若兩個 host 上都找不到檔案就直接結束 + if (!File.Exists(pathToPlay)) + { + Console.WriteLine($"文件不存在:{pathToPlay}"); + return; + } + + // 更新目前正在播放的歌曲 + currentPlayingSong = songToPlay; + + // 更新畫面上顯示的下一首歌資訊 + UpdateNextSongFromPlaylist(); + + // 顯示 QRCode(可能是點歌頁用) + overlayForm.DisplayQRCodeOnOverlay(HttpServer.randomFolderPath); + + // 隱藏「暫停中」標籤 + overlayForm.HidePauseLabel(); + try { @@ -813,54 +847,77 @@ namespace DualScreenDemo } } + /// + /// 跳至下一首歌曲的方法,會根據目前播放清單(使用者清單或公播清單)做切換與播放邏輯控制。 + /// public async Task SkipToNextSong() { try { + // 停止當前播放並釋放資源(如播放器、影片檔等) StopAndReleaseResources(); + + // 稍作延遲,確保資源已被釋放 await Task.Delay(100); + // 如果目前正在播放使用者點播清單,且清單還有歌曲 if (isUserPlaylistPlaying && playingSongList != null && playingSongList.Count > 0) { - // 还有用户歌曲要播放 + // 移除目前播放的第一首歌(已經播放過的) playingSongList.RemoveAt(0); + if (playingSongList.Count == 0) { - // 用户歌单播完,切换到公播 + // 使用者點播清單播完了,切換回公播清單 Console.WriteLine("用戶播放列表已清空,切換至公播清單"); isUserPlaylistPlaying = false; lastPlayedIndex = -1; currentSongIndex = -1; + + // 初始化並開始播放公播清單 await InitializeAndPlayPublicPlaylist(); } else { - // 继续播放用户歌单 + // 還有歌曲可播,繼續播放下一首使用者歌曲 currentSongIndex = -1; await PlayNextSong(); } } else { - // 当前是公播状态,重新初始化公播列表 + // 如果不是在播放使用者清單(或清單為空),直接初始化並播放公播清單 await InitializeAndPlayPublicPlaylist(); } - if (PrimaryForm.currentSongIndexInHistory >= 0 && PrimaryForm.currentSongIndexInHistory < PrimaryForm.playedSongsHistory.Count) { + // 如果目前歌曲在播放歷史列表的索引是合法的(防呆) + if (PrimaryForm.currentSongIndexInHistory >= 0 && PrimaryForm.currentSongIndexInHistory < PrimaryForm.playedSongsHistory.Count) + { var currentSong = PrimaryForm.playedSongsHistory[PrimaryForm.currentSongIndexInHistory]; - if (playingSongList.Count > 0 && currentSong == playingSongList[0]) { + + // 如果新的播放清單還有歌曲,並且當前歷史記錄中的歌曲與播放清單的第一首一致,則標記為已播畢 + if (playingSongList.Count > 0 && currentSong == playingSongList[0]) + { PrimaryForm.playStates[PrimaryForm.currentSongIndexInHistory] = PlayState.Played; } } - PrimaryForm.currentSongIndexInHistory += 1; + /*如果當前為公播,不可以+1*/ + bool isPlayingPublicList = PrimaryForm.userRequestedSongs.Count == 0 || + (PrimaryForm.currentSongIndexInHistory >= PrimaryForm.userRequestedSongs.Count - 1 && PrimaryForm.Instance.videoPlayerForm.IsPlayingPublicSong); + if(!isPlayingPublicList){ + PrimaryForm.currentSongIndexInHistory+=1; + } + Console.WriteLine("currentSongIndexInHistory : " + PrimaryForm.currentSongIndexInHistory); } catch (Exception ex) { + // 若有例外錯誤,列印錯誤訊息並切回公播模式 Console.WriteLine($"切換歌曲時發生錯誤: {ex.Message}"); await InitializeAndPlayPublicPlaylist(); } } + // 新增一个方法来处理公播列表的初始化和播放 private async Task InitializeAndPlayPublicPlaylist() {