Jump to content

zPlayer - My own little audio/video player


Go to solution Solved by TheXman,

Recommended Posts

Posted
#include <WindowsConstants.au3>

Local $sTitle = "Beethoven - Symphony No.9 in D minor, Op.125 - 'Choral' - 4. Presto Allegro assai.flac"
Local $guiWidth = 400, $aLabel[3], $aWidth[3], $alabelX[3], $iMarqueeInterval = 40
$alabelX[0] = 0
$hGUI = GUICreate("", $guiWidth, 100)
GUISetStyle(-1, BitOR($WS_EX_COMPOSITED, $WS_EX_TOPMOST)) ; $WS_EX_COMPOSITED $WS_EX_TOPMOST
GUISetFont(10, 400, 0, "Arial")
$aLabel[0] = GUICtrlCreateLabel($sTitle, $alabelX[0], 10, -1, 18)
$aWidth[0] = ControlGetPos($hGUI, "", $aLabel[0])[2]
GUISetState()

; Check if the label width exceeds the GUI width
If $aWidth[0] > $guiWidth Then
    $aLabel[1] = GUICtrlCreateLabel("  ðŸŽµ  ", $alabelX[0] + $aWidth[0], 10, -1, 18)
    $aWidth[1] = ControlGetPos($hGUI, "", $aLabel[1])[2]
    $aLabel[2] = GUICtrlCreateLabel($sTitle, $alabelX[1] + $aWidth[1], 10, -1, 18)
    $aWidth[2] = ControlGetPos($hGUI, "", $aLabel[2])[2]
    Sleep(3000)
    AdlibRegister("_Marquee", $iMarqueeInterval)
EndIf


Do
    Sleep(10)
Until GUIGetMsg() = -3
;~ AdlibUnRegister()

Func _Marquee()

    If $alabelX[0] = 0 Then
        $alabelX[1] = $alabelX[0] + $aWidth[0]
        $alabelX[2] = $alabelX[1] + $aWidth[1]
;~      Sleep(3000)
    EndIf

    If $alabelX[2] = 0 Then
        $alabelX[1] = $alabelX[2] + $aWidth[2]
        $alabelX[0] = $alabelX[1] + $aWidth[1]
;~      Sleep(3000)
    EndIf

    $alabelX[0] -= 1
    $alabelX[1] -= 1
    $alabelX[2] -= 1

    ControlMove($hGUI, "", $aLabel[0], $alabelX[0], 10)
    ControlMove($hGUI, "", $aLabel[1], $alabelX[1], 10)
    ControlMove($hGUI, "", $aLabel[2], $alabelX[2], 10)
EndFunc   ;==>_Marquee

 

I know that I know nothing

Posted (edited)

I am happy to report that I have implemented a smooth and infinite marquee for displaying long file names in zPlayer. Below is an exact replica of the code. You can try this code with filenames of different lengths. In this example, the 2nd and 3rd files are both 53 characters long, but their string widths are different: the 2nd is 320 pixels, the same as the GUI, and the 3rd is 340 pixels, slightly wider than the GUI. The first two files do not need to scroll, but the third does.

#include <GUIConstants.au3>

Global $sTitle, $hMain, $guiWidth = 320, $idTitle, $titlePosX = 5, $titlePosY = 10
Global $titleWidth, $sGap = "     ", $titlePosX2, $marqueeInterval = 40, $iMarquee

$sTitle = "Luciano Pavarotti - Una Furtiva Lagrima.mp3"             ; 34 characters, 254 pixels
;$sTitle = "Schubert - Symphony No.8 in B minor, 'Unfinished'.mp3"  ; 53 characters, 320 pixels
;$sTitle = "Schumann - Scenes from Childhood, Op 15, Taumerei.mp3"  ; 53 characters, 340 pixels - 'r' intentionally omitted

$hMain = GUICreate("zPlayer", $guiWidth, 100)
GUISetFont(10, 400, 0, "Arial")
$idTitle = GUICtrlCreateLabel($sTitle, $titlePosX, $titlePosY, $guiWidth, 18, BitOR($SS_NOPREFIX, $SS_LEFTNOWORDWRAP))
GUISetState()

