From 9786a447ca1ba55f90d58118acf4f6c4c1357e04 Mon Sep 17 00:00:00 2001 From: tangge233 Date: Sat, 26 Oct 2024 11:50:08 +0800 Subject: [PATCH 1/5] =?UTF-8?q?chore:=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Plain Craft Launcher 2/Modules/ModMusic.vb | 80 +++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/Plain Craft Launcher 2/Modules/ModMusic.vb b/Plain Craft Launcher 2/Modules/ModMusic.vb index 52a87a8..da27e44 100644 --- a/Plain Craft Launcher 2/Modules/ModMusic.vb +++ b/Plain Craft Launcher 2/Modules/ModMusic.vb @@ -1,4 +1,7 @@ -Public Module ModMusic +Imports NAudio.CoreAudioApi +Imports NAudio.CoreAudioApi.Interfaces + +Public Module ModMusic #Region "播放列表" @@ -248,6 +251,8 @@ ''' Private MusicCurrent As String = "" + Dim deviceHandler As New AudioDeviceChangeHandler + ''' ''' 在 MusicUuid 不变的前提下,持续播放某地址的音乐,且在播放结束后随机播放下一曲。 ''' @@ -305,4 +310,77 @@ End Try End Sub + Public Class AudioDeviceChangeHandler + Implements Interfaces.IMMNotificationClient + Private deviceWatcher As MMDeviceEnumerator + Private callback As IMMNotificationClient + + Public Sub New() + ' 初始化音频设备枚举器 + deviceWatcher = New MMDeviceEnumerator() + ' 创建设备通知回调对象 + callback = New DeviceNotificationClient(Me) + ' 注册回调以接收音频设备更改通知 + deviceWatcher.RegisterEndpointNotificationCallback(callback) + End Sub + + ' 实现IMMNotificationClient接口的方法以处理设备更改事件 + Public Sub OnDefaultDeviceChanged(dataFlow As DataFlow, role As Role, defaultDeviceId As String) Implements IMMNotificationClient.OnDefaultDeviceChanged + ' 处理默认音频设备更改事件 + If MusicNAudio Is Nothing Then Exit Sub + CType(MusicNAudio, NAudio.Wave.WaveOut).DeviceNumber = 0 + End Sub + + Public Sub OnDeviceAdded(deviceId As String) Implements IMMNotificationClient.OnDeviceAdded + ' 处理音频设备添加事件 + If MusicNAudio Is Nothing Then Exit Sub + CType(MusicNAudio, NAudio.Wave.WaveOut).DeviceNumber = 0 + End Sub + + Public Sub OnDeviceRemoved(deviceId As String) Implements IMMNotificationClient.OnDeviceRemoved + ' 处理音频设备移除事件 + If MusicNAudio Is Nothing Then Exit Sub + CType(MusicNAudio, NAudio.Wave.WaveOut).DeviceNumber = 0 + End Sub + + Public Sub OnDeviceStateChanged(deviceId As String, newState As DeviceState) Implements IMMNotificationClient.OnDeviceStateChanged + ' 处理音频设备状态更改事件 + End Sub + + Public Sub OnPropertyValueChanged(deviceId As String, key As PropertyKey) Implements IMMNotificationClient.OnPropertyValueChanged + ' 处理音频设备属性值更改事件 + End Sub + End Class + + ' 实现IMMNotificationClient接口的类 + Friend Class DeviceNotificationClient + Implements IMMNotificationClient + + Private container As AudioDeviceChangeHandler + + Public Sub New(container As AudioDeviceChangeHandler) + Me.container = container + End Sub + + Public Sub OnDefaultDeviceChanged(dataFlow As DataFlow, role As Role, defaultDeviceId As String) Implements IMMNotificationClient.OnDefaultDeviceChanged + container.OnDefaultDeviceChanged(dataFlow, role, defaultDeviceId) + End Sub + + Public Sub OnDeviceAdded(deviceId As String) Implements IMMNotificationClient.OnDeviceAdded + container.OnDeviceAdded(deviceId) + End Sub + + Public Sub OnDeviceRemoved(deviceId As String) Implements IMMNotificationClient.OnDeviceRemoved + container.OnDeviceRemoved(deviceId) + End Sub + + Public Sub OnDeviceStateChanged(deviceId As String, newState As DeviceState) Implements IMMNotificationClient.OnDeviceStateChanged + container.OnDeviceStateChanged(deviceId, newState) + End Sub + + Public Sub OnPropertyValueChanged(deviceId As String, key As PropertyKey) Implements IMMNotificationClient.OnPropertyValueChanged + container.OnPropertyValueChanged(deviceId, key) + End Sub + End Class + End Module From 7dff62aebfc2f6405255f7c7682ce26b408295fa Mon Sep 17 00:00:00 2001 From: tangge233 Date: Mon, 13 Jan 2025 21:46:12 +0800 Subject: [PATCH 2/5] feat: output device change --- Plain Craft Launcher 2/Modules/ModMusic.vb | 93 ++++++++++++---------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/Plain Craft Launcher 2/Modules/ModMusic.vb b/Plain Craft Launcher 2/Modules/ModMusic.vb index 12de669..b368691 100644 --- a/Plain Craft Launcher 2/Modules/ModMusic.vb +++ b/Plain Craft Launcher 2/Modules/ModMusic.vb @@ -69,44 +69,44 @@ Public Module ModMusic ''' Private Sub MusicRefreshUI() RunInUi( - Sub() - Try + Sub() + Try - If Not MusicAllList.Any() Then - '无背景音乐 - FrmMain.BtnExtraMusic.Show = False - Else - '有背景音乐 - FrmMain.BtnExtraMusic.Show = True - Dim ToolTipText As String - If MusicState = MusicStates.Pause Then - FrmMain.BtnExtraMusic.Logo = Logo.IconPlay - FrmMain.BtnExtraMusic.LogoScale = 0.8 - ToolTipText = "已暂停:" & GetFileNameWithoutExtentionFromPath(MusicCurrent) - If MusicAllList.Count > 1 Then - ToolTipText += vbCrLf & "左键恢复播放,右键播放下一曲。" - Else - ToolTipText += vbCrLf & "左键恢复播放,右键重新从头播放。" - End If + If Not MusicAllList.Any() Then + '无背景音乐 + FrmMain.BtnExtraMusic.Show = False Else - FrmMain.BtnExtraMusic.Logo = Logo.IconMusic - FrmMain.BtnExtraMusic.LogoScale = 1 - ToolTipText = "正在播放:" & GetFileNameWithoutExtentionFromPath(MusicCurrent) - If MusicAllList.Count > 1 Then - ToolTipText += vbCrLf & "左键暂停,右键播放下一曲。" + '有背景音乐 + FrmMain.BtnExtraMusic.Show = True + Dim ToolTipText As String + If MusicState = MusicStates.Pause Then + FrmMain.BtnExtraMusic.Logo = Logo.IconPlay + FrmMain.BtnExtraMusic.LogoScale = 0.8 + ToolTipText = "已暂停:" & GetFileNameWithoutExtentionFromPath(MusicCurrent) + If MusicAllList.Count > 1 Then + ToolTipText += vbCrLf & "左键恢复播放,右键播放下一曲。" + Else + ToolTipText += vbCrLf & "左键恢复播放,右键重新从头播放。" + End If Else - ToolTipText += vbCrLf & "左键暂停,右键重新从头播放。" + FrmMain.BtnExtraMusic.Logo = Logo.IconMusic + FrmMain.BtnExtraMusic.LogoScale = 1 + ToolTipText = "正在播放:" & GetFileNameWithoutExtentionFromPath(MusicCurrent) + If MusicAllList.Count > 1 Then + ToolTipText += vbCrLf & "左键暂停,右键播放下一曲。" + Else + ToolTipText += vbCrLf & "左键暂停,右键重新从头播放。" + End If End If + FrmMain.BtnExtraMusic.ToolTip = ToolTipText + ToolTipService.SetVerticalOffset(FrmMain.BtnExtraMusic, If(ToolTipText.Contains(vbLf), 10, 16)) End If - FrmMain.BtnExtraMusic.ToolTip = ToolTipText - ToolTipService.SetVerticalOffset(FrmMain.BtnExtraMusic, If(ToolTipText.Contains(vbLf), 10, 16)) - End If - If FrmSetupUI IsNot Nothing Then FrmSetupUI.MusicRefreshUI() + If FrmSetupUI IsNot Nothing Then FrmSetupUI.MusicRefreshUI() - Catch ex As Exception - Log(ex, "刷新背景音乐 UI 失败", LogLevel.Feedback) - End Try - End Sub) + Catch ex As Exception + Log(ex, "刷新背景音乐 UI 失败", LogLevel.Feedback) + End Try + End Sub) End Sub ''' @@ -226,11 +226,11 @@ Public Module ModMusic Public Function MusicPause() As Boolean If MusicState = MusicStates.Play Then RunInThread( - Sub() - Log("[Music] 已暂停播放") - MusicNAudio?.Pause() - MusicRefreshUI() - End Sub) + Sub() + Log("[Music] 已暂停播放") + MusicNAudio?.Pause() + MusicRefreshUI() + End Sub) Return True Else Log($"[Music] 无需暂停播放,当前状态为 {MusicState}") @@ -246,11 +246,11 @@ Public Module ModMusic Return False Else RunInThread( - Sub() - Log("[Music] 已恢复播放") - MusicNAudio?.Play() - MusicRefreshUI() - End Sub) + Sub() + Log("[Music] 已恢复播放") + MusicNAudio?.Play() + MusicRefreshUI() + End Sub) Return True End If End Function @@ -308,7 +308,7 @@ Public Module ModMusic If ex.Message.Contains("Got a frame at sample rate") OrElse ex.Message.Contains("does not support changes to") Then Hint("播放音乐失败(" & GetFileNameFromPath(MusicCurrent) & "):PCL 不支持播放音频属性在中途发生变化的音乐", HintType.Critical) ElseIf Not (MusicCurrent.EndsWithF(".wav", True) OrElse MusicCurrent.EndsWithF(".mp3", True) OrElse MusicCurrent.EndsWithF(".flac", True)) OrElse - ex.Message.Contains("0xC00D36C4") Then '#5096:不支持给定的 URL 的字节流类型。 (异常来自 HRESULT:0xC00D36C4) + ex.Message.Contains("0xC00D36C4") Then '#5096:不支持给定的 URL 的字节流类型。 (异常来自 HRESULT:0xC00D36C4) Hint("播放音乐失败(" & GetFileNameFromPath(MusicCurrent) & "):PCL 可能不支持此音乐格式,请将格式转换为 .wav、.mp3 或 .flac 后再试", HintType.Critical) Else Log(ex, "播放音乐失败(" & GetFileNameFromPath(MusicCurrent) & ")", LogLevel.Hint) @@ -385,6 +385,13 @@ Public Module ModMusic Public Sub OnDefaultDeviceChanged(dataFlow As DataFlow, role As Role, defaultDeviceId As String) Implements IMMNotificationClient.OnDefaultDeviceChanged container.OnDefaultDeviceChanged(dataFlow, role, defaultDeviceId) + ' 切换到系统默认输出设备 + If MusicNAudio IsNot Nothing Then + Dim target As NAudio.Wave.WaveOut = MusicNAudio + target.Stop() + target.DeviceNumber = 0 + target.Resume() + End If End Sub Public Sub OnDeviceAdded(deviceId As String) Implements IMMNotificationClient.OnDeviceAdded From 39b84e8701a6febc951db5b1d3e6c75bd18c20d3 Mon Sep 17 00:00:00 2001 From: tangge233 Date: Sat, 15 Mar 2025 00:36:06 +0800 Subject: [PATCH 3/5] =?UTF-8?q?style:=20=E5=88=87=E6=8D=A2=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E7=A7=BB=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Plain Craft Launcher 2/Modules/ModMusic.vb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Plain Craft Launcher 2/Modules/ModMusic.vb b/Plain Craft Launcher 2/Modules/ModMusic.vb index b368691..9c09f89 100644 --- a/Plain Craft Launcher 2/Modules/ModMusic.vb +++ b/Plain Craft Launcher 2/Modules/ModMusic.vb @@ -349,7 +349,12 @@ Public Module ModMusic Public Sub OnDefaultDeviceChanged(dataFlow As DataFlow, role As Role, defaultDeviceId As String) Implements IMMNotificationClient.OnDefaultDeviceChanged ' 处理默认音频设备更改事件 If MusicNAudio Is Nothing Then Exit Sub - CType(MusicNAudio, NAudio.Wave.WaveOut).DeviceNumber = 0 + ' 切换到系统默认输出设备 + Log($"音频默认输出设备切换到 {defaultDeviceId}") + Dim target As NAudio.Wave.WaveOut = MusicNAudio + target.Stop() + target.DeviceNumber = 0 + target.Resume() End Sub Public Sub OnDeviceAdded(deviceId As String) Implements IMMNotificationClient.OnDeviceAdded @@ -385,13 +390,6 @@ Public Module ModMusic Public Sub OnDefaultDeviceChanged(dataFlow As DataFlow, role As Role, defaultDeviceId As String) Implements IMMNotificationClient.OnDefaultDeviceChanged container.OnDefaultDeviceChanged(dataFlow, role, defaultDeviceId) - ' 切换到系统默认输出设备 - If MusicNAudio IsNot Nothing Then - Dim target As NAudio.Wave.WaveOut = MusicNAudio - target.Stop() - target.DeviceNumber = 0 - target.Resume() - End If End Sub Public Sub OnDeviceAdded(deviceId As String) Implements IMMNotificationClient.OnDeviceAdded From bf86b0732ae84bdd0b355b0bdacf3f4fb10a97a3 Mon Sep 17 00:00:00 2001 From: tangge233 Date: Sat, 15 Mar 2025 01:07:23 +0800 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20=E9=BB=98=E8=AE=A4=E9=9F=B3=E9=A2=91?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E7=9A=84=E4=BB=A3=E5=8F=B7=E5=BA=94=E8=AF=A5?= =?UTF-8?q?=E6=98=AF=20-1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Plain Craft Launcher 2/Modules/ModMusic.vb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Plain Craft Launcher 2/Modules/ModMusic.vb b/Plain Craft Launcher 2/Modules/ModMusic.vb index 9c09f89..3e24a0f 100644 --- a/Plain Craft Launcher 2/Modules/ModMusic.vb +++ b/Plain Craft Launcher 2/Modules/ModMusic.vb @@ -353,20 +353,20 @@ Public Module ModMusic Log($"音频默认输出设备切换到 {defaultDeviceId}") Dim target As NAudio.Wave.WaveOut = MusicNAudio target.Stop() - target.DeviceNumber = 0 + target.DeviceNumber = -1 target.Resume() End Sub Public Sub OnDeviceAdded(deviceId As String) Implements IMMNotificationClient.OnDeviceAdded ' 处理音频设备添加事件 If MusicNAudio Is Nothing Then Exit Sub - CType(MusicNAudio, NAudio.Wave.WaveOut).DeviceNumber = 0 + CType(MusicNAudio, NAudio.Wave.WaveOut).DeviceNumber = -1 End Sub Public Sub OnDeviceRemoved(deviceId As String) Implements IMMNotificationClient.OnDeviceRemoved ' 处理音频设备移除事件 If MusicNAudio Is Nothing Then Exit Sub - CType(MusicNAudio, NAudio.Wave.WaveOut).DeviceNumber = 0 + CType(MusicNAudio, NAudio.Wave.WaveOut).DeviceNumber = -1 End Sub Public Sub OnDeviceStateChanged(deviceId As String, newState As DeviceState) Implements IMMNotificationClient.OnDeviceStateChanged From 482d6f71fcbcb116faf4012268c616608a72e533 Mon Sep 17 00:00:00 2001 From: tangge233 Date: Sat, 15 Mar 2025 01:24:57 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix(ModMusic):=20=E5=8D=83=E5=B9=B4?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E8=80=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Plain Craft Launcher 2/Modules/ModMusic.vb | 87 +--------------------- 1 file changed, 4 insertions(+), 83 deletions(-) diff --git a/Plain Craft Launcher 2/Modules/ModMusic.vb b/Plain Craft Launcher 2/Modules/ModMusic.vb index 3e24a0f..0632b83 100644 --- a/Plain Craft Launcher 2/Modules/ModMusic.vb +++ b/Plain Craft Launcher 2/Modules/ModMusic.vb @@ -258,7 +258,7 @@ Public Module ModMusic #End Region ''' - ''' 当前正在播放的 NAudio.Wave.WaveOut。 + ''' 当前正在播放的 NAudio.Wave.WaveOutEvent。 ''' Public MusicNAudio = Nothing ''' @@ -266,18 +266,17 @@ Public Module ModMusic ''' Private MusicCurrent As String = "" - Dim deviceHandler As New AudioDeviceChangeHandler - ''' ''' 在 MusicUuid 不变的前提下,持续播放某地址的音乐,且在播放结束后随机播放下一曲。 ''' Private Sub MusicLoop(Optional IsFirstLoad As Boolean = False) - Dim CurrentWave As NAudio.Wave.WaveOut = Nothing + Dim CurrentWave As NAudio.Wave.WaveOutEvent = Nothing Dim Reader As NAudio.Wave.WaveStream = Nothing Try '开始播放 - CurrentWave = New NAudio.Wave.WaveOut() + CurrentWave = New NAudio.Wave.WaveOutEvent() MusicNAudio = CurrentWave + CurrentWave.DeviceNumber = -1 Reader = New NAudio.Wave.AudioFileReader(MusicCurrent) CurrentWave.Init(Reader) CurrentWave.Play() @@ -331,82 +330,4 @@ Public Module ModMusic End Try End Sub - Public Class AudioDeviceChangeHandler - Implements Interfaces.IMMNotificationClient - Private deviceWatcher As MMDeviceEnumerator - Private callback As IMMNotificationClient - - Public Sub New() - ' 初始化音频设备枚举器 - deviceWatcher = New MMDeviceEnumerator() - ' 创建设备通知回调对象 - callback = New DeviceNotificationClient(Me) - ' 注册回调以接收音频设备更改通知 - deviceWatcher.RegisterEndpointNotificationCallback(callback) - End Sub - - ' 实现IMMNotificationClient接口的方法以处理设备更改事件 - Public Sub OnDefaultDeviceChanged(dataFlow As DataFlow, role As Role, defaultDeviceId As String) Implements IMMNotificationClient.OnDefaultDeviceChanged - ' 处理默认音频设备更改事件 - If MusicNAudio Is Nothing Then Exit Sub - ' 切换到系统默认输出设备 - Log($"音频默认输出设备切换到 {defaultDeviceId}") - Dim target As NAudio.Wave.WaveOut = MusicNAudio - target.Stop() - target.DeviceNumber = -1 - target.Resume() - End Sub - - Public Sub OnDeviceAdded(deviceId As String) Implements IMMNotificationClient.OnDeviceAdded - ' 处理音频设备添加事件 - If MusicNAudio Is Nothing Then Exit Sub - CType(MusicNAudio, NAudio.Wave.WaveOut).DeviceNumber = -1 - End Sub - - Public Sub OnDeviceRemoved(deviceId As String) Implements IMMNotificationClient.OnDeviceRemoved - ' 处理音频设备移除事件 - If MusicNAudio Is Nothing Then Exit Sub - CType(MusicNAudio, NAudio.Wave.WaveOut).DeviceNumber = -1 - End Sub - - Public Sub OnDeviceStateChanged(deviceId As String, newState As DeviceState) Implements IMMNotificationClient.OnDeviceStateChanged - ' 处理音频设备状态更改事件 - End Sub - - Public Sub OnPropertyValueChanged(deviceId As String, key As PropertyKey) Implements IMMNotificationClient.OnPropertyValueChanged - ' 处理音频设备属性值更改事件 - End Sub - End Class - - ' 实现IMMNotificationClient接口的类 - Friend Class DeviceNotificationClient - Implements IMMNotificationClient - - Private container As AudioDeviceChangeHandler - - Public Sub New(container As AudioDeviceChangeHandler) - Me.container = container - End Sub - - Public Sub OnDefaultDeviceChanged(dataFlow As DataFlow, role As Role, defaultDeviceId As String) Implements IMMNotificationClient.OnDefaultDeviceChanged - container.OnDefaultDeviceChanged(dataFlow, role, defaultDeviceId) - End Sub - - Public Sub OnDeviceAdded(deviceId As String) Implements IMMNotificationClient.OnDeviceAdded - container.OnDeviceAdded(deviceId) - End Sub - - Public Sub OnDeviceRemoved(deviceId As String) Implements IMMNotificationClient.OnDeviceRemoved - container.OnDeviceRemoved(deviceId) - End Sub - - Public Sub OnDeviceStateChanged(deviceId As String, newState As DeviceState) Implements IMMNotificationClient.OnDeviceStateChanged - container.OnDeviceStateChanged(deviceId, newState) - End Sub - - Public Sub OnPropertyValueChanged(deviceId As String, key As PropertyKey) Implements IMMNotificationClient.OnPropertyValueChanged - container.OnPropertyValueChanged(deviceId, key) - End Sub - End Class - End Module