Attribute VB_Name = "mod_Mixer"
Option Explicit

Public Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Public Declare Function GlobalFree Lib "kernel32" (ByVal hmem As Long) As Long
Public Declare Function GlobalLock Lib "kernel32" (ByVal hmem As Long) As Long
Public Declare Function mixerClose Lib "winmm.dll" (ByVal hmx As Long) As Long
Public Declare Function mixerGetControlDetails Lib "winmm.dll" Alias "mixerGetControlDetailsA" (ByVal hmxobj As Long, pmxcd As MIXERCONTROLDETAILS, ByVal fdwDetails As Long) As Long
Public Declare Function mixerGetLineControls Lib "winmm.dll" Alias "mixerGetLineControlsA" (ByVal hmxobj As Long, pmxlc As MIXERLINECONTROLS, ByVal fdwControls As Long) As Long
Public Declare Function mixerGetLineInfo Lib "winmm.dll" Alias "mixerGetLineInfoA" (ByVal hmxobj As Long, pmxl As MIXERLINE, ByVal fdwInfo As Long) As Long
Public Declare Function mixerOpen Lib "winmm.dll" (phmx As Long, ByVal uMxId As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal fdwOpen As Long) As Long
Public Declare Function mixerSetControlDetails Lib "winmm.dll" (ByVal hmxobj As Long, pmxcd As MIXERCONTROLDETAILS, ByVal fdwDetails As Long) As Long

Public Declare Sub CopyPtrFromStruct Lib "kernel32" Alias "RtlMoveMemory" (ByVal ptr As Long, struct As Any, ByVal cb As Long)
Public Declare Sub CopyStructFromPtr Lib "kernel32" Alias "RtlMoveMemory" (struct As Any, ByVal ptr As Long, ByVal cb As Long)

Public hmem As Long
Public hmixer As Long             ' mixer handle
Public rc As Long
Public VolCtrl(0 To 9) As MIXERCONTROL      ' volume control
Public MuteCtrl(0 To 9) As MIXERCONTROL     ' mute control
Public VolLong(0 To 9) As Long              ' volume value
Public VolMode(0 To 9) As Boolean           ' False=mono, true=stereo
Public volMute(0 To 9) As Boolean           ' Mute true/false
Public volume As Long
Public mxl As MIXERLINE
Public txtMixer As String

Public Const MAXPNAMELEN = 32
Public Const MIXER_GETLINECONTROLSF_ONEBYTYPE = &H2& ' separate left-right volume control
Public Const MIXER_GETLINEINFOF_COMPONENTTYPE = &H3&
Public Const MIXER_LONG_NAME_CHARS = 64
Public Const MIXER_SHORT_NAME_CHARS = 16
Public Const MIXER_SETCONTROLDETAILSF_VALUE = &H0&

Public Const MIXER_GETCONTROLDETAILSF_VALUE = &H0&
Public Const MIXERCONTROL_CT_CLASS_FADER = &H50000000
Public Const MIXERCONTROL_CT_UNITS_UNSIGNED = &H30000
Public Const MIXERCONTROL_CONTROLTYPE_FADER = (MIXERCONTROL_CT_CLASS_FADER Or MIXERCONTROL_CT_UNITS_UNSIGNED)
Public Const MIXERCONTROL_CONTROLTYPE_VOLUME = (MIXERCONTROL_CONTROLTYPE_FADER + 1)
Public Const MIXERLINE_COMPONENTTYPE_DST_FIRST = &H0&
Public Const MIXERLINE_COMPONENTTYPE_DST_SPEAKERS = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 4)
Public Const MIXERLINE_COMPONENTTYPE_SRC_FIRST = &H1000&
Public Const MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 9)
Public Const MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 5)
Public Const MIXERLINE_COMPONENTTYPE_SRC_DIGITAL = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 1)
Public Const MIXERLINE_COMPONENTTYPE_SRC_LINE = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 2)
Public Const MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 3)
Public Const MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 7)
Public Const MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 4)
Public Const MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 6)
Public Const MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 8)
Public Const MMSYSERR_NOERROR = 0
Public Const MIXERCONTROL_CT_CLASS_SWITCH = &H20000000
Public Const MIXERCONTROL_CT_SC_SWITCH_BOOLEAN = &H0&
Public Const MIXERCONTROL_CT_UNITS_BOOLEAN = &H10000
Public Const MIXERCONTROL_CONTROLTYPE_BOOLEAN = (MIXERCONTROL_CT_CLASS_SWITCH Or MIXERCONTROL_CT_SC_SWITCH_BOOLEAN Or MIXERCONTROL_CT_UNITS_BOOLEAN)
Public Const MIXERCONTROL_CONTROLTYPE_MUTE = (MIXERCONTROL_CONTROLTYPE_BOOLEAN + 2)