Local $tmpGUI, $tmpLabel
$tmpGUI = GUICreate("")     ; Temporary GUI to measure pixel width of $sTitle
GUISetFont(10, 400, 0, "Arial", $tmpGUI)
$tmpLabel = GUICtrlCreateLabel($sTitle, 0, 0, -1, 18, BitOR($SS_NOPREFIX, $SS_LEFTNOWORDWRAP))
$titleWidth = ControlGetPos($tmpGUI, "", $tmpLabel)[2] - 9  ; The label width is wider than actual string width by 9 pixels.
GUIDelete($tmpGUI)

ConsoleWrite("Title Length:" & @TAB & StringLen($sTitle) & " characters" & @CRLF)
ConsoleWrite("Title Width:" & @TAB & $titleWidth & " pixels" & @CRLF)

If $titleWidth >= $guiWidth - $titlePosX*2 Then
    If $titleWidth <= $guiWidth Then
        ControlMove($hMain, "", $idTitle, Round(($guiWidth-$titleWidth)/2), $titlePosY)
    Else
        ControlMove($hMain, "", $idTitle, $titlePosX, $titlePosY, $titleWidth+$guiWidth+StringLen($sGap)*4)
        GUICtrlSetData($idTitle, $sTitle & $sGap & $sTitle) ; 5 spaces between tail and trailing head, 4 pixels each
        $titlePosX2 = $titlePosX
        $iMarquee = 0
        AdlibRegister("_Marquee", $marqueeInterval)
    EndIf
EndIf

Do
    Sleep(10)
Until GUIGetMsg() = -3

Func _Marquee()
    ; 3 seconds of halt when the head comes to the initial position. Sleep() is not recommended.
    $iMarquee += 1
    If $iMarquee < 3000/$marqueeInterval Then Return
    $titlePosX2 -= 1
    ControlMove($hMain, "", $idTitle, $titlePosX2, $titlePosY)
    If -$titlePosX2 = $titleWidth + StringLen($sGap) * 4 - $titlePosX Then  ; Each space is 4 pixels wide
        $titlePosX2 = $titlePosX
        $iMarquee = 0
    EndIf
EndFunc


 

Edited by CYCho
Posted

If the master volume of my audio device was muted for whatever reason when I started my media player, I would wonder for a moment if something was wrong. So I came up with this code based on what @wraithdu wrote many years ago. I will place this code just before playing the first file so that the master volume is unmuted on startup.
 

Opt("WinTitleMatchMode", 2)

If ProcessExists("sndvol.exe") Then
    ProcessClose("sndvol.exe")
EndIf
Run(@SystemDir & "\sndvol.exe")
$hWnd = WinWaitActive("Mixer")
$aPos = WinGetPos($hWnd)
WinMove("Mixer", "", (@DesktopWidth - $aPos[2])/2, 0)

$bMute = _MasterVolume("GetMute")
$sMsg = ($bMute = 1) ? ('muted!') : ('not muted!')
$sMsg = 'Audio device is ' & $sMsg & @CRLF & 'Please watch how the Windows volume mixer changes.'
MsgBox(0, 'Mute state', $sMsg)

If $bMute = 0 Then
    _MasterVolume("Mute")
    Sleep(3000)
    _MasterVolume("UnMute")
Else
    _MasterVolume("UnMute")
    Sleep(3000)
    _MasterVolume("Mute")
EndIf

