diff --git a/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.BopomofoSearch.cs b/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.BopomofoSearch.cs index d88d2ee..a02ab96 100644 --- a/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.BopomofoSearch.cs +++ b/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.BopomofoSearch.cs @@ -41,7 +41,7 @@ namespace DualScreenDemo { // 設定按鈕背景,將「注音搜尋」設為啟動狀態,其餘按鈕恢復為正常狀態 - UpdateButtonBackgrounds(zhuyinSearchButton, zhuyinSearchActiveBackground); + UpdateSSearchBtn(zhuyinSearchButton, zhuyinSearchActiveBackground); // 載入設定檔,取得圖片路徑資訊 var configData = LoadBtnConfigData(); diff --git a/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.EnglishSearch.cs b/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.EnglishSearch.cs index e3741a2..00fbae1 100644 --- a/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.EnglishSearch.cs +++ b/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.EnglishSearch.cs @@ -22,12 +22,7 @@ namespace DualScreenDemo private void EnglishSearchSingersButton_Click(object sender, EventArgs e) { - zhuyinSearchButton.BackgroundImage = zhuyinSearchNormalBackground; - englishSearchButton.BackgroundImage = englishSearchActiveBackground; - pinyinSearchButton.BackgroundImage = pinyinSearchNormalBackground; - wordCountSearchButton.BackgroundImage = wordCountSearchNormalBackground; - handWritingSearchButton.BackgroundImage = handWritingSearchNormalBackground; - + UpdateSSearchBtn(englishSearchButton, englishSearchActiveBackground); bool shouldBeVisible = !pictureBoxEnglishSingers.Visible; diff --git a/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.HandwritingSearch.cs b/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.HandwritingSearch.cs index bae66b2..6751279 100644 --- a/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.HandwritingSearch.cs +++ b/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.HandwritingSearch.cs @@ -19,12 +19,7 @@ namespace DualScreenDemo { this.SuspendLayout(); - zhuyinSearchButton.BackgroundImage = zhuyinSearchNormalBackground; - englishSearchButton.BackgroundImage = englishSearchNormalBackground; - pinyinSearchButton.BackgroundImage = pinyinSearchNormalBackground; - wordCountSearchButton.BackgroundImage = wordCountSearchNormalBackground; - handWritingSearchButton.BackgroundImage = handWritingSearchActiveBackground; - + UpdateSSearchBtn(handWritingSearchButton, handWritingSearchActiveBackground); EnableDoubleBuffering(handWritingPanelForSingers); EnableDoubleBuffering(handwritingInputBoxForSingers); diff --git a/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.PinyinSearch.cs b/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.PinyinSearch.cs index 68d8999..436a5d4 100644 --- a/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.PinyinSearch.cs +++ b/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.PinyinSearch.cs @@ -20,12 +20,8 @@ namespace DualScreenDemo private void PinyinSingerSearchButton_Click(object sender, EventArgs e) { - zhuyinSearchButton.BackgroundImage = zhuyinSearchNormalBackground; - englishSearchButton.BackgroundImage = englishSearchNormalBackground; - pinyinSearchButton.BackgroundImage = pinyinSearchActiveBackground; - wordCountSearchButton.BackgroundImage = wordCountSearchNormalBackground; - handWritingSearchButton.BackgroundImage = handWritingSearchNormalBackground; + UpdateSSearchBtn(pinyinSearchButton, pinyinSearchActiveBackground); var configData = LoadBtnConfigData(); string pinyinImagePath = Path.Combine(serverPath, configData["ImagePaths"]["PinYinSingers"]); diff --git a/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.WordCountSearch.cs b/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.WordCountSearch.cs index 245d47d..218b82b 100644 --- a/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.WordCountSearch.cs +++ b/PrimaryFormParts/SingerSearch/PrimaryForm.SingerSearch.WordCountSearch.cs @@ -62,12 +62,7 @@ namespace DualScreenDemo private void WordCountSearchSingersButton_Click(object sender, EventArgs e) { // 設定按鈕背景,將「字數搜尋」設為啟動狀態,其餘按鈕恢復為正常狀態 - wordCountSearchButton.BackgroundImage = wordCountSearchActiveBackground; - englishSearchButton.BackgroundImage = englishSearchNormalBackground; - pinyinSearchButton.BackgroundImage = pinyinSearchNormalBackground; - zhuyinSearchButton.BackgroundImage = zhuyinSearchNormalBackground; - handWritingSearchButton.BackgroundImage = handWritingSearchNormalBackground; - + UpdateSSearchBtn(wordCountSearchButton, wordCountSearchActiveBackground); // 載入設定檔,取得圖片路徑資訊 var configData = LoadConfigDataforWordCountSingers(); diff --git a/Program.cs b/Program.cs index c449a96..0446f49 100644 --- a/Program.cs +++ b/Program.cs @@ -14,17 +14,16 @@ namespace DualScreenDemo private static PrimaryForm primaryForm; // 儲存實例的參考 public static Room room = new Room(); - public static string verSion = "Server V2.91 202508141836"; + public static string verSion = "Server V2.9 202508151059"; [STAThread] static void Main() { Console.WriteLine(verSion); - + CheckScreens(); if (Utils.Env.GetBool("IsCursor", true)) Cursor.Hide(); AppDomain.CurrentDomain.ProcessExit += (s, e) => Cursor.Show(); //Console.WriteLine("正在與中控取得聯繫..."); - var cherker=new DataCheck.PublicSongChecker(DBObj.SongList.PublicSong()); try { @@ -96,9 +95,23 @@ namespace DualScreenDemo //SystemEvents.DisplaySettingsChanged -= OnDisplaySettingsChanged; } } - - + private static void CheckScreens() + { + + if (Screen.AllScreens.Length > 1) + { + return; + } + else + { + MessageBox.Show("無法偵測第二顯示器", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Warning); + Application.Exit(); + throw new InvalidOperationException("僅偵測到一個顯示器"); + } + } + + private static void OnDisplaySettingsChanged(object sender, EventArgs e) { // UI操作應該放在try-catch塊中 diff --git a/Services/MediaService.cs b/Services/MediaService.cs index 24c6544..4f63fc0 100644 --- a/Services/MediaService.cs +++ b/Services/MediaService.cs @@ -13,11 +13,12 @@ namespace DualScreenDemo.Services { Core.Initialize(); _libVLC = new LibVLC( + "--aout=directsound", "--network-caching=300", "--file-caching=300", "--audio-time-stretch", - "--video-filter=clone", - $"--clone-views={handle}" // 這是 clone 的目標視窗 + "--video-filter=clone" + //$"--clone-views={handle}" // 這是 clone 的目標視窗 ); _mediaPlayer = new MediaPlayer(_libVLC); @@ -49,6 +50,7 @@ namespace DualScreenDemo.Services _media?.Dispose(); _media = new Media(_libVLC, filePath, FromType.FromPath); + _media.AddOption(":audio-output=directsound"); _media.AddOption($":audio-track={audioTrackIndex}"); } diff --git a/VideoPlayerForm.cs b/VideoPlayerForm.cs index 5c45eb1..6613d34 100644 --- a/VideoPlayerForm.cs +++ b/VideoPlayerForm.cs @@ -67,7 +67,8 @@ namespace DualScreenDemo private const int WS_EX_TOPMOST = 0x00000008; private const uint SWP_NOZORDER = 0x0004; //private MediaServicePrimary primary = new MediaServicePrimary(); - private MediaService secondary; + private MediaService _media; + public static OverlayForm overlayForm; public bool isMuted = false; public int previousVolume = 100; @@ -120,8 +121,8 @@ namespace DualScreenDemo } else { - secondary= new MediaService(PrimaryForm.Instance.videoPanel.Handle); - secondary.SetVideoOutput(this.Handle, secondMonitor.Bounds.Width, secondMonitor.Bounds.Height); + _media= new MediaService(PrimaryForm.Instance.videoPanel.Handle); + _media.SetVideoOutput(this.Handle, secondMonitor.Bounds.Width, secondMonitor.Bounds.Height); PlayNextSong(); } @@ -129,7 +130,7 @@ namespace DualScreenDemo private void VideoPlayerForm_FormClosing(object sender, FormClosingEventArgs e) { - secondary.Dispose(); + _media.Dispose(); // 清理COM CoUninitialize(); } @@ -256,7 +257,18 @@ namespace DualScreenDemo } - public async Task ReplayCurrentSong() =>await _InitializeAndPlayMedia(SongList.Current()); + public async Task ReplayCurrentSong() + { + if (Program.room.IsClose()) + { + return; + } + else + { + await _InitializeAndPlayMedia(SongList.Current()); + } + + } private async Task _InitializeAndPlayMedia(SongData song) { @@ -321,9 +333,9 @@ namespace DualScreenDemo { string pathToPlay = song.getFile(); // 渲染媒體文件 - secondary.LoadMedia(pathToPlay,song.isPublicSong ? 0 : 1); - secondary.Mute(isMuted); - secondary.Play(); + _media.LoadMedia(pathToPlay,song.isPublicSong ? 0 : 1); + _media.Mute(isMuted); + _media.Play(); // 音量處理 //SetVolume(isMuted ? 0 : previousVolume); @@ -358,7 +370,7 @@ namespace DualScreenDemo { try { - if (secondary.IsAtEnd()) + if (_media.IsAtEnd()) { BeginInvoke(new Action(async () => { @@ -393,19 +405,19 @@ namespace DualScreenDemo public void Play() { - secondary.Play(); + _media.Play(); isPaused = false; OverlayForm.MainForm.HidePauseLabel(); } public void Stop() { - secondary.Stop(); + _media.Stop(); } public void Pause() { - secondary.Pause(); + _media.Pause(); isPaused = true; OverlayForm.MainForm.ShowPauseLabel(); } @@ -444,23 +456,23 @@ namespace DualScreenDemo } public bool Mute(bool isMuted) { - return secondary.Mute(isMuted); + return _media.Mute(isMuted); } public void SetVolume(int volume) { Console.WriteLine($"SetVolume: {volume}"); - secondary.SetVolume(volume); + _media.SetVolume(volume); } public int GetVolume() { - return secondary.GetVolume(); + return _media.GetVolume(); } private bool isVocalRemoved = false; public void ToggleVocalRemoval() { isVocalRemoved=!isVocalRemoved; int trackIndex = isVocalRemoved ? 1:0; - secondary.SetAudioTrack(trackIndex); + _media.SetAudioTrack(trackIndex); OverlayForm.MainForm.ShowTopRightLabelTime(isVocalRemoved ? "無人聲" : "有人聲"); } }