Type Target
     dwType As Long                 '  MIXERLINE_TARGETTYPE_xxxx
     dwDeviceID As Long             '  target device ID of device type
     wMid As Integer                   '  of target device
     wPid As Integer                   '       "
     vDriverVersion As Long            '       "
     szPname As String * MAXPNAMELEN
End Type

Type MIXERCONTROL
     cbStruct As Long           '  size in Byte of MIXERCONTROL
     dwControlID As Long        '  unique control id for mixer device
     dwControlType As Long      '  MIXERCONTROL_CONTROLTYPE_xxx
     fdwControl As Long         '  MIXERCONTROL_CONTROLF_xxx
     cMultipleItems As Long     '  if MIXERCONTROL_CONTROLF_MULTIPLE set
     szShortName(1 To MIXER_SHORT_NAME_CHARS) As Byte
     szName(1 To MIXER_LONG_NAME_CHARS) As Byte
     Bounds(1 To 6) As Long
     Metrics(1 To 6) As Long
End Type

Type MIXERCONTROLDETAILS_UNSIGNED
     dwValue As Long
End Type

Type MIXERLINE
     cbStruct As Long               '  size of MIXERLINE structure
     dwDestination As Long          '  zero based destination index
     dwSource As Long               '  zero based source index (if source)
     dwLineID As Long               '  unique line id for mixer device
     fdwLine As Long                '  state/information about line
     dwUser As Long                 '  driver specific information
     dwComponentType As Long        '  component type line connects to
     cChannels As Long              '  number of channels line supports
     cConnections As Long           '  number of connections (possible)
     cControls As Long              '  number of controls at this line
     szShortName As String * MIXER_SHORT_NAME_CHARS
     szName As String * MIXER_LONG_NAME_CHARS
     lpTarget As Target
End Type

Type MIXERCONTROLDETAILS
     cbStruct As Long       '  size in Byte of MIXERCONTROLDETAILS
     dwControlID As Long    '  control id to get/set details on
     cChannels As Long      '  number of channels in paDetails array
     item As Long                           ' hwndOwner or cMultipleItems
     cbDetails As Long      '  size of _one_ details_XX struct
     paDetails As Long      '  pointer to array of details_XX structs
End Type

Type MIXERLINECONTROLS
     cbStruct As Long         '  size in Byte of MIXERLINECONTROLS
     dwLineID As Long         '  line id (from MIXERLINE.dwLineID)
     dwControl As Long        '  used with MIXER_GETLINECONTROLSF_ONEBYTYPE or MIXER_GETLINECONTROLSF_ONEBYID
     cControls As Long        '  count of controls pmxctrl points to
     cbmxctrl As Long         '  size in Byte of _one_ MIXERCONTROL
     pamxctrl As Long         '  pointer to first MIXERCONTROL array
End Type


Function GetMixerControl(ByVal hmixer As Long, _
                        ByVal componentType As Long, _
                        ByVal ctrlType As Long, _
                        ByRef mxc As MIXERCONTROL) As Boolean
                        
