You can set the default audio playback device in windows 2000, Me, and XP with the DRVM_MAPPER_PREFERRED_SET message, which is sent with waveOutMessage().
It doesn't work on vista - you get MMSYSERR_NOTSUPPORTED (8), returned.
You can do it in Vista - see http://vachanger.sourceforge.net/
Anyway, the code uses the Windows Media .Net library.
Imports MultiMedia ' http://windowsmedianet.sourceforge.net/ Imports System.Runtime.InteropServices Imports System.ComponentModel Public Class Form1 Private DevicesComboBox As New ComboBox Private DefaultDeviceLabel As New Label Private WithEvents SetDefaultButton As New Button Private Const DRVM_MAPPER_PREFERRED_GET As Integer = &H2015 Private Const DRVM_MAPPER_PREFERRED_SET As Integer = &H2016 Private WAVE_MAPPER As New IntPtr(-1) ' This just brings together a device ID and a WaveOutCaps so ' that we can store them in a combobox. Private Structure WaveOutDevice Private m_id As Integer Public Property Id() As Integer Get Return m_id End Get Set(ByVal value As Integer) m_id = value End Set End Property Private m_caps As WaveOutCaps Public Property WaveOutCaps() As WaveOutCaps Get Return m_caps End Get Set(ByVal value As WaveOutCaps) m_caps = value End Set End Property Sub New(ByVal id As Integer, ByVal caps As WaveOutCaps) m_id = id m_caps = caps End Sub Public Overrides Function ToString() As String Return WaveOutCaps.szPname End Function End Structure Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ' I do use the IDE for this stuff normally... (in case anyone is wondering) Me.Controls.AddRange(New Control() {DevicesComboBox, DefaultDeviceLabel, SetDefaultButton}) DevicesComboBox.Location = New Point(5, 5) DevicesComboBox.DropDownStyle = ComboBoxStyle.DropDownList DevicesComboBox.Width = Me.ClientSize.Width - 10 DevicesComboBox.Anchor = AnchorStyles.Left Or AnchorStyles.Right DefaultDeviceLabel.Location = New Point(DevicesComboBox.Left, DevicesComboBox.Bottom + 5) DefaultDeviceLabel.AutoSize = True SetDefaultButton.Location = New Point(DefaultDeviceLabel.Left, DefaultDeviceLabel.Bottom + 5) SetDefaultButton.Text = "Set Default" SetDefaultButton.AutoSize = True RefreshInformation() End Sub Private Sub RefreshInformation() PopulateDeviceComboBox() DisplayDefaultWaveOutDevice() End Sub Private Sub PopulateDeviceComboBox() DevicesComboBox.Items.Clear() ' How many wave out devices are there? WaveOutGetNumDevs API call. Dim waveOutDeviceCount As Integer = waveOut.GetNumDevs() For i As Integer = 0 To waveOutDeviceCount - 1 Dim caps As New WaveOutCaps ' Get a name - its in a WAVEOUTCAPS structure. ' The name is truncated to 31 chars by the api call. You probably have to ' dig around in the registry to get the full name. Dim result As Integer = waveOut.GetDevCaps(i, caps, Marshal.SizeOf(caps)) If result <> MMSYSERR.NoError Then Dim err As MMSYSERR = DirectCast(result, MMSYSERR) Throw New Win32Exception("GetDevCaps() error, Result: " & result.ToString("x8") & ", " & err.ToString) End If DevicesComboBox.Items.Add(New WaveOutDevice(i, caps)) Next DevicesComboBox.SelectedIndex = 0 End Sub Private Sub DisplayDefaultWaveOutDevice() Dim currentDefault As Integer = GetIdOfDefaultWaveOutDevice() Dim device As WaveOutDevice = DirectCast(DevicesComboBox.Items(currentDefault), WaveOutDevice) DefaultDeviceLabel.Text = "Defualt: " & device.WaveOutCaps.szPname End Sub Private Function GetIdOfDefaultWaveOutDevice() As Integer Dim id As Integer = 0 Dim hId As IntPtr Dim flags As Integer = 0 Dim hFlags As IntPtr Dim result As Integer Try ' It would be easier to declare a nice overload with ByRef Integers. hId = Marshal.AllocHGlobal(4) hFlags = Marshal.AllocHGlobal(4) ' http://msdn.microsoft.com/en-us/library/bb981557.aspx result = waveOut.Message(WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, hId, hFlags) If result <> MMSYSERR.NoError Then Dim err As MMSYSERR = DirectCast(result, MMSYSERR) Throw New Win32Exception("waveOutMessage() error, Result: " & result.ToString("x8") & ", " & err.ToString) End If id = Marshal.ReadInt32(hId) flags = Marshal.ReadInt32(hFlags) Finally Marshal.FreeHGlobal(hId) Marshal.FreeHGlobal(hFlags) End Try ' There is only one flag, DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY, defined as 1 ' "When the DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY flag bit is set, ... blah ..., ' the waveIn and waveOut APIs use only the current preferred device and do not search ' for other available devices if the preferred device is unavailable. Return id End Function Private Sub SetDefaultButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SetDefaultButton.Click If DevicesComboBox.Items.Count = 0 Then Return Dim selectedDevice As WaveOutDevice = DirectCast(DevicesComboBox.SelectedItem, WaveOutDevice) SetDefault(selectedDevice.Id) RefreshInformation() End Sub Private Sub SetDefault(ByVal id As Integer) Dim defaultId As Integer = GetIdOfDefaultWaveOutDevice() If defaultId = id Then Return ' no change. Dim result As Integer ' So here we say "change the Id of the device that has id id to 0", which makes it the default. result = waveOut.Message(WAVE_MAPPER, DRVM_MAPPER_PREFERRED_SET, New IntPtr(id), IntPtr.Zero) If result <> MMSYSERR.NoError Then Dim err As MMSYSERR = DirectCast(result, MMSYSERR) Throw New Win32Exception("waveOutMessage() error, Result: " & result.ToString("x8") & ", " & err.ToString) End If End Sub End Class
Actually, Visual Studio, return me an error : System.ComponentModel.Win32Exception: 'waveOutMessage() error, Result: 00000008, NotSupported'. And Exit.
ReplyDelete