Func _MasterVolume($action)
    ; https://www.autoitscript.com/forum/topic/84834-control-vista-master-volume/
    Local Const $CLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
    Local Const $IID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
    Local Const $tagIMMDeviceEnumerator = _
        "EnumAudioEndpoints hresult(int;dword;ptr*);" & _
        "GetDefaultAudioEndpoint hresult(int;int;ptr*);" & _
        "GetDevice hresult(wstr;ptr*);" & _
        "RegisterEndpointNotificationCallback hresult(ptr);" & _
        "UnregisterEndpointNotificationCallback hresult(ptr)"

    Local Const $IID_IMMDevice = "{D666063F-1587-4E43-81F1-B948E807363F}"
    Local Const $tagIMMDevice = _
        "Activate hresult(struct*;dword;ptr;ptr*);" & _
        "OpenPropertyStore hresult(dword;ptr*);" & _
        "GetId hresult(wstr*);" & _
        "GetState hresult(dword*)"
    Local Const $eRender = 0, $eConsole = 0

    Local Const $IID_IAudioEndpointVolume = "{5CDF2C82-841E-4546-9722-0CF74078229A}"
    Local Const $tagIAudioEndpointVolume = _
        "RegisterControlChangeNotify hresult(ptr);" & _
        "UnregisterControlChangeNotify hresult(ptr);" & _
        "GetChannelCount hresult(uint*);" & _
        "SetMasterVolumeLevel hresult(float;ptr);" & _
        "SetMasterVolumeLevelScalar hresult(float;ptr);" & _
        "GetMasterVolumeLevel hresult(float*);" & _
        "GetMasterVolumeLevelScalar hresult(float*);" & _
        "SetChannelVolumeLevel hresult(uint;float;ptr);" & _
        "SetChannelVolumeLevelScalar hresult(uint;float;ptr);" & _
        "GetChannelVolumeLevel hresult(uint;float*);" & _
        "GetChannelVolumeLevelScalar hresult(uint;float*);" & _
        "SetMute hresult(int;ptr);" & _
        "GetMute hresult(int*);" & _
        "GetVolumeStepInfo hresult(uint*;uint*);" & _
        "VolumeStepUp hresult(ptr);" & _
        "VolumeStepDown hresult(ptr);" & _
        "QueryHardwareSupport hresult(dword*);" & _
        "GetVolumeRange hresult(float*;float*;float*)"

    Local $oIAudioEndpointVolume = 0;, $err = 1
    ; create device enumerator interface
    Local $oDevEnum = ObjCreateInterface($CLSID_MMDeviceEnumerator, $IID_IMMDeviceEnumerator, $tagIMMDeviceEnumerator)
    If IsObj($oDevEnum) Then
        ; get default audio endpoint interface pointer
        Local $pDefaultDevice = 0
        If $oDevEnum.GetDefaultAudioEndpoint($eRender, $eConsole, $pDefaultDevice) >= 0 Then
            ; create default audio endpoint interface
            Local $oIMMDevice = ObjCreateInterface($pDefaultDevice, $IID_IMMDevice, $tagIMMDevice)
            If IsObj($oIMMDevice) Then
                ; get endpoint volume interface pointer
                Local $pEndpointVolume = 0
                Local $tGUID = DllStructCreate("ulong Data1;ushort Data2;ushort Data3;byte Data4[8]")
                DllCall("ole32.dll", "long", "CLSIDFromString", "wstr", $IID_IAudioEndpointVolume, "struct*", $tGUID)
                If $oIMMDevice.Activate($tGUID, 1, 0, $pEndpointVolume) >= 0 Then
                    ; create endpoint volume interface
                    $oIAudioEndpointVolume = ObjCreateInterface($pEndpointVolume, $IID_IAudioEndpointVolume, $tagIAudioEndpointVolume)
                EndIf
                $oIMMDevice = 0
            EndIf
        EndIf
        $oDevEnum = 0
    EndIf

    If $action = "GetMute" Then                 ; Get mute state of the audio device
        Local $bMute = 0
        $oIAudioEndpointVolume.GetMute($bMute)
        Return $bMute                           ; 0 - not muted, 1 - muted
    ElseIf $action = "Mute" Then                ; Mute the audio device
        $oIAudioEndpointVolume.SetMute(1, 0)    ; 1st parameter: 1 to mute, 0 to unmute
    ElseIf $action = "UnMute" Then              ; Unmute the audio device
        $oIAudioEndpointVolume.SetMute(0, 0)    ; 1st parameter: 1 to mute, 0 to unmute
    EndIf
EndFunc     ;==>_Audio_MasterVolume

 

Posted (edited)

zPlayer6-ColorSchemes.png
I purposely made my GUI as small as possible, and every inch of the space in the GUI is too dear to spare. That's why I came up with an idea to make use of the empty space in the title bar. That brought an added bonus: I could give a color to the title bar. I will upload the latest version of zPlayer with these features when they are fine-tuned.

Edit: Version 6.1.5.0 with these features was uploaded on Feb. 16, 2025.

Edited by CYCho
Posted

When I implemented the marquee-style display of media titles in zPlayer, I had to make an assumption about how long the longest file name would be. Of all the files I have, the longest full path was 247 characters, consisting of 104 for the pathname and 143 for the filename. What mattered for my display was the file name, and I assumed that the file name could be as long as 260 characters, which is the limit set by Windows. I needed the display to be as wide as the title width plus the width of the GUI. Assuming that each character would be 6.5 pixels on average, I decided to use 2000 pixels. My GUI is only 320 pixels wide, but the display label had to be long enough to hold the longest filename without truncation. I couldn't find any penalty for having a label much wider than the width of the GUI. I don't know if anyone has tried this, but I'm happy with it. The result is a smooth and infinitely scrolling marquee-style display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...