' This function attempts to obtain a mixer control. Returns True if successful.
   Dim mxlc As MIXERLINECONTROLS
   'Dim mxl As MIXERLINE
   Dim hmem As Long
   Dim rc As Long
       
   mxl.cbStruct = Len(mxl)
   mxl.dwComponentType = componentType
   ' Obtain a line corresponding to the component type
   rc = mixerGetLineInfo(hmixer, mxl, MIXER_GETLINEINFOF_COMPONENTTYPE)
   If (MMSYSERR_NOERROR = rc) Then
       mxlc.cbStruct = Len(mxlc)
       mxlc.dwLineID = mxl.dwLineID
       mxlc.dwControl = ctrlType
       mxlc.cControls = 1
       mxlc.cbmxctrl = Len(mxc)
       ' Allocate a buffer for the control
       hmem = GlobalAlloc(&H40, Len(mxc))
       mxlc.pamxctrl = GlobalLock(hmem)
       mxc.cbStruct = Len(mxc)
       ' Get the control
       rc = mixerGetLineControls(hmixer, mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE)
       If (MMSYSERR_NOERROR = rc) Then
           GetMixerControl = True
           ' Copy the control into the destination structure
           CopyStructFromPtr mxc, mxlc.pamxctrl, Len(mxc)
       Else
           GetMixerControl = False
       End If
       GlobalFree (hmem)
       Exit Function
   End If
   GetMixerControl = False
End Function

Function GetMuteControl(ByVal hmixer As Long, mxc As MIXERCONTROL) As Long
   Dim mxcd As MIXERCONTROLDETAILS
   Dim vol As MIXERCONTROLDETAILS_UNSIGNED
   mxcd.cbStruct = Len(mxcd)
   mxcd.dwControlID = mxc.dwControlID
   mxcd.cChannels = 1
   mxcd.item = 0
   mxcd.cbDetails = Len(vol)
   mxcd.paDetails = 0
   hmem = GlobalAlloc(&H40, Len(vol))
   mxcd.paDetails = GlobalLock(hmem)
   rc = mixerGetControlDetails(hmixer, mxcd, MIXER_GETCONTROLDETAILSF_VALUE)
   CopyStructFromPtr vol, mxcd.paDetails, Len(vol)
   GlobalFree (hmem)
   If (MMSYSERR_NOERROR = rc) Then
       GetMuteControl = vol.dwValue
   Else
       GetMuteControl = -1
   End If
End Function

Function GetVolumeControlValue(ByVal hmixer As Long, mxc As MIXERCONTROL) As Long
'This function Gets the value for a volume control. Returns True if successful
    Dim mxcd As MIXERCONTROLDETAILS
    Dim vol As MIXERCONTROLDETAILS_UNSIGNED
    mxcd.cbStruct = Len(mxcd)
    mxcd.dwControlID = mxc.dwControlID
    mxcd.cChannels = 1
    mxcd.item = 0
    mxcd.cbDetails = Len(vol)
    mxcd.paDetails = 0
    hmem = GlobalAlloc(&H40, Len(vol))
    mxcd.paDetails = GlobalLock(hmem)
    rc = mixerGetControlDetails(hmixer, mxcd, MIXER_GETCONTROLDETAILSF_VALUE)
    CopyStructFromPtr vol, mxcd.paDetails, Len(vol)
    GlobalFree (hmem)
    If (MMSYSERR_NOERROR = rc) Then
       GetVolumeControlValue = vol.dwValue
    Else
        GetVolumeControlValue = -1
    End If
End Function

Public Sub Mixer_AudioLevel(Button As Integer, Index As Integer, Y As Single, X As Single)
    Dim Left1 As Long
    Dim Right1 As Long
    Dim Verify As Long
    Dim Ret As Long
    'frmMain.aniMeter(Index).Play 0, 3, 3
    
    If frmMain.imgVol(Index - 1).Visible = True Then
        If Y >= 0 And Y <= frmMain.imgVol(Index - 1).Height And Button = 1 Then
            Verify = Int(19 - ((19 * Y) / frmMain.imgVol(Index - 1).Height))
            If Verify > 19 Then Verify = 19
            If Verify < 0 Then Verify = 0
            Left1 = Int(Verify * 65536 / 19)
            If Left1 <> VolLong(Index - 1) Then
                SetPANControl hmixer, VolCtrl(Index - 1), Left1, Left1
            End If
        End If
    End If
