2508151214

This commit is contained in:
jasonchenwork 2025-08-15 12:15:33 +08:00
parent 4d94dc6d8e
commit d11cfd4987
8 changed files with 55 additions and 47 deletions

View File

@ -41,7 +41,7 @@ namespace DualScreenDemo
{ {
// 設定按鈕背景,將「注音搜尋」設為啟動狀態,其餘按鈕恢復為正常狀態 // 設定按鈕背景,將「注音搜尋」設為啟動狀態,其餘按鈕恢復為正常狀態
UpdateButtonBackgrounds(zhuyinSearchButton, zhuyinSearchActiveBackground); UpdateSSearchBtn(zhuyinSearchButton, zhuyinSearchActiveBackground);
// 載入設定檔,取得圖片路徑資訊 // 載入設定檔,取得圖片路徑資訊
var configData = LoadBtnConfigData(); var configData = LoadBtnConfigData();

View File

@ -22,12 +22,7 @@ namespace DualScreenDemo
private void EnglishSearchSingersButton_Click(object sender, EventArgs e) private void EnglishSearchSingersButton_Click(object sender, EventArgs e)
{ {
zhuyinSearchButton.BackgroundImage = zhuyinSearchNormalBackground; UpdateSSearchBtn(englishSearchButton, englishSearchActiveBackground);
englishSearchButton.BackgroundImage = englishSearchActiveBackground;
pinyinSearchButton.BackgroundImage = pinyinSearchNormalBackground;
wordCountSearchButton.BackgroundImage = wordCountSearchNormalBackground;
handWritingSearchButton.BackgroundImage = handWritingSearchNormalBackground;
bool shouldBeVisible = !pictureBoxEnglishSingers.Visible; bool shouldBeVisible = !pictureBoxEnglishSingers.Visible;

View File

@ -19,12 +19,7 @@ namespace DualScreenDemo
{ {
this.SuspendLayout(); this.SuspendLayout();
zhuyinSearchButton.BackgroundImage = zhuyinSearchNormalBackground; UpdateSSearchBtn(handWritingSearchButton, handWritingSearchActiveBackground);
englishSearchButton.BackgroundImage = englishSearchNormalBackground;
pinyinSearchButton.BackgroundImage = pinyinSearchNormalBackground;
wordCountSearchButton.BackgroundImage = wordCountSearchNormalBackground;
handWritingSearchButton.BackgroundImage = handWritingSearchActiveBackground;
EnableDoubleBuffering(handWritingPanelForSingers); EnableDoubleBuffering(handWritingPanelForSingers);
EnableDoubleBuffering(handwritingInputBoxForSingers); EnableDoubleBuffering(handwritingInputBoxForSingers);

View File

@ -20,12 +20,8 @@ namespace DualScreenDemo
private void PinyinSingerSearchButton_Click(object sender, EventArgs e) 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(); var configData = LoadBtnConfigData();
string pinyinImagePath = Path.Combine(serverPath, configData["ImagePaths"]["PinYinSingers"]); string pinyinImagePath = Path.Combine(serverPath, configData["ImagePaths"]["PinYinSingers"]);

View File

@ -62,12 +62,7 @@ namespace DualScreenDemo
private void WordCountSearchSingersButton_Click(object sender, EventArgs e) private void WordCountSearchSingersButton_Click(object sender, EventArgs e)
{ {
// 設定按鈕背景,將「字數搜尋」設為啟動狀態,其餘按鈕恢復為正常狀態 // 設定按鈕背景,將「字數搜尋」設為啟動狀態,其餘按鈕恢復為正常狀態
wordCountSearchButton.BackgroundImage = wordCountSearchActiveBackground; UpdateSSearchBtn(wordCountSearchButton, wordCountSearchActiveBackground);
englishSearchButton.BackgroundImage = englishSearchNormalBackground;
pinyinSearchButton.BackgroundImage = pinyinSearchNormalBackground;
zhuyinSearchButton.BackgroundImage = zhuyinSearchNormalBackground;
handWritingSearchButton.BackgroundImage = handWritingSearchNormalBackground;
// 載入設定檔,取得圖片路徑資訊 // 載入設定檔,取得圖片路徑資訊
var configData = LoadConfigDataforWordCountSingers(); var configData = LoadConfigDataforWordCountSingers();

View File

@ -14,17 +14,16 @@ namespace DualScreenDemo
private static PrimaryForm primaryForm; // 儲存實例的參考 private static PrimaryForm primaryForm; // 儲存實例的參考
public static Room room = new Room(); public static Room room = new Room();
public static string verSion = "Server V2.91 202508141836"; public static string verSion = "Server V2.9 202508151059";
[STAThread] [STAThread]
static void Main() static void Main()
{ {
Console.WriteLine(verSion); Console.WriteLine(verSion);
CheckScreens();
if (Utils.Env.GetBool("IsCursor", true)) Cursor.Hide(); if (Utils.Env.GetBool("IsCursor", true)) Cursor.Hide();
AppDomain.CurrentDomain.ProcessExit += (s, e) => Cursor.Show(); AppDomain.CurrentDomain.ProcessExit += (s, e) => Cursor.Show();
//Console.WriteLine("正在與中控取得聯繫..."); //Console.WriteLine("正在與中控取得聯繫...");
var cherker=new DataCheck.PublicSongChecker(DBObj.SongList.PublicSong()); var cherker=new DataCheck.PublicSongChecker(DBObj.SongList.PublicSong());
try try
{ {
@ -97,6 +96,20 @@ namespace DualScreenDemo
} }
} }
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) private static void OnDisplaySettingsChanged(object sender, EventArgs e)

View File

@ -13,11 +13,12 @@ namespace DualScreenDemo.Services
{ {
Core.Initialize(); Core.Initialize();
_libVLC = new LibVLC( _libVLC = new LibVLC(
"--aout=directsound",
"--network-caching=300", "--network-caching=300",
"--file-caching=300", "--file-caching=300",
"--audio-time-stretch", "--audio-time-stretch",
"--video-filter=clone", "--video-filter=clone"
$"--clone-views={handle}" // 這是 clone 的目標視窗 //$"--clone-views={handle}" // 這是 clone 的目標視窗
); );
_mediaPlayer = new MediaPlayer(_libVLC); _mediaPlayer = new MediaPlayer(_libVLC);
@ -49,6 +50,7 @@ namespace DualScreenDemo.Services
_media?.Dispose(); _media?.Dispose();
_media = new Media(_libVLC, filePath, FromType.FromPath); _media = new Media(_libVLC, filePath, FromType.FromPath);
_media.AddOption(":audio-output=directsound");
_media.AddOption($":audio-track={audioTrackIndex}"); _media.AddOption($":audio-track={audioTrackIndex}");
} }

View File

@ -67,7 +67,8 @@ namespace DualScreenDemo
private const int WS_EX_TOPMOST = 0x00000008; private const int WS_EX_TOPMOST = 0x00000008;
private const uint SWP_NOZORDER = 0x0004; private const uint SWP_NOZORDER = 0x0004;
//private MediaServicePrimary primary = new MediaServicePrimary(); //private MediaServicePrimary primary = new MediaServicePrimary();
private MediaService secondary; private MediaService _media;
public static OverlayForm overlayForm; public static OverlayForm overlayForm;
public bool isMuted = false; public bool isMuted = false;
public int previousVolume = 100; public int previousVolume = 100;
@ -120,8 +121,8 @@ namespace DualScreenDemo
} }
else else
{ {
secondary= new MediaService(PrimaryForm.Instance.videoPanel.Handle); _media= new MediaService(PrimaryForm.Instance.videoPanel.Handle);
secondary.SetVideoOutput(this.Handle, secondMonitor.Bounds.Width, secondMonitor.Bounds.Height); _media.SetVideoOutput(this.Handle, secondMonitor.Bounds.Width, secondMonitor.Bounds.Height);
PlayNextSong(); PlayNextSong();
} }
@ -129,7 +130,7 @@ namespace DualScreenDemo
private void VideoPlayerForm_FormClosing(object sender, FormClosingEventArgs e) private void VideoPlayerForm_FormClosing(object sender, FormClosingEventArgs e)
{ {
secondary.Dispose(); _media.Dispose();
// 清理COM // 清理COM
CoUninitialize(); 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) private async Task _InitializeAndPlayMedia(SongData song)
{ {
@ -321,9 +333,9 @@ namespace DualScreenDemo
{ {
string pathToPlay = song.getFile(); string pathToPlay = song.getFile();
// 渲染媒體文件 // 渲染媒體文件
secondary.LoadMedia(pathToPlay,song.isPublicSong ? 0 : 1); _media.LoadMedia(pathToPlay,song.isPublicSong ? 0 : 1);
secondary.Mute(isMuted); _media.Mute(isMuted);
secondary.Play(); _media.Play();
// 音量處理 // 音量處理
//SetVolume(isMuted ? 0 : previousVolume); //SetVolume(isMuted ? 0 : previousVolume);
@ -358,7 +370,7 @@ namespace DualScreenDemo
{ {
try try
{ {
if (secondary.IsAtEnd()) if (_media.IsAtEnd())
{ {
BeginInvoke(new Action(async () => BeginInvoke(new Action(async () =>
{ {
@ -393,19 +405,19 @@ namespace DualScreenDemo
public void Play() public void Play()
{ {
secondary.Play(); _media.Play();
isPaused = false; isPaused = false;
OverlayForm.MainForm.HidePauseLabel(); OverlayForm.MainForm.HidePauseLabel();
} }
public void Stop() public void Stop()
{ {
secondary.Stop(); _media.Stop();
} }
public void Pause() public void Pause()
{ {
secondary.Pause(); _media.Pause();
isPaused = true; isPaused = true;
OverlayForm.MainForm.ShowPauseLabel(); OverlayForm.MainForm.ShowPauseLabel();
} }
@ -444,23 +456,23 @@ namespace DualScreenDemo
} }
public bool Mute(bool isMuted) public bool Mute(bool isMuted)
{ {
return secondary.Mute(isMuted); return _media.Mute(isMuted);
} }
public void SetVolume(int volume) public void SetVolume(int volume)
{ {
Console.WriteLine($"SetVolume: {volume}"); Console.WriteLine($"SetVolume: {volume}");
secondary.SetVolume(volume); _media.SetVolume(volume);
} }
public int GetVolume() public int GetVolume()
{ {
return secondary.GetVolume(); return _media.GetVolume();
} }
private bool isVocalRemoved = false; private bool isVocalRemoved = false;
public void ToggleVocalRemoval() public void ToggleVocalRemoval()
{ {
isVocalRemoved=!isVocalRemoved; isVocalRemoved=!isVocalRemoved;
int trackIndex = isVocalRemoved ? 1:0; int trackIndex = isVocalRemoved ? 1:0;
secondary.SetAudioTrack(trackIndex); _media.SetAudioTrack(trackIndex);
OverlayForm.MainForm.ShowTopRightLabelTime(isVocalRemoved ? "無人聲" : "有人聲"); OverlayForm.MainForm.ShowTopRightLabelTime(isVocalRemoved ? "無人聲" : "有人聲");
} }
} }