End Sub

Public Sub Mixer_Close()
    Dim lngloop
    frmMain.tmrAudio.Enabled = False
    For lngloop = 0 To 9
        frmMain.imgLbl(lngloop).Visible = False
        frmMain.imgVol(lngloop).Visible = False
        frmMain.imgMute(lngloop).Visible = False
    Next
    
    mixerClose hmixer
End Sub

Public Sub Mixer_Info()
    Dim lngWidth As Long
    Dim lngFont As Long
    

    frmMain.FontName = frmMain.txtBox(2).FontName
    frmMain.FontSize = frmMain.txtBox(2).FontSize
    lngFont = frmMain.TextWidth(" ")
    lngWidth = Int(((frmMain.txtBox(2).Width / lngFont) - 4) / 2)

    If txtMixer = "" Then
        iniValue = "SoundCard"
        txtMixer = txtMixer & Pad(CStr(iniValue), lngWidth) & " " & Pad(Level_StripTerminator(mxl.lpTarget.szPname), lngWidth) & vbCrLf
        iniValue = "Driver Version"
        txtMixer = txtMixer & Pad(CStr(iniValue), lngWidth) & " " & Pad(CStr(mxl.lpTarget.vDriverVersion), lngWidth) & vbCrLf
    End If
    txtMixer = txtMixer & " " & vbCrLf
    txtMixer = txtMixer & Pad("AudioDevice:", lngWidth) & " " & Pad(Level_StripTerminator(mxl.szName), lngWidth) & vbCrLf
    txtMixer = txtMixer & Pad("Channels:", lngWidth) & " " & Pad(CStr(mxl.cChannels), lngWidth) & vbCrLf
    txtMixer = txtMixer & Pad("Connections:", lngWidth) & " " & Pad(CStr(mxl.cConnections), lngWidth) & vbCrLf
    txtMixer = txtMixer & Pad("Controls:", lngWidth) & " " & Pad(CStr(mxl.cControls), lngWidth) & vbCrLf
    txtMixer = txtMixer & Pad("Shortname:", lngWidth) & " " & Pad(Level_StripTerminator(mxl.szShortName), lngWidth) & vbCrLf
End Sub

Public Sub Mixer_Open()
    Dim ok As Boolean
    Dim lngloop As Long
    Dim lngLeft As Long
    Dim lngTop As Long
    Dim lngWidth As Long
    Dim lngHeight As Long
    Dim strTemp As String
    Dim mxLoop As Long
    Dim lngVolume As Long
    Dim Label(0 To 9) As String
    Dim lngLabel(0 To 9) As Long
    
    rc = mixerOpen(hmixer, 0, 0, 0, 0)
    If ((MMSYSERR_NOERROR <> rc)) Then
        MsgBox "Couldn't open the mixer please check if a audio mixer is installed then retry."
        Exit Sub
    End If

    For lngloop = 0 To 9
        VolLong(lngloop) = -1
    Next
    txtMixer = ""
    lngVolume = 0
    'Master Volume
    ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, MIXERCONTROL_CONTROLTYPE_VOLUME, VolCtrl(lngVolume))
    If (ok = True) Then
        Mixer_Info
        VolLong(lngVolume) = GetVolumeControlValue(hmixer, VolCtrl(lngVolume))
        VolMode(lngVolume) = True
        lngLabel(lngVolume) = 0
        ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, MIXERCONTROL_CONTROLTYPE_MUTE, MuteCtrl(lngVolume))
        If ok Then
            volMute(lngVolume) = GetMuteControl(hmixer, MuteCtrl(lngVolume))
        End If
        lngVolume = lngVolume + 1
    End If

    'Wave OUT
    If lngVolume < 10 Then
        ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT, MIXERCONTROL_CONTROLTYPE_VOLUME, VolCtrl(lngVolume))
        If (ok = True) Then
            Mixer_Info
            VolLong(lngVolume) = GetVolumeControlValue(hmixer, VolCtrl(lngVolume))
            VolMode(lngVolume) = True
            lngLabel(lngVolume) = 1
            ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT, MIXERCONTROL_CONTROLTYPE_MUTE, MuteCtrl(lngVolume))
            If ok Then
                volMute(lngVolume) = GetMuteControl(hmixer, MuteCtrl(lngVolume))
            End If
            lngVolume = lngVolume + 1
        End If
    End If
    'CD
    If lngVolume < 10 Then
        ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC, MIXERCONTROL_CONTROLTYPE_VOLUME, VolCtrl(lngVolume))
        If (ok = True) Then
            Mixer_Info
            VolLong(lngVolume) = GetVolumeControlValue(hmixer, VolCtrl(lngVolume))
            VolMode(lngVolume) = True
            lngLabel(lngVolume) = 2
            ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC, MIXERCONTROL_CONTROLTYPE_MUTE, MuteCtrl(lngVolume))
            If ok Then
                volMute(lngVolume) = GetMuteControl(hmixer, MuteCtrl(lngVolume))
            End If
            lngVolume = lngVolume + 1
        End If
    End If
    'Line In
    If lngVolume < 10 Then
        ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_LINE, MIXERCONTROL_CONTROLTYPE_VOLUME, VolCtrl(lngVolume))
        If (ok = True) Then
            Mixer_Info
            VolLong(lngVolume) = GetVolumeControlValue(hmixer, VolCtrl(lngVolume))
            VolMode(lngVolume) = True
            lngLabel(lngVolume) = 3
            ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_LINE, MIXERCONTROL_CONTROLTYPE_MUTE, MuteCtrl(lngVolume))
            If ok Then
                volMute(lngVolume) = GetMuteControl(hmixer, MuteCtrl(lngVolume))
            End If
            lngVolume = lngVolume + 1
        End If
    End If
    'Midi
    If lngVolume < 10 Then
        ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER, MIXERCONTROL_CONTROLTYPE_VOLUME, VolCtrl(lngVolume))
        If (ok = True) Then
            Mixer_Info
            VolLong(lngVolume) = GetVolumeControlValue(hmixer, VolCtrl(lngVolume))
            VolMode(lngVolume) = True
            lngLabel(lngVolume) = 4
            ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER, MIXERCONTROL_CONTROLTYPE_MUTE, MuteCtrl(lngVolume))
            If ok Then
                volMute(lngVolume) = GetMuteControl(hmixer, MuteCtrl(lngVolume))
            End If
            lngVolume = lngVolume + 1
        End If
    End If
    'Aux
    If lngVolume < 10 Then
        ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY, MIXERCONTROL_CONTROLTYPE_VOLUME, VolCtrl(lngVolume))
        If (ok = True) Then
            Mixer_Info
            VolLong(lngVolume) = GetVolumeControlValue(hmixer, VolCtrl(lngVolume))
            VolMode(lngVolume) = True
            lngLabel(lngVolume) = 5
            ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY, MIXERCONTROL_CONTROLTYPE_MUTE, MuteCtrl(lngVolume))
            If ok Then
                volMute(lngVolume) = GetMuteControl(hmixer, MuteCtrl(lngVolume))
            End If
            lngVolume = lngVolume + 1
        End If
    End If
    'Digital IN
    If lngVolume < 10 Then
        ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_DIGITAL, MIXERCONTROL_CONTROLTYPE_VOLUME, VolCtrl(lngVolume))
        If (ok = True) Then
            Mixer_Info
            VolLong(lngVolume) = GetVolumeControlValue(hmixer, VolCtrl(lngVolume))
            VolMode(lngVolume) = True
            lngLabel(lngVolume) = 6
            ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_DIGITAL, MIXERCONTROL_CONTROLTYPE_MUTE, MuteCtrl(lngVolume))
            If ok Then
                volMute(lngVolume) = GetMuteControl(hmixer, MuteCtrl(lngVolume))
            End If
            lngVolume = lngVolume + 1
        End If
    End If
    'Phone
    If lngVolume < 10 Then
        ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE, MIXERCONTROL_CONTROLTYPE_VOLUME, VolCtrl(lngVolume))
        If (ok = True) Then
            Mixer_Info
            VolLong(lngVolume) = GetVolumeControlValue(hmixer, VolCtrl(lngVolume))
            VolMode(lngVolume) = True
            lngLabel(lngVolume) = 7
            ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE, MIXERCONTROL_CONTROLTYPE_MUTE, MuteCtrl(lngVolume))
            If ok Then
                volMute(lngVolume) = GetMuteControl(hmixer, MuteCtrl(lngVolume))
            End If
            lngVolume = lngVolume + 1
        End If
    End If
    'pcspeaker
    If lngVolume < 10 Then
        ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER, MIXERCONTROL_CONTROLTYPE_VOLUME, VolCtrl(lngVolume))
        If (ok = True) Then
            Mixer_Info
            VolLong(lngVolume) = GetVolumeControlValue(hmixer, VolCtrl(lngVolume))
            VolMode(lngVolume) = False
            lngLabel(lngVolume) = 8
            ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER, MIXERCONTROL_CONTROLTYPE_MUTE, MuteCtrl(lngVolume))
            If ok Then
                volMute(lngVolume) = GetMuteControl(hmixer, MuteCtrl(lngVolume))
            End If
            lngVolume = lngVolume + 1
        End If
    End If
    'Microphone
    If lngVolume < 10 Then
        ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE, MIXERCONTROL_CONTROLTYPE_VOLUME, VolCtrl(lngVolume))
        If (ok = True) Then
            Mixer_Info
            VolLong(lngVolume) = GetVolumeControlValue(hmixer, VolCtrl(lngVolume))
            VolMode(lngVolume) = False
            lngLabel(lngVolume) = 9
            ok = GetMixerControl(hmixer, MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE, MIXERCONTROL_CONTROLTYPE_MUTE, MuteCtrl(lngVolume))
            If ok Then
                volMute(lngVolume) = GetMuteControl(hmixer, MuteCtrl(lngVolume))
            End If
            lngVolume = lngVolume + 1
        End If
    End If


    For lngloop = 0 To 21
        INI_GetKey "VOLUME", "Meter" & Format(lngloop, "00"), strProgramdir & strThemedir & strThemeName & ".skn"
        frmMain.imgMeter(lngloop).Picture = LoadPicture(strProgramdir & strThemedir & iniValue)
    Next
    
    For mxLoop = 0 To 9
        If INI_GetKey("VOLUME", "label" & CStr(mxLoop), strProgramdir & strThemedir & strThemeName & ".skn") = True Then
            Label(mxLoop) = iniValue
        End If
    Next
    
    For mxLoop = 0 To 9
        If VolLong(mxLoop) <> -1 Then
            If INI_GetKey("VOLUME", "volume" & CStr(mxLoop), strProgramdir & strThemedir & strThemeName & ".skn") = True Then
                strTemp = iniValue
                lngloop = InStr(strTemp, ",")
                lngLeft = CStr(Left(strTemp, lngloop - 1))
                If lngLeft <= 0 Then lngLeft = frmMain.ScaleHeight + lngLeft
                strTemp = Mid(strTemp, lngloop + 1)
                lngloop = InStr(strTemp, ",")
                lngTop = CStr(Left(strTemp, lngloop - 1))
                If lngTop <= 0 Then lngTop = frmMain.ScaleHeight + lngTop
                strTemp = Mid(strTemp, lngloop + 1)
                lngloop = InStr(strTemp, ",")
                lngWidth = CStr(Left(strTemp, lngloop - 1))
                If lngWidth <= 0 Then lngWidth = frmMain.ScaleWidth + lngWidth
                strTemp = Mid(strTemp, lngloop + 1)
                lngloop = InStr(strTemp, ",")
                lngHeight = CStr(Left(strTemp, lngloop - 1))
                If lngHeight <= 0 Then lngHeight = frmMain.ScaleHeight + lngHeight
                frmMain.imgVol(mxLoop).Left = lngLeft
                frmMain.imgVol(mxLoop).Top = lngTop
                frmMain.imgVol(mxLoop).Width = lngWidth
                frmMain.imgVol(mxLoop).Height = lngHeight
                frmMain.imgVol(mxLoop).Picture = frmMain.imgMeter(Int((VolLong(mxLoop) * 20) / 65536)).Picture
                frmMain.imgVol(mxLoop).Visible = True
                strTemp = Mid(strTemp, lngloop + 1)
                lngloop = InStr(strTemp, ",")
                lngLeft = CStr(Left(strTemp, lngloop - 1))
                If lngLeft <= 0 Then lngLeft = frmMain.ScaleHeight + lngLeft
                strTemp = Mid(strTemp, lngloop + 1)
                lngloop = InStr(strTemp, ",")
                lngTop = CStr(Left(strTemp, lngloop - 1))
                If lngTop <= 0 Then lngTop = frmMain.ScaleHeight + lngTop
                strTemp = Mid(strTemp, lngloop + 1)
                lngloop = InStr(strTemp, ",")
                lngWidth = CStr(Left(strTemp, lngloop - 1))
                If lngWidth <= 0 Then lngWidth = frmMain.ScaleWidth + lngWidth
                strTemp = Mid(strTemp, lngloop + 1)
                lngloop = InStr(strTemp, ",")
                lngHeight = CStr(Left(strTemp, lngloop - 1))
                If lngHeight <= 0 Then lngHeight = frmMain.ScaleHeight + lngHeight
                frmMain.imgLbl(mxLoop).Left = lngLeft
                frmMain.imgLbl(mxLoop).Top = lngTop
                frmMain.imgLbl(mxLoop).Width = lngWidth
                frmMain.imgLbl(mxLoop).Height = lngHeight
                frmMain.imgLbl(mxLoop).Picture = LoadPicture(strProgramdir & strThemedir & Label(lngLabel(mxLoop)))
                frmMain.imgLbl(mxLoop).Visible = True
                strTemp = Mid(strTemp, lngloop + 1)
                lngloop = InStr(strTemp, ",")
                lngLeft = CStr(Left(strTemp, lngloop - 1))
                If lngLeft <= 0 Then lngLeft = frmMain.ScaleHeight + lngLeft
                strTemp = Mid(strTemp, lngloop + 1)
                lngloop = InStr(strTemp, ",")
                lngTop = CStr(Left(strTemp, lngloop - 1))
                If lngTop <= 0 Then lngTop = frmMain.ScaleHeight + lngTop
                strTemp = Mid(strTemp, lngloop + 1)
                lngloop = InStr(strTemp, ",")
                lngWidth = CStr(Left(strTemp, lngloop - 1))
                If lngWidth <= 0 Then lngWidth = frmMain.ScaleWidth + lngWidth
                lngHeight = CStr(Mid(strTemp, lngloop + 1))
                If lngHeight <= 0 Then lngHeight = frmMain.ScaleHeight + lngHeight
                frmMain.imgMute(mxLoop).Left = lngLeft
                frmMain.imgMute(mxLoop).Top = lngTop
                frmMain.imgMute(mxLoop).Width = lngWidth
                frmMain.imgMute(mxLoop).Height = lngHeight
                If volMute(mxLoop) = True Then
                    frmMain.imgMute(mxLoop).Picture = frmMain.imgMeter(21).Picture
                Else
                    frmMain.imgMute(mxLoop).Picture = frmMain.imgMeter(20).Picture
                End If
                frmMain.imgMute(mxLoop).Visible = True
            Else
                VolLong(mxLoop) = -1
            End If
        End If
    Next
    frmMain.tmrAudio.Enabled = True
    frmMain.txtBox(2).Text = txtMixer
End Sub

Public Function SetMuteControl(ByVal hmixer As Long, mxc As MIXERCONTROL, ByVal mute As Long) As Boolean
   Dim mxcd As MIXERCONTROLDETAILS
   Dim vol As MIXERCONTROLDETAILS_UNSIGNED
   mxcd.cbStruct = Len(mxcd)
   mxcd.dwControlID = mxc.dwControlID
   mxcd.cChannels = 1
   mxcd.item = 0
   mxcd.cbDetails = Len(vol)
   hmem = GlobalAlloc(&H40, Len(vol))
   mxcd.paDetails = GlobalLock(hmem)
   vol.dwValue = mute
   CopyPtrFromStruct mxcd.paDetails, vol, Len(vol)
   rc = mixerSetControlDetails(hmixer, mxcd, MIXER_SETCONTROLDETAILSF_VALUE)
   GlobalFree (hmem)
   If (MMSYSERR_NOERROR = rc) Then
       SetMuteControl = True
   Else
       SetMuteControl = False
   End If
End Function


Public Function SetPANControl(ByVal hmixer As Long, mxc As MIXERCONTROL, ByVal volL As Long, ByVal volR As Long) As Boolean
'This function sets the value for a volume control. Returns True if successful
   Dim mxcd As MIXERCONTROLDETAILS
   Dim vol(1) As MIXERCONTROLDETAILS_UNSIGNED
   mxcd.item = mxc.cMultipleItems
   mxcd.dwControlID = mxc.dwControlID
   mxcd.cbStruct = Len(mxcd)
   mxcd.cbDetails = Len(vol(1))
   ' Allocate a buffer for the control value buffer
   mxcd.cChannels = 2
   hmem = GlobalAlloc(&H40, Len(vol(1)))
   mxcd.paDetails = GlobalLock(hmem)
   vol(1).dwValue = volR
   vol(0).dwValue = volL
   ' Copy the data into the control value buffer
   CopyPtrFromStruct mxcd.paDetails, vol(1).dwValue, Len(vol(0)) * mxcd.cChannels
   CopyPtrFromStruct mxcd.paDetails, vol(0).dwValue, Len(vol(1)) * mxcd.cChannels
   ' Set the control value
   rc = mixerSetControlDetails(hmixer, mxcd, MIXER_SETCONTROLDETAILSF_VALUE)
   GlobalFree (hmem)
   If (MMSYSERR_NOERROR = rc) Then
       SetPANControl = True
   Else
       SetPANControl = False
   End If
   
End Function

Public Function unSetMuteControl(ByVal hmixer As Long, mxc As MIXERCONTROL, ByVal unmute As Long) As Boolean
   Dim mxcd As MIXERCONTROLDETAILS
   Dim vol As MIXERCONTROLDETAILS_UNSIGNED
   mxcd.cbStruct = Len(mxcd)
   mxcd.dwControlID = mxc.dwControlID
   mxcd.cChannels = 1
   mxcd.item = 0
   mxcd.cbDetails = Len(vol)
   hmem = GlobalAlloc(&H40, Len(vol))
   mxcd.paDetails = GlobalLock(hmem)
   vol.dwValue = unmute
   CopyPtrFromStruct mxcd.paDetails, vol, Len(vol)
   rc = mixerSetControlDetails(hmixer, mxcd, MIXER_SETCONTROLDETAILSF_VALUE)
   GlobalFree (hmem)
   If (MMSYSERR_NOERROR = rc) Then
       unSetMuteControl = True
   Else
       unSetMuteControl = False
   End If
